Commit 6f21c57a authored by Tom Lane's avatar Tom Lane

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.
parent 93407d39
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -336,16 +336,27 @@ date_mii(PG_FUNCTION_ARGS)
* time zone * time zone
*/ */
static Timestamp
date2timestamp(DateADT dateVal)
{
Timestamp result;
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
/* date is days since 2000, timestamp is microseconds since same... */ /* date is days since 2000, timestamp is microseconds since same... */
#define date2timestamp(dateVal) \ result = dateVal * USECS_PER_DAY;
((Timestamp) ((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 #else
/* date is days since 2000, timestamp is seconds since same... */ /* date is days since 2000, timestamp is seconds since same... */
#define date2timestamp(dateVal) \ result = dateVal * (double) SECS_PER_DAY;
((Timestamp) ((dateVal) * (double)SECS_PER_DAY))
#endif #endif
return result;
}
static TimestampTz static TimestampTz
date2timestamptz(DateADT dateVal) date2timestamptz(DateADT dateVal)
{ {
...@@ -364,6 +375,11 @@ date2timestamptz(DateADT dateVal) ...@@ -364,6 +375,11 @@ date2timestamptz(DateADT dateVal)
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC; 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 #else
result = dateVal * (double) SECS_PER_DAY + tz; result = dateVal * (double) SECS_PER_DAY + tz;
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment