aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-05-18 20:28:31 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-05-18 20:28:31 +0200
commit94edb85d253e5ae066481e4e369ad9e35dea41b5 (patch)
tree54424c6053dbfdf5b0cad3001028bbd4c0c613e9
parent23c2b76a8322233ce0b2c135c10ad52d48a4a22b (diff)
downloadpostgresql-94edb85d253e5ae066481e4e369ad9e35dea41b5.tar.gz
postgresql-94edb85d253e5ae066481e4e369ad9e35dea41b5.zip
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
-rw-r--r--src/backend/parser/parse_clause.c15
-rw-r--r--src/backend/parser/parse_relation.c12
-rw-r--r--src/test/regress/expected/int2.out4
-rw-r--r--src/test/regress/expected/join.out3
-rw-r--r--src/test/regress/expected/with.out5
-rw-r--r--src/test/regress/expected/xml.out3
-rw-r--r--src/test/regress/sql/int2.sql4
-rw-r--r--src/test/regress/sql/join.sql3
-rw-r--r--src/test/regress/sql/with.sql3
-rw-r--r--src/test/regress/sql/xml.sql3
10 files changed, 40 insertions, 15 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 71c360bea58..2763af9470e 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -1439,21 +1439,6 @@ transformFromClauseItem(ParseState *pstate, Node *n,
res_nscolumns + res_colindex);
/*
- * Check alias (AS clause), if any.
- */
- if (j->alias)
- {
- if (j->alias->colnames != NIL)
- {
- if (list_length(j->alias->colnames) > list_length(res_colnames))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("column alias list for \"%s\" has too many entries",
- j->alias->aliasname)));
- }
- }
-
- /*
* Now build an RTE and nsitem for the result of the join.
* res_nscolumns isn't totally done yet, but that's OK because
* addRangeTableEntryForJoin doesn't examine it, only store a pointer.
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 74659190447..863cddad10b 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -2001,6 +2001,12 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
eref->colnames = list_concat(eref->colnames,
list_copy_tail(tf->colnames, numaliases));
+ if (numaliases > list_length(tf->colnames))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+ errmsg("%s function has %d columns available but %d columns specified",
+ "XMLTABLE", list_length(tf->colnames), numaliases)));
+
rte->eref = eref;
/*
@@ -2180,6 +2186,12 @@ addRangeTableEntryForJoin(ParseState *pstate,
eref->colnames = list_concat(eref->colnames,
list_copy_tail(colnames, numaliases));
+ if (numaliases > list_length(colnames))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+ errmsg("join expression \"%s\" has %d columns available but %d columns specified",
+ eref->aliasname, list_length(colnames), numaliases)));
+
rte->eref = eref;
/*
diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out
index 55ea7202cd3..8a64df725c6 100644
--- a/src/test/regress/expected/int2.out
+++ b/src/test/regress/expected/int2.out
@@ -51,6 +51,10 @@ SELECT * FROM INT2_TBL;
-32767
(5 rows)
+SELECT * FROM INT2_TBL AS f(a, b);
+ERROR: table "f" has 1 columns available but 2 columns specified
+SELECT * FROM (TABLE int2_tbl) AS s (a, b);
+ERROR: table "s" has 1 columns available but 2 columns specified
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0';
f1
--------
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 50b5b37b047..3cb1b383dc1 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -5870,6 +5870,9 @@ select * from
3 | 3
(6 rows)
+-- check the number of columns specified
+SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d);
+ERROR: join expression "ss" has 3 columns available but 4 columns specified
-- check we don't try to do a unique-ified semijoin with LATERAL
explain (verbose, costs off)
select * from
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index f435c9834bd..f24b4de9b4e 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -1763,6 +1763,11 @@ DROP TABLE y;
--
-- error cases
--
+WITH x(n, b) AS (SELECT 1)
+SELECT * FROM x;
+ERROR: WITH query "x" has 1 columns available but 2 columns specified
+LINE 1: WITH x(n, b) AS (SELECT 1)
+ ^
-- INTERSECT
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
SELECT * FROM x;
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index 55b65ef324d..55ac49be261 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -1145,6 +1145,9 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
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))
(7 rows)
+-- errors
+SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2);
+ERROR: XMLTABLE function has 1 columns available but 2 columns specified
-- XMLNAMESPACES tests
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
'/zz:rows/zz:row'
diff --git a/src/test/regress/sql/int2.sql b/src/test/regress/sql/int2.sql
index 613b344704c..2f5ea64e3b4 100644
--- a/src/test/regress/sql/int2.sql
+++ b/src/test/regress/sql/int2.sql
@@ -29,6 +29,10 @@ INSERT INTO INT2_TBL(f1) VALUES ('');
SELECT * FROM INT2_TBL;
+SELECT * FROM INT2_TBL AS f(a, b);
+
+SELECT * FROM (TABLE int2_tbl) AS s (a, b);
+
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0';
SELECT i.* FROM INT2_TBL i WHERE i.f1 <> int4 '0';
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 52240fea7e3..c451efa9589 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -1985,6 +1985,9 @@ select * from
(select q1.v)
) as q2;
+-- check the number of columns specified
+SELECT * FROM (int8_tbl i cross join int4_tbl j) ss(a,b,c,d);
+
-- check we don't try to do a unique-ified semijoin with LATERAL
explain (verbose, costs off)
select * from
diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql
index 254e9b1c444..97255e6b185 100644
--- a/src/test/regress/sql/with.sql
+++ b/src/test/regress/sql/with.sql
@@ -795,6 +795,9 @@ DROP TABLE y;
-- error cases
--
+WITH x(n, b) AS (SELECT 1)
+SELECT * FROM x;
+
-- INTERSECT
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
SELECT * FROM x;
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index f3f83c7827d..e3f90db4d56 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -384,6 +384,9 @@ SELECT * FROM xmltableview1;
EXPLAIN (COSTS OFF) SELECT * FROM xmltableview1;
EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
+-- errors
+SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2);
+
-- XMLNAMESPACES tests
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
'/zz:rows/zz:row'