v2-0003-Reject-timestamps-beyond-48-bit-limit-in-uuidv7-i.patch

application/octet-stream

Filename: v2-0003-Reject-timestamps-beyond-48-bit-limit-in-uuidv7-i.patch
Type: application/octet-stream
Part: 1
Message: Re: uuidv7 improperly accepts dates before 1970-01-01

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v2-0003
Subject: Reject timestamps beyond 48-bit limit in uuidv7(interval)
File+
src/backend/utils/adt/uuid.c 7 0
src/test/regress/expected/uuid.out 4 0
src/test/regress/sql/uuid.sql 3 0
From 620b2a4398e2820b8b750d99f41d75b45066e2ff Mon Sep 17 00:00:00 2001
From: Baji Shaik <baji.pgdev@gmail.com>
Date: Wed, 24 Jun 2026 18:08:44 -0500
Subject: [PATCH v2 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 10889-08-02 05:31:50.655 UTC.

Reject shifted timestamps that exceed this maximum.  Use INT64CONST() for the 48-bit constant.

Author: Baji Shaik <baji.pgdev@gmail.com>
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 ca5dbca8ac3..5fa7cd72761 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 does not support timestamps before the Unix epoch (1970-01-01 00:00:00 UTC).")));
 
+	/* 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 does not support timestamps beyond 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 72730825cda..1fe95454dcf 100644
--- a/src/test/regress/expected/uuid.out
+++ b/src/test/regress/expected/uuid.out
@@ -276,6 +276,10 @@ DETAIL:  UUID version 7 does not support timestamps before the Unix epoch (1970-
 SELECT uuidv7('292230 years'::interval);
 ERROR:  timestamp out of range for UUID version 7
 DETAIL:  The shifted timestamp overflows the representable range.
+-- 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 does not support timestamps beyond 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)