public inbox for [email protected]
help / color / mirror / Atom feedFrom: Joseph Koshakow <[email protected]>
To: [email protected]
Subject: Fix overflow in justify_interval related functions
Date: Sun, 13 Feb 2022 13:28:38 -0500
Message-ID: <CAAvxfHeNqsJ2xYFbPUf_8nNQUiJqkag04NW6aBQQ0dbZsxfWHA@mail.gmail.com> (raw)
I mentioned this issue briefly in another thread, but the
justify_interval, justify_days, and justify_hours functions
all have the potential to overflow. The attached patch fixes
this issue.
Cheers,
Joe Koshakow
Attachments:
[text/x-patch] 0001-Check-for-overflow-in-justify_interval-functions.patch (4.5K, ../CAAvxfHeNqsJ2xYFbPUf_8nNQUiJqkag04NW6aBQQ0dbZsxfWHA@mail.gmail.com/2-0001-Check-for-overflow-in-justify_interval-functions.patch)
download | inline diff:
From 4400f2e6886097e3b75d455aeec1ffa9cbc88510 Mon Sep 17 00:00:00 2001
From: Joseph Koshakow <[email protected]>
Date: Sun, 13 Feb 2022 13:26:16 -0500
Subject: [PATCH] Check for overflow in justify_interval functions
justify_interval, justify_hours, and justify_days didn't check for
overflow when moving hours to days or days to hours. This commit adds
check for overflow and returns an appropriate error.
---
src/backend/utils/adt/timestamp.c | 20 ++++++++++++++++----
src/test/regress/expected/interval.out | 8 ++++++++
src/test/regress/sql/interval.sql | 6 ++++++
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 36f8a84bcc..fb4b3ae0aa 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -2718,11 +2718,17 @@ interval_justify_interval(PG_FUNCTION_ARGS)
result->time = span->time;
TMODULO(result->time, wholeday, USECS_PER_DAY);
- result->day += wholeday; /* could overflow... */
+ if (pg_add_s32_overflow(result->day, wholeday, &result->day))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("interval out of range")));
wholemonth = result->day / DAYS_PER_MONTH;
result->day -= wholemonth * DAYS_PER_MONTH;
- result->month += wholemonth;
+ if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("interval out of range")));
if (result->month > 0 &&
(result->day < 0 || (result->day == 0 && result->time < 0)))
@@ -2772,7 +2778,10 @@ interval_justify_hours(PG_FUNCTION_ARGS)
result->time = span->time;
TMODULO(result->time, wholeday, USECS_PER_DAY);
- result->day += wholeday; /* could overflow... */
+ if (pg_add_s32_overflow(result->day, wholeday, &result->day))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("interval out of range")));
if (result->day > 0 && result->time < 0)
{
@@ -2808,7 +2817,10 @@ interval_justify_days(PG_FUNCTION_ARGS)
wholemonth = result->day / DAYS_PER_MONTH;
result->day -= wholemonth * DAYS_PER_MONTH;
- result->month += wholemonth;
+ if (pg_add_s32_overflow(result->month, wholemonth, &result->month))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("interval out of range")));
if (result->month > 0 && result->day < 0)
{
diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
index accd4a7d90..e2bb8095c3 100644
--- a/src/test/regress/expected/interval.out
+++ b/src/test/regress/expected/interval.out
@@ -396,6 +396,10 @@ SELECT justify_days(interval '6 months 36 days 5 hours 4 minutes 3 seconds') as
@ 7 mons 6 days 5 hours 4 mins 3 secs
(1 row)
+SELECT justify_hours(interval '2147483647 days 24 hrs');
+ERROR: interval out of range
+SELECT justify_days(interval '2147483647 months 30 days');
+ERROR: interval out of range
-- test justify_interval()
SELECT justify_interval(interval '1 month -1 hour') as "1 month -1 hour";
1 month -1 hour
@@ -403,6 +407,10 @@ SELECT justify_interval(interval '1 month -1 hour') as "1 month -1 hour";
@ 29 days 23 hours
(1 row)
+SELECT justify_interval(interval '2147483647 days 24 hrs');
+ERROR: interval out of range
+SELECT justify_interval(interval '2147483647 months 30 days');
+ERROR: interval out of range
-- test fractional second input, and detection of duplicate units
SET DATESTYLE = 'ISO';
SET IntervalStyle TO postgres;
diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql
index 6d532398bd..3ebdca5023 100644
--- a/src/test/regress/sql/interval.sql
+++ b/src/test/regress/sql/interval.sql
@@ -149,10 +149,16 @@ select '100000000y 10mon -1000000000d -100000h -10min -10.000001s ago'::interval
SELECT justify_hours(interval '6 months 3 days 52 hours 3 minutes 2 seconds') as "6 mons 5 days 4 hours 3 mins 2 seconds";
SELECT justify_days(interval '6 months 36 days 5 hours 4 minutes 3 seconds') as "7 mons 6 days 5 hours 4 mins 3 seconds";
+SELECT justify_hours(interval '2147483647 days 24 hrs');
+SELECT justify_days(interval '2147483647 months 30 days');
+
-- test justify_interval()
SELECT justify_interval(interval '1 month -1 hour') as "1 month -1 hour";
+SELECT justify_interval(interval '2147483647 days 24 hrs');
+SELECT justify_interval(interval '2147483647 months 30 days');
+
-- test fractional second input, and detection of duplicate units
SET DATESTYLE = 'ISO';
SET IntervalStyle TO postgres;
--
2.25.1
view thread (2+ messages)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: Fix overflow in justify_interval related functions
In-Reply-To: <CAAvxfHeNqsJ2xYFbPUf_8nNQUiJqkag04NW6aBQQ0dbZsxfWHA@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox