interval_cmp_value_overflow_check.patch
text/x-patch
Filename: interval_cmp_value_overflow_check.patch
Type: text/x-patch
Part: 0
Message:
Re: Unexpected interval comparison
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/adt/timestamp.c | 17 | 3 |
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 4be1999..f77cfcc 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -2293,10 +2293,23 @@ static inline TimeOffset
interval_cmp_value(const Interval *interval)
{
TimeOffset span;
+ TimeOffset timedayfraction;
+ TimeOffset timedays;
- span = interval->time;
- span += interval->month * INT64CONST(30) * USECS_PER_DAY;
- span += interval->day * INT64CONST(24) * USECS_PER_HOUR;
+ timedays = ((int64)interval->time) / USECS_PER_DAY;
+ timedayfraction = interval->time - timedays * USECS_PER_DAY;
+
+ /* calculate span in days. this cannot overflow */
+ span = timedays;
+ span += interval->month * INT64CONST(30);
+ span += interval->day;
+
+ /* overflow check */
+ if (span > INT64CONST(0x7fffffffffffffff) / USECS_PER_DAY - 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg ("interval out of range during comparison")));
+ span = span * USECS_PER_DAY + timedayfraction;
return span;
}
@@ -2304,6 +2317,7 @@ interval_cmp_value(const Interval *interval)
static int
interval_cmp_internal(Interval *interval1, Interval *interval2)
{
+
TimeOffset span1 = interval_cmp_value(interval1);
TimeOffset span2 = interval_cmp_value(interval2);