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

Commitc0c8807

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 parentb500297 commitc0c8807

File tree

3 files changed

+55
-21
lines changed

3 files changed

+55
-21
lines changed

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

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,19 +1601,47 @@ json_populate_recordset(PG_FUNCTION_ARGS)
16011601
errmsg("set-valued function called in context that "
16021602
"cannot accept a set")));
16031603

1604-
16051604
rsi->returnMode=SFRM_Materialize;
16061605

1607-
/*
1608-
* get the tupdesc from the result set info - it must be a record type
1609-
* because we already checked that arg1 is a record type.
1610-
*/
1611-
(void)get_call_result_type(fcinfo,NULL,&tupdesc);
1606+
/* if the json is null send back an empty set */
1607+
if (PG_ARGISNULL(1))
1608+
PG_RETURN_NULL();
1609+
1610+
json=PG_GETARG_TEXT_P(1);
1611+
1612+
if (PG_ARGISNULL(0))
1613+
{
1614+
rec=NULL;
1615+
1616+
/*
1617+
* get the tupdesc from the result set info - it must be a record type
1618+
* because we already checked that arg1 is a record type
1619+
*/
1620+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
1621+
ereport(ERROR,
1622+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1623+
errmsg("function returning record called in context "
1624+
"that cannot accept type record")));
1625+
}
1626+
else
1627+
{
1628+
rec=PG_GETARG_HEAPTUPLEHEADER(0);
1629+
1630+
/*
1631+
* use the input record's own type marking to find a tupdesc for it.
1632+
*/
1633+
tupType=HeapTupleHeaderGetTypeId(rec);
1634+
tupTypmod=HeapTupleHeaderGetTypMod(rec);
1635+
tupdesc=lookup_rowtype_tupdesc(tupType,tupTypmod);
1636+
}
1637+
1638+
tupType=tupdesc->tdtypeid;
1639+
tupTypmod=tupdesc->tdtypmod;
1640+
ncolumns=tupdesc->natts;
16121641

16131642
state=palloc0(sizeof(PopulateRecordsetState));
16141643
sem=palloc0(sizeof(JsonSemAction));
16151644

1616-
16171645
/* make these in a sufficiently long-lived memory context */
16181646
old_cxt=MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
16191647

@@ -1625,20 +1653,8 @@ json_populate_recordset(PG_FUNCTION_ARGS)
16251653

16261654
MemoryContextSwitchTo(old_cxt);
16271655

1628-
/* if the json is null send back an empty set */
1629-
if (PG_ARGISNULL(1))
1630-
PG_RETURN_NULL();
1631-
1632-
json=PG_GETARG_TEXT_P(1);
1633-
1634-
if (PG_ARGISNULL(0))
1635-
rec=NULL;
1636-
else
1637-
rec=PG_GETARG_HEAPTUPLEHEADER(0);
1638-
1639-
tupType=tupdesc->tdtypeid;
1640-
tupTypmod=tupdesc->tdtypmod;
1641-
ncolumns=tupdesc->natts;
1656+
/* unnecessary, but harmless, if tupdesc came from get_call_result_type: */
1657+
ReleaseTupleDesc(tupdesc);
16421658

16431659
lex=makeJsonLexContext(json, true);
16441660

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,3 +907,16 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,3
907907
ERROR: cannot call json_populate_recordset on a nested object
908908
select * from json_populate_recordset(row('def',99,null)::jpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
909909
ERROR: cannot call json_populate_recordset on a nested object
910+
-- negative cases where the wrong record type is supplied
911+
select * from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
912+
ERROR: function return row and query-specified return row do not match
913+
DETAIL: Returned row contains 1 attribute, but query expects 2.
914+
select * from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
915+
ERROR: function return row and query-specified return row do not match
916+
DETAIL: Returned type integer at ordinal position 1, but query expects text.
917+
select * from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
918+
ERROR: function return row and query-specified return row do not match
919+
DETAIL: Returned row contains 3 attributes, but query expects 2.
920+
select * from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
921+
ERROR: function return row and query-specified return row do not match
922+
DETAIL: Returned type integer at ordinal position 1, but query expects text.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,8 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":"blurfl","
302302
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;
303303
select*from json_populate_recordset(row('def',99,null)::jpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
304304

305+
-- negative cases where the wrong record type is supplied
306+
select*from json_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
307+
select*from json_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
308+
select*from json_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (atext, btext);
309+
select*from json_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (atext, btext);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp