From 0450bf625da1ff00ebf9f581bc9e4351edcc668a Mon Sep 17 00:00:00 2001
From: Andrey Chernyy <andrey.cherny@tantorlabs.com>
Date: Thu, 11 Jun 2026 02:24:40 +0300
Subject: [PATCH] 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.
---
 contrib/xml2/xpath.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 283bb51178d..25a1cc47577 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

