On Thu, Feb 16, 2023 at 1:12 AM Tom Lane <t...@sss.pgh.pa.us> wrote: > Yeah, I don't think this would create a performance problem, at least not > if you're using a compiler that implements pg_sub_s64_overflow reasonably. > (And if you're not, and this bugs you, the answer is to get a better
Please find attached the v2 of the said patch with the tests added. I tested and it applies with all tests passing both on REL_14_STABLE, REL_15_STABLE and master. I don't know how the decision on backpatching is made and whether it makes sense here or not. If any additional work is required, please let me know. > By chance did you look at all other nearby cases, is it the only place > with overflow? Not really, no. The other place where it could overflow was in the interval justification function and it was fixed about a year ago. That wasn't backpatched afaict. See https://postgr.es/m/caavxfhenqsj2xyfbpuf_8nnquijqkag04nw6abqq0dbzsxf...@mail.gmail.com Regards, Nick
From 52d49e90b73d13c9acfd2b85f1ae38dfb0f64f9d Mon Sep 17 00:00:00 2001 From: Nick Babadzhanian <pgni...@gmail.com> Date: Thu, 16 Feb 2023 13:38:34 +0100 Subject: [PATCH] Address interval overflow and add corresponding tests --- src/backend/utils/adt/timestamp.c | 6 +++++- src/test/regress/expected/interval.out | 9 +++++++++ src/test/regress/sql/interval.sql | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index f70f829d83..3ff51102a8 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -2688,7 +2688,11 @@ timestamp_mi(PG_FUNCTION_ARGS) (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("cannot subtract infinite timestamps"))); - result->time = dt1 - dt2; + /* Subtract dt1 and dt2 with overflow detection */ + if (unlikely(pg_sub_s64_overflow(dt1, dt2, &result->time))) + ereport(ERROR, + (errcode(ERRCODE_INTERVAL_FIELD_OVERFLOW), + errmsg("interval field out of range"))); result->month = 0; result->day = 0; diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index 78c1fab2b6..280f25c218 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -235,6 +235,15 @@ LINE 1: INSERT INTO INTERVAL_TBL_OF (f1) VALUES ('-2147483648 years'... -- Test edge-case overflow detection in interval multiplication select extract(epoch from '256 microseconds'::interval * (2^55)::float8); ERROR: interval out of range +-- Test edge-case overflow in timestamp[tz] subtraction +SELECT timestamptz'294276-12-31 23:59:59 UTC' - timestamptz'1999-12-23 19:59:04.224193 UTC' AS doesnt_overflow; + doesnt_overflow +-------------------------------- + 106751991 days 04:00:54.775807 +(1 row) + +SELECT timestamptz'294276-12-31 23:59:59 UTC' - timestamptz'1999-12-23 19:59:04.224192 UTC' AS overflows; +ERROR: interval field out of range SELECT r1.*, r2.* FROM INTERVAL_TBL_OF r1, INTERVAL_TBL_OF r2 WHERE r1.f1 > r2.f1 diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql index 55a449b617..a228cf1445 100644 --- a/src/test/regress/sql/interval.sql +++ b/src/test/regress/sql/interval.sql @@ -76,6 +76,10 @@ INSERT INTO INTERVAL_TBL_OF (f1) VALUES ('-2147483648 years'); -- Test edge-case overflow detection in interval multiplication select extract(epoch from '256 microseconds'::interval * (2^55)::float8); +-- Test edge-case overflow in timestamp[tz] subtraction +SELECT timestamptz'294276-12-31 23:59:59 UTC' - timestamptz'1999-12-23 19:59:04.224193 UTC' AS doesnt_overflow; +SELECT timestamptz'294276-12-31 23:59:59 UTC' - timestamptz'1999-12-23 19:59:04.224192 UTC' AS overflows; + SELECT r1.*, r2.* FROM INTERVAL_TBL_OF r1, INTERVAL_TBL_OF r2 WHERE r1.f1 > r2.f1 -- 2.39.1