]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
In array_position()/array_positions(), beware of empty input array.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 4 May 2023 15:48:23 +0000 (11:48 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 4 May 2023 15:48:23 +0000 (11:48 -0400)
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

src/backend/utils/adt/array_userfuncs.c

index 8689a56e8c783cb0330f561a9c3b60df4cf867df..1b243b10e8316215cc0545f400031dad096c6328 100644 (file)
@@ -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