postgres.git / summary / log / commit / refs
commit bc5775149f59cc6d80c2a5ceb410bba473a12407
Author: Michael Paquier <michael@paquier.xyz>
Date: Thu Jun 11 05:29:28 2026 +0000
xml2: Fix crash with namespace nodes in xpath_nodeset()
pgxmlNodeSetToText() passed nodeTab[i]->doc to xmlNodeDump() without
checking the node type, which could cause a crash as a
XML_NAMESPACE_DECL maps to a xmlNs struct. The passed-in code would
then be dereferenced in xmlNodeDump().
This commit switches the code to render XML_NAMESPACE_DECL nodes with
xmlXPathCastNodeToString(), like xpath_table(). Some tests are added,
written by me.
Author: Andrey Chernyy <andrey.cherny@tantorlabs.com>
Co-authored-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/20260611031436.5afde3cb@andrnote
Backpatch-through: 14
contrib/xml2/expected/xml2.out | 8 ++++++++
contrib/xml2/expected/xml2_1.out | 8 ++++++++
contrib/xml2/sql/xml2.sql | 4 ++++
contrib/xml2/xpath.c | 15 +++++++++++----
4 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/contrib/xml2/expected/xml2.out b/contrib/xml2/expected/xml2.out
index 3027e4df868..b802599decc 100644
--- a/contrib/xml2/expected/xml2.out
+++ b/contrib/xml2/expected/xml2.out
@@ -207,6 +207,14 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
(1 row)
+-- xpath_nodeset() with namespace node
+SELECT xpath_nodeset('<root xmlns:foo="http://icl.com/saxon"/>',
+ '//namespace::foo');
+ xpath_nodeset
+----------------------
+ http://icl.com/saxon
+(1 row)
+
-- possible security exploit
SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>',
$$<xsl:stylesheet version="1.0"
diff --git a/contrib/xml2/expected/xml2_1.out b/contrib/xml2/expected/xml2_1.out
index ed3e399aa31..7b046cf28b3 100644
--- a/contrib/xml2/expected/xml2_1.out
+++ b/contrib/xml2/expected/xml2_1.out
@@ -151,6 +151,14 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
</xsl:template>
</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
ERROR: xslt_process() is not available without libxslt
+-- xpath_nodeset() with namespace node
+SELECT xpath_nodeset('<root xmlns:foo="http://icl.com/saxon"/>',
+ '//namespace::foo');
+ xpath_nodeset
+----------------------
+ http://icl.com/saxon
+(1 row)
+
-- possible security exploit
SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>',
$$<xsl:stylesheet version="1.0"
diff --git a/contrib/xml2/sql/xml2.sql b/contrib/xml2/sql/xml2.sql
index c7fe0c102da..254fae01f51 100644
--- a/contrib/xml2/sql/xml2.sql
+++ b/contrib/xml2/sql/xml2.sql
@@ -123,6 +123,10 @@ SELECT xslt_process('<employee><name>cim</name><age>30</age><pay>400</pay></empl
</xsl:template>
</xsl:stylesheet>$$::text, 'n1="v1",n2="v2",n3="v3",n4="v4",n5="v5",n6="v6",n7="v7",n8="v8",n9="v9",n10="v10",n11="v11",n12="v12"'::text);
+-- xpath_nodeset() with namespace node
+SELECT xpath_nodeset('<root xmlns:foo="http://icl.com/saxon"/>',
+ '//namespace::foo');
+
-- possible security exploit
SELECT xslt_process('<xml><foo>Hello from XML</foo></xml>',
$$<xsl:stylesheet version="1.0"
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 94bb31434c8..1ac15e5e1b0 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -147,16 +147,23 @@ pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
}
else
{
+ xmlNodePtr node = nodeset->nodeTab[i];
+
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
{
xmlBufferWriteChar(buf, "<");
xmlBufferWriteCHAR(buf, septagname);
xmlBufferWriteChar(buf, ">");
}
- xmlNodeDump(buf,
- nodeset->nodeTab[i]->doc,
- nodeset->nodeTab[i],
- 1, 0);
+
+ /*
+ * XML_NAMESPACE_DECL nodes are xmlNs structs, that cannot
+ * be processed by xmlNodeDump().
+ */
+ if (node->type == XML_NAMESPACE_DECL)
+ xmlBufferWriteCHAR(buf, xmlXPathCastNodeToString(node));
+ else
+ xmlNodeDump(buf, node->doc, node, 1, 0);
if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
{
[parent: a7e0e42a226d]