From dc28a08b2fe17990051454f4db935a0ef4d023d3 Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Wed, 27 May 2026 19:43:15 -0500 Subject: [PATCH] Fix uuidv7() with infinite interval causing integer overflow uuidv7('infinity'::interval) and uuidv7('-infinity'::interval) cause integer overflow when converting the infinite TimestampTz back to a Unix epoch microsecond value. timestamptz_pl_interval() returns the special infinity/negative-infinity TimestampTz values, and the subsequent addition of the epoch offset overflows int64, producing a garbage timestamp. Fix by checking TIMESTAMP_NOT_FINITE(ts) immediately after the interval arithmetic and rejecting with a clear error. --- src/backend/utils/adt/uuid.c | 7 +++++++ src/test/regress/expected/uuid.out | 5 +++++ src/test/regress/sql/uuid.sql | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c index 6ee3752ac78..2bba07bb09c 100644 --- a/src/backend/utils/adt/uuid.c +++ b/src/backend/utils/adt/uuid.c @@ -687,6 +687,13 @@ uuidv7_interval(PG_FUNCTION_ARGS) TimestampTzGetDatum(ts), IntervalPGetDatum(shift))); + + /* Reject infinite timestamps */ + if (TIMESTAMP_NOT_FINITE(ts)) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("timestamp out of range for UUID version 7"))); + /* Convert a TimestampTz value back to an UNIX epoch timestamp */ us = ts + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out index 9c5dda9e9ab..4388739f462 100644 --- a/src/test/regress/expected/uuid.out +++ b/src/test/regress/expected/uuid.out @@ -280,6 +280,11 @@ SELECT uuid_extract_version('11111111-1111-1111-1111-111111111111'); -- null ---------------------- (1 row) +-- uuidv7(interval) rejects infinite intervals +SELECT uuidv7('infinity'::interval); +ERROR: timestamp out of range for UUID version 7 +SELECT uuidv7('-infinity'::interval); +ERROR: timestamp out of range for UUID version 7 SELECT uuid_extract_version(uuidv4()); -- 4 uuid_extract_version diff --git a/src/test/regress/sql/uuid.sql b/src/test/regress/sql/uuid.sql index 8cc2ad40614..d9f0401880b 100644 --- a/src/test/regress/sql/uuid.sql +++ b/src/test/regress/sql/uuid.sql @@ -146,6 +146,10 @@ SELECT y, ts, prev_ts FROM uuidts WHERE ts < prev_ts; SELECT uuid_extract_version('11111111-1111-5111-8111-111111111111'); -- 5 SELECT uuid_extract_version(gen_random_uuid()); -- 4 SELECT uuid_extract_version('11111111-1111-1111-1111-111111111111'); -- null + +-- uuidv7(interval) rejects infinite intervals +SELECT uuidv7('infinity'::interval); +SELECT uuidv7('-infinity'::interval); SELECT uuid_extract_version(uuidv4()); -- 4 SELECT uuid_extract_version(uuidv7()); -- 7 -- 2.50.1 (Apple Git-155)