Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0fbf011

Browse files
committed
Check column list length in XMLTABLE/JSON_TABLE alias
We weren't checking the length of the column list in the alias clause of an XMLTABLE or JSON_TABLE function (a "tablefunc" RTE), and it was possible to make the server crash by passing an overly long one. Fix it by throwing an error in that case, like the other places that deal with alias lists. In passing, modify the equivalent test used for join RTEs to look like the other ones, which was different for no apparent reason. This bug came in when XMLTABLE was born in version 10; backpatch to all stable versions. Reported-by: Wang Ke <krking@zju.edu.cn> Discussion: https://postgr.es/m/17480-1c9d73565bb28e90@postgresql.org
1 parent 598ac10 commit 0fbf011

File tree

12 files changed

+49
-17
lines changed

12 files changed

+49
-17
lines changed

src/backend/parser/parse_clause.c

-15
Original file line numberDiff line numberDiff line change
@@ -1444,21 +1444,6 @@ transformFromClauseItem(ParseState *pstate, Node *n,
14441444
&res_colnames, &res_colvars,
14451445
res_nscolumns + res_colindex);
14461446

1447-
/*
1448-
* Check alias (AS clause), if any.
1449-
*/
1450-
if (j->alias)
1451-
{
1452-
if (j->alias->colnames != NIL)
1453-
{
1454-
if (list_length(j->alias->colnames) > list_length(res_colnames))
1455-
ereport(ERROR,
1456-
(errcode(ERRCODE_SYNTAX_ERROR),
1457-
errmsg("column alias list for \"%s\" has too many entries",
1458-
j->alias->aliasname)));
1459-
}
1460-
}
1461-
14621447
/*
14631448
* Now build an RTE and nsitem for the result of the join.
14641449
* res_nscolumns isn't totally done yet, but that's OK because

src/backend/parser/parse_relation.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -1989,11 +1989,13 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
19891989
bool inFromCl)
19901990
{
19911991
RangeTblEntry *rte = makeNode(RangeTblEntry);
1992-
char *refname = alias ? alias->aliasname :
1993-
pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table");
1992+
char *refname;
19941993
Alias *eref;
19951994
int numaliases;
19961995

1996+
refname = alias ? alias->aliasname :
1997+
pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table");
1998+
19971999
Assert(pstate != NULL);
19982000

19992001
rte->rtekind = RTE_TABLEFUNC;
@@ -2013,6 +2015,13 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
20132015
eref->colnames = list_concat(eref->colnames,
20142016
list_copy_tail(tf->colnames, numaliases));
20152017

2018+
if (numaliases > list_length(tf->colnames))
2019+
ereport(ERROR,
2020+
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2021+
errmsg("%s function has %d columns available but %d columns specified",
2022+
tf->functype == TFT_XMLTABLE ? "XMLTABLE" : "JSON_TABLE",
2023+
list_length(tf->colnames), numaliases)));
2024+
20162025
rte->eref = eref;
20172026

20182027
/*
@@ -2192,6 +2201,12 @@ addRangeTableEntryForJoin(ParseState *pstate,
21922201
eref->colnames = list_concat(eref->colnames,
21932202
list_copy_tail(colnames, numaliases));
21942203

2204+
if (numaliases > list_length(colnames))
2205+
ereport(ERROR,
2206+
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2207+
errmsg("join expression \"%s\" has %d columns available but %d columns specified",
2208+
eref->aliasname, list_length(colnames), numaliases)));
2209+
21952210
rte->eref = eref;
21962211

21972212
/*

src/test/regress/expected/int2.out

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ SELECT * FROM INT2_TBL;
4545
-32767
4646
(5 rows)
4747

48+
SELECT * FROM INT2_TBL AS f(a, b);
49+
ERROR: table "f" has 1 columns available but 2 columns specified
50+
SELECT * FROM (TABLE int2_tbl) AS s (a, b);
51+
ERROR: table "s" has 1 columns available but 2 columns specified
4852
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0';
4953
f1
5054
--------

src/test/regress/expected/join.out

+3
Original file line numberDiff line numberDiff line change
@@ -5872,6 +5872,9 @@ select * from
58725872
3 | 3
58735873
(6 rows)
58745874

5875+
-- check the number of columns specified
5876+
SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d);
5877+
ERROR: join expression "ss" has 3 columns available but 4 columns specified
58755878
-- check we don't try to do a unique-ified semijoin with LATERAL
58765879
explain (verbose, costs off)
58775880
select * from

src/test/regress/expected/jsonb_sqljson.out

+2
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,8 @@ SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
10311031
ERROR: syntax error at or near ")"
10321032
LINE 1: SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
10331033
^
1034+
SELECT * FROM JSON_TABLE (NULL::jsonb, '$' COLUMNS (v1 timestamp)) AS f (v1, v2);
1035+
ERROR: JSON_TABLE function has 1 columns available but 2 columns specified
10341036
-- NULL => empty table
10351037
SELECT * FROM JSON_TABLE(NULL::jsonb, '$' COLUMNS (foo int)) bar;
10361038
foo

src/test/regress/expected/with.out

+5
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,11 @@ DROP TABLE y;
17941794
--
17951795
-- error cases
17961796
--
1797+
WITH x(n, b) AS (SELECT 1)
1798+
SELECT * FROM x;
1799+
ERROR: WITH query "x" has 1 columns available but 2 columns specified
1800+
LINE 1: WITH x(n, b) AS (SELECT 1)
1801+
^
17971802
-- INTERSECT
17981803
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
17991804
SELECT * FROM x;

src/test/regress/expected/xml.out

+3
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,9 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
11451145
Table Function Call: XMLTABLE(('/ROWS/ROW'::text) PASSING (xmldata.data) COLUMNS id integer PATH ('@id'::text), _id FOR ORDINALITY, country_name text PATH ('COUNTRY_NAME/text()'::text) NOT NULL, country_id text PATH ('COUNTRY_ID'::text), region_id integer PATH ('REGION_ID'::text), size double precision PATH ('SIZE'::text), unit text PATH ('SIZE/@unit'::text), premier_name text DEFAULT ('not specified'::text) PATH ('PREMIER_NAME'::text))
11461146
(7 rows)
11471147

1148+
-- errors
1149+
SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2);
1150+
ERROR: XMLTABLE function has 1 columns available but 2 columns specified
11481151
-- XMLNAMESPACES tests
11491152
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
11501153
'/zz:rows/zz:row'

src/test/regress/sql/int2.sql

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ INSERT INTO INT2_TBL(f1) VALUES ('');
1717

1818
SELECT * FROM INT2_TBL;
1919

20+
SELECT * FROM INT2_TBL AS f(a, b);
21+
22+
SELECT * FROM (TABLE int2_tbl) AS s (a, b);
23+
2024
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0';
2125

2226
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int4 '0';

src/test/regress/sql/join.sql

+3
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,9 @@ select * from
19851985
(select q1.v)
19861986
) as q2;
19871987

1988+
-- check the number of columns specified
1989+
SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d);
1990+
19881991
-- check we don't try to do a unique-ified semijoin with LATERAL
19891992
explain (verbose, costs off)
19901993
select * from

src/test/regress/sql/jsonb_sqljson.sql

+2
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@ SELECT JSON_TABLE('[]', '$');
328328
-- Should fail (no columns)
329329
SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
330330

331+
SELECT * FROM JSON_TABLE (NULL::jsonb, '$' COLUMNS (v1 timestamp)) AS f (v1, v2);
332+
331333
-- NULL => empty table
332334
SELECT * FROM JSON_TABLE(NULL::jsonb, '$' COLUMNS (foo int)) bar;
333335

src/test/regress/sql/with.sql

+3
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,9 @@ DROP TABLE y;
803803
-- error cases
804804
--
805805

806+
WITH x(n, b) AS (SELECT 1)
807+
SELECT * FROM x;
808+
806809
-- INTERSECT
807810
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
808811
SELECT * FROM x;

src/test/regress/sql/xml.sql

+3
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ SELECT * FROM xmltableview1;
384384
EXPLAIN (COSTS OFF) SELECT * FROM xmltableview1;
385385
EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
386386

387+
-- errors
388+
SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2);
389+
387390
-- XMLNAMESPACES tests
388391
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
389392
'/zz:rows/zz:row'

0 commit comments

Comments
 (0)