diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-09-26 01:10:42 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-09-26 01:10:42 +0000 |
commit | 6f21c57a975acdc600c22f16521f2f6a3847e83d (patch) | |
tree | 8808cfcab28e5e917955d301409a41fb439a8683 /src | |
parent | 93407d3998cc8717993dbc102f854a478985bc19 (diff) | |
download | postgresql-6f21c57a975acdc600c22f16521f2f6a3847e83d.tar.gz postgresql-6f21c57a975acdc600c22f16521f2f6a3847e83d.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/date.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index c3cc78977ff..be37584190e 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 |