* date.c
* implements DATE and TIME data types specified in SQL-92 standard
*
- * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.143 2008/10/14 17:12:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.150 2010/01/02 16:57:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
date_recv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ DateADT result;
- PG_RETURN_DATEADT((DateADT) pq_getmsgint(buf, sizeof(DateADT)));
+ result = (DateADT) pq_getmsgint(buf, sizeof(DateADT));
+
+ /* Limit to the same range that date_in() accepts. */
+ if (result < -POSTGRES_EPOCH_JDATE ||
+ result >= JULIAN_MAX - POSTGRES_EPOCH_JDATE)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("date out of range")));
+
+ PG_RETURN_DATEADT(result);
}
/*
strcpy(str, EARLY);
else if (DATE_IS_NOEND(dt))
strcpy(str, LATE);
- else /* shouldn't happen */
+ else /* shouldn't happen */
elog(ERROR, "invalid argument for EncodeSpecialDate");
}
#ifdef HAVE_INT64_TIMESTAMP
result = pq_getmsgint64(buf);
+
+ if (result < INT64CONST(0) || result > USECS_PER_DAY)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("time out of range")));
#else
result = pq_getmsgfloat8(buf);
+
+ if (result < 0 || result > (double) SECS_PER_DAY)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("time out of range")));
#endif
AdjustTimeForTypmod(&result, typmod);
{
case DTK_MICROSEC:
#ifdef HAVE_INT64_TIMESTAMP
- result = tm->tm_sec * USECS_PER_SEC + fsec;
+ result = tm->tm_sec * 1000000.0 + fsec;
#else
result = (tm->tm_sec + fsec) * 1000000;
#endif
case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
- result = tm->tm_sec * INT64CONST(1000) + fsec / INT64CONST(1000);
+ result = tm->tm_sec * 1000.0 + fsec / 1000.0;
#else
result = (tm->tm_sec + fsec) * 1000;
#endif
case DTK_SECOND:
#ifdef HAVE_INT64_TIMESTAMP
- result = tm->tm_sec + fsec / USECS_PER_SEC;
+ result = tm->tm_sec + fsec / 1000000.0;
#else
result = tm->tm_sec + fsec;
#endif
#ifdef HAVE_INT64_TIMESTAMP
result->time = pq_getmsgint64(buf);
+
+ if (result->time < INT64CONST(0) || result->time > USECS_PER_DAY)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("time out of range")));
#else
result->time = pq_getmsgfloat8(buf);
+
+ if (result->time < 0 || result->time > (double) SECS_PER_DAY)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("time out of range")));
#endif
+
result->zone = pq_getmsgint(buf, sizeof(result->zone));
+ /* we allow GMT displacements up to 14:59:59, cf DecodeTimezone() */
+ if (result->zone <= -15 * SECS_PER_HOUR ||
+ result->zone >= 15 * SECS_PER_HOUR)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE),
+ errmsg("time zone displacement out of range")));
+
AdjustTimeForTypmod(&(result->time), typmod);
PG_RETURN_TIMETZADT_P(result);
case DTK_MICROSEC:
#ifdef HAVE_INT64_TIMESTAMP
- result = tm->tm_sec * USECS_PER_SEC + fsec;
+ result = tm->tm_sec * 1000000.0 + fsec;
#else
result = (tm->tm_sec + fsec) * 1000000;
#endif
case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
- result = tm->tm_sec * INT64CONST(1000) + fsec / INT64CONST(1000);
+ result = tm->tm_sec * 1000.0 + fsec / 1000.0;
#else
result = (tm->tm_sec + fsec) * 1000;
#endif
case DTK_SECOND:
#ifdef HAVE_INT64_TIMESTAMP
- result = tm->tm_sec + fsec / USECS_PER_SEC;
+ result = tm->tm_sec + fsec / 1000000.0;
#else
result = tm->tm_sec + fsec;
#endif
pg_tz *tzp;
/*
- * Look up the requested timezone. First we look in the date token table
+ * Look up the requested timezone. First we look in the date token table
* (to handle cases like "EST"), and if that fails, we look in the
* timezone database (to handle cases like "America/New_York"). (This
* matches the order in which timestamp input checks the cases; it's