From cfe57c7893ad43fb3adf01f9ded266b0c7de782a Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 4 Sep 2009 11:20:23 +0000 Subject: [PATCH] Tigthen binary receive functions so that they reject values that the text 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-patching. --- src/backend/utils/adt/arrayfuncs.c | 9 +++++++++ src/backend/utils/adt/date.c | 11 ++++++++++- src/backend/utils/adt/int.c | 12 ++++++++++-- src/backend/utils/adt/nabstime.c | 15 ++++++++++----- src/backend/utils/adt/oid.c | 12 ++++++++++-- src/backend/utils/adt/timestamp.c | 5 +++++ src/include/utils/datetime.h | 2 ++ 7 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index fb96541bdf..2b5ea70ba1 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -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 */ diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 2085d8555e..23a33a8881 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -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); } /* diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 548662f53a..63a4ab36ff 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -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); } diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 59b11c90a8..0801ec402a 100644 --- a/src/backend/utils/adt/nabstime.c +++ b/src/backend/utils/adt/nabstime.c @@ -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); } diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index f5800e7a69..a4b1c7afa2 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -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); } diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index e00f729e6f..b4059d4a41 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -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 */ diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index db297f2642..68352d32d9 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -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) */ -- 2.30.2