aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/timestamp.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-03-05 16:42:18 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2014-03-05 16:42:18 -0500
commitf1ba94bcd9717b94b36868d6905547e313f3a359 (patch)
tree1a4707b67dcfb1c22734961ea92d8326f2f5126f /src/backend/utils/adt/timestamp.c
parent8cf0ad1ea38db3e16ac04b408168df4c937862e6 (diff)
downloadpostgresql-f1ba94bcd9717b94b36868d6905547e313f3a359.tar.gz
postgresql-f1ba94bcd9717b94b36868d6905547e313f3a359.zip
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.
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r--src/backend/utils/adt/timestamp.c32
1 files changed, 20 insertions, 12 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;
+ secs += hours * (double) SECS_PER_HOUR + mins * (double) SECS_PER_MINUTE;
+
#ifdef HAVE_INT64_TIMESTAMP
- result->time = ((((hours * INT64CONST(60)) +
- mins) * INT64CONST(60)) +
- secs) * USECS_PER_SEC;
+ result->time = (int64) (secs * USECS_PER_SEC);
#else
- result->time = (((hours * (double) MINS_PER_HOUR) +
- mins) * (double) SECS_PER_MINUTE) +
- secs;
-#endif
-
-#ifdef NOT_USED
- /* this is a no-op for negative typmods */
- AdjustIntervalForTypmod(result, -1);
+ result->time = secs;
#endif
PG_RETURN_INTERVAL_P(result);