fix: prevent crash converting UUID timestamps near the Unix epoch

PhpTimeConverter::convertTime() threw an uncaught
InvalidArgumentException for v1/v6 UUID timestamps within about
100 microseconds of the Unix epoch (on the pre-1970 side), because
PHP renders such small floats in scientific notation, which
splitTime() misparsed as a malformed microseconds fragment.

splitTime() now recognizes scientific notation and defers to the
existing GenericTimeConverter fallback, the same mechanism already
used for other precision-loss cases.
This commit is contained in:
dualfroz committed 2026-09-06 00:58:57 +02:00
1 parent a27d5edc8f
commit 90c8548448
2 files changed
+15

No files matched your search

+7
View File
@@ -26,6 +26,7 @@ use function dechex;
use function explode; use function explode;
use function is_float; use function is_float;
use function is_int; use function is_int;
use function str_contains;
use function str_pad; use function str_pad;
use function strlen; use function strlen;
use function substr; use function substr;
@@ -142,6 +143,12 @@ class PhpTimeConverter implements TimeConverterInterface
return ['sec' => $split[0], 'usec' => '0']; return ['sec' => $split[0], 'usec' => '0'];
} }
// Near zero PHP renders the float in scientific notation ("-1.0E-6"), whose
// exponent would be misparsed as microseconds; fall back instead.
if (str_contains($split[1], 'E')) {
return [];
}
// If the microseconds are less than six characters AND the length of the number is greater than or equal to the // If the microseconds are less than six characters AND the length of the number is greater than or equal to the
// PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so // PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so
// that we can choose to use the fallback converter. // that we can choose to use the fallback converter.
@@ -133,6 +133,14 @@ class PhpTimeConverterTest extends TestCase
'unixTimestamp' => '0', 'unixTimestamp' => '0',
'microseconds' => '0', 'microseconds' => '0',
], ],
// One microsecond before the epoch: PHP renders "-1.0E-6", which must not
// be misparsed as microseconds.
[
'uuidTimestamp' => new Hexadecimal('1b21dd213813ff6'),
'unixTimestamp' => '0',
'microseconds' => '1',
],
]; ];
} }