8000 [Uid] Fix validating UUID variant bits by nicolas-grekas · Pull Request #47518 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Uid] Fix validating UUID variant bits #47518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/Symfony/Component/Uid/Tests/UuidTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,32 @@ public function provideInvalidUuids(): iterable
yield ['these are just thirty-six characters'];
}

/**
* @dataProvider provideInvalidVariant
*/
public function testInvalidVariant(string $uuid)
{
$uuid = new Uuid($uuid);
$this->assertFalse(Uuid::isValid($uuid));
8000
$uuid = (string) $uuid;
$class = Uuid::class.'V'.$uuid[14];

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid UUIDv'.$uuid[14].': "'.$uuid.'".');

new $class($uuid);
}

public function provideInvalidVariant(): iterable
{
yield ['8dac64d3-937a-1e7c-fa1d-d5d6c06a61f5'];
yield ['8dac64d3-937a-3e7c-fa1d-d5d6c06a61f5'];
yield ['8dac64d3-937a-4e7c-fa1d-d5d6c06a61f5'];
yield ['8dac64d3-937a-5e7c-fa1d-d5d6c06a61f5'];
yield ['8dac64d3-937a-6e7c-fa1d-d5d6c06a61f5'];
}

public function testConstructorWithValidUuid()
{
$uuid = new UuidV4(self::A_UUID_V4);
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Component/Uid/Ulid.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public static function isValid(string $ulid): bool
*/
public static function fromString(string $ulid): parent
{
if (36 === \strlen($ulid) && Uuid::isValid($ulid)) {
$ulid = (new Uuid($ulid))->toBinary();
if (36 === \strlen($ulid) && preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $ulid)) {
$ulid = uuid_parse($ulid);
} elseif (22 === \strlen($ulid) && 22 === strspn($ulid, BinaryUtil::BASE58[''])) {
$ulid = str_pad(BinaryUtil::fromBase($ulid, BinaryUtil::BASE58), 16, "\0", \STR_PAD_LEFT);
}
Expand Down
22 changes: 14 additions & 8 deletions src/Symfony/Component/Uid/Uuid.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Uuid extends AbstractUid
protected const TYPE = 0;
protected const NIL = '00000000-0000-0000-0000-000000000000';

public function __construct(string $uuid)
public function __construct(string $uuid, bool $checkVariant = false)
{
$type = preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid) ? (int) $uuid[14] : false;

Expand All @@ -35,6 +35,10 @@ public function __construct(string $uuid)
}

$this->uid = strtolower($uuid);

if ($checkVariant && !\in_array($this->uid[19], ['8', '9', 'a', 'b'], true)) {
throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid));
}
}

/**
Expand Down Expand Up @@ -67,12 +71,14 @@ public static function fromString(string $uuid): parent
return new NilUuid();
}

switch ($uuid[14]) {
case UuidV1::TYPE: return new UuidV1($uuid);
case UuidV3::TYPE: return new UuidV3($uuid);
case UuidV4::TYPE: return new UuidV4($uuid);
case UuidV5::TYPE: return new UuidV5($uuid);
case UuidV6::TYPE: return new UuidV6($uuid);
if (\in_array($uuid[19], ['8', '9', 'a', 'b', 'A', 'B'], true)) {
switch ($uuid[14]) {
case UuidV1::TYPE: return new UuidV1($uuid);
case UuidV3::TYPE: return new UuidV3($uuid);
case UuidV4::TYPE: return new UuidV4($uuid);
case UuidV5::TYPE: return new UuidV5($uuid);
case UuidV6::TYPE: return new UuidV6($uuid);
}
}

return new self($uuid);
Expand Down Expand Up @@ -111,7 +117,7 @@ final public static function v6(): UuidV6

public static function isValid(string $uuid): bool
{
if (!preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid)) {
if (!preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){2}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$}Di', $uuid)) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Uid/UuidV1.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function __construct(string $uuid = null)
if (null === $uuid) {
$this->uid = uuid_create(static::TYPE);
} else {
parent::__construct($uuid);
parent::__construct($uuid, true);
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/Uid/UuidV3.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@
class UuidV3 extends Uuid
{
protected const TYPE = 3;

public function __construct(string $uuid)
{
parent::__construct($uuid, true);
}
}
2 changes: 1 addition & 1 deletion src/Symfony/Component/Uid/UuidV4.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function __construct(string $uuid = null)

$this->uid = substr($uuid, 0, 8).'-'.substr($uuid, 8, 4).'-'.substr($uuid, 12, 4).'-'.substr($uuid, 16, 4).'-'.substr($uuid, 20, 12);
} else {
parent::__construct($uuid);
parent::__construct($uuid, true);
}
}
}
5 changes: 5 additions & 0 deletions src/Symfony/Component/Uid/UuidV5.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@
class UuidV5 extends Uuid
{
protected const TYPE = 5;

public function __construct(string $uuid)
{
parent::__construct($uuid, true);
}
}
2 changes: 1 addition & 1 deletion src/Symfony/Component/Uid/UuidV6.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function __construct(string $uuid = null)
if (null === $uuid) {
$this->uid = static::generate();
} else {
parent::__construct($uuid);
parent::__construct($uuid, true);
}
}

Expand Down
0