postgres.git / summary / log / commit / refs

commit    a898b409f66f956e99694710f537829db02652c0
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Tue Mar 29 21:21:12 2016 +0000

    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.


src/backend/utils/adt/timestamp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index b9c26b68544..7456808a427 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -3351,14 +3351,16 @@ interval_mul(PG_FUNCTION_ARGS) result = (Interval *) palloc(sizeof(Interval)); result_double = span->month * factor; - if (result_double > INT_MAX || result_double < INT_MIN) + if (isnan(result_double) || + result_double > INT_MAX || result_double < INT_MIN) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("interval out of range"))); result->month = (int32) result_double; result_double = span->day * factor; - if (result_double > INT_MAX || result_double < INT_MIN) + if (isnan(result_double) || + result_double > INT_MAX || result_double < INT_MIN) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("interval out of range"))); [parent: e511d878f3bb]