From ea53fc18bccd88a5a010e63bf5d94b2f3f7a6fc8 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Mon, 7 Feb 2022 18:24:03 +0100 Subject: [PATCH] Properly handle nested documents in xmlFreeNode Client code should never add document nodes as children of other nodes, but even our own XPointer code has a bug that can produce such trees. Make sure to really free nested documents. Also see commits 0815302d and 0762c9b6. Should fix #269. --- tree.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tree.c b/tree.c index 50b6763b..96d3f324 100644 --- a/tree.c +++ b/tree.c @@ -3695,17 +3695,14 @@ xmlFreeNodeList(xmlNodePtr cur) { xmlFreeNsList((xmlNsPtr) cur); return; } - if ((cur->type == XML_DOCUMENT_NODE) || -#ifdef LIBXML_DOCB_ENABLED - (cur->type == XML_DOCB_DOCUMENT_NODE) || -#endif - (cur->type == XML_HTML_DOCUMENT_NODE)) { - xmlFreeDoc((xmlDocPtr) cur); - return; - } if (cur->doc != NULL) dict = cur->doc->dict; while (1) { while ((cur->children != NULL) && + (cur->type != XML_DOCUMENT_NODE) && +#ifdef LIBXML_DOCB_ENABLED + (cur->type != XML_DOCB_DOCUMENT_NODE) && +#endif + (cur->type != XML_HTML_DOCUMENT_NODE) && (cur->type != XML_DTD_NODE) && (cur->type != XML_ENTITY_REF_NODE)) { cur = cur->children; @@ -3714,7 +3711,13 @@ xmlFreeNodeList(xmlNodePtr cur) { next = cur->next; parent = cur->parent; - if (cur->type != XML_DTD_NODE) { + if ((cur->type == XML_DOCUMENT_NODE) || +#ifdef LIBXML_DOCB_ENABLED + (cur->type == XML_DOCB_DOCUMENT_NODE) || +#endif + (cur->type == XML_HTML_DOCUMENT_NODE)) { + xmlFreeDoc((xmlDocPtr) cur); + } else if (cur->type != XML_DTD_NODE) { if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) xmlDeregisterNodeDefaultValue(cur); @@ -3728,11 +3731,6 @@ xmlFreeNodeList(xmlNodePtr cur) { (cur->type != XML_XINCLUDE_START) && (cur->type != XML_XINCLUDE_END) && (cur->type != XML_ENTITY_REF_NODE) && - (cur->type != XML_DOCUMENT_NODE) && -#ifdef LIBXML_DOCB_ENABLED - (cur->type != XML_DOCB_DOCUMENT_NODE) && -#endif - (cur->type != XML_HTML_DOCUMENT_NODE) && (cur->content != (xmlChar *) &(cur->properties))) { DICT_FREE(cur->content) }