[libxml2] Make xmlFreeNodeList non-recursive



commit 0762c9b69ba01628f72eada1c64ff3d361fb5716
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Mon Sep 23 17:07:40 2019 +0200

    Make xmlFreeNodeList non-recursive
    
    Avoid call stack overflow when freeing deeply nested documents.

 tree.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)
---
diff --git a/tree.c b/tree.c
index bba06140..47813267 100644
--- a/tree.c
+++ b/tree.c
@@ -3664,7 +3664,9 @@ xmlNextElementSibling(xmlNodePtr node) {
 void
 xmlFreeNodeList(xmlNodePtr cur) {
     xmlNodePtr next;
+    xmlNodePtr parent;
     xmlDictPtr dict = NULL;
+    size_t depth = 0;
 
     if (cur == NULL) return;
     if (cur->type == XML_NAMESPACE_DECL) {
@@ -3680,16 +3682,21 @@ xmlFreeNodeList(xmlNodePtr cur) {
        return;
     }
     if (cur->doc != NULL) dict = cur->doc->dict;
-    while (cur != NULL) {
+    while (1) {
+        while ((cur->children != NULL) &&
+               (cur->type != XML_DTD_NODE) &&
+               (cur->type != XML_ENTITY_REF_NODE)) {
+            cur = cur->children;
+            depth += 1;
+        }
+
         next = cur->next;
+        parent = cur->parent;
        if (cur->type != XML_DTD_NODE) {
 
            if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
                xmlDeregisterNodeDefaultValue(cur);
 
-           if ((cur->children != NULL) &&
-               (cur->type != XML_ENTITY_REF_NODE))
-               xmlFreeNodeList(cur->children);
            if (((cur->type == XML_ELEMENT_NODE) ||
                 (cur->type == XML_XINCLUDE_START) ||
                 (cur->type == XML_XINCLUDE_END)) &&
@@ -3720,7 +3727,16 @@ xmlFreeNodeList(xmlNodePtr cur) {
                DICT_FREE(cur->name)
            xmlFree(cur);
        }
-       cur = next;
+
+        if (next != NULL) {
+           cur = next;
+        } else {
+            if ((depth == 0) || (parent == NULL))
+                break;
+            depth -= 1;
+            cur = parent;
+            cur->children = NULL;
+        }
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]