78 lines
2.1 KiB
Diff
78 lines
2.1 KiB
Diff
From 1fbcf4098ba2aefe241de8d7ceb229b995d8daec Mon Sep 17 00:00:00 2001
|
|
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
Date: Mon, 23 Sep 2019 17:13:05 +0200
|
|
Subject: [PATCH 3/3] Make xmlTextReaderFreeNodeList non-recursive
|
|
|
|
Avoid call stack overflow when freeing deeply nested documents.
|
|
|
|
Found by OSS-Fuzz.
|
|
---
|
|
xmlreader.c | 32 +++++++++++++++++++++++---------
|
|
1 file changed, 23 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/xmlreader.c b/xmlreader.c
|
|
index d715071..9229c18 100644
|
|
--- a/xmlreader.c
|
|
+++ b/xmlreader.c
|
|
@@ -348,7 +348,9 @@ xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
|
|
static void
|
|
xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
|
|
xmlNodePtr next;
|
|
+ xmlNodePtr parent;
|
|
xmlDictPtr dict;
|
|
+ size_t depth = 0;
|
|
|
|
if ((reader != NULL) && (reader->ctxt != NULL))
|
|
dict = reader->ctxt->dict;
|
|
@@ -364,18 +366,21 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
|
|
xmlFreeDoc((xmlDocPtr) cur);
|
|
return;
|
|
}
|
|
- while (cur != NULL) {
|
|
+ while (1) {
|
|
+ while ((cur->children != NULL) &&
|
|
+ (cur->children->parent == cur) &&
|
|
+ (cur->type != XML_DTD_NODE) &&
|
|
+ (cur->type != XML_ENTITY_REF_NODE)) {
|
|
+ cur = cur->children;
|
|
+ depth += 1;
|
|
+ }
|
|
+
|
|
next = cur->next;
|
|
+ parent = cur->parent;
|
|
+
|
|
/* unroll to speed up freeing the document */
|
|
if (cur->type != XML_DTD_NODE) {
|
|
|
|
- if ((cur->children != NULL) &&
|
|
- (cur->type != XML_ENTITY_REF_NODE)) {
|
|
- if (cur->children->parent == cur)
|
|
- xmlTextReaderFreeNodeList(reader, cur->children);
|
|
- cur->children = NULL;
|
|
- }
|
|
-
|
|
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
|
|
xmlDeregisterNodeDefaultValue(cur);
|
|
|
|
@@ -414,7 +419,16 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
|
|
xmlFree(cur);
|
|
}
|
|
}
|
|
- cur = next;
|
|
+
|
|
+ if (next != NULL) {
|
|
+ cur = next;
|
|
+ } else {
|
|
+ if ((depth == 0) || (parent == NULL))
|
|
+ break;
|
|
+ depth -= 1;
|
|
+ cur = parent;
|
|
+ cur->children = NULL;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
--
|
|
1.7.12.4
|
|
|