Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8028e29

Browse filesBrowse files
committed
Detect overflow in timestamp[tz] subtraction.
It's possible to overflow the int64 microseconds field of the output interval when subtracting two timestamps. Detect that instead of silently returning a bogus result. Nick Babadzhanian Discussion: https://postgr.es/m/CABw73Uq2oJ3E+kYvvDuY04EkhhkChim2e-PaghBDjOmgUAMWGw@mail.gmail.com
1 parent f0d0394 commit 8028e29
Copy full SHA for 8028e29

File tree

5 files changed

+30
-1
lines changed
Filter options

5 files changed

+30
-1
lines changed

‎src/backend/utils/adt/timestamp.c

Copy file name to clipboardExpand all lines: src/backend/utils/adt/timestamp.c
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2713,7 +2713,10 @@ timestamp_mi(PG_FUNCTION_ARGS)
27132713
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
27142714
errmsg("cannot subtract infinite timestamps")));
27152715

2716-
result->time = dt1 - dt2;
2716+
if (unlikely(pg_sub_s64_overflow(dt1, dt2, &result->time)))
2717+
ereport(ERROR,
2718+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2719+
errmsg("interval out of range")));
27172720

27182721
result->month = 0;
27192722
result->day = 0;

‎src/test/regress/expected/timestamp.out

Copy file name to clipboardExpand all lines: src/test/regress/expected/timestamp.out
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,15 @@ SELECT extract(epoch from '5000-01-01 00:00:00'::timestamp);
12071207
95617584000.000000
12081208
(1 row)
12091209

1210+
-- test edge-case overflow in timestamp subtraction
1211+
SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224193' AS ok;
1212+
ok
1213+
-----------------------------------------
1214+
@ 106751991 days 4 hours 54.775807 secs
1215+
(1 row)
1216+
1217+
SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224192' AS overflows;
1218+
ERROR: interval out of range
12101219
-- TO_CHAR()
12111220
SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon')
12121221
FROM TIMESTAMP_TBL;

‎src/test/regress/expected/timestamptz.out

Copy file name to clipboardExpand all lines: src/test/regress/expected/timestamptz.out
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,15 @@ SELECT extract(epoch from '5000-01-01 00:00:00+00'::timestamptz);
13311331
95617584000.000000
13321332
(1 row)
13331333

1334+
-- test edge-case overflow in timestamp subtraction
1335+
SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224193 UTC' AS ok;
1336+
ok
1337+
-----------------------------------------
1338+
@ 106751991 days 4 hours 54.775807 secs
1339+
(1 row)
1340+
1341+
SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224192 UTC' AS overflows;
1342+
ERROR: interval out of range
13341343
-- TO_CHAR()
13351344
SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon')
13361345
FROM TIMESTAMPTZ_TBL;

‎src/test/regress/sql/timestamp.sql

Copy file name to clipboardExpand all lines: src/test/regress/sql/timestamp.sql
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@ SELECT extract(epoch from '294270-01-01 00:00:00'::timestamp);
326326
-- another internal overflow test case
327327
SELECT extract(epoch from '5000-01-01 00:00:00'::timestamp);
328328

329+
-- test edge-case overflow in timestamp subtraction
330+
SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224193' AS ok;
331+
SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224192' AS overflows;
332+
329333
-- TO_CHAR()
330334
SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon')
331335
FROM TIMESTAMP_TBL;

‎src/test/regress/sql/timestamptz.sql

Copy file name to clipboardExpand all lines: src/test/regress/sql/timestamptz.sql
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ SELECT extract(epoch from '294270-01-01 00:00:00+00'::timestamptz);
306306
-- another internal overflow test case
307307
SELECT extract(epoch from '5000-01-01 00:00:00+00'::timestamptz);
308308

309+
-- test edge-case overflow in timestamp subtraction
310+
SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224193 UTC' AS ok;
311+
SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224192 UTC' AS overflows;
312+
309313
-- TO_CHAR()
310314
SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon')
311315
FROM TIMESTAMPTZ_TBL;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.