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

Commit70846ee

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 parent29d0670 commit70846ee

File tree

5 files changed

+63
-11
lines changed

5 files changed

+63
-11
lines changed

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

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2607,26 +2607,37 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
26072607

26082608
rsi->returnMode=SFRM_Materialize;
26092609

2610-
/*
2611-
* get the tupdesc from the result set info - it must be a record type
2612-
* because we already checked that arg1 is a record type, or we're in a
2613-
* to_record function which returns a setof record.
2614-
*/
2615-
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
2616-
ereport(ERROR,
2617-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2618-
errmsg("function returning record called in context "
2619-
"that cannot accept type record")));
2620-
26212610
/* if the json is null send back an empty set */
26222611
if (PG_ARGISNULL(json_arg_num))
26232612
PG_RETURN_NULL();
26242613

26252614
if (!have_record_arg||PG_ARGISNULL(0))
2615+
{
26262616
rec=NULL;
2617+
2618+
/*
2619+
* get the tupdesc from the result set info - it must be a record type
2620+
* because we already checked that arg1 is a record type, or we're in
2621+
* a to_record function which returns a setof record.
2622+
*/
2623+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
2624+
ereport(ERROR,
2625+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2626+
errmsg("function returning record called in context "
2627+
"that cannot accept type record")));
2628+
}
26272629
else
2630+
{
26282631
rec=PG_GETARG_HEAPTUPLEHEADER(0);
26292632

2633+
/*
2634+
* use the input record's own type marking to find a tupdesc for it.
2635+
*/
2636+
tupType=HeapTupleHeaderGetTypeId(rec);
2637+
tupTypmod=HeapTupleHeaderGetTypMod(rec);
2638+
tupdesc=lookup_rowtype_tupdesc(tupType,tupTypmod);
2639+
}
2640+
26302641
tupType=tupdesc->tdtypeid;
26312642
tupTypmod=tupdesc->tdtypmod;
26322643
ncolumns=tupdesc->natts;
@@ -2670,6 +2681,9 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
26702681
false,work_mem);
26712682
MemoryContextSwitchTo(old_cxt);
26722683

2684+
/* unnecessary, but harmless, if tupdesc came from get_call_result_type: */
2685+
ReleaseTupleDesc(tupdesc);
2686+
26732687
state->function_name=funcname;
26742688
state->my_extra=my_extra;
26752689
state->rec=rec;

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

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

1387+
-- negative cases where the wrong record type is supplied
1388+
select * from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1389+
ERROR: function return row and query-specified return row do not match
1390+
DETAIL: Returned row contains 1 attribute, but query expects 2.
1391+
select * from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1392+
ERROR: function return row and query-specified return row do not match
1393+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
1394+
select * from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1395+
ERROR: function return row and query-specified return row do not match
1396+
DETAIL: Returned row contains 3 attributes, but query expects 2.
1397+
select * from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
1398+
ERROR: function return row and query-specified return row do not match
1399+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
13871400
--json_typeof() function
13881401
select value, json_typeof(value)
13891402
from (values (json '123.4'),

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

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

1747+
-- negative cases where the wrong record type is supplied
1748+
select * from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1749+
ERROR: function return row and query-specified return row do not match
1750+
DETAIL: Returned row contains 1 attribute, but query expects 2.
1751+
select * from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1752+
ERROR: function return row and query-specified return row do not match
1753+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
1754+
select * from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1755+
ERROR: function return row and query-specified return row do not match
1756+
DETAIL: Returned row contains 3 attributes, but query expects 2.
1757+
select * from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
1758+
ERROR: function return row and query-specified return row do not match
1759+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
17471760
-- jsonb_to_record and jsonb_to_recordset
17481761
select * from jsonb_to_record('{"a":1,"b":"foo","c":"bar"}')
17491762
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
@@ -394,6 +394,12 @@ select * from json_populate_recordset(null::jpop,'[{"a":"blurfl","x":43.2},{"b":
394394
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;
395395
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;
396396

397+
-- negative cases where the wrong record type is supplied
398+
select*from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
399+
select*from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
400+
select*from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
401+
select*from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);
402+
397403
--json_typeof() function
398404
select value, json_typeof(value)
399405
from (values (json'123.4'),

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b
364364
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;
365365
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;
366366

367+
-- negative cases where the wrong record type is supplied
368+
select*from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
369+
select*from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
370+
select*from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
371+
select*from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);
372+
367373
-- jsonb_to_record and jsonb_to_recordset
368374

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp