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

Commitd5fe5fb

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 parented546dd commitd5fe5fb

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

26962696
rsi->returnMode=SFRM_Materialize;
26972697

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

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

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

2772+
/* unnecessary, but harmless, if tupdesc came from get_call_result_type: */
2773+
ReleaseTupleDesc(tupdesc);
2774+
27612775
state->function_name=funcname;
27622776
state->my_extra=my_extra;
27632777
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