1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Catch overflow when rounding intervals in AdjustIntervalForTypmod.

Previously, an interval microseconds field close to INT64_MAX or
INT64_MIN could overflow, producing a result with not even the
correct sign, while being rounded to match a precision specification.

This seems worth fixing, but not worth back-patching, in part
because the ereturn() notation doesn't exist very far back.

Report and patch by Joseph Koshakow (some cosmetic mods by me)

Discussion: https://postgr.es/m/CAAvxfHfpuLgqJYzkUcher466Z1LpmE+5Sm+zc8L6zKCOQ+6TDQ@mail.gmail.com
This commit is contained in:
Tom Lane
2024-02-13 15:58:40 -05:00
parent fbf9a7ac4d
commit 5ebc9c9017
3 changed files with 24 additions and 8 deletions

View File

@ -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];
}
}
}