Tigthen binary receive functions so that they reject values that the text
authorHeikki Linnakangas <[email protected]>
Fri, 4 Sep 2009 11:20:23 +0000 (11:20 +0000)
committerHeikki Linnakangas <[email protected]>
Fri, 4 Sep 2009 11:20:23 +0000 (11:20 +0000)
input functions don't accept either. While the backend can handle such
values fine, they can cause trouble in clients and in pg_dump/restore.

This is followup to the original issue on time datatype reported by Andrew
McNamara a while ago. Like that one, none of these seem worth
back-ing.

src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/date.c
src/backend/utils/adt/int.c
src/backend/utils/adt/nabstime.c
src/backend/utils/adt/oid.c
src/backend/utils/adt/timestamp.c
src/include/utils/datetime.h

index fb96541bdfc9e42ee0e3515248c2e22c5da9ebb2..2b5ea70ba1ad56f232525eee09578e55bc816a41 100644 (file)
@@ -1207,8 +1207,17 @@ array_recv(PG_FUNCTION_ARGS)
 
        for (i = 0; i < ndim; i++)
        {
+               int ub;
+
                dim[i] = pq_getmsgint(buf, 4);
                lBound[i] = pq_getmsgint(buf, 4);
+
+               ub = lBound[i] + dim[i] - 1;
+               /* overflow? */
+               if (lBound[i] > ub)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+                                        errmsg("integer out of range")));
        }
 
        /* This checks for overflow of array dimensions */
index 2085d8555e7f98804aea04d0594c0015e2e2911b..23a33a8881f6e8bdffb4ce7aec553defb4eb3a12 100644 (file)
@@ -203,8 +203,17 @@ Datum
 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 < 0 || result > JULIAN_MAX)
+               ereport(ERROR,
+                               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                                errmsg("date out of range")));
+
+       PG_RETURN_DATEADT(result);
 }
 
 /*
index 548662f53ab9288717e8549a515408c8cc314103..63a4ab36ffde7c99efdbd67514e4d51cff227716 100644 (file)
@@ -225,13 +225,21 @@ int2vectorrecv(PG_FUNCTION_ARGS)
 
        Assert(!locfcinfo.isnull);
 
-       /* sanity checks: int2vector must be 1-D, no nulls */
+       /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
        if (ARR_NDIM(result) != 1 ||
                ARR_HASNULL(result) ||
-               ARR_ELEMTYPE(result) != INT2OID)
+               ARR_ELEMTYPE(result) != INT2OID ||
+               ARR_LBOUND(result)[0] != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                 errmsg("invalid int2vector data")));
+
+       /* check length for consistency with int2vectorin() */
+       if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("oidvector has too many elements")));
+
        PG_RETURN_POINTER(result);
 }
 
index 59b11c90a812759fb3471a66ca923daadcbaa722..0801ec402a88da8789033b678a11aea7b5e86634 100644 (file)
@@ -786,20 +786,25 @@ tintervalrecv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
        TimeInterval tinterval;
+       int32 status;
 
        tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData));
 
        tinterval->status = pq_getmsgint(buf, sizeof(tinterval->status));
+       tinterval->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0]));
+       tinterval->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1]));
+
+       if (tinterval->data[0] == INVALID_ABSTIME ||
+               tinterval->data[1] == INVALID_ABSTIME)
+               status = T_INTERVAL_INVAL;      /* undefined  */
+       else
+               status = T_INTERVAL_VALID;
 
-       if (!(tinterval->status == T_INTERVAL_INVAL ||
-                 tinterval->status == T_INTERVAL_VALID))
+       if (status != tinterval->status)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                 errmsg("invalid status in external \"tinterval\" value")));
 
-       tinterval->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0]));
-       tinterval->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1]));
-
        PG_RETURN_TIMEINTERVAL(tinterval);
 }
 
index f5800e7a69a390e6786497860598849d72791707..a4b1c7afa290a727c8e55f46b52a8a641ce0ff8e 100644 (file)
@@ -276,13 +276,21 @@ oidvectorrecv(PG_FUNCTION_ARGS)
 
        Assert(!locfcinfo.isnull);
 
-       /* sanity checks: oidvector must be 1-D, no nulls */
+       /* sanity checks: oidvector must be 1-D, 0-based, no nulls */
        if (ARR_NDIM(result) != 1 ||
                ARR_HASNULL(result) ||
-               ARR_ELEMTYPE(result) != OIDOID)
+               ARR_ELEMTYPE(result) != OIDOID ||
+               ARR_LBOUND(result)[0] != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                 errmsg("invalid oidvector data")));
+
+       /* check length for consistency with oidvectorin() */
+       if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("oidvector has too many elements")));
+
        PG_RETURN_POINTER(result);
 }
 
index e00f729e6fcda08fd2633faefd1e856417f8f5f6..b4059d4a41daa1dba706de76a0571a4dc2ffa465 100644 (file)
@@ -253,6 +253,11 @@ timestamp_recv(PG_FUNCTION_ARGS)
        timestamp = (Timestamp) pq_getmsgint64(buf);
 #else
        timestamp = (Timestamp) pq_getmsgfloat8(buf);
+
+       if (isnan(timestamp))
+               ereport(ERROR,
+                               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                                errmsg("timestamp cannot be NaN")));
 #endif
 
        /* rangecheck: see if timestamp_out would like it */
index db297f26425bcfdf062b5c4ec7cdf5f2cdabc4ab..68352d32d97ec00f6706d630b6a29b38aa80ec96 100644 (file)
@@ -262,6 +262,8 @@ extern const int day_tab[2][13];
   || (((m) == JULIAN_MINMONTH) && ((d) >= JULIAN_MINDAY))))) \
  && ((y) < JULIAN_MAXYEAR))
 
+#define JULIAN_MAX (2145031948) /* == date2j(JULIAN_MAXYEAR, 1 ,1) */
+
 /* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */
 #define UNIX_EPOCH_JDATE               2440588 /* == date2j(1970, 1, 1) */
 #define POSTGRES_EPOCH_JDATE   2451545 /* == date2j(2000, 1, 1) */