Skip to content

Commit 9286ff7

Browse files
committed
Prevent stack overflow in container-type functions.
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.
1 parent f886217 commit 9286ff7

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

src/backend/utils/adt/rangetypes.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "access/hash.h"
3434
#include "lib/stringinfo.h"
3535
#include "libpq/pqformat.h"
36+
#include "miscadmin.h"
3637
#include "utils/builtins.h"
3738
#include "utils/date.h"
3839
#include "utils/int8.h"
@@ -89,6 +90,8 @@ range_in(PG_FUNCTION_ARGS)
8990
RangeBound lower;
9091
RangeBound upper;
9192

93+
check_stack_depth(); /* recurses when subtype is a range type */
94+
9295
cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
9396

9497
/* parse */
@@ -128,6 +131,8 @@ range_out(PG_FUNCTION_ARGS)
128131
RangeBound upper;
129132
bool empty;
130133

134+
check_stack_depth(); /* recurses when subtype is a range type */
135+
131136
cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
132137

133138
/* deserialize */
@@ -165,6 +170,8 @@ range_recv(PG_FUNCTION_ARGS)
165170
RangeBound lower;
166171
RangeBound upper;
167172

173+
check_stack_depth(); /* recurses when subtype is a range type */
174+
168175
cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
169176

170177
/* receive the flags... */
@@ -245,6 +252,8 @@ range_send(PG_FUNCTION_ARGS)
245252
RangeBound upper;
246253
bool empty;
247254

255+
check_stack_depth(); /* recurses when subtype is a range type */
256+
248257
cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
249258

250259
/* deserialize */
@@ -1114,6 +1123,8 @@ range_cmp(PG_FUNCTION_ARGS)
11141123
empty2;
11151124
int cmp;
11161125

1126+
check_stack_depth(); /* recurses when subtype is a range type */
1127+
11171128
/* Different types should be prevented by ANYRANGE matching rules */
11181129
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
11191130
elog(ERROR, "range types do not match");
@@ -1193,6 +1204,8 @@ hash_range(PG_FUNCTION_ARGS)
11931204
uint32 lower_hash;
11941205
uint32 upper_hash;
11951206

1207+
check_stack_depth(); /* recurses when subtype is a range type */
1208+
11961209
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
11971210

11981211
/* deserialize */

src/backend/utils/adt/rowtypes.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "catalog/pg_type.h"
2121
#include "funcapi.h"
2222
#include "libpq/pqformat.h"
23+
#include "miscadmin.h"
2324
#include "utils/builtins.h"
2425
#include "utils/lsyscache.h"
2526
#include "utils/typcache.h"
@@ -85,6 +86,8 @@ record_in(PG_FUNCTION_ARGS)
8586
bool *nulls;
8687
StringInfoData buf;
8788

89+
check_stack_depth(); /* recurses for record-type columns */
90+
8891
/*
8992
* Give a friendly error message if we did not get enough info to identify
9093
* the target record type. (lookup_rowtype_tupdesc would fail anyway, but
@@ -308,6 +311,8 @@ record_out(PG_FUNCTION_ARGS)
308311
bool *nulls;
309312
StringInfoData buf;
310313

314+
check_stack_depth(); /* recurses for record-type columns */
315+
311316
/* Extract type info from the tuple itself */
312317
tupType = HeapTupleHeaderGetTypeId(rec);
313318
tupTypmod = HeapTupleHeaderGetTypMod(rec);
@@ -457,6 +462,8 @@ record_recv(PG_FUNCTION_ARGS)
457462
Datum *values;
458463
bool *nulls;
459464

465+
check_stack_depth(); /* recurses for record-type columns */
466+
460467
/*
461468
* Give a friendly error message if we did not get enough info to identify
462469
* the target record type. (lookup_rowtype_tupdesc would fail anyway, but
@@ -649,6 +656,8 @@ record_send(PG_FUNCTION_ARGS)
649656
bool *nulls;
650657
StringInfoData buf;
651658

659+
check_stack_depth(); /* recurses for record-type columns */
660+
652661
/* Extract type info from the tuple itself */
653662
tupType = HeapTupleHeaderGetTypeId(rec);
654663
tupTypmod = HeapTupleHeaderGetTypMod(rec);
@@ -792,6 +801,8 @@ record_cmp(FunctionCallInfo fcinfo)
792801
int i2;
793802
int j;
794803

804+
check_stack_depth(); /* recurses for record-type columns */
805+
795806
/* Extract type info from the tuples */
796807
tupType1 = HeapTupleHeaderGetTypeId(record1);
797808
tupTypmod1 = HeapTupleHeaderGetTypMod(record1);
@@ -1027,6 +1038,8 @@ record_eq(PG_FUNCTION_ARGS)
10271038
int i2;
10281039
int j;
10291040

1041+
check_stack_depth(); /* recurses for record-type columns */
1042+
10301043
/* Extract type info from the tuples */
10311044
tupType1 = HeapTupleHeaderGetTypeId(record1);
10321045
tupTypmod1 = HeapTupleHeaderGetTypMod(record1);

0 commit comments

Comments
 (0)