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]