Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4984784

Browse files
committed
Fix crash in json{b}_populate_recordset() and json{b}_to_recordset().
As of commit37a795a, populate_recordset_worker() tried to pass back(as rsi.setDesc) a tupdesc that it also had cached in its fn_extra.But the core executor would free the passed-back tupdesc, risking acrash if the function were called again in the same query. The safestand least invasive way to fix that is to make an extra tupdesc copyto pass back.While at it, I failed to resist the temptation to get rid of unnecessaryget_fn_expr_argtype() calls here and in populate_record_worker().Per report from Dmitry Dolgov; thanks to Michael Paquier andAndrew Gierth for investigation and discussion.Discussion:https://postgr.es/m/CA+q6zcWzN9ztCfR47ZwgTr1KLnuO6BAY6FurxXhovP4hxr+yOQ@mail.gmail.com
1 parent93ad00c commit4984784

File tree

5 files changed

+59
-23
lines changed

5 files changed

+59
-23
lines changed

‎src/backend/utils/adt/jsonfuncs.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,9 @@ static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
421421

422422
/* worker functions for populate_record, to_record, populate_recordset and to_recordset */
423423
staticDatumpopulate_recordset_worker(FunctionCallInfofcinfo,constchar*funcname,
424-
boolhave_record_arg);
424+
boolis_json,boolhave_record_arg);
425425
staticDatumpopulate_record_worker(FunctionCallInfofcinfo,constchar*funcname,
426-
boolhave_record_arg);
426+
boolis_json,boolhave_record_arg);
427427

428428
/* helper functions for populate_record[set] */
429429
staticHeapTupleHeaderpopulate_record(TupleDesctupdesc,RecordIOData**record_p,
@@ -2296,25 +2296,29 @@ elements_scalar(void *state, char *token, JsonTokenType tokentype)
22962296
Datum
22972297
jsonb_populate_record(PG_FUNCTION_ARGS)
22982298
{
2299-
returnpopulate_record_worker(fcinfo,"jsonb_populate_record", true);
2299+
returnpopulate_record_worker(fcinfo,"jsonb_populate_record",
2300+
false, true);
23002301
}
23012302

23022303
Datum
23032304
jsonb_to_record(PG_FUNCTION_ARGS)
23042305
{
2305-
returnpopulate_record_worker(fcinfo,"jsonb_to_record", false);
2306+
returnpopulate_record_worker(fcinfo,"jsonb_to_record",
2307+
false, false);
23062308
}
23072309

23082310
Datum
23092311
json_populate_record(PG_FUNCTION_ARGS)
23102312
{
2311-
returnpopulate_record_worker(fcinfo,"json_populate_record", true);
2313+
returnpopulate_record_worker(fcinfo,"json_populate_record",
2314+
true, true);
23122315
}
23132316

23142317
Datum
23152318
json_to_record(PG_FUNCTION_ARGS)
23162319
{
2317-
returnpopulate_record_worker(fcinfo,"json_to_record", false);
2320+
returnpopulate_record_worker(fcinfo,"json_to_record",
2321+
true, false);
23182322
}
23192323

23202324
/* helper function for diagnostics */
@@ -3203,21 +3207,22 @@ populate_record(TupleDesc tupdesc,
32033207
returnres->t_data;
32043208
}
32053209

3210+
/*
3211+
* common worker for json{b}_populate_record() and json{b}_to_record()
3212+
* is_json and have_record_arg identify the specific function
3213+
*/
32063214
staticDatum
32073215
populate_record_worker(FunctionCallInfofcinfo,constchar*funcname,
3208-
boolhave_record_arg)
3216+
boolis_json,boolhave_record_arg)
32093217
{
32103218
intjson_arg_num=have_record_arg ?1 :0;
3211-
Oidjtype=get_fn_expr_argtype(fcinfo->flinfo,json_arg_num);
32123219
JsValuejsv= {0};
32133220
HeapTupleHeaderrec;
32143221
Datumrettuple;
32153222
JsonbValuejbv;
32163223
MemoryContextfnmcxt=fcinfo->flinfo->fn_mcxt;
32173224
PopulateRecordCache*cache=fcinfo->flinfo->fn_extra;
32183225

3219-
Assert(jtype==JSONOID||jtype==JSONBOID);
3220-
32213226
/*
32223227
* If first time through, identify input/result record type. Note that
32233228
* this stanza looks only at fcinfo context, which can't change during the
@@ -3303,9 +3308,9 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
33033308
PG_RETURN_NULL();
33043309
}
33053310

3306-
jsv.is_json=jtype==JSONOID;
3311+
jsv.is_json=is_json;
33073312

3308-
if (jsv.is_json)
3313+
if (is_json)
33093314
{
33103315
text*json=PG_GETARG_TEXT_PP(json_arg_num);
33113316

@@ -3489,25 +3494,29 @@ hash_scalar(void *state, char *token, JsonTokenType tokentype)
34893494
Datum
34903495
jsonb_populate_recordset(PG_FUNCTION_ARGS)
34913496
{
3492-
returnpopulate_recordset_worker(fcinfo,"jsonb_populate_recordset", true);
3497+
returnpopulate_recordset_worker(fcinfo,"jsonb_populate_recordset",
3498+
false, true);
34933499
}
34943500

34953501
Datum
34963502
jsonb_to_recordset(PG_FUNCTION_ARGS)
34973503
{
3498-
returnpopulate_recordset_worker(fcinfo,"jsonb_to_recordset", false);
3504+
returnpopulate_recordset_worker(fcinfo,"jsonb_to_recordset",
3505+
false, false);
34993506
}
35003507

35013508
Datum
35023509
json_populate_recordset(PG_FUNCTION_ARGS)
35033510
{
3504-
returnpopulate_recordset_worker(fcinfo,"json_populate_recordset", true);
3511+
returnpopulate_recordset_worker(fcinfo,"json_populate_recordset",
3512+
true, true);
35053513
}
35063514

35073515
Datum
35083516
json_to_recordset(PG_FUNCTION_ARGS)
35093517
{
3510-
returnpopulate_recordset_worker(fcinfo,"json_to_recordset", false);
3518+
returnpopulate_recordset_worker(fcinfo,"json_to_recordset",
3519+
true, false);
35113520
}
35123521

35133522
staticvoid
@@ -3544,14 +3553,14 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
35443553
}
35453554

35463555
/*
3547-
* common worker for json_populate_recordset() and json_to_recordset()
3556+
* common worker for json{b}_populate_recordset() and json{b}_to_recordset()
3557+
* is_json and have_record_arg identify the specific function
35483558
*/
35493559
staticDatum
35503560
populate_recordset_worker(FunctionCallInfofcinfo,constchar*funcname,
3551-
boolhave_record_arg)
3561+
boolis_json,boolhave_record_arg)
35523562
{
35533563
intjson_arg_num=have_record_arg ?1 :0;
3554-
Oidjtype=get_fn_expr_argtype(fcinfo->flinfo,json_arg_num);
35553564
ReturnSetInfo*rsi;
35563565
MemoryContextold_cxt;
35573566
HeapTupleHeaderrec;
@@ -3662,7 +3671,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
36623671
state->cache=cache;
36633672
state->rec=rec;
36643673

3665-
if (jtype==JSONOID)
3674+
if (is_json)
36663675
{
36673676
text*json=PG_GETARG_TEXT_PP(json_arg_num);
36683677
JsonLexContext*lex;
@@ -3693,8 +3702,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
36933702
boolskipNested= false;
36943703
JsonbIteratorTokenr;
36953704

3696-
Assert(jtype==JSONBOID);
3697-
36983705
if (JB_ROOT_IS_SCALAR(jb)|| !JB_ROOT_IS_ARRAY(jb))
36993706
ereport(ERROR,
37003707
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -3726,8 +3733,13 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
37263733
}
37273734
}
37283735

3736+
/*
3737+
* Note: we must copy the cached tupdesc because the executor will free
3738+
* the passed-back setDesc, but we want to hang onto the cache in case
3739+
* we're called again in the same query.
3740+
*/
37293741
rsi->setResult=state->tuple_store;
3730-
rsi->setDesc=cache->c.io.composite.tupdesc;
3742+
rsi->setDesc=CreateTupleDescCopy(cache->c.io.composite.tupdesc);
37313743

37323744
PG_RETURN_NULL();
37333745
}

