summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Guo <rguo@postgresql.org>2025-05-15 17:09:04 +0900
committerRichard Guo <rguo@postgresql.org>2025-05-15 17:26:13 +0900
commit666103090f1d18e26388aef1ee5840d86cb8604b (patch)
tree2983b3d9c0f04ac079d003bdceabd8b9c0f73fad /src
parent7f1da18d679e125eb454ce31fdd2b69d4da32d68 (diff)
Fix Assert failure in XMLTABLE parser
In an XMLTABLE expression, columns can be marked NOT NULL, and the parser internally fabricates an option named "is_not_null" to represent this. However, the parser also allows users to specify arbitrary option names. This creates a conflict: a user can explicitly use "is_not_null" as an option name and assign it a non-Boolean value, which violates internal assumptions and triggers an assertion failure. To fix, this patch checks whether a user-supplied name collides with the internally reserved option name and raises an error if so. Additionally, the internal name is renamed to "__pg__is_not_null" to further reduce the risk of collision with user-defined names. Reported-by: Евгений Горбанев <gorbanyoves@basealt.ru> Author: Richard Guo <guofenglinux@gmail.com> Reviewed-by: Alvaro Herrera <alvherre@kurilemu.de> Discussion: https://postgr.es/m/6bac9886-65bf-4cec-96bd-e304159f28db@basealt.ru Backpatch-through: 15
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/gram.y15
-rw-r--r--src/test/regress/expected/xml.out4
-rw-r--r--src/test/regress/expected/xml_1.out4
-rw-r--r--src/test/regress/expected/xml_2.out4
-rw-r--r--src/test/regress/sql/xml.sql2
5 files changed, 25 insertions, 4 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8379e48c97b..c77060c2cea 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -13820,7 +13820,7 @@ xmltable_column_el:
parser_errposition(defel->location)));
fc->colexpr = defel->arg;
}
- else if (strcmp(defel->defname, "is_not_null") == 0)
+ else if (strcmp(defel->defname, "__pg__is_not_null") == 0)
{
if (nullability_seen)
ereport(ERROR,
@@ -13863,13 +13863,20 @@ xmltable_column_option_list:
xmltable_column_option_el:
IDENT b_expr
- { $$ = makeDefElem($1, $2, @1); }
+ {
+ if (strcmp($1, "__pg__is_not_null") == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("option name \"%s\" cannot be used in XMLTABLE", $1),
+ parser_errposition(@1)));
+ $$ = makeDefElem($1, $2, @1);
+ }
| DEFAULT b_expr
{ $$ = makeDefElem("default", $2, @1); }
| NOT NULL_P
- { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); }
+ { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(true), @1); }
| NULL_P
- { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); }
+ { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(false), @1); }
;
xml_namespace_list:
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index f9b7ec0bab8..79054b75311 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -1139,6 +1139,10 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
-- 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
+SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1);
+ERROR: option name "__pg__is_not_null" cannot be used in XMLTABLE
+LINE 1: ...MLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_n...
+ ^
-- XMLNAMESPACES tests
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
'/zz:rows/zz:row'
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index 5b28ea01eea..abf27626a21 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -876,6 +876,10 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
-- 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
+SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1);
+ERROR: option name "__pg__is_not_null" cannot be used in XMLTABLE
+LINE 1: ...MLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_n...
+ ^
-- XMLNAMESPACES tests
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
'/zz:rows/zz:row'
diff --git a/src/test/regress/expected/xml_2.out b/src/test/regress/expected/xml_2.out
index 044a4917d86..23e0c14a2d2 100644
--- a/src/test/regress/expected/xml_2.out
+++ b/src/test/regress/expected/xml_2.out
@@ -1125,6 +1125,10 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
-- 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
+SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1);
+ERROR: option name "__pg__is_not_null" cannot be used in XMLTABLE
+LINE 1: ...MLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_n...
+ ^
-- XMLNAMESPACES tests
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
'/zz:rows/zz:row'
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index e908b6c3957..83c5b73d8d3 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -387,6 +387,8 @@ EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM xmltableview1;
-- errors
SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp) AS f (v1, v2);
+SELECT * FROM XMLTABLE (ROW () PASSING null COLUMNS v1 timestamp __pg__is_not_null 1) AS f (v1);
+
-- XMLNAMESPACES tests
SELECT * FROM XMLTABLE(XMLNAMESPACES('http://x.y' AS zz),
'/zz:rows/zz:row'