8000 Fix interval_mul() to not produce insane results. · postgrespro/postgres@a898b40 · GitHub
[go: up one dir, main page]

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 co 8000 mplaints, 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

    Lines changed: 4 additions & 2 deletions
    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)
    0