]> granicus.if.org Git - postgresql/commitdiff
Prevent stack overflow in container-type functions.
authorNoah Misch <noah@leadboat.com>
Mon, 5 Oct 2015 14:06:29 +0000 (10:06 -0400)
committerNoah Misch <noah@leadboat.com>
Mon, 5 Oct 2015 14:06:36 +0000 (10:06 -0400)
A range type can name another range type as its subtype, and a record
type can bear a column of another record type.  Consequently, functions
like range_cmp() and record_recv() are recursive.  Functions at risk
include operator family members and referents of pg_type regproc
columns.  Treat as recursive any such function that looks up and calls
the same-purpose function for a record column type or the range subtype.
Back-patch to 9.0 (all supported versions).

An array type's element type is never itself an array type, so array
functions are unaffected.  Recursion depth proportional to array
dimensionality, found in array_dim_to_jsonb(), is fine thanks to MAXDIM.

src/backend/utils/adt/rowtypes.c

index fa2a1c4773e6ed992816ee299b1a43cf686e7ae2..00e361f016e996047ae1858afb5c5fdf302bc41b 100644 (file)
@@ -19,6 +19,7 @@
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "libpq/pqformat.h"
+#include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/typcache.h"
@@ -88,6 +89,8 @@ record_in(PG_FUNCTION_ARGS)
        bool       *nulls;
        StringInfoData buf;
 
+       check_stack_depth();            /* recurses for record-type columns */
+
        /*
         * Use the passed type unless it's RECORD; we can't support input of
         * anonymous types, mainly because there's no good way to figure out which
@@ -310,6 +313,8 @@ record_out(PG_FUNCTION_ARGS)
        bool       *nulls;
        StringInfoData buf;
 
+       check_stack_depth();            /* recurses for record-type columns */
+
        /* Extract type info from the tuple itself */
        tupType = HeapTupleHeaderGetTypeId(rec);
        tupTypmod = HeapTupleHeaderGetTypMod(rec);
@@ -477,6 +482,8 @@ record_recv(PG_FUNCTION_ARGS)
        Datum      *values;
        bool       *nulls;
 
+       check_stack_depth();            /* recurses for record-type columns */
+
        /*
         * Use the passed type unless it's RECORD; we can't support input of
         * anonymous types, mainly because there's no good way to figure out which
@@ -667,6 +674,8 @@ record_send(PG_FUNCTION_ARGS)
        bool       *nulls;
        StringInfoData buf;
 
+       check_stack_depth();            /* recurses for record-type columns */
+
        /* Extract type info from the tuple itself */
        tupType = HeapTupleHeaderGetTypeId(rec);
        tupTypmod = HeapTupleHeaderGetTypMod(rec);
@@ -826,6 +835,8 @@ record_cmp(FunctionCallInfo fcinfo)
        int                     i2;
        int                     j;
 
+       check_stack_depth();            /* recurses for record-type columns */
+
        /* Extract type info from the tuples */
        tupType1 = HeapTupleHeaderGetTypeId(record1);
        tupTypmod1 = HeapTupleHeaderGetTypMod(record1);
@@ -1052,6 +1063,8 @@ record_eq(PG_FUNCTION_ARGS)
        int                     i2;
        int                     j;
 
+       check_stack_depth();            /* recurses for record-type columns */
+
        /* Extract type info from the tuples */
        tupType1 = HeapTupleHeaderGetTypeId(record1);
        tupTypmod1 = HeapTupleHeaderGetTypMod(record1);