‎src/test/regress/expected/json.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,16 @@ SELECT json_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]');
18411841
(0,1)
18421842
(1 row)
18431843

1844+
SELECT i, json_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]')
1845+
FROM (VALUES (1),(2)) v(i);
1846+
i | json_populate_recordset
1847+
---+-------------------------
1848+
1 | (42,50)
1849+
1 | (1,43)
1850+
2 | (42,50)
1851+
2 | (2,43)
1852+
(4 rows)
1853+
18441854
-- composite domain
18451855
SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]');
18461856
json_populate_recordset

‎src/test/regress/expected/jsonb.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,16 @@ SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]');
25232523
(0,1)
25242524
(1 row)
25252525

2526+
SELECT i, jsonb_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]')
2527+
FROM (VALUES (1),(2)) v(i);
2528+
i | jsonb_populate_recordset
2529+
---+--------------------------
2530+
1 | (42,50)
2531+
1 | (1,43)
2532+
2 | (42,50)
2533+
2 | (2,43)
2534+
(4 rows)
2535+
25262536
-- composite domain
25272537
SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]');
25282538
jsonb_populate_recordset

‎src/test/regress/sql/json.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,8 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,3
547547
-- anonymous record type
548548
SELECT json_populate_recordset(null::record,'[{"x": 0, "y": 1}]');
549549
SELECT json_populate_recordset(row(1,2),'[{"f1": 0, "f2": 1}]');
550+
SELECT i, json_populate_recordset(row(i,50),'[{"f1":"42"},{"f2":"43"}]')
551+
FROM (VALUES (1),(2)) v(i);
550552

551553
-- composite domain
552554
SELECT json_populate_recordset(null::j_ordered_pair,'[{"x": 0, "y": 1}]');

‎src/test/regress/sql/jsonb.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,8 @@ SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200
663663
-- anonymous record type
664664
SELECT jsonb_populate_recordset(null::record,'[{"x": 0, "y": 1}]');
665665
SELECT jsonb_populate_recordset(row(1,2),'[{"f1": 0, "f2": 1}]');
666+
SELECT i, jsonb_populate_recordset(row(i,50),'[{"f1":"42"},{"f2":"43"}]')
667+
FROM (VALUES (1),(2)) v(i);
666668

667669
-- composite domain
668670
SELECT jsonb_populate_recordset(null::jb_ordered_pair,'[{"x": 0, "y": 1}]');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp