aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/adt/timestamp.c22
-rw-r--r--src/test/regress/expected/interval.out8
-rw-r--r--src/test/regress/sql/interval.sql2
3 files changed, 24 insertions, 8 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index c38f88dba78..ed03c50a6de 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -1509,17 +1509,23 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod,
if (interval->time >= INT64CONST(0))
{
- interval->time = ((interval->time +
- IntervalOffsets[precision]) /
- IntervalScales[precision]) *
- IntervalScales[precision];
+ if (pg_add_s64_overflow(interval->time,
+ IntervalOffsets[precision],
+ &interval->time))
+ ereturn(escontext, false,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("interval out of range")));
+ interval->time -= interval->time % IntervalScales[precision];
}
else
{
- interval->time = -(((-interval->time +
- IntervalOffsets[precision]) /
- IntervalScales[precision]) *
- IntervalScales[precision]);
+ if (pg_sub_s64_overflow(interval->time,
+ IntervalOffsets[precision],
+ &interval->time))
+ ereturn(escontext, false,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("interval out of range")));
+ interval->time -= interval->time % IntervalScales[precision];
}
}
}
diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
index b79b6fcd4d7..51ae010c7ba 100644
--- a/src/test/regress/expected/interval.out
+++ b/src/test/regress/expected/interval.out
@@ -929,6 +929,14 @@ SELECT interval '1 2:03:04.5678' minute to second(2);
1 day 02:03:04.57
(1 row)
+SELECT interval '2562047788:00:54.775807' second(2); -- out of range
+ERROR: interval out of range
+LINE 1: SELECT interval '2562047788:00:54.775807' second(2);
+ ^
+SELECT interval '-2562047788:00:54.775807' second(2); -- out of range
+ERROR: interval out of range
+LINE 1: SELECT interval '-2562047788:00:54.775807' second(2);
+ ^
-- test casting to restricted precision (bug #14479)
SELECT f1, f1::INTERVAL DAY TO MINUTE AS "minutes",
(f1 + INTERVAL '1 month')::INTERVAL MONTH::INTERVAL YEAR AS "years"
diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql
index 5566ad0e516..fbf6e064d66 100644
--- a/src/test/regress/sql/interval.sql
+++ b/src/test/regress/sql/interval.sql
@@ -270,6 +270,8 @@ SELECT interval '1 2:03:04.5678' hour to second(2);
SELECT interval '1 2.3456' minute to second(2);
SELECT interval '1 2:03.5678' minute to second(2);
SELECT interval '1 2:03:04.5678' minute to second(2);
+SELECT interval '2562047788:00:54.775807' second(2); -- out of range
+SELECT interval '-2562047788:00:54.775807' second(2); -- out of range
-- test casting to restricted precision (bug #14479)
SELECT f1, f1::INTERVAL DAY TO MINUTE AS "minutes",