aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2023-05-04 11:48:23 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2023-05-04 11:48:23 -0400
commit9a72f499a4b61c34e3ae7759c209e92e0cfef6e1 (patch)
treeca58da0d4f4147997e0fd7aa7f4e85e891484ccd
parent0e6354ed97833a15a6a7dfa328298ad02e0947e3 (diff)
downloadpostgresql-9a72f499a4b61c34e3ae7759c209e92e0cfef6e1.tar.gz
postgresql-9a72f499a4b61c34e3ae7759c209e92e0cfef6e1.zip
In array_position()/array_positions(), beware of empty input array.
These functions incautiously fetched the array's first lower bound even when the array is zero-dimensional, thus fetching the word after the allocated array space. While almost always harmless, with very bad luck this could result in SIGSEGV. Fix by adding an early exit for empty input. Per bug #17920 from Alexander Lakhin. Discussion: https://postgr.es/m/17920-f7c228c627b6d02e%40postgresql.org
-rw-r--r--src/backend/utils/adt/array_userfuncs.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 624483dc5d9..d4c5edb69d2 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -651,7 +651,6 @@ array_position_common(FunctionCallInfo fcinfo)
PG_RETURN_NULL();
array = PG_GETARG_ARRAYTYPE_P(0);
- element_type = ARR_ELEMTYPE(array);
/*
* We refuse to search for elements in multi-dimensional arrays, since we
@@ -662,6 +661,10 @@ array_position_common(FunctionCallInfo fcinfo)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("searching for elements in multidimensional arrays is not supported")));
+ /* Searching in an empty array is well-defined, though: it always fails */
+ if (ARR_NDIM(array) < 1)
+ PG_RETURN_NULL();
+
if (PG_ARGISNULL(1))
{
/* fast return when the array doesn't have nulls */
@@ -676,6 +679,7 @@ array_position_common(FunctionCallInfo fcinfo)
null_search = false;
}
+ element_type = ARR_ELEMTYPE(array);
position = (ARR_LBOUND(array))[0] - 1;
/* figure out where to start */
@@ -801,9 +805,6 @@ array_positions(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
array = PG_GETARG_ARRAYTYPE_P(0);
- element_type = ARR_ELEMTYPE(array);
-
- position = (ARR_LBOUND(array))[0] - 1;
/*
* We refuse to search for elements in multi-dimensional arrays, since we
@@ -816,6 +817,10 @@ array_positions(PG_FUNCTION_ARGS)
astate = initArrayResult(INT4OID, CurrentMemoryContext, false);
+ /* Searching in an empty array is well-defined, though: it always fails */
+ if (ARR_NDIM(array) < 1)
+ PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
+
if (PG_ARGISNULL(1))
{
/* fast return when the array doesn't have nulls */
@@ -830,6 +835,9 @@ array_positions(PG_FUNCTION_ARGS)
null_search = false;
}
+ element_type = ARR_ELEMTYPE(array);
+ position = (ARR_LBOUND(array))[0] - 1;
+
/*
* We arrange to look up type info for array_create_iterator only once per
* series of calls, assuming the element type doesn't change underneath