Skip to content

Commit eba2ce1

Browse files
committed
Fix another crash in json{b}_populate_recordset and json{b}_to_recordset.
populate_recordset_worker() failed to consider the possibility that the supplied JSON data contains no rows, so that update_cached_tupdesc never got called. This led to a null-pointer dereference since commit 9a5e8ed; before that it led to a bogus "set-valued function called in context that cannot accept a set" error. Fix by forcing the update to happen. Per bug #15514. Back-patch to v11 as 9a5e8ed was. (If we were excited about the bogus error, we could perhaps go back further, but it'd take more work to figure out how to fix it in older branches. Given the lack of field complaints about that aspect, I'm not excited.) Discussion: https://postgr.es/m/15514-59d5b4c4065b178b@postgresql.org
1 parent fe375d3 commit eba2ce1

File tree

5 files changed

+42
-0
lines changed

5 files changed

+42
-0
lines changed

src/backend/utils/adt/jsonfuncs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3658,6 +3658,12 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
36583658
if (PG_ARGISNULL(json_arg_num))
36593659
PG_RETURN_NULL();
36603660

3661+
/*
3662+
* Forcibly update the cached tupdesc, to ensure we have the right tupdesc
3663+
* to return even if the JSON contains no rows.
3664+
*/
3665+
update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
3666+
36613667
state = palloc0(sizeof(PopulateRecordsetState));
36623668

36633669
/* make tuplestore in a sufficiently long-lived memory context */

src/test/regress/expected/json.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,19 @@ FROM (VALUES (1),(2)) v(i);
18511851
2 | (2,43)
18521852
(4 rows)
18531853

1854+
-- empty array is a corner case
1855+
SELECT json_populate_recordset(null::record, '[]');
1856+
ERROR: record type has not been registered
1857+
SELECT json_populate_recordset(row(1,2), '[]');
1858+
json_populate_recordset
1859+
-------------------------
1860+
(0 rows)
1861+
1862+
SELECT * FROM json_populate_recordset(NULL::jpop,'[]') q;
1863+
a | b | c
1864+
---+---+---
1865+
(0 rows)
1866+
18541867
-- composite domain
18551868
SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]');
18561869
json_populate_recordset

src/test/regress/expected/jsonb.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,19 @@ FROM (VALUES (1),(2)) v(i);
25332533
2 | (2,43)
25342534
(4 rows)
25352535

2536+
-- empty array is a corner case
2537+
SELECT jsonb_populate_recordset(null::record, '[]');
2538+
ERROR: record type has not been registered
2539+
SELECT jsonb_populate_recordset(row(1,2), '[]');
2540+
jsonb_populate_recordset
2541+
--------------------------
2542+
(0 rows)
2543+
2544+
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q;
2545+
a | b | c
2546+
---+---+---
2547+
(0 rows)
2548+
25362549
-- composite domain
25372550
SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]');
25382551
jsonb_populate_recordset

src/test/regress/sql/json.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,11 @@ SELECT json_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]');
550550
SELECT i, json_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]')
551551
FROM (VALUES (1),(2)) v(i);
552552

553+
-- empty array is a corner case
554+
SELECT json_populate_recordset(null::record, '[]');
555+
SELECT json_populate_recordset(row(1,2), '[]');
556+
SELECT * FROM json_populate_recordset(NULL::jpop,'[]') q;
557+
553558
-- composite domain
554559
SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]');
555560
SELECT json_populate_recordset(row(1,2)::j_ordered_pair, '[{"x": 0}, {"y": 3}]');

src/test/regress/sql/jsonb.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,11 @@ SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]');
666666
SELECT i, jsonb_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]')
667667
FROM (VALUES (1),(2)) v(i);
668668

669+
-- empty array is a corner case
670+
SELECT jsonb_populate_recordset(null::record, '[]');
671+
SELECT jsonb_populate_recordset(row(1,2), '[]');
672+
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q;
673+
669674
-- composite domain
670675
SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]');
671676
SELECT jsonb_populate_recordset(row(1,2)::jb_ordered_pair, '[{"x": 0}, {"y": 3}]');

0 commit comments

Comments
 (0)