From 075d59e29cd4a1fd5595bb4fb2596f40e5a12569 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 11 Jun 2026 10:45:10 +0900 Subject: [PATCH v2] xml2: don't crash on namespace nodes in xpath_nodeset() pgxmlNodeSetToText() passed nodeTab[i]->doc to xmlNodeDump() without checking the node type. Namespace-axis results are XML_NAMESPACE_DECL nodes (xmlNs structs cast to xmlNodePtr) whose ->doc field is out of bounds, so xmlNodeDump() dereferenced a bogus pointer and crashed the backend. Render such nodes with xmlXPathCastNodeToString() instead, as xpath_table() already does. --- src/backend/utils/adt/xml.c | 3 ++- contrib/xml2/xpath.c | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 2c7f778cfdb7..a50992876cd6 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -4199,7 +4199,8 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt) { xmltype *result = NULL; - if (cur->type != XML_ATTRIBUTE_NODE && cur->type != XML_TEXT_NODE) + if (cur->type != XML_ATTRIBUTE_NODE && cur->type != XML_TEXT_NODE && + cur->type != XML_NAMESPACE_DECL) { void (*volatile nodefree) (xmlNodePtr) = NULL; volatile xmlBufferPtr buf = NULL; diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c index 283bb51178d1..25a1cc47577a 100644 --- a/contrib/xml2/xpath.c +++ b/contrib/xml2/xpath.c @@ -188,16 +188,27 @@ 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); + + if (node->type == XML_NAMESPACE_DECL) + { + str = xmlXPathCastNodeToString(node); + if (str == NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate node text"); + xmlBufferWriteCHAR(buf, str); + xmlFree(str); + str = NULL; + } + else + xmlNodeDump(buf, node->doc, node, 1, 0); if ((septagname != NULL) && (xmlStrlen(septagname) > 0)) { -- 2.54.0