From 44b966e94a5909088c5cb9052c5be3d854a4bd63 Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Thu, 25 Jun 2026 08:40:39 -0500 Subject: [PATCH v3 3/3] Reject timestamps beyond 48-bit limit in uuidv7(interval) uuidv7() with a large positive interval silently produced UUIDs whose timestamp overflowed the 48-bit field, wrapping around and producing incorrect time-ordering. UUID version 7's timestamp field can represent dates up to approximately year 10889. Reject shifted timestamps that exceed this maximum. Author: Baji Shaik Discussion: https://postgr.es/m/18F007D6-1A33-48C8-BA51-E7A858DE0C89%40thebuild.com --- src/backend/utils/adt/uuid.c | 7 +++++++ src/test/regress/expected/uuid.out | 4 ++++ src/test/regress/sql/uuid.sql | 3 +++ 3 files changed, 14 insertions(+) diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c index 35f727a13ec..c083cc987c5 100644 --- a/src/backend/utils/adt/uuid.c +++ b/src/backend/utils/adt/uuid.c @@ -715,6 +715,13 @@ uuidv7_interval(PG_FUNCTION_ARGS) errmsg("timestamp out of range for UUID version 7"), errdetail("UUID version 7 supports timestamps from 1970-01-01 to approximately year 10889."))); + /* Reject timestamps beyond the 48-bit millisecond field maximum */ + if (us / US_PER_MS > (INT64CONST(1) << 48) - 1) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range for UUID version 7"), + errdetail("UUID version 7 supports timestamps from 1970-01-01 to approximately year 10889."))); + /* Generate an UUIDv7 */ uuid = generate_uuidv7(us / US_PER_MS, (us % US_PER_MS) * NS_PER_US + ns % NS_PER_US); diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out index 32b44fa578a..0930a3c73ed 100644 --- a/src/test/regress/expected/uuid.out +++ b/src/test/regress/expected/uuid.out @@ -276,6 +276,10 @@ DETAIL: UUID version 7 supports timestamps from 1970-01-01 to approximately yea SELECT uuidv7('292230 years'::interval); ERROR: timestamp out of range for UUID version 7 DETAIL: UUID version 7 supports timestamps from 1970-01-01 to approximately year 10889. +-- uuidv7: timestamps beyond 48-bit ms field (~year 10889) are rejected +SELECT uuidv7('9000 years'::interval); +ERROR: timestamp out of range for UUID version 7 +DETAIL: UUID version 7 supports timestamps from 1970-01-01 to approximately year 10889. -- extract functions -- version SELECT uuid_extract_version('11111111-1111-5111-8111-111111111111'); -- 5 diff --git a/src/test/regress/sql/uuid.sql b/src/test/regress/sql/uuid.sql index eb1a12949c5..2bd2fc51620 100644 --- a/src/test/regress/sql/uuid.sql +++ b/src/test/regress/sql/uuid.sql @@ -150,6 +150,9 @@ SELECT uuidv7('-1000 years'::interval); -- uuidv7: large future intervals that overflow epoch conversion are rejected SELECT uuidv7('292230 years'::interval); +-- uuidv7: timestamps beyond 48-bit ms field (~year 10889) are rejected +SELECT uuidv7('9000 years'::interval); + -- extract functions -- version -- 2.50.1 (Apple Git-155)