Skip to content

Commit 9bf2476

Browse files
committed
Avoid failure when selecting a namespace node in XMLTABLE.
It appears that libxml2 doesn't bother to set the "children" field of an XML_NAMESPACE_DECL node to null; that field just contains garbage. In v10 and v11, this can result in a crash in XMLTABLE(). The rewrite done in commit 251cf2e fixed this, somewhat accidentally, in v12. We're not going to back-patch 251cf2e, however. The case apparently doesn't have wide use, so rather than risk introducing other problems, just add a safety check to throw an error. Even though no bug manifests in v12/HEAD, add the relevant test case there too, to prevent future regressions. Chapman Flack (per private report)
1 parent 84d1c5c commit 9bf2476

File tree

5 files changed

+26
-1
lines changed

5 files changed

+26
-1
lines changed

src/backend/utils/adt/xml.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4608,14 +4608,19 @@ XmlTableGetValue(TableFuncScanState *state, int colnum,
46084608
xmlChar *str;
46094609
xmlNodePtr node;
46104610

4611+
node = xpathobj->nodesetval->nodeTab[0];
4612+
if (node->type == XML_NAMESPACE_DECL)
4613+
ereport(ERROR,
4614+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4615+
errmsg("XMLTABLE cannot cast a namespace node to a non-XML result type")));
4616+
46114617
/*
46124618
* Most nodes (elements and even attributes) store their data
46134619
* in children nodes. If they don't have children nodes, it
46144620
* means that they are empty (e.g. <element/>). Text nodes and
46154621
* CDATA sections are an exception: they don't have children
46164622
* but have content in the Text/CDATA node itself.
46174623
*/
4618-
node = xpathobj->nodesetval->nodeTab[0];
46194624
if (node->type != XML_CDATA_SECTION_NODE &&
46204625
node->type != XML_TEXT_NODE)
46214626
node = node->xmlChildrenNode;

src/test/regress/expected/xml.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,10 @@ SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'),
11671167
PASSING '<rows xmlns="http://x.y"><row><a>10</a></row></rows>'
11681168
COLUMNS a int PATH 'a');
11691169
ERROR: DEFAULT namespace is not supported
1170+
SELECT * FROM XMLTABLE('/'
1171+
PASSING '<foo/>'
1172+
COLUMNS a text PATH 'foo/namespace::node()');
1173+
ERROR: XMLTABLE cannot cast a namespace node to a non-XML result type
11701174
-- used in prepare statements
11711175
PREPARE pp AS
11721176
SELECT xmltable.*

src/test/regress/expected/xml_1.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,14 @@ LINE 3: PASSING '<rows xmlns="http://x.y"><row...
10421042
^
10431043
DETAIL: This functionality requires the server to be built with libxml support.
10441044
HINT: You need to rebuild PostgreSQL using --with-libxml.
1045+
SELECT * FROM XMLTABLE('/'
1046+
PASSING '<foo/>'
1047+
COLUMNS a text PATH 'foo/namespace::node()');
1048+
ERROR: unsupported XML feature
1049+
LINE 2: PASSING '<foo/>'
1050+
^
1051+
DETAIL: This functionality requires the server to be built with libxml support.
1052+
HINT: You need to rebuild PostgreSQL using --with-libxml.
10451053
-- used in prepare statements
10461054
PREPARE pp AS
10471055
SELECT xmltable.*

src/test/regress/expected/xml_2.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,10 @@ SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'),
11471147
PASSING '<rows xmlns="http://x.y"><row><a>10</a></row></rows>'
11481148
COLUMNS a int PATH 'a');
11491149
ERROR: DEFAULT namespace is not supported
1150+
SELECT * FROM XMLTABLE('/'
1151+
PASSING '<foo/>'
1152+
COLUMNS a text PATH 'foo/namespace::node()');
1153+
ERROR: XMLTABLE cannot cast a namespace node to a non-XML result type
11501154
-- used in prepare statements
11511155
PREPARE pp AS
11521156
SELECT xmltable.*

src/test/regress/sql/xml.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,10 @@ SELECT * FROM XMLTABLE(XMLNAMESPACES(DEFAULT 'http://x.y'),
401401
PASSING '<rows xmlns="http://x.y"><row><a>10</a></row></rows>'
402402
COLUMNS a int PATH 'a');
403403

404+
SELECT * FROM XMLTABLE('/'
405+
PASSING '<foo/>'
406+
COLUMNS a text PATH 'foo/namespace::node()');
407+
404408
-- used in prepare statements
405409
PREPARE pp AS
406410
SELECT xmltable.*

0 commit comments

Comments
 (0)