From f1ba94bcd9717b94b36868d6905547e313f3a359 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 5 Mar 2014 16:42:18 -0500 Subject: [PATCH] Fix portability issues in recently added make_timestamp/make_interval code. Explicitly reject infinity/NaN inputs, rather than just assuming that something else will do it for us. Per buildfarm. While at it, make some over-parenthesized and under-legible code more readable. --- src/backend/utils/adt/timestamp.c | 34 +++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index f21bbae3696..8ba3209fda5 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -597,8 +597,14 @@ make_timestamp_internal(int year, int month, int day, date = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE; - /* This should match the checks in DecodeTimeOnly */ + /* + * This should match the checks in DecodeTimeOnly, except that since we're + * dealing with a float "sec" value, we also explicitly reject NaN. (An + * infinity input should get rejected by the range comparisons, but we + * can't be sure how those will treat a NaN.) + */ if (hour < 0 || min < 0 || min > MINS_PER_HOUR - 1 || + isnan(sec) || sec < 0 || sec > SECS_PER_MINUTE || hour > HOURS_PER_DAY || /* test for > 24:00:00 */ @@ -1463,23 +1469,25 @@ make_interval(PG_FUNCTION_ARGS) double secs = PG_GETARG_FLOAT8(6); Interval *result; + /* + * Reject out-of-range inputs. We really ought to check the integer + * inputs as well, but it's not entirely clear what limits to apply. + */ + if (isinf(secs) || isnan(secs)) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("interval out of range"))); + result = (Interval *) palloc(sizeof(Interval)); result->month = years * MONTHS_PER_YEAR + months; result->day = weeks * 7 + days; -#ifdef HAVE_INT64_TIMESTAMP - result->time = ((((hours * INT64CONST(60)) + - mins) * INT64CONST(60)) + - secs) * USECS_PER_SEC; -#else - result->time = (((hours * (double) MINS_PER_HOUR) + - mins) * (double) SECS_PER_MINUTE) + - secs; -#endif + secs += hours * (double) SECS_PER_HOUR + mins * (double) SECS_PER_MINUTE; -#ifdef NOT_USED - /* this is a no-op for negative typmods */ - AdjustIntervalForTypmod(result, -1); +#ifdef HAVE_INT64_TIMESTAMP + result->time = (int64) (secs * USECS_PER_SEC); +#else + result->time = secs; #endif PG_RETURN_INTERVAL_P(result);