]> granicus.if.org Git - postgresql/commitdiff
Add range-checking in timestamp_recv and timestamptz_recv, per
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 3 Jun 2004 17:57:09 +0000 (17:57 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 3 Jun 2004 17:57:09 +0000 (17:57 +0000)
Stephen Frost.  Also tighten date range check in timestamp2tm.

src/backend/utils/adt/timestamp.c

index 91a34ed5388529215750dc4a8388fc531308d6ab..3f6d431523062c9fa93672387e7242257e09f83c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.108 2004/06/03 02:08:04 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.109 2004/06/03 17:57:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -166,12 +166,26 @@ Datum
 timestamp_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+       Timestamp       timestamp;
+       struct pg_tm    tt,
+                          *tm = &tt;
+       fsec_t          fsec;
 
 #ifdef HAVE_INT64_TIMESTAMP
-       PG_RETURN_TIMESTAMP((Timestamp) pq_getmsgint64(buf));
+       timestamp = (Timestamp) pq_getmsgint64(buf);
 #else
-       PG_RETURN_TIMESTAMP((Timestamp) pq_getmsgfloat8(buf));
+       timestamp = (Timestamp) pq_getmsgfloat8(buf);
 #endif
+
+       /* rangecheck: see if timestamp_out would like it */
+       if (TIMESTAMP_NOT_FINITE(timestamp))
+               /* ok */;
+       else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
+               ereport(ERROR,
+                               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                                errmsg("timestamp out of range")));
+
+       PG_RETURN_TIMESTAMP(timestamp);
 }
 
 /*
@@ -393,12 +407,28 @@ Datum
 timestamptz_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+       TimestampTz     timestamp;
+       int                     tz;
+       struct pg_tm    tt,
+                          *tm = &tt;
+       fsec_t          fsec;
+       char       *tzn;
 
 #ifdef HAVE_INT64_TIMESTAMP
-       PG_RETURN_TIMESTAMPTZ((TimestampTz) pq_getmsgint64(buf));
+       timestamp = (TimestampTz) pq_getmsgint64(buf);
 #else
-       PG_RETURN_TIMESTAMPTZ((TimestampTz) pq_getmsgfloat8(buf));
+       timestamp = (TimestampTz) pq_getmsgfloat8(buf);
 #endif
+
+       /* rangecheck: see if timestamptz_out would like it */
+       if (TIMESTAMP_NOT_FINITE(timestamp))
+               /* ok */;
+       else if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
+               ereport(ERROR,
+                               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                                errmsg("timestamp out of range")));
+
+       PG_RETURN_TIMESTAMPTZ(timestamp);
 }
 
 /*
@@ -933,13 +963,8 @@ dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
 int
 timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, char **tzn)
 {
-#ifdef HAVE_INT64_TIMESTAMP
-       int                     date;
-       int64           time;
-#else
-       double          date;
-       double          time;
-#endif
+       Timestamp       date;
+       Timestamp       time;
        pg_time_t       utime;
 
        /*
@@ -950,7 +975,7 @@ timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, char **tzn)
        if (HasCTZSet && (tzp != NULL))
        {
 #ifdef HAVE_INT64_TIMESTAMP
-               dt -= (CTimeZone * INT64CONST(1000000));
+               dt -= CTimeZone * INT64CONST(1000000);
 #else
                dt -= CTimeZone;
 #endif
@@ -975,13 +1000,13 @@ timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, char **tzn)
        }
 #endif
 
-       /* Julian day routine does not work for negative Julian days */
-       if (date < -POSTGRES_EPOCH_JDATE)
-               return -1;
-
        /* add offset to go from J2000 back to standard Julian date */
        date += POSTGRES_EPOCH_JDATE;
 
+       /* Julian day routine does not work for negative Julian days */
+       if (date < 0 || date > (Timestamp) INT_MAX)
+               return -1;
+
        j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
        dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);