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
This commit is contained in:
Michael Paquier 2026-06-11 14:29:22 +09:00
parent beb09e9117
commit 91b57eadeb
4 changed files with 30 additions and 4 deletions

View file

@ -231,6 +231,14 @@ SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages',
<result><item><author>test</author></item><item><pages>37</pages></item></result>
(1 row)
-- namespace node
SELECT xpath_nodeset('<root xmlns:foo="http://icl.com/saxon"/>',
'//namespace::foo');
xpath_nodeset
----------------------
http://icl.com/saxon
(1 row)
-- xpath_list()
SELECT xpath_list(article_xml::text, '/article/author|/article/pages')
FROM articles;

View file

@ -175,6 +175,14 @@ SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages',
<result><item><author>test</author></item><item><pages>37</pages></item></result>
(1 row)
-- namespace node
SELECT xpath_nodeset('<root xmlns:foo="http://icl.com/saxon"/>',
'//namespace::foo');
xpath_nodeset
----------------------
http://icl.com/saxon
(1 row)
-- xpath_list()
SELECT xpath_list(article_xml::text, '/article/author|/article/pages')
FROM articles;

View file

@ -132,6 +132,9 @@ SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages',
SELECT xpath_nodeset(article_xml::text, '/article/author|/article/pages',
'result', 'item')
FROM articles;
-- namespace node
SELECT xpath_nodeset('<root xmlns:foo="http://icl.com/saxon"/>',
'//namespace::foo');
-- xpath_list()
SELECT xpath_list(article_xml::text, '/article/author|/article/pages')

View file

@ -149,16 +149,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))
{