Author: Filip Januš Backport of https://git.postgresql.org/gitweb/?p=postgresql.git;a=patch;h=0c1caa48d3ccb7a5d1343b53aa32fcae45dc2d00 diff -ur postgresql-9.2.24/src/backend/executor/execQual.c postgresql-9.2.24-patched/src/backend/executor/execQual.c --- postgresql-9.2.24/src/backend/executor/execQual.c 2017-11-06 23:17:39.000000000 +0100 +++ postgresql-9.2.24-patched/src/backend/executor/execQual.c 2021-06-02 10:05:19.781390954 +0200 @@ -3212,6 +3212,9 @@ dims[i] = elem_dims[i - 1]; lbs[i] = elem_lbs[i - 1]; } + /* Check subscript owerflow */ + (void) ArrayGetNItems(ndims, dims); + ArrayCheckBounds(ndims, dims, lbs); if (havenulls) { diff -ur postgresql-9.2.24/src/backend/utils/adt/arrayfuncs.c postgresql-9.2.24-patched/src/backend/utils/adt/arrayfuncs.c --- postgresql-9.2.24/src/backend/utils/adt/arrayfuncs.c 2017-11-06 23:17:39.000000000 +0100 +++ postgresql-9.2.24-patched/src/backend/utils/adt/arrayfuncs.c 2021-06-02 10:05:19.785391004 +0200 @@ -325,7 +325,9 @@ /* This checks for overflow of the array dimensions */ nitems = ArrayGetNItems(ndim, dim); - /* Empty array? */ + ArrayCheckBounds(ndim, dim, lBound); + + /* Empty array? */ if (nitems == 0) PG_RETURN_ARRAYTYPE_P(construct_empty_array(element_type)); @@ -1261,24 +1263,11 @@ dim[i] = pq_getmsgint(buf, 4); lBound[i] = pq_getmsgint(buf, 4); - /* - * Check overflow of upper bound. (ArrayNItems() below checks that - * dim[i] >= 0) - */ - if (dim[i] != 0) - { - int ub = lBound[i] + dim[i] - 1; - - 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 */ nitems = ArrayGetNItems(ndim, dim); - + ArrayCheckBounds(ndim, dim, lBound); /* * We arrange to look up info about element type, including its receive * conversion proc, only once per series of calls, assuming the element @@ -2074,7 +2063,7 @@ (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); - if (indx[0] < 0 || indx[0] * elmlen >= arraytyplen) + if (indx[0] < 0 || indx[0] >= arraytyplen / elmlen) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array subscript out of range"))); @@ -2178,6 +2167,8 @@ * Compute sizes of items and areas to copy */ newnitems = ArrayGetNItems(ndim, dim); + /* Check for overflow of the array dimension */ + ArrayCheckBounds(ndim, dim, lb); if (newhasnulls) overheadlen = ARR_OVERHEAD_WITHNULLS(ndim, newnitems); else @@ -2481,6 +2472,7 @@ /* Do this mainly to check for overflow */ nitems = ArrayGetNItems(ndim, dim); + ArrayCheckBounds(ndim, dim, lb); /* * Make sure source array has enough entries. Note we ignore the shape of @@ -2919,6 +2911,7 @@ return construct_empty_array(elmtype); nelems = ArrayGetNItems(ndims, dims); + ArrayCheckBounds(ndims, dims, lbs); /* compute required space */ nbytes = 0; @@ -4965,6 +4958,7 @@ } nitems = ArrayGetNItems(ndims, dimv); + ArrayCheckBounds(ndims,dimv, lbsv); /* fast track for empty array */ if (nitems <= 0) diff -ur postgresql-9.2.24/src/backend/utils/adt/array_userfuncs.c postgresql-9.2.24-patched/src/backend/utils/adt/array_userfuncs.c --- postgresql-9.2.24/src/backend/utils/adt/array_userfuncs.c 2017-11-06 23:17:39.000000000 +0100 +++ postgresql-9.2.24-patched/src/backend/utils/adt/array_userfuncs.c 2021-06-02 10:05:19.785391004 +0200 @@ -362,6 +362,7 @@ /* Do this mainly for overflow checking */ nitems = ArrayGetNItems(ndims, dims); + ArrayCheckBounds(ndims, dims, lbs); /* build the result array */ ndatabytes = ndatabytes1 + ndatabytes2; diff -ur postgresql-9.2.24/src/backend/utils/adt/arrayutils.c postgresql-9.2.24-patched/src/backend/utils/adt/arrayutils.c --- postgresql-9.2.24/src/backend/utils/adt/arrayutils.c 2017-11-06 23:17:39.000000000 +0100 +++ postgresql-9.2.24-patched/src/backend/utils/adt/arrayutils.c 2021-06-02 10:05:19.782390966 +0200 @@ -233,3 +233,29 @@ return result; } +/* + * Verify sanity of proposed lower-bound values for an array + * + * The lower-bound values must not be so large as to cause overflow when + * calculating subscripts, e.g. lower bound 2147483640 with length 10 + * must be disallowed. We actually insist that dims[i] + lb[i] be + * computable without overflow, meaning that an array with last subscript + * equal to INT_MAX will be disallowed. + * + * It is assumed that the caller already called ArrayGetNItems, so that + * overflowed (negative) dims[] values have been eliminated. + */ +void +ArrayCheckBounds(int ndim, const int *dims, const int *lb) +{ + int i; + + for (i = 0; i < ndim; i++) + { + if (dims[i] + lb[i] < lb[i]) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("array lower bound is too large: %d", + lb[i]))); + } +} diff -ur postgresql-9.2.24/src/include/utils/array.h postgresql-9.2.24-patched/src/include/utils/array.h --- postgresql-9.2.24/src/include/utils/array.h 2017-11-06 23:17:39.000000000 +0100 +++ postgresql-9.2.24-patched/src/include/utils/array.h 2021-06-02 10:05:19.713390098 +0200 @@ -273,7 +273,7 @@ extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span); extern int mda_next_tuple(int n, int *curr, const int *span); extern int32 *ArrayGetIntegerTypmods(ArrayType *arr, int *n); - +extern void ArrayCheckBounds(int ndim, const int *dims, const int *lb); /* * prototypes for functions defined in array_userfuncs.c */