diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/geo_ops.c | 30 | ||||
-rw-r--r-- | src/backend/utils/adt/tsquery.c | 7 | ||||
-rw-r--r-- | src/backend/utils/adt/tsquery_util.c | 5 | ||||
-rw-r--r-- | src/backend/utils/adt/txid.c | 15 | ||||
-rw-r--r-- | src/backend/utils/adt/varbit.c | 32 | ||||
-rw-r--r-- | src/include/tsearch/ts_type.h | 3 | ||||
-rw-r--r-- | src/include/utils/varbit.h | 7 |
7 files changed, 84 insertions, 15 deletions
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 2cf2f644117..ca03947bc83 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -1403,6 +1403,7 @@ path_in(PG_FUNCTION_ARGS) char *s; int npts; int size; + int base_size; int depth = 0; if ((npts = pair_count(str, ',')) <= 0) @@ -1421,7 +1422,15 @@ path_in(PG_FUNCTION_ARGS) depth++; } - size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts; + base_size = sizeof(path->p[0]) * npts; + size = offsetof(PATH, p[0]) + base_size; + + /* Check for integer overflow */ + if (base_size / npts != sizeof(path->p[0]) || size <= base_size) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("too many points requested"))); + path = (PATH *) palloc(size); SET_VARSIZE(path, size); @@ -3465,6 +3474,7 @@ poly_in(PG_FUNCTION_ARGS) POLYGON *poly; int npts; int size; + int base_size; int isopen; char *s; @@ -3473,7 +3483,15 @@ poly_in(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type polygon: \"%s\"", str))); - size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts; + base_size = sizeof(poly->p[0]) * npts; + size = offsetof(POLYGON, p[0]) + base_size; + + /* Check for integer overflow */ + if (base_size / npts != sizeof(poly->p[0]) || size <= base_size) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("too many points requested"))); + poly = (POLYGON *) palloc0(size); /* zero any holes */ SET_VARSIZE(poly, size); @@ -4379,6 +4397,10 @@ path_poly(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("open path cannot be converted to polygon"))); + /* + * Never overflows: the old size fit in MaxAllocSize, and the new size is + * just a small constant larger. + */ size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * path->npts; poly = (POLYGON *) palloc(size); @@ -4484,6 +4506,10 @@ poly_path(PG_FUNCTION_ARGS) int size; int i; + /* + * Never overflows: the old size fit in MaxAllocSize, and the new size is + * smaller by a small constant. + */ size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * poly->npts; path = (PATH *) palloc(size); diff --git a/src/backend/utils/adt/tsquery.c b/src/backend/utils/adt/tsquery.c index 5baa02b1c03..625421545c4 100644 --- a/src/backend/utils/adt/tsquery.c +++ b/src/backend/utils/adt/tsquery.c @@ -517,8 +517,13 @@ parse_tsquery(char *buf, return query; } - /* Pack the QueryItems in the final TSQuery struct to return to caller */ + if (TSQUERY_TOO_BIG(list_length(state.polstr), state.sumlen)) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("tsquery is too large"))); commonlen = COMPUTESIZE(list_length(state.polstr), state.sumlen); + + /* Pack the QueryItems in the final TSQuery struct to return to caller */ query = (TSQuery) palloc0(commonlen); SET_VARSIZE(query, commonlen); query->size = list_length(state.polstr); diff --git a/src/backend/utils/adt/tsquery_util.c b/src/backend/utils/adt/tsquery_util.c index 53093f1e864..08411b0ade0 100644 --- a/src/backend/utils/adt/tsquery_util.c +++ b/src/backend/utils/adt/tsquery_util.c @@ -334,6 +334,11 @@ QTN2QT(QTNode *in) QTN2QTState state; cntsize(in, &sumlen, &nnode); + + if (TSQUERY_TOO_BIG(nnode, sumlen)) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("tsquery is too large"))); len = COMPUTESIZE(nnode, sumlen); out = (TSQuery) palloc0(len); diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c index 2907306e928..31867c4fa85 100644 --- a/src/backend/utils/adt/txid.c +++ b/src/backend/utils/adt/txid.c @@ -27,6 +27,7 @@ #include "miscadmin.h" #include "libpq/pqformat.h" #include "utils/builtins.h" +#include "utils/memutils.h" #include "utils/snapmgr.h" @@ -66,6 +67,8 @@ typedef struct #define TXID_SNAPSHOT_SIZE(nxip) \ (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip)) +#define TXID_SNAPSHOT_MAX_NXIP \ + ((MaxAllocSize - offsetof(TxidSnapshot, xip)) / sizeof(txid)) /* * Epoch values from xact.c @@ -444,20 +447,12 @@ txid_snapshot_recv(PG_FUNCTION_ARGS) txid last = 0; int nxip; int i; - int avail; - int expect; txid xmin, xmax; - /* - * load nxip and check for nonsense. - * - * (nxip > avail) check is against int overflows in 'expect'. - */ + /* load and validate nxip */ nxip = pq_getmsgint(buf, 4); - avail = buf->len - buf->cursor; - expect = 8 + 8 + nxip * 8; - if (nxip < 0 || nxip > avail || expect > avail) + if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP) goto bad_format; xmin = pq_getmsgint64(buf); diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 3fa81175fd8..1727f25679e 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -147,12 +147,22 @@ bit_in(PG_FUNCTION_ARGS) sp = input_string; } + /* + * Determine bitlength from input string. MaxAllocSize ensures a regular + * input is small enough, but we must check hex input. + */ slen = strlen(sp); - /* Determine bitlength from input string */ if (bit_not_hex) bitlen = slen; else + { + if (slen > VARBITMAXLEN / 4) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("bit string length exceeds the maximum allowed (%d)", + VARBITMAXLEN))); bitlen = slen * 4; + } /* * Sometimes atttypmod is not supplied. If it is supplied we need to make @@ -449,12 +459,22 @@ varbit_in(PG_FUNCTION_ARGS) sp = input_string; } + /* + * Determine bitlength from input string. MaxAllocSize ensures a regular + * input is small enough, but we must check hex input. + */ slen = strlen(sp); - /* Determine bitlength from input string */ if (bit_not_hex) bitlen = slen; else + { + if (slen > VARBITMAXLEN / 4) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("bit string length exceeds the maximum allowed (%d)", + VARBITMAXLEN))); bitlen = slen * 4; + } /* * Sometimes atttypmod is not supplied. If it is supplied we need to make @@ -534,6 +554,9 @@ varbit_in(PG_FUNCTION_ARGS) /* * varbit_out - * Prints the string as bits to preserve length accurately + * + * XXX varbit_recv() and hex input to varbit_in() can load a value that this + * cannot emit. Consider using hex output for such values. */ Datum varbit_out(PG_FUNCTION_ARGS) @@ -910,6 +933,11 @@ bit_catenate(VarBit *arg1, VarBit *arg2) bitlen1 = VARBITLEN(arg1); bitlen2 = VARBITLEN(arg2); + if (bitlen1 > VARBITMAXLEN - bitlen2) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("bit string length exceeds the maximum allowed (%d)", + VARBITMAXLEN))); bytelen = VARBITTOTALLEN(bitlen1 + bitlen2); result = (VarBit *) palloc(bytelen); diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h index 6a33f851a32..3aa81fd2ff5 100644 --- a/src/include/tsearch/ts_type.h +++ b/src/include/tsearch/ts_type.h @@ -13,6 +13,7 @@ #define _PG_TSTYPE_H_ #include "fmgr.h" +#include "utils/memutils.h" #include "utils/pg_crc.h" @@ -242,6 +243,8 @@ typedef TSQueryData *TSQuery; * QueryItems, and lenofoperand is the total length of all operands */ #define COMPUTESIZE(size, lenofoperand) ( HDRSIZETQ + (size) * sizeof(QueryItem) + (lenofoperand) ) +#define TSQUERY_TOO_BIG(size, lenofoperand) \ + ((size) > (MaxAllocSize - HDRSIZETQ - (lenofoperand)) / sizeof(QueryItem)) /* Returns a pointer to the first QueryItem in a TSQuery */ #define GETQUERY(x) ((QueryItem*)( (char*)(x)+HDRSIZETQ )) diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h index e329d52e247..58727c66b9a 100644 --- a/src/include/utils/varbit.h +++ b/src/include/utils/varbit.h @@ -15,6 +15,8 @@ #ifndef VARBIT_H #define VARBIT_H +#include <limits.h> + #include "fmgr.h" /* @@ -53,6 +55,11 @@ typedef struct /* Number of bytes needed to store a bit string of a given length */ #define VARBITTOTALLEN(BITLEN) (((BITLEN) + BITS_PER_BYTE-1)/BITS_PER_BYTE + \ VARHDRSZ + VARBITHDRSZ) +/* + * Maximum number of bits. Several code sites assume no overflow from + * computing bitlen + X; VARBITTOTALLEN() has the largest such X. + */ +#define VARBITMAXLEN (INT_MAX - BITS_PER_BYTE + 1) /* pointer beyond the end of the bit string (like end() in STL containers) */ #define VARBITEND(PTR) (((bits8 *) (PTR)) + VARSIZE(PTR)) /* Mask that will cover exactly one byte, i.e. BITS_PER_BYTE bits */ |