From 6f21c57a975acdc600c22f16521f2f6a3847e83d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 26 Sep 2007 01:10:42 +0000 Subject: [PATCH] In the integer-datetimes case, date2timestamp and date2timestamptz need to check for overflow because the legal range of type date is actually wider than timestamp's. Problem found by Neil Conway. --- src/backend/utils/adt/date.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index c3cc78977f..be37584190 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.135 2007/08/04 01:26:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.136 2007/09/26 01:10:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -336,16 +336,27 @@ date_mii(PG_FUNCTION_ARGS) * time zone */ +static Timestamp +date2timestamp(DateADT dateVal) +{ + Timestamp result; + #ifdef HAVE_INT64_TIMESTAMP -/* date is days since 2000, timestamp is microseconds since same... */ -#define date2timestamp(dateVal) \ - ((Timestamp) ((dateVal) * USECS_PER_DAY)) + /* date is days since 2000, timestamp is microseconds since same... */ + result = dateVal * USECS_PER_DAY; + /* Date's range is wider than timestamp's, so must check for overflow */ + if (result / USECS_PER_DAY != dateVal) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("date out of range for timestamp"))); #else -/* date is days since 2000, timestamp is seconds since same... */ -#define date2timestamp(dateVal) \ - ((Timestamp) ((dateVal) * (double)SECS_PER_DAY)) + /* date is days since 2000, timestamp is seconds since same... */ + result = dateVal * (double) SECS_PER_DAY; #endif + return result; +} + static TimestampTz date2timestamptz(DateADT dateVal) { @@ -364,6 +375,11 @@ date2timestamptz(DateADT dateVal) #ifdef HAVE_INT64_TIMESTAMP result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC; + /* Date's range is wider than timestamp's, so must check for overflow */ + if ((result - tz * USECS_PER_SEC) / USECS_PER_DAY != dateVal) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("date out of range for timestamp"))); #else result = dateVal * (double) SECS_PER_DAY + tz; #endif