]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
xml2: Fix crash with namespace nodes in xpath_nodeset()
authorMichael Paquier <michael@paquier.xyz>
Thu, 11 Jun 2026 05:29:29 +0000 (14:29 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 11 Jun 2026 05:29:29 +0000 (14:29 +0900)
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
contrib/xml2/expected/xml2_1.out
contrib/xml2/sql/xml2.sql
contrib/xml2/xpath.c

index 3027e4df868d83a77aabfe3e2d935f361b74a0b6..b802599decc80cab5151c409ece58a0141f093a4 100644 (file)
@@ -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"
index ed3e399aa317597afb0f3dce8c7f2cf4a602040a..7b046cf28b3f85683a2d161ad306407a5a2a5a61 100644 (file)
@@ -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"
index c7fe0c102dab616a8dbf8809b05fd9e429d99257..254fae01f51fa710096070f10fb31c2bf9262fdb 100644 (file)
@@ -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"
index 48cd7032178a623a2711bd0ed33e6980a29b902f..548ad94ffd5adbe2df373e4d4b0d42d56088d82e 100644 (file)
@@ -193,16 +193,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))
                                {