xml-more-robust-handling-2.patch

text/x-patch

Filename: xml-more-robust-handling-2.patch
Type: text/x-patch
Part: 0
Message: Re: PostgreSQL vs SQL/XML Standards

Patch

Format: unified
File+
src/backend/utils/adt/xml.c 41 18
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 28b3eaaa20..41145e697a 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -3720,35 +3720,58 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt)
 
 	if (cur->type != XML_ATTRIBUTE_NODE && cur->type != XML_TEXT_NODE)
 	{
-		xmlBufferPtr buf;
-		xmlNodePtr	cur_copy;
+		volatile xmlBufferPtr buf = NULL;
+		volatile xmlNodePtr	cur_copy = NULL;
 
-		buf = xmlBufferCreate();
+		PG_TRY();
+		{
+			int		bytes;
 
-		/*
-		 * The result of xmlNodeDump() won't contain namespace definitions
-		 * from parent nodes, but xmlCopyNode() duplicates a node along with
-		 * its required namespace definitions.
-		 */
-		cur_copy = xmlCopyNode(cur, 1);
+			buf = xmlBufferCreate();
 
-		if (cur_copy == NULL)
-			xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
-						"could not copy node");
+			if (buf == NULL || xmlerrcxt->err_occurred)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not allocate xmlBuffer");
+
+			/*
+			 * The result of xmlNodeDump() won't contain namespace definitions
+			 * from parent nodes, but xmlCopyNode() duplicates a node along with
+			 * its required namespace definitions.
+			 *
+			 * Some older libxml2 like 2.7.6 produces partialy broken
+			 * XML_DOCUMENT_NODE nodes (unset content field). The copy of this node
+			 * is ok, but xmlFreeNode fails. Fortunately, XML_DOCUMENT_NODE should
+			 * not to have parent nodes, and we don't need to use xmlCopyNode.
+			 */
+			if (cur->type != XML_DOCUMENT_NODE)
+			{
+				cur_copy = xmlCopyNode(cur, 1);
+				if (cur == NULL || xmlerrcxt->err_occurred)
+					xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+								"could not copy node");
+			}
+			else
+				cur_copy = cur;
+
+			bytes = xmlNodeDump(buf, NULL, cur_copy, 0, 1);
+			if (bytes == -1 || xmlerrcxt->err_occurred)
+				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+							"could not dump node");
 
-		PG_TRY();
-		{
-			xmlNodeDump(buf, NULL, cur_copy, 0, 1);
 			result = xmlBuffer_to_xmltype(buf);
 		}
 		PG_CATCH();
 		{
-			xmlFreeNode(cur_copy);
-			xmlBufferFree(buf);
+			if (cur_copy && cur_copy != cur)
+				xmlFreeNode(cur_copy);
+			if (buf)
+				xmlBufferFree(buf);
 			PG_RE_THROW();
 		}
 		PG_END_TRY();
-		xmlFreeNode(cur_copy);
+
+		if (cur_copy != cur)
+			xmlFreeNode(cur_copy);
 		xmlBufferFree(buf);
 	}
 	else