Skip to content

Commit 94edb85

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 23c2b76 commit 94edb85

File tree

10 files changed

+40
-15
lines changed

10 files changed

+40
-15
lines changed

src/backend/parser/parse_clause.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,21 +1438,6 @@ transformFromClauseItem(ParseState *pstate, Node *n,
14381438
&res_colnames, &res_colvars,
14391439
res_nscolumns + res_colindex);
14401440

1441-
/*
1442-
* Check alias (AS clause), if any.
1443-
*/
1444-
if (j->alias)
1445-
{
1446-
if (j->alias->colnames != NIL)
1447-
{
1448-
if (list_length(j->alias->colnames) > list_length(res_colnames))
1449-
ereport(ERROR,
1450-
(errcode(ERRCODE_SYNTAX_ERROR),
1451-
errmsg("column alias list for \"%s\" has too many entries",
1452-
j->alias->aliasname)));
1453-
}
1454-
}
1455-
14561441
/*
14571442
* Now build an RTE and nsitem for the result of the join.
14581443
* res_nscolumns isn't totally done yet, but that's OK because

src/backend/parser/parse_relation.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,12 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
20012001
eref->colnames = list_concat(eref->colnames,
20022002
list_copy_tail(tf->colnames, numaliases));
20032003

2004+
if (numaliases > list_length(tf->colnames))
2005+
ereport(ERROR,
2006+
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2007+
errmsg("%s function has %d columns available but %d columns specified",
2008+
"XMLTABLE", list_length(tf->colnames), numaliases)));
2009+
20042010
rte->eref = eref;
20052011

20062012
/*
@@ -2180,6 +2186,12 @@ addRangeTableEntryForJoin(ParseState *pstate,
21802186
eref->colnames = list_concat(eref->colnames,
21812187
list_copy_tail(colnames, numaliases));
21822188

2189+
if (numaliases > list_length(colnames))
2190+
ereport(ERROR,
2191+
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2192+
errmsg("join expression \"%s\" has %d columns available but %d columns specified",
2193+
eref->aliasname, list_length(colnames), numaliases)));
2194+
21832195
rte->eref = eref;
21842196

21852197
/*

src/test/regress/expected/int2.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ SELECT * FROM INT2_TBL;
5151
-32767
5252
(5 rows)
5353

54+
SELECT * FROM INT2_TBL AS f(a, b);
55+
ERROR: table "f" has 1 columns available but 2 columns specified
56+
SELECT * FROM (TABLE int2_tbl) AS s (a, b);
57+
ERROR: table "s" has 1 columns available but 2 columns specified
5458
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0';
5559
f1
5660
--------

src/test/regress/expected/join.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5870,6 +5870,9 @@ select * from
58705870
3 | 3
58715871
(6 rows)
58725872

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

src/test/regress/expected/with.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,11 @@ DROP TABLE y;
17631763
--
17641764
-- error cases
17651765
--
1766+
WITH x(n, b) AS (SELECT 1)
1767+
SELECT * FROM x;
1768+
ERROR: WITH query "x" has 1 columns available but 2 columns specified
1769+
LINE 1: WITH x(n, b) AS (SELECT 1)
1770+
^
17661771
-- INTERSECT
17671772
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
17681773
SELECT * FROM x;

src/test/regress/expected/xml.out

Lines changed: 3 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ INSERT INTO INT2_TBL(f1) VALUES ('');
2929

3030
SELECT * FROM INT2_TBL;
3131

32+
SELECT * FROM INT2_TBL AS f(a, b);
33+
34+
SELECT * FROM (TABLE int2_tbl) AS s (a, b);
35+
3236
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0';
3337

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

src/test/regress/sql/join.sql

Lines changed: 3 additions & 0 deletions
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/with.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,9 @@ DROP TABLE y;
795795
-- error cases
796796
--
797797

798+
WITH x(n, b) AS (SELECT 1)
799+
SELECT * FROM x;
800+
798801
-- INTERSECT
799802
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
800803
SELECT * FROM x;

src/test/regress/sql/xml.sql

Lines changed: 3 additions & 0 deletions
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)