0003-Fix-uuidv7-with-far-future-interval-silently-overflo.patch

application/octet-stream

Filename: 0003-Fix-uuidv7-with-far-future-interval-silently-overflo.patch
Type: application/octet-stream
Part: 2
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 0003
Subject: Fix uuidv7() with far-future interval silently overflowing 48-bit timestamp
File+
src/backend/utils/adt/uuid.c 11 0
src/test/regress/expected/uuid.out 4 0
src/test/regress/sql/uuid.sql 3 0
From 4cf381e8ad3604c00c2e506bc89d2fa46625df63 Mon Sep 17 00:00:00 2001
From: Baji Shaik <baji.pgdev@gmail.com>
Date: Fri, 12 Jun 2026 17:30:47 -0500
Subject: [PATCH 3/3] Fix uuidv7() with far-future interval silently
 overflowing 48-bit timestamp

uuidv7(interval) with a large positive interval that pushes the
timestamp beyond approximately year 10889 silently produces a UUID
with a truncated timestamp.  The UUID version 7 timestamp field is
48 bits wide; when the millisecond value exceeds 2^48, the upper
bits are silently discarded, and the resulting UUID breaks sort ordering.

Fix by rejecting timestamps that would overflow the 48-bit field.
---
 src/backend/utils/adt/uuid.c       | 11 +++++++++++
 src/test/regress/expected/uuid.out |  4 ++++
 src/test/regress/sql/uuid.sql      |  3 +++
 3 files changed, 18 insertions(+)

diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index 3269bfd922c..4bec3de1ad2 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -712,6 +712,17 @@ 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.")));
 
+	/*
+	 * The UUID version 7 timestamp field is 48 bits wide, storing
+	 * milliseconds since the Unix epoch.  Reject timestamps that would
+	 * overflow this field (dates beyond approximately year 10889).
+	 */
+	if (us / US_PER_MS > (int64) 0xFFFFFFFFFFFF)
+		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 17693f20639..589f0b6ea42 100644
--- a/src/test/regress/expected/uuid.out
+++ b/src/test/regress/expected/uuid.out
@@ -329,6 +329,10 @@ DETAIL:  UUID version 7 does not support infinite timestamps.
 SELECT uuidv7('-infinity'::interval);
 ERROR:  timestamp out of range for UUID version 7
 DETAIL:  UUID version 7 does not support infinite timestamps.
+-- uuidv7(interval) rejects timestamps that overflow the 48-bit field
+SELECT uuidv7('8920 years'::interval);
+ERROR:  timestamp out of range for UUID version 7
+DETAIL:  UUID version 7 does not support timestamps beyond approximately year 10889.
 -- casts
 SELECT '5b35380a-7143-4912-9b55-f322699c6770'::uuid::bytea;
                bytea                
diff --git a/src/test/regress/sql/uuid.sql b/src/test/regress/sql/uuid.sql
index e88696ee793..3fcc68110bf 100644
--- a/src/test/regress/sql/uuid.sql
+++ b/src/test/regress/sql/uuid.sql
@@ -162,6 +162,9 @@ SELECT uuidv7('-1000 years'::interval);
 SELECT uuidv7('infinity'::interval);
 SELECT uuidv7('-infinity'::interval);
 
+-- uuidv7(interval) rejects timestamps that overflow the 48-bit field
+SELECT uuidv7('8920 years'::interval);
+
 -- casts
 SELECT '5b35380a-7143-4912-9b55-f322699c6770'::uuid::bytea;
 SELECT '\x019a2f859ced7225b99d9c55044a2563'::bytea::uuid;
-- 
2.50.1 (Apple Git-155)