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

Commitc30f082

Browse files
committed
Make json{b}_populate_recordset() use the right tuple descriptor.
json{b}_populate_recordset() used the tuple descriptor created from thequery-level AS clause without worrying about whether it matched the actualinput record type. If it didn't, that would usually result in a crash,though disclosure of server memory contents seems possible as well, for askilled attacker capable of issuing crafted SQL commands. Instead, usethe query-supplied descriptor only when there is no input tuple to look at,and otherwise get a tuple descriptor based on the input tuple's own typemarking. The core code will detect any type mismatch in the latter case.Michael Paquier and Tom Lane, per a report from David Rowley.Back-patch to 9.3 where this functionality was introduced.Security:CVE-2017-15098
1 parent6b0b983 commitc30f082

File tree

5 files changed

+66
-11
lines changed

5 files changed

+66
-11
lines changed

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

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3491,26 +3491,40 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
34913491

34923492
rsi->returnMode=SFRM_Materialize;
34933493

3494-
/*
3495-
* get the tupdesc from the result set info - it must be a record type
3496-
* because we already checked that arg1 is a record type, or we're in a
3497-
* to_record function which returns a setof record.
3498-
*/
3499-
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
3500-
ereport(ERROR,
3501-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3502-
errmsg("function returning record called in context "
3503-
"that cannot accept type record")));
3504-
35053494
/* if the json is null send back an empty set */
35063495
if (PG_ARGISNULL(json_arg_num))
35073496
PG_RETURN_NULL();
35083497

35093498
if (!have_record_arg||PG_ARGISNULL(0))
3499+
{
35103500
rec=NULL;
3501+
3502+
/*
3503+
* get the tupdesc from the result set info - it must be a record type
3504+
* because we already checked that arg1 is a record type, or we're in
3505+
* a to_record function which returns a setof record.
3506+
*/
3507+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
3508+
ereport(ERROR,
3509+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3510+
errmsg("function returning record called in context "
3511+
"that cannot accept type record")));
3512+
}
35113513
else
3514+
{
3515+
OidtupType;
3516+
int32tupTypmod;
3517+
35123518
rec=PG_GETARG_HEAPTUPLEHEADER(0);
35133519

3520+
/*
3521+
* use the input record's own type marking to find a tupdesc for it.
3522+
*/
3523+
tupType=HeapTupleHeaderGetTypeId(rec);
3524+
tupTypmod=HeapTupleHeaderGetTypMod(rec);
3525+
tupdesc=lookup_rowtype_tupdesc(tupType,tupTypmod);
3526+
}
3527+
35143528
state=palloc0(sizeof(PopulateRecordsetState));
35153529

35163530
/* make these in a sufficiently long-lived memory context */
@@ -3522,6 +3536,9 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
35223536
false,work_mem);
35233537
MemoryContextSwitchTo(old_cxt);
35243538

3539+
/* unnecessary, but harmless, if tupdesc came from get_call_result_type: */
3540+
ReleaseTupleDesc(tupdesc);
3541+
35253542
state->function_name=funcname;
35263543
state->my_extra= (RecordIOData**)&fcinfo->flinfo->fn_extra;
35273544
state->rec=rec;

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,19 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,3
18061806
{"z":true} | 3 | Fri Jan 20 10:42:53 2012
18071807
(2 rows)
18081808

1809+
-- negative cases where the wrong record type is supplied
1810+
select * from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1811+
ERROR: function return row and query-specified return row do not match
1812+
DETAIL: Returned row contains 1 attribute, but query expects 2.
1813+
select * from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1814+
ERROR: function return row and query-specified return row do not match
1815+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
1816+
select * from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1817+
ERROR: function return row and query-specified return row do not match
1818+
DETAIL: Returned row contains 3 attributes, but query expects 2.
1819+
select * from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
1820+
ERROR: function return row and query-specified return row do not match
1821+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
18091822
-- test type info caching in json_populate_record()
18101823
CREATE TEMP TABLE jspoptest (js json);
18111824
INSERT INTO jspoptest

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,19 @@ SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200
24882488
{"z": true} | 3 | Fri Jan 20 10:42:53 2012
24892489
(2 rows)
24902490

2491+
-- negative cases where the wrong record type is supplied
2492+
select * from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
2493+
ERROR: function return row and query-specified return row do not match
2494+
DETAIL: Returned row contains 1 attribute, but query expects 2.
2495+
select * from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
2496+
ERROR: function return row and query-specified return row do not match
2497+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
2498+
select * from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
2499+
ERROR: function return row and query-specified return row do not match
2500+
DETAIL: Returned row contains 3 attributes, but query expects 2.
2501+
select * from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
2502+
ERROR: function return row and query-specified return row do not match
2503+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
24912504
-- jsonb_to_record and jsonb_to_recordset
24922505
select * from jsonb_to_record('{"a":1,"b":"foo","c":"bar"}')
24932506
as x(a int, b text, d text);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,12 @@ select * from json_populate_recordset(null::jpop,'[{"a":"blurfl","x":43.2},{"b":
532532
select*from json_populate_recordset(row('def',99,null)::jpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
533533
select*from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
534534

535+
-- negative cases where the wrong record type is supplied
536+
select*from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
537+
select*from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
538+
select*from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
539+
select*from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);
540+
535541
-- test type info caching in json_populate_record()
536542
CREATE TEMP TABLE jspoptest (js json);
537543

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,12 @@ SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b
648648
SELECT*FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
649649
SELECT*FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
650650

651+
-- negative cases where the wrong record type is supplied
652+
select*from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
653+
select*from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
654+
select*from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
655+
select*from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);
656+
651657
-- jsonb_to_record and jsonb_to_recordset
652658

653659
select*from jsonb_to_record('{"a":1,"b":"foo","c":"bar"}')

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp