Skip to content

Commit a898b40

Browse files
committed
Fix interval_mul() to not produce insane results.
interval_mul() attempts to prevent its calculations from producing silly results, but it forgot that zero times infinity yields NaN in IEEE arithmetic. Hence, a case like '1 second'::interval * 'infinity'::float8 produced a NaN for the months product, which didn't trigger the range check, resulting in bogus and possibly platform-dependent output. This isn't terribly obvious to the naked eye because if you try that exact case, you get "interval out of range" which is what you expect --- but if you look closer, the error is coming from interval_out not interval_mul. interval_mul has allowed a bogus value into the system. Fix by adding isnan tests. Noted while testing Vitaly Burovoy's fix for infinity input to to_timestamp(). Given the lack of field complaints, I doubt this is worth a back-patch.
1 parent e511d87 commit a898b40

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

src/backend/utils/adt/timestamp.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -3351,14 +3351,16 @@ interval_mul(PG_FUNCTION_ARGS)
33513351
result = (Interval *) palloc(sizeof(Interval));
33523352

33533353
result_double = span->month * factor;
3354-
if (result_double > INT_MAX || result_double < INT_MIN)
3354+
if (isnan(result_double) ||
3355+
result_double > INT_MAX || result_double < INT_MIN)
33553356
ereport(ERROR,
33563357
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
33573358
errmsg("interval out of range")));
33583359
result->month = (int32) result_double;
33593360

33603361
result_double = span->day * factor;
3361-
if (result_double > INT_MAX || result_double < INT_MIN)
3362+
if (isnan(result_double) ||
3363+
result_double > INT_MAX || result_double < INT_MIN)
33623364
ereport(ERROR,
33633365
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
33643366
errmsg("interval out of range")));

0 commit comments

Comments
 (0)