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

Commit38e8256

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 parentb7d6f75 commit38e8256

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
@@ -2696,26 +2696,37 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
26962696

26972697
rsi->returnMode=SFRM_Materialize;
26982698

2699-
/*
2700-
* get the tupdesc from the result set info - it must be a record type
2701-
* because we already checked that arg1 is a record type, or we're in a
2702-
* to_record function which returns a setof record.
2703-
*/
2704-
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
2705-
ereport(ERROR,
2706-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2707-
errmsg("function returning record called in context "
2708-
"that cannot accept type record")));
2709-
27102699
/* if the json is null send back an empty set */
27112700
if (PG_ARGISNULL(json_arg_num))
27122701
PG_RETURN_NULL();
27132702

27142703
if (!have_record_arg||PG_ARGISNULL(0))
2704+
{
27152705
rec=NULL;
2706+
2707+
/*
2708+
* get the tupdesc from the result set info - it must be a record type
2709+
* because we already checked that arg1 is a record type, or we're in
2710+
* a to_record function which returns a setof record.
2711+
*/
2712+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
2713+
ereport(ERROR,
2714+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2715+
errmsg("function returning record called in context "
2716+
"that cannot accept type record")));
2717+
}
27162718
else
2719+
{
27172720
rec=PG_GETARG_HEAPTUPLEHEADER(0);
27182721

2722+
/*
2723+
* use the input record's own type marking to find a tupdesc for it.
2724+
*/
2725+
tupType=HeapTupleHeaderGetTypeId(rec);
2726+
tupTypmod=HeapTupleHeaderGetTypMod(rec);
2727+
tupdesc=lookup_rowtype_tupdesc(tupType,tupTypmod);
2728+
}
2729+
27192730
tupType=tupdesc->tdtypeid;
27202731
tupTypmod=tupdesc->tdtypmod;
27212732
ncolumns=tupdesc->natts;
@@ -2759,6 +2770,9 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
27592770
false,work_mem);
27602771
MemoryContextSwitchTo(old_cxt);
27612772

2773+
/* unnecessary, but harmless, if tupdesc came from get_call_result_type: */
2774+
ReleaseTupleDesc(tupdesc);
2775+
27622776
state->function_name=funcname;
27632777
state->my_extra=my_extra;
27642778
state->rec=rec;

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

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

1411+
-- negative cases where the wrong record type is supplied
1412+
select * from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1413+
ERROR: function return row and query-specified return row do not match
1414+
DETAIL: Returned row contains 1 attribute, but query expects 2.
1415+
select * from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1416+
ERROR: function return row and query-specified return row do not match
1417+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
1418+
select * from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
1419+
ERROR: function return row and query-specified return row do not match
1420+
DETAIL: Returned row contains 3 attributes, but query expects 2.
1421+
select * from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
1422+
ERROR: function return row and query-specified return row do not match
1423+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
14111424
--json_typeof() function
14121425
select value, json_typeof(value)
14131426
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
@@ -2090,6 +2090,19 @@ SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200
20902090
{"z": true} | 3 | Fri Jan 20 10:42:53 2012
20912091
(2 rows)
20922092

2093+
-- negative cases where the wrong record type is supplied
2094+
select * from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
2095+
ERROR: function return row and query-specified return row do not match
2096+
DETAIL: Returned row contains 1 attribute, but query expects 2.
2097+
select * from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
2098+
ERROR: function return row and query-specified return row do not match
2099+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
2100+
select * from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
2101+
ERROR: function return row and query-specified return row do not match
2102+
DETAIL: Returned row contains 3 attributes, but query expects 2.
2103+
select * from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
2104+
ERROR: function return row and query-specified return row do not match
2105+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
20932106
-- jsonb_to_record and jsonb_to_recordset
20942107
select * from jsonb_to_record('{"a":1,"b":"foo","c":"bar"}')
20952108
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
@@ -404,6 +404,12 @@ select * from json_populate_recordset(null::jpop,'[{"a":"blurfl","x":43.2},{"b":
404404
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;
405405
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;
406406

407+
-- negative cases where the wrong record type is supplied
408+
select*from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
409+
select*from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
410+
select*from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
411+
select*from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);
412+
407413
--json_typeof() function
408414
select value, json_typeof(value)
409415
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
@@ -520,6 +520,12 @@ SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b
520520
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;
521521
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;
522522

523+
-- negative cases where the wrong record type is supplied
524+
select*from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
525+
select*from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
526+
select*from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
527+
select*from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);
528+
523529
-- jsonb_to_record and jsonb_to_recordset
524530

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp