From ac290ac7f8bbcb7523f432fb684ec5791975262e Mon Sep 17 00:00:00 2001 From: pgaddict Date: Mon, 11 Sep 2023 12:17:55 +0800 Subject: [PATCH v9 6/7] refactor ReadDimensionInt. in array_in, if bound info explicily mentioned, then check and validdate bound info of a array. in array_in initialize variable dim and lBound. we need use the variable defaults valus in function ReadArrayDimensions and ReadArrayStr. --- src/backend/utils/adt/arrayfuncs.c | 51 ++++++++++++---------------- src/test/regress/expected/arrays.out | 6 ++++ src/test/regress/sql/arrays.sql | 1 + 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index a2d806e3..95a3d5f6 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -188,7 +188,6 @@ array_in(PG_FUNCTION_ARGS) Oid typioparam; char *p; int nitems; - int nitems_according_to_dims; Datum *values; bool *nulls; bool hasnulls; @@ -232,7 +231,12 @@ array_in(PG_FUNCTION_ARGS) typalign = my_extra->typalign; typdelim = my_extra->typdelim; typioparam = my_extra->typioparam; - + /* initialize dim, lBound for ReadArrayDimensions, ReadArrayStr */ + for (int i = 0; i < MAXDIM; i++) + { + dim[i] = -1; + lBound[i] = 1; + } /* * Start processing the input string. * @@ -245,14 +249,12 @@ array_in(PG_FUNCTION_ARGS) if (ndim == 0) { - /* No array dimensions, so intuit dimensions from brace structure */ + /* No array dimensions, so first literal character should be an opening brace */ if (*p != '{') ereturn(escontext, (Datum) 0, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("malformed array literal: \"%s\"", string), errdetail("Array value must start with \"{\" or dimension information."))); - for (int i = 0; i < MAXDIM; i++) - lBound[i] = 1; } else { @@ -304,28 +306,17 @@ array_in(PG_FUNCTION_ARGS) initStringInfo(&buf); appendStringInfo(&buf, "array_in- ndim %d (", ndim); - for (int i = 0; i < ndim; i++) + for (int i = 0; i < MAXDIM; i++) appendStringInfo(&buf, " %d", dim[i]); + appendStringInfo(&buf, "lBound info"); + for (int i = 0; i < MAXDIM; i++) + appendStringInfo(&buf, " %d", lBound[i]); appendStringInfo(&buf, ") for %s\n", string); elog(NOTICE, "%s", buf.data); pfree(buf.data); } #endif - /* This checks for overflow of the array dimensions */ - - /* - * FIXME: Is this still required? I believe all the checks it performs are - * redundant with other checks in ReadArrayDimension() and ReadArrayStr() - */ - nitems_according_to_dims = ArrayGetNItemsSafe(ndim, dim, escontext); - if (nitems_according_to_dims < 0) - PG_RETURN_NULL(); - if (nitems != nitems_according_to_dims) - elog(ERROR, "mismatch nitems, %d vs %d", nitems, nitems_according_to_dims); - if (!ArrayCheckBoundsSafe(ndim, dim, lBound, escontext)) - PG_RETURN_NULL(); - /* Empty array? */ if (nitems == 0) PG_RETURN_ARRAYTYPE_P(construct_empty_array(element_type)); @@ -485,8 +476,8 @@ ReadArrayDimensions(char **srcptr, int *ndim_p, int *dim, int *lBound, "]"))); p++; - /* Upper bound of INT_MAX is disallowed, cf ArrayCheckBounds() */ - if (ub == INT_MAX) + /* Upper bound of PG_INT32_MAX is disallowed, cf ArrayCheckBounds() */ + if (ub == PG_INT32_MAX) ereturn(escontext, false, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array upper bound is too large: %d", ub))); @@ -521,6 +512,7 @@ static bool ReadDimensionInt(char **srcptr, int *result, const char *origStr, Node *escontext) { char *p = *srcptr; + long l; /* don't accept leading whitespace */ if (!isdigit((unsigned char) *p) && *p != '-' && *p != '+') @@ -530,11 +522,16 @@ ReadDimensionInt(char **srcptr, int *result, const char *origStr, Node *escontex } errno = 0; - *result = strtol(p, srcptr, 10); - if (errno == ERANGE) + l = strtol(p, srcptr, 10); + + if (errno == ERANGE || l > PG_INT32_MAX || l < PG_INT32_MIN) + { ereturn(escontext, false, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array bound is out of range"))); + } + + *result = l; return true; } @@ -603,12 +600,6 @@ ReadArrayStr(char **srcptr, /* The caller already checked this */ Assert(**srcptr == '{'); - if (!dimensions_specified) - { - /* Initialize dim[] entries to -1 meaning "unknown" */ - for (int i = 0; i < MAXDIM; ++i) - dim[i] = -1; - } ndim_frozen = dimensions_specified; maxitems = 16; diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index 93e11068..bea0d00b 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -1615,6 +1615,12 @@ select '[1:0]={}'::int[]; {} (1 row) +select '[-2147483648:-2147483647]={1,2}'::int[]; + int4 +--------------------------------- + [-2147483648:-2147483647]={1,2} +(1 row) + -- all of the above should be accepted -- tests for array aggregates CREATE TEMP TABLE arraggtest ( f1 INT[], f2 TEXT[][], f3 FLOAT[]); diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index b7e2b180..5eacb351 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -485,6 +485,7 @@ select array[]::text[]; select '[0:1]={1.1,2.2}'::float8[]; select '[2147483646:2147483646]={1}'::int[]; select '[1:0]={}'::int[]; +select '[-2147483648:-2147483647]={1,2}'::int[]; -- all of the above should be accepted -- tests for array aggregates -- 2.34.1