aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-07-31 13:43:17 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-07-31 13:43:17 -0400
commite71d4254f710bef53fa40d0b49b5af9bad10ce40 (patch)
treefa8813d531086a8b568dbab016dfafacbe6012cc
parente90c4fc881e2c836b4d4fb9fae03310f9c0d8597 (diff)
downloadpostgresql-e71d4254f710bef53fa40d0b49b5af9bad10ce40.tar.gz
postgresql-e71d4254f710bef53fa40d0b49b5af9bad10ce40.zip
Fix trim_array() for zero-dimensional array argument.
The code tried to access ARR_DIMS(v)[0] and ARR_LBOUND(v)[0] whether or not those values exist. This made the range check on the "n" argument unstable --- it might or might not fail, and if it did it would report garbage for the allowed upper limit. These bogus accesses would probably annoy Valgrind, and if you were very unlucky even lead to SIGSEGV. Report and fix by Martin Kalcher. Back-patch to v14 where this function was added. Discussion: https://postgr.es/m/baaeb413-b8a8-4656-5757-ef347e5ec11f@aboutsource.net
-rw-r--r--src/backend/utils/adt/arrayfuncs.c9
-rw-r--r--src/test/regress/expected/arrays.out2
-rw-r--r--src/test/regress/sql/arrays.sql1
3 files changed, 9 insertions, 3 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 660e854e93f..55ba9f73deb 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -6684,7 +6684,7 @@ trim_array(PG_FUNCTION_ARGS)
{
ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
int n = PG_GETARG_INT32(1);
- int array_length = ARR_DIMS(v)[0];
+ int array_length = (ARR_NDIM(v) > 0) ? ARR_DIMS(v)[0] : 0;
int16 elmlen;
bool elmbyval;
char elmalign;
@@ -6704,8 +6704,11 @@ trim_array(PG_FUNCTION_ARGS)
/* Set all the bounds as unprovided except the first upper bound */
memset(lowerProvided, false, sizeof(lowerProvided));
memset(upperProvided, false, sizeof(upperProvided));
- upper[0] = ARR_LBOUND(v)[0] + array_length - n - 1;
- upperProvided[0] = true;
+ if (ARR_NDIM(v) > 0)
+ {
+ upper[0] = ARR_LBOUND(v)[0] + array_length - n - 1;
+ upperProvided[0] = true;
+ }
/* Fetch the needed information about the element type */
get_typlenbyvalalign(ARR_ELEMTYPE(v), &elmlen, &elmbyval, &elmalign);
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index 95481ce568a..4923cf36d65 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -2432,3 +2432,5 @@ SELECT trim_array(ARRAY[1, 2, 3], -1); -- fail
ERROR: number of elements to trim must be between 0 and 3
SELECT trim_array(ARRAY[1, 2, 3], 10); -- fail
ERROR: number of elements to trim must be between 0 and 3
+SELECT trim_array(ARRAY[]::int[], 1); -- fail
+ERROR: number of elements to trim must be between 0 and 0
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index 3ab7f392be4..5eedc4c3ce4 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -737,3 +737,4 @@ FROM
SELECT trim_array(ARRAY[1, 2, 3], -1); -- fail
SELECT trim_array(ARRAY[1, 2, 3], 10); -- fail
+SELECT trim_array(ARRAY[]::int[], 1); -- fail