Fixed the UUID generation logic so that the variant digit is RFC 4122 (#4554)

conforming.
This commit is contained in:
Ahson Khan 2023-04-17 18:37:51 -07:00 committed by GitHub
parent 1ae675a1bb
commit f166699120
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 7 deletions

View File

@ -12,6 +12,7 @@ This is useful when the UUID was generated outside the Azure SDK, or needs to be
### Bugs Fixed
- [[#4490]](https://github.com/Azure/azure-sdk-for-cpp/issues/4490) Fixed WinHTTP memory leak during failed requests.
- Fixed the UUID generation so the variant is RFC 4122 conforming.
### Other Changes

View File

@ -24,11 +24,6 @@ namespace Azure { namespace Core {
static constexpr size_t UuidSize = 16;
std::array<uint8_t, UuidSize> m_uuid;
// The UUID reserved variants.
static constexpr uint8_t ReservedNCS = 0x80;
static constexpr uint8_t ReservedRFC4122 = 0x40;
static constexpr uint8_t ReservedMicrosoft = 0x20;
static constexpr uint8_t ReservedFuture = 0x00;
private:
Uuid(uint8_t const uuid[UuidSize]) { std::memcpy(m_uuid.data(), uuid, UuidSize); }

View File

@ -67,8 +67,15 @@ namespace Azure { namespace Core {
std::memcpy(uuid + i, &x, 4);
}
// SetVariant to ReservedRFC4122
uuid[8] = (uuid[8] | ReservedRFC4122) & 0x7F;
// The variant field consists of a variable number of the most significant bits of octet 8 of
// the UUID.
// https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.1
// For setting the variant to conform to RFC4122, the high bits need to be of the form 10xx,
// which means the hex value of the first 4 bits can only be either 8, 9, A|a, B|b. The 0-7
// values are reserved for backward compatibility. The C|c, D|d values are reserved for
// Microsoft, and the E|e, F|f values are reserved for future use.
// Therefore, we have to zero out the two high bits, and then set the highest bit to 1.
uuid[8] = (uuid[8] & 0x3F) | 0x80;
constexpr uint8_t version = 4; // Version 4: Pseudo-random number

View File

@ -36,6 +36,33 @@ TEST(Uuid, Randomness)
EXPECT_EQ(uuids.size(), size);
}
TEST(Uuid, Rfc4122Conforming)
{
const int size = 100;
for (int i = 0; i < size; i++)
{
auto uuid = Uuid::CreateUuid();
auto uuidStr = uuid.ToString();
auto version = uuidStr[14];
EXPECT_EQ(version, '4'); // Version 4: Pseudo-random number
// The variant field consists of a variable number of the most significant bits of octet 8 of
// the UUID.
// https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.1
// The high bits of the variant need to be of the form 10xx, which means they can only be either
// 8, 9, A|a, B|b. The 0-7 values are reserved for backward compatibility. The C|c, D|d values
// are reserved for Microsoft, and the E|e, F|f values are reserved for future use.
auto variant = uuidStr[19];
// The test is written this way to improve logging IF it was to fail, so we can see the value
// of the incorrect variant.
EXPECT_TRUE(
(variant == '8' || variant == '9' || variant == 'A' || variant == 'B' || variant == 'a'
|| variant == 'b'))
<< variant << " is not one of the expected values of 8, 9, A, B, a, b";
}
}
TEST(Uuid, separatorPosition)
{
auto uuidKey = Uuid::CreateUuid().ToString();