From bc5775149f59cc6d80c2a5ceb410bba473a12407 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 11 Jun 2026 14:29:28 +0900 Subject: [PATCH] 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 Co-authored-by: Michael Paquier 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('cim30400', + '//namespace::foo'); + xpath_nodeset +---------------------- + http://icl.com/saxon +(1 row) + -- possible security exploit SELECT xslt_process('Hello from XML', $$cim30400 $$::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('', + '//namespace::foo'); + xpath_nodeset +---------------------- + http://icl.com/saxon +(1 row) + -- possible security exploit SELECT xslt_process('Hello from XML', $$cim30400 $$::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('', + '//namespace::foo'); + -- possible security exploit SELECT xslt_process('Hello from XML', $$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)) {