Sync some patches from community
This commit is contained in:
parent
7225a592c9
commit
ebcc4287e9
@ -0,0 +1,85 @@
|
||||
From 44e7a0d5f7a7e2c167a8a4196a5358830f695ab0 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Thu, 16 May 2019 21:17:28 +0200
|
||||
Subject: [PATCH] Annotate functions with __attribute__((no_sanitize))
|
||||
|
||||
---
|
||||
dict.c | 2 ++
|
||||
hash.c | 2 ++
|
||||
libxml.h | 7 +++++++
|
||||
xpath.c | 1 +
|
||||
4 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/dict.c b/dict.c
|
||||
index 14fe398..13a7b93 100644
|
||||
--- a/dict.c
|
||||
+++ b/dict.c
|
||||
@@ -372,6 +372,7 @@ found_pool:
|
||||
* http://burtleburtle.net/bob/hash/doobs.html
|
||||
*/
|
||||
|
||||
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static uint32_t
|
||||
xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
|
||||
uint32_t hash;
|
||||
@@ -404,6 +405,7 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
|
||||
*
|
||||
* Neither of the two strings must be NULL.
|
||||
*/
|
||||
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static unsigned long
|
||||
xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
|
||||
const xmlChar *name, int len, int seed)
|
||||
diff --git a/hash.c b/hash.c
|
||||
index 1145cb9..f037af6 100644
|
||||
--- a/hash.c
|
||||
+++ b/hash.c
|
||||
@@ -79,6 +79,7 @@ struct _xmlHashTable {
|
||||
* xmlHashComputeKey:
|
||||
* Calculate the hash key
|
||||
*/
|
||||
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static unsigned long
|
||||
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
|
||||
const xmlChar *name2, const xmlChar *name3) {
|
||||
@@ -109,6 +110,7 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
|
||||
return (value % table->size);
|
||||
}
|
||||
|
||||
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
static unsigned long
|
||||
xmlHashComputeQKey(xmlHashTablePtr table,
|
||||
const xmlChar *prefix, const xmlChar *name,
|
||||
diff --git a/libxml.h b/libxml.h
|
||||
index 64e30f7..7762331 100644
|
||||
--- a/libxml.h
|
||||
+++ b/libxml.h
|
||||
@@ -72,6 +72,13 @@ int vfprintf(FILE *, const char *, va_list);
|
||||
#define XML_POP_WARNINGS
|
||||
#endif
|
||||
|
||||
+#if defined(__clang__) || \
|
||||
+ (defined(__GNUC__) && (__GNUC__ >= 8))
|
||||
+#define ATTRIBUTE_NO_SANITIZE(arg) __attribute__((no_sanitize(arg)))
|
||||
+#else
|
||||
+#define ATTRIBUTE_NO_SANITIZE(arg)
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Internal variable indicating if a callback has been registered for
|
||||
* node creation/destruction. It avoids spending a lot of time in locking
|
||||
diff --git a/xpath.c b/xpath.c
|
||||
index 031772c..e68975e 100644
|
||||
--- a/xpath.c
|
||||
+++ b/xpath.c
|
||||
@@ -7497,6 +7497,7 @@ xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
|
||||
* The numeric operators convert their operands to numbers as if
|
||||
* by calling the number function.
|
||||
*/
|
||||
+ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
|
||||
void
|
||||
xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathObjectPtr arg;
|
||||
--
|
||||
1.7.12.4
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
From 443fd9665e9471b8083e2b5770f14f200b880381 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Tue, 29 Oct 2019 16:19:37 +0100
|
||||
Subject: [PATCH 3/3] Another fix for conditional sections at end of document
|
||||
|
||||
The previous fix introduced an uninitialized read.
|
||||
|
||||
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/9737ec071786c29788b9aa0971156f9e19a9c6a0
|
||||
---
|
||||
parser.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index f188c9d..84f1723 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -6725,6 +6725,7 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
|
||||
|
||||
if (RAW == 0) {
|
||||
xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
|
||||
+ goto error;
|
||||
}
|
||||
if (ctxt->input->id != id) {
|
||||
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
--
|
||||
2.18.1
|
||||
|
||||
62
backport-Avoid-ignored-attribute-warnings-under-GCC.patch
Normal file
62
backport-Avoid-ignored-attribute-warnings-under-GCC.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From b88ae6d2e1c9f22931f59ff1ec490befe201fb26 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Mon, 14 Oct 2019 15:38:28 +0200
|
||||
Subject: [PATCH] Avoid ignored attribute warnings under GCC
|
||||
|
||||
GCC doesn't support the unsigned-integer-overflow sanitizer.
|
||||
---
|
||||
dict.c | 4 ++++
|
||||
hash.c | 4 ++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dict.c b/dict.c
|
||||
index fb0773b..336e046 100644
|
||||
--- a/dict.c
|
||||
+++ b/dict.c
|
||||
@@ -372,7 +372,9 @@ found_pool:
|
||||
* http://burtleburtle.net/bob/hash/doobs.html
|
||||
*/
|
||||
|
||||
+#ifdef __clang__
|
||||
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
+#endif
|
||||
static uint32_t
|
||||
xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
|
||||
uint32_t hash;
|
||||
@@ -405,7 +407,9 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
|
||||
*
|
||||
* Neither of the two strings must be NULL.
|
||||
*/
|
||||
+#ifdef __clang__
|
||||
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
+#endif
|
||||
static unsigned long
|
||||
xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
|
||||
const xmlChar *name, int len, int seed)
|
||||
diff --git a/hash.c b/hash.c
|
||||
index f037af6..a83d979 100644
|
||||
--- a/hash.c
|
||||
+++ b/hash.c
|
||||
@@ -79,7 +79,9 @@ struct _xmlHashTable {
|
||||
* xmlHashComputeKey:
|
||||
* Calculate the hash key
|
||||
*/
|
||||
+#ifdef __clang__
|
||||
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
+#endif
|
||||
static unsigned long
|
||||
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
|
||||
const xmlChar *name2, const xmlChar *name3) {
|
||||
@@ -110,7 +112,9 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
|
||||
return (value % table->size);
|
||||
}
|
||||
|
||||
+#ifdef __clang__
|
||||
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
|
||||
+#endif
|
||||
static unsigned long
|
||||
xmlHashComputeQKey(xmlHashTablePtr table,
|
||||
const xmlChar *prefix, const xmlChar *name,
|
||||
--
|
||||
1.7.12.4
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
From 2b9fee2b0baf675b38b5e11756e9339d14c27a3a Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Wed, 23 Oct 2019 11:40:34 +0200
|
||||
Subject: [PATCH 2/3] Fix for conditional sections at end of document
|
||||
|
||||
Parsing conditional sections would fail if the final ']]>' was at the
|
||||
end of the document. Short-lived regression caused by commit c51e38cb.
|
||||
|
||||
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/c1035664f989c2ac7ca31407bc6f0b48396db42c
|
||||
---
|
||||
parser.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index bfa6585..f188c9d 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -6723,6 +6723,9 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
|
||||
ctxt->disableSAX = state;
|
||||
ctxt->instate = instate;
|
||||
|
||||
+ if (RAW == 0) {
|
||||
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
|
||||
+ }
|
||||
if (ctxt->input->id != id) {
|
||||
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
"All markup of the conditional section is"
|
||||
@@ -6763,10 +6766,6 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
|
||||
GROW;
|
||||
}
|
||||
|
||||
- if (RAW == 0) {
|
||||
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
|
||||
- }
|
||||
-
|
||||
error:
|
||||
xmlFree(inputIds);
|
||||
}
|
||||
--
|
||||
2.18.1
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
From 664f881008f40356c0502c8cc154e17e3c80e353 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Thu, 26 Sep 2019 11:01:58 +0200
|
||||
Subject: [PATCH] Fix use-after-free in xmlTextReaderFreeNodeList
|
||||
|
||||
Recent commit 1fbcf40 caused a use-after-free read because it didn't
|
||||
account for the fact that xmlTextReaderFreeDoc frees entities before
|
||||
freeing entity references via xmlTextReaderFreeNodeList.
|
||||
|
||||
Found by OSS-Fuzz.
|
||||
---
|
||||
xmlreader.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/xmlreader.c b/xmlreader.c
|
||||
index 9229c18..b505f16 100644
|
||||
--- a/xmlreader.c
|
||||
+++ b/xmlreader.c
|
||||
@@ -367,10 +367,10 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
- while ((cur->children != NULL) &&
|
||||
- (cur->children->parent == cur) &&
|
||||
- (cur->type != XML_DTD_NODE) &&
|
||||
- (cur->type != XML_ENTITY_REF_NODE)) {
|
||||
+ while ((cur->type != XML_DTD_NODE) &&
|
||||
+ (cur->type != XML_ENTITY_REF_NODE) &&
|
||||
+ (cur->children != NULL) &&
|
||||
+ (cur->children->parent == cur)) {
|
||||
cur = cur->children;
|
||||
depth += 1;
|
||||
}
|
||||
--
|
||||
1.7.12.4
|
||||
|
||||
211
backport-Make-xmlDumpElementContent-non-recursive.patch
Normal file
211
backport-Make-xmlDumpElementContent-non-recursive.patch
Normal file
@ -0,0 +1,211 @@
|
||||
From 3be39335ced799eb1ec312b7b542c84dac4ebd57 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Fri, 4 Oct 2019 14:42:59 +0200
|
||||
Subject: [PATCH] Make xmlDumpElementContent non-recursive
|
||||
|
||||
Avoid call stack overflow when dumping deeply nested element
|
||||
declarations.
|
||||
|
||||
Found by OSS-Fuzz.
|
||||
|
||||
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/24e3973bc03c15d534b2eac6e70fc2b2bef2b6c0
|
||||
---
|
||||
valid.c | 157 ++++++++++++++++++++++++++++++++------------------------
|
||||
1 file changed, 89 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/valid.c b/valid.c
|
||||
index b1cfede..632c5e7 100644
|
||||
--- a/valid.c
|
||||
+++ b/valid.c
|
||||
@@ -1148,83 +1148,104 @@ xmlFreeElementContent(xmlElementContentPtr cur) {
|
||||
|
||||
#ifdef LIBXML_OUTPUT_ENABLED
|
||||
/**
|
||||
- * xmlDumpElementContent:
|
||||
+ * xmlDumpElementOccur:
|
||||
* @buf: An XML buffer
|
||||
- * @content: An element table
|
||||
- * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
|
||||
+ * @cur: An element table
|
||||
*
|
||||
- * This will dump the content of the element table as an XML DTD definition
|
||||
+ * Dump the occurence operator of an element.
|
||||
*/
|
||||
static void
|
||||
-xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) {
|
||||
- if (content == NULL) return;
|
||||
-
|
||||
- if (glob) xmlBufferWriteChar(buf, "(");
|
||||
- switch (content->type) {
|
||||
- case XML_ELEMENT_CONTENT_PCDATA:
|
||||
- xmlBufferWriteChar(buf, "#PCDATA");
|
||||
- break;
|
||||
- case XML_ELEMENT_CONTENT_ELEMENT:
|
||||
- if (content->prefix != NULL) {
|
||||
- xmlBufferWriteCHAR(buf, content->prefix);
|
||||
- xmlBufferWriteChar(buf, ":");
|
||||
- }
|
||||
- xmlBufferWriteCHAR(buf, content->name);
|
||||
- break;
|
||||
- case XML_ELEMENT_CONTENT_SEQ:
|
||||
- if ((content->c1 != NULL) &&
|
||||
- ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
- (content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
|
||||
- xmlDumpElementContent(buf, content->c1, 1);
|
||||
- else
|
||||
- xmlDumpElementContent(buf, content->c1, 0);
|
||||
- xmlBufferWriteChar(buf, " , ");
|
||||
- if ((content->c2 != NULL) &&
|
||||
- ((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
- ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) &&
|
||||
- (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
|
||||
- xmlDumpElementContent(buf, content->c2, 1);
|
||||
- else
|
||||
- xmlDumpElementContent(buf, content->c2, 0);
|
||||
- break;
|
||||
- case XML_ELEMENT_CONTENT_OR:
|
||||
- if ((content->c1 != NULL) &&
|
||||
- ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
- (content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
|
||||
- xmlDumpElementContent(buf, content->c1, 1);
|
||||
- else
|
||||
- xmlDumpElementContent(buf, content->c1, 0);
|
||||
- xmlBufferWriteChar(buf, " | ");
|
||||
- if ((content->c2 != NULL) &&
|
||||
- ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
|
||||
- ((content->c2->type == XML_ELEMENT_CONTENT_OR) &&
|
||||
- (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
|
||||
- xmlDumpElementContent(buf, content->c2, 1);
|
||||
- else
|
||||
- xmlDumpElementContent(buf, content->c2, 0);
|
||||
- break;
|
||||
- default:
|
||||
- xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
|
||||
- "Internal: ELEMENT content corrupted invalid type\n",
|
||||
- NULL);
|
||||
- }
|
||||
- if (glob)
|
||||
- xmlBufferWriteChar(buf, ")");
|
||||
- switch (content->ocur) {
|
||||
+xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
|
||||
+ switch (cur->ocur) {
|
||||
case XML_ELEMENT_CONTENT_ONCE:
|
||||
- break;
|
||||
+ break;
|
||||
case XML_ELEMENT_CONTENT_OPT:
|
||||
- xmlBufferWriteChar(buf, "?");
|
||||
- break;
|
||||
+ xmlBufferWriteChar(buf, "?");
|
||||
+ break;
|
||||
case XML_ELEMENT_CONTENT_MULT:
|
||||
- xmlBufferWriteChar(buf, "*");
|
||||
- break;
|
||||
+ xmlBufferWriteChar(buf, "*");
|
||||
+ break;
|
||||
case XML_ELEMENT_CONTENT_PLUS:
|
||||
- xmlBufferWriteChar(buf, "+");
|
||||
- break;
|
||||
+ xmlBufferWriteChar(buf, "+");
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * xmlDumpElementContent:
|
||||
+ * @buf: An XML buffer
|
||||
+ * @content: An element table
|
||||
+ *
|
||||
+ * This will dump the content of the element table as an XML DTD definition
|
||||
+ */
|
||||
+static void
|
||||
+xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
|
||||
+ xmlElementContentPtr cur;
|
||||
+
|
||||
+ if (content == NULL) return;
|
||||
+
|
||||
+ xmlBufferWriteChar(buf, "(");
|
||||
+ cur = content;
|
||||
+
|
||||
+ do {
|
||||
+ if (cur == NULL) return;
|
||||
+
|
||||
+ switch (cur->type) {
|
||||
+ case XML_ELEMENT_CONTENT_PCDATA:
|
||||
+ xmlBufferWriteChar(buf, "#PCDATA");
|
||||
+ break;
|
||||
+ case XML_ELEMENT_CONTENT_ELEMENT:
|
||||
+ if (cur->prefix != NULL) {
|
||||
+ xmlBufferWriteCHAR(buf, cur->prefix);
|
||||
+ xmlBufferWriteChar(buf, ":");
|
||||
+ }
|
||||
+ xmlBufferWriteCHAR(buf, cur->name);
|
||||
+ break;
|
||||
+ case XML_ELEMENT_CONTENT_SEQ:
|
||||
+ case XML_ELEMENT_CONTENT_OR:
|
||||
+ if ((cur != content) &&
|
||||
+ (cur->parent != NULL) &&
|
||||
+ ((cur->type != cur->parent->type) ||
|
||||
+ (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
|
||||
+ xmlBufferWriteChar(buf, "(");
|
||||
+ cur = cur->c1;
|
||||
+ continue;
|
||||
+ default:
|
||||
+ xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
|
||||
+ "Internal: ELEMENT cur corrupted invalid type\n",
|
||||
+ NULL);
|
||||
+ }
|
||||
+
|
||||
+ while (cur != content) {
|
||||
+ xmlElementContentPtr parent = cur->parent;
|
||||
+
|
||||
+ if (parent == NULL) return;
|
||||
+
|
||||
+ if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
|
||||
+ (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
|
||||
+ ((cur->type != parent->type) ||
|
||||
+ (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
|
||||
+ xmlBufferWriteChar(buf, ")");
|
||||
+ xmlDumpElementOccur(buf, cur);
|
||||
+
|
||||
+ if (cur == parent->c1) {
|
||||
+ if (parent->type == XML_ELEMENT_CONTENT_SEQ)
|
||||
+ xmlBufferWriteChar(buf, " , ");
|
||||
+ else if (parent->type == XML_ELEMENT_CONTENT_OR)
|
||||
+ xmlBufferWriteChar(buf, " | ");
|
||||
+
|
||||
+ cur = parent->c2;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ cur = parent;
|
||||
+ }
|
||||
+ } while (cur != content);
|
||||
+
|
||||
+ xmlBufferWriteChar(buf, ")");
|
||||
+ xmlDumpElementOccur(buf, content);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* xmlSprintfElementContent:
|
||||
* @buf: an output buffer
|
||||
@@ -1703,7 +1724,7 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, elem->name);
|
||||
xmlBufferWriteChar(buf, " ");
|
||||
- xmlDumpElementContent(buf, elem->content, 1);
|
||||
+ xmlDumpElementContent(buf, elem->content);
|
||||
xmlBufferWriteChar(buf, ">\n");
|
||||
break;
|
||||
case XML_ELEMENT_TYPE_ELEMENT:
|
||||
@@ -1714,7 +1735,7 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
|
||||
}
|
||||
xmlBufferWriteCHAR(buf, elem->name);
|
||||
xmlBufferWriteChar(buf, " ");
|
||||
- xmlDumpElementContent(buf, elem->content, 1);
|
||||
+ xmlDumpElementContent(buf, elem->content);
|
||||
xmlBufferWriteChar(buf, ">\n");
|
||||
break;
|
||||
default:
|
||||
--
|
||||
2.18.1
|
||||
|
||||
71
backport-Make-xmlFreeNodeList-non-recursive.patch
Normal file
71
backport-Make-xmlFreeNodeList-non-recursive.patch
Normal file
@ -0,0 +1,71 @@
|
||||
From 0762c9b69ba01628f72eada1c64ff3d361fb5716 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Mon, 23 Sep 2019 17:07:40 +0200
|
||||
Subject: [PATCH 2/3] 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 bba0614..4781326 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;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.7.12.4
|
||||
|
||||
510
backport-Make-xmlParseConditionalSections-non-recursive.patch
Normal file
510
backport-Make-xmlParseConditionalSections-non-recursive.patch
Normal file
@ -0,0 +1,510 @@
|
||||
From 94aa233233dac8d6f497f6584d183e3b5cc2a0f8 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Mon, 30 Sep 2019 13:50:02 +0200
|
||||
Subject: [PATCH] Make xmlParseConditionalSections non-recursive
|
||||
|
||||
Avoid call stack overflow in deeply nested conditional sections.
|
||||
|
||||
Found by OSS-Fuzz.
|
||||
|
||||
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/c51e38cb3a808e315248e03c9e52bce08943c22b
|
||||
---
|
||||
parser.c | 265 ++++++++++++++--------------
|
||||
result/errors/759573-2.xml.err | 10 --
|
||||
result/errors/759573.xml.err | 13 --
|
||||
result/valid/cond_sect1.xml | 8 +
|
||||
result/valid/cond_sect1.xml.err | 0
|
||||
result/valid/cond_sect1.xml.err.rdr | 0
|
||||
result/valid/cond_sect2.xml | 0
|
||||
result/valid/cond_sect2.xml.err | 9 +
|
||||
result/valid/cond_sect2.xml.err.rdr | 10 ++
|
||||
test/valid/cond_sect1.xml | 7 +
|
||||
test/valid/cond_sect2.xml | 4 +
|
||||
test/valid/dtds/cond_sect1.dtd | 20 +++
|
||||
test/valid/dtds/cond_sect2.dtd | 16 ++
|
||||
13 files changed, 203 insertions(+), 159 deletions(-)
|
||||
create mode 100644 result/valid/cond_sect1.xml
|
||||
create mode 100644 result/valid/cond_sect1.xml.err
|
||||
create mode 100644 result/valid/cond_sect1.xml.err.rdr
|
||||
create mode 100644 result/valid/cond_sect2.xml
|
||||
create mode 100644 result/valid/cond_sect2.xml.err
|
||||
create mode 100644 result/valid/cond_sect2.xml.err.rdr
|
||||
create mode 100644 test/valid/cond_sect1.xml
|
||||
create mode 100644 test/valid/cond_sect2.xml
|
||||
create mode 100644 test/valid/dtds/cond_sect1.dtd
|
||||
create mode 100644 test/valid/dtds/cond_sect2.dtd
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index 9fb14fe..bfa6585 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -6632,149 +6632,143 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
|
||||
|
||||
static void
|
||||
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
|
||||
- int id = ctxt->input->id;
|
||||
+ int *inputIds = NULL;
|
||||
+ size_t inputIdsSize = 0;
|
||||
+ size_t depth = 0;
|
||||
|
||||
- SKIP(3);
|
||||
- SKIP_BLANKS;
|
||||
- if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
|
||||
- SKIP(7);
|
||||
- SKIP_BLANKS;
|
||||
- if (RAW != '[') {
|
||||
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
|
||||
- xmlHaltParser(ctxt);
|
||||
- return;
|
||||
- } else {
|
||||
- if (ctxt->input->id != id) {
|
||||
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
- "All markup of the conditional section is not"
|
||||
- " in the same entity\n");
|
||||
- }
|
||||
- NEXT;
|
||||
- }
|
||||
- if (xmlParserDebugEntities) {
|
||||
- if ((ctxt->input != NULL) && (ctxt->input->filename))
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "%s(%d): ", ctxt->input->filename,
|
||||
- ctxt->input->line);
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "Entering INCLUDE Conditional Section\n");
|
||||
- }
|
||||
+ while (ctxt->instate != XML_PARSER_EOF) {
|
||||
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
|
||||
+ int id = ctxt->input->id;
|
||||
|
||||
- SKIP_BLANKS;
|
||||
- GROW;
|
||||
- while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
|
||||
- (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
|
||||
- const xmlChar *check = CUR_PTR;
|
||||
- unsigned int cons = ctxt->input->consumed;
|
||||
+ SKIP(3);
|
||||
+ SKIP_BLANKS;
|
||||
|
||||
- if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
|
||||
- xmlParseConditionalSections(ctxt);
|
||||
- } else
|
||||
- xmlParseMarkupDecl(ctxt);
|
||||
+ if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
|
||||
+ SKIP(7);
|
||||
+ SKIP_BLANKS;
|
||||
+ if (RAW != '[') {
|
||||
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
|
||||
+ xmlHaltParser(ctxt);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ if (ctxt->input->id != id) {
|
||||
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
+ "All markup of the conditional section is"
|
||||
+ " not in the same entity\n");
|
||||
+ }
|
||||
+ NEXT;
|
||||
|
||||
- SKIP_BLANKS;
|
||||
- GROW;
|
||||
+ if (inputIdsSize <= depth) {
|
||||
+ int *tmp;
|
||||
|
||||
- if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
|
||||
- xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
|
||||
- xmlHaltParser(ctxt);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- if (xmlParserDebugEntities) {
|
||||
- if ((ctxt->input != NULL) && (ctxt->input->filename))
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "%s(%d): ", ctxt->input->filename,
|
||||
- ctxt->input->line);
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "Leaving INCLUDE Conditional Section\n");
|
||||
- }
|
||||
+ inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
|
||||
+ tmp = (int *) xmlRealloc(inputIds,
|
||||
+ inputIdsSize * sizeof(int));
|
||||
+ if (tmp == NULL) {
|
||||
+ xmlErrMemory(ctxt, NULL);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ inputIds = tmp;
|
||||
+ }
|
||||
+ inputIds[depth] = id;
|
||||
+ depth++;
|
||||
+ } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
|
||||
+ int state;
|
||||
+ xmlParserInputState instate;
|
||||
+ size_t ignoreDepth = 0;
|
||||
+
|
||||
+ SKIP(6);
|
||||
+ SKIP_BLANKS;
|
||||
+ if (RAW != '[') {
|
||||
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
|
||||
+ xmlHaltParser(ctxt);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ if (ctxt->input->id != id) {
|
||||
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
+ "All markup of the conditional section is"
|
||||
+ " not in the same entity\n");
|
||||
+ }
|
||||
+ NEXT;
|
||||
|
||||
- } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
|
||||
- int state;
|
||||
- xmlParserInputState instate;
|
||||
- int depth = 0;
|
||||
+ /*
|
||||
+ * Parse up to the end of the conditional section but disable
|
||||
+ * SAX event generating DTD building in the meantime
|
||||
+ */
|
||||
+ state = ctxt->disableSAX;
|
||||
+ instate = ctxt->instate;
|
||||
+ if (ctxt->recovery == 0) ctxt->disableSAX = 1;
|
||||
+ ctxt->instate = XML_PARSER_IGNORE;
|
||||
+
|
||||
+ while (RAW != 0) {
|
||||
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
|
||||
+ SKIP(3);
|
||||
+ ignoreDepth++;
|
||||
+ /* Check for integer overflow */
|
||||
+ if (ignoreDepth == 0) {
|
||||
+ xmlErrMemory(ctxt, NULL);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ } else if ((RAW == ']') && (NXT(1) == ']') &&
|
||||
+ (NXT(2) == '>')) {
|
||||
+ if (ignoreDepth == 0)
|
||||
+ break;
|
||||
+ SKIP(3);
|
||||
+ ignoreDepth--;
|
||||
+ } else {
|
||||
+ NEXT;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- SKIP(6);
|
||||
- SKIP_BLANKS;
|
||||
- if (RAW != '[') {
|
||||
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
|
||||
- xmlHaltParser(ctxt);
|
||||
- return;
|
||||
- } else {
|
||||
- if (ctxt->input->id != id) {
|
||||
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
- "All markup of the conditional section is not"
|
||||
- " in the same entity\n");
|
||||
- }
|
||||
- NEXT;
|
||||
- }
|
||||
- if (xmlParserDebugEntities) {
|
||||
- if ((ctxt->input != NULL) && (ctxt->input->filename))
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "%s(%d): ", ctxt->input->filename,
|
||||
- ctxt->input->line);
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "Entering IGNORE Conditional Section\n");
|
||||
- }
|
||||
+ ctxt->disableSAX = state;
|
||||
+ ctxt->instate = instate;
|
||||
|
||||
- /*
|
||||
- * Parse up to the end of the conditional section
|
||||
- * But disable SAX event generating DTD building in the meantime
|
||||
- */
|
||||
- state = ctxt->disableSAX;
|
||||
- instate = ctxt->instate;
|
||||
- if (ctxt->recovery == 0) ctxt->disableSAX = 1;
|
||||
- ctxt->instate = XML_PARSER_IGNORE;
|
||||
+ if (ctxt->input->id != id) {
|
||||
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
+ "All markup of the conditional section is"
|
||||
+ " not in the same entity\n");
|
||||
+ }
|
||||
+ SKIP(3);
|
||||
+ } else {
|
||||
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
|
||||
+ xmlHaltParser(ctxt);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ } else if ((depth > 0) &&
|
||||
+ (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
|
||||
+ depth--;
|
||||
+ if (ctxt->input->id != inputIds[depth]) {
|
||||
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
+ "All markup of the conditional section is not"
|
||||
+ " in the same entity\n");
|
||||
+ }
|
||||
+ SKIP(3);
|
||||
+ } else {
|
||||
+ const xmlChar *check = CUR_PTR;
|
||||
+ unsigned int cons = ctxt->input->consumed;
|
||||
|
||||
- while (((depth >= 0) && (RAW != 0)) &&
|
||||
- (ctxt->instate != XML_PARSER_EOF)) {
|
||||
- if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
|
||||
- depth++;
|
||||
- SKIP(3);
|
||||
- continue;
|
||||
- }
|
||||
- if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
|
||||
- if (--depth >= 0) SKIP(3);
|
||||
- continue;
|
||||
- }
|
||||
- NEXT;
|
||||
- continue;
|
||||
- }
|
||||
+ xmlParseMarkupDecl(ctxt);
|
||||
|
||||
- ctxt->disableSAX = state;
|
||||
- ctxt->instate = instate;
|
||||
+ if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
|
||||
+ xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
|
||||
+ xmlHaltParser(ctxt);
|
||||
+ goto error;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (xmlParserDebugEntities) {
|
||||
- if ((ctxt->input != NULL) && (ctxt->input->filename))
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "%s(%d): ", ctxt->input->filename,
|
||||
- ctxt->input->line);
|
||||
- xmlGenericError(xmlGenericErrorContext,
|
||||
- "Leaving IGNORE Conditional Section\n");
|
||||
- }
|
||||
+ if (depth == 0)
|
||||
+ break;
|
||||
|
||||
- } else {
|
||||
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
|
||||
- xmlHaltParser(ctxt);
|
||||
- return;
|
||||
+ SKIP_BLANKS;
|
||||
+ GROW;
|
||||
}
|
||||
|
||||
- if (RAW == 0)
|
||||
- SHRINK;
|
||||
-
|
||||
if (RAW == 0) {
|
||||
xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
|
||||
- } else {
|
||||
- if (ctxt->input->id != id) {
|
||||
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
|
||||
- "All markup of the conditional section is not in"
|
||||
- " the same entity\n");
|
||||
- }
|
||||
- if ((ctxt-> instate != XML_PARSER_EOF) &&
|
||||
- ((ctxt->input->cur + 3) <= ctxt->input->end))
|
||||
- SKIP(3);
|
||||
}
|
||||
+
|
||||
+error:
|
||||
+ xmlFree(inputIds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6836,16 +6830,6 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
|
||||
if (ctxt->instate == XML_PARSER_EOF)
|
||||
return;
|
||||
|
||||
- /*
|
||||
- * Conditional sections are allowed from entities included
|
||||
- * by PE References in the internal subset.
|
||||
- */
|
||||
- if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
|
||||
- if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
|
||||
- xmlParseConditionalSections(ctxt);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
ctxt->instate = XML_PARSER_DTD;
|
||||
}
|
||||
|
||||
@@ -8306,6 +8290,15 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
|
||||
xmlParseMarkupDecl(ctxt);
|
||||
xmlParsePEReference(ctxt);
|
||||
|
||||
+ /*
|
||||
+ * Conditional sections are allowed from entities included
|
||||
+ * by PE References in the internal subset.
|
||||
+ */
|
||||
+ if ((ctxt->inputNr > 1) &&
|
||||
+ (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
|
||||
+ xmlParseConditionalSections(ctxt);
|
||||
+ }
|
||||
+
|
||||
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
|
||||
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||
"xmlParseInternalSubset: error detected in Markup declaration\n");
|
||||
diff --git a/result/errors/759573-2.xml.err b/result/errors/759573-2.xml.err
|
||||
index 86d6420..ecaf18f 100644
|
||||
--- a/result/errors/759573-2.xml.err
|
||||
+++ b/result/errors/759573-2.xml.err
|
||||
@@ -46,13 +46,3 @@ Entity: line 3:
|
||||
Entity: line 3:
|
||||
%zz;<!ELEMENTD(%MENT%MENTDŹMENTD%zNMT9KENSMYSYSTEM;MENT9%zz;
|
||||
^
|
||||
-./test/errors/759573-2.xml:6: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
|
||||
-
|
||||
-
|
||||
-^
|
||||
-./test/errors/759573-2.xml:6: parser error : DOCTYPE improperly terminated
|
||||
-
|
||||
-^
|
||||
-./test/errors/759573-2.xml:6: parser error : Start tag expected, '<' not found
|
||||
-
|
||||
-^
|
||||
diff --git a/result/errors/759573.xml.err b/result/errors/759573.xml.err
|
||||
index 554039f..2617cad 100644
|
||||
--- a/result/errors/759573.xml.err
|
||||
+++ b/result/errors/759573.xml.err
|
||||
@@ -19,16 +19,3 @@ T t (A)><!ENTITY % xx '%<![INCLUDE[000%ஸ000%z;'><!ENTITYz>%xx;
|
||||
Entity: line 1:
|
||||
%<![INCLUDE[000%ஸ000%z;
|
||||
^
|
||||
-./test/errors/759573.xml:1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
|
||||
-
|
||||
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '%<![INCLUDE[000%ஸ00
|
||||
- ^
|
||||
-./test/errors/759573.xml:1: parser error : DOCTYPE improperly terminated
|
||||
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '%<![INCLUDE[000%ஸ00
|
||||
- ^
|
||||
-./test/errors/759573.xml:1: parser error : StartTag: invalid element name
|
||||
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '%<![INCLUDE[000%ஸ00
|
||||
- ^
|
||||
-./test/errors/759573.xml:1: parser error : Extra content at the end of the document
|
||||
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '%<![INCLUDE[000%ஸ00
|
||||
- ^
|
||||
diff --git a/result/valid/cond_sect1.xml b/result/valid/cond_sect1.xml
|
||||
new file mode 100644
|
||||
index 0000000..dd2e5b4
|
||||
--- /dev/null
|
||||
+++ b/result/valid/cond_sect1.xml
|
||||
@@ -0,0 +1,8 @@
|
||||
+<?xml version="1.0"?>
|
||||
+<!DOCTYPE doc SYSTEM "dtds/cond_sect1.dtd" [
|
||||
+<!ENTITY % include "INCLUDE">
|
||||
+<!ENTITY % ignore "IGNORE">
|
||||
+]>
|
||||
+<doc>
|
||||
+ <child>text</child>
|
||||
+</doc>
|
||||
diff --git a/result/valid/cond_sect1.xml.err b/result/valid/cond_sect1.xml.err
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/result/valid/cond_sect1.xml.err.rdr b/result/valid/cond_sect1.xml.err.rdr
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/result/valid/cond_sect2.xml b/result/valid/cond_sect2.xml
|
||||
new file mode 100644
|
||||
index 0000000..e69de29
|
||||
diff --git a/result/valid/cond_sect2.xml.err b/result/valid/cond_sect2.xml.err
|
||||
new file mode 100644
|
||||
index 0000000..9a7624b
|
||||
--- /dev/null
|
||||
+++ b/result/valid/cond_sect2.xml.err
|
||||
@@ -0,0 +1,9 @@
|
||||
+test/valid/dtds/cond_sect2.dtd:15: parser error : All markup of the conditional section is not in the same entity
|
||||
+ %ent;
|
||||
+ ^
|
||||
+Entity: line 1:
|
||||
+]]>
|
||||
+^
|
||||
+test/valid/dtds/cond_sect2.dtd:17: parser error : Content error in the external subset
|
||||
+
|
||||
+^
|
||||
diff --git a/result/valid/cond_sect2.xml.err.rdr b/result/valid/cond_sect2.xml.err.rdr
|
||||
new file mode 100644
|
||||
index 0000000..fd3cb75
|
||||
--- /dev/null
|
||||
+++ b/result/valid/cond_sect2.xml.err.rdr
|
||||
@@ -0,0 +1,10 @@
|
||||
+test/valid/dtds/cond_sect2.dtd:15: parser error : All markup of the conditional section is not in the same entity
|
||||
+ %ent;
|
||||
+ ^
|
||||
+Entity: line 1:
|
||||
+]]>
|
||||
+^
|
||||
+test/valid/dtds/cond_sect2.dtd:17: parser error : Content error in the external subset
|
||||
+
|
||||
+^
|
||||
+./test/valid/cond_sect2.xml : failed to parse
|
||||
diff --git a/test/valid/cond_sect1.xml b/test/valid/cond_sect1.xml
|
||||
new file mode 100644
|
||||
index 0000000..796faa4
|
||||
--- /dev/null
|
||||
+++ b/test/valid/cond_sect1.xml
|
||||
@@ -0,0 +1,7 @@
|
||||
+<!DOCTYPE doc SYSTEM "dtds/cond_sect1.dtd" [
|
||||
+ <!ENTITY % include "INCLUDE">
|
||||
+ <!ENTITY % ignore "IGNORE">
|
||||
+]>
|
||||
+<doc>
|
||||
+ <child>text</child>
|
||||
+</doc>
|
||||
diff --git a/test/valid/cond_sect2.xml b/test/valid/cond_sect2.xml
|
||||
new file mode 100644
|
||||
index 0000000..5153d05
|
||||
--- /dev/null
|
||||
+++ b/test/valid/cond_sect2.xml
|
||||
@@ -0,0 +1,4 @@
|
||||
+<!DOCTYPE doc SYSTEM "dtds/cond_sect2.dtd">
|
||||
+<doc>
|
||||
+ <child>text</child>
|
||||
+</doc>
|
||||
diff --git a/test/valid/dtds/cond_sect1.dtd b/test/valid/dtds/cond_sect1.dtd
|
||||
new file mode 100644
|
||||
index 0000000..e327022
|
||||
--- /dev/null
|
||||
+++ b/test/valid/dtds/cond_sect1.dtd
|
||||
@@ -0,0 +1,20 @@
|
||||
+<![ %include; [
|
||||
+ <![%include; [
|
||||
+ <![ %include;[
|
||||
+ <![%include;[
|
||||
+ <!ELEMENT doc (child)>
|
||||
+ <!ELEMENT child (#PCDATA)>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+]]>
|
||||
+<![ %ignore; [
|
||||
+ <![%include; [
|
||||
+ <![ %include;[
|
||||
+ <![%ignore;[
|
||||
+ <!ELEMENT doc (x)>
|
||||
+ <!ELEMENT child (y)>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+]]>
|
||||
diff --git a/test/valid/dtds/cond_sect2.dtd b/test/valid/dtds/cond_sect2.dtd
|
||||
new file mode 100644
|
||||
index 0000000..29eb4bf
|
||||
--- /dev/null
|
||||
+++ b/test/valid/dtds/cond_sect2.dtd
|
||||
@@ -0,0 +1,16 @@
|
||||
+<!ENTITY % ent "]]>">
|
||||
+<![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ <![INCLUDE[
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+ ]]>
|
||||
+ %ent;
|
||||
+]]>
|
||||
--
|
||||
2.18.1
|
||||
|
||||
@ -0,0 +1,286 @@
|
||||
From 62150ed2ab19a4dd76c15acc62c7d923d9f3b2cc Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Mon, 23 Sep 2019 14:46:41 +0200
|
||||
Subject: [PATCH 1/3] Make xmlParseContent and xmlParseElement non-recursive
|
||||
|
||||
Split xmlParseElement into subfunctions. Use nameNsPush to store prefix,
|
||||
URI and nsNr on the heap, similar to the push parser.
|
||||
|
||||
Closes #84.
|
||||
---
|
||||
parser.c | 121 +++++++++++++++++++++++++------------------
|
||||
result/errors/754947.xml.err | 2 +-
|
||||
result/errors/759398.xml.err | 4 +-
|
||||
3 files changed, 74 insertions(+), 53 deletions(-)
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index 5b8df8c..cad0a9d 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -96,6 +96,12 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
|
||||
|
||||
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
|
||||
|
||||
+static int
|
||||
+xmlParseElementStart(xmlParserCtxtPtr ctxt);
|
||||
+
|
||||
+static void
|
||||
+xmlParseElementEnd(xmlParserCtxtPtr ctxt);
|
||||
+
|
||||
/************************************************************************
|
||||
* *
|
||||
* Arbitrary limits set in the parser. See XML_PARSE_HUGE *
|
||||
@@ -1822,7 +1828,6 @@ nodePop(xmlParserCtxtPtr ctxt)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
-#ifdef LIBXML_PUSH_ENABLED
|
||||
/**
|
||||
* nameNsPush:
|
||||
* @ctxt: an XML parser context
|
||||
@@ -1858,6 +1863,11 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
|
||||
goto mem_error;
|
||||
}
|
||||
ctxt->pushTab = tmp2;
|
||||
+ } else if (ctxt->pushTab == NULL) {
|
||||
+ ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
|
||||
+ sizeof(ctxt->pushTab[0]));
|
||||
+ if (ctxt->pushTab == NULL)
|
||||
+ goto mem_error;
|
||||
}
|
||||
ctxt->nameTab[ctxt->nameNr] = value;
|
||||
ctxt->name = value;
|
||||
@@ -1869,6 +1879,7 @@ mem_error:
|
||||
xmlErrMemory(ctxt, NULL);
|
||||
return (-1);
|
||||
}
|
||||
+#ifdef LIBXML_PUSH_ENABLED
|
||||
/**
|
||||
* nameNsPop:
|
||||
* @ctxt: an XML parser context
|
||||
@@ -9812,9 +9823,10 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
|
||||
|
||||
void
|
||||
xmlParseContent(xmlParserCtxtPtr ctxt) {
|
||||
+ int nameNr = ctxt->nameNr;
|
||||
+
|
||||
GROW;
|
||||
while ((RAW != 0) &&
|
||||
- ((RAW != '<') || (NXT(1) != '/')) &&
|
||||
(ctxt->instate != XML_PARSER_EOF)) {
|
||||
const xmlChar *test = CUR_PTR;
|
||||
unsigned int cons = ctxt->input->consumed;
|
||||
@@ -9848,7 +9860,13 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
||||
* Fourth case : a sub-element.
|
||||
*/
|
||||
else if (*cur == '<') {
|
||||
- xmlParseElement(ctxt);
|
||||
+ if (NXT(1) == '/') {
|
||||
+ if (ctxt->nameNr <= nameNr)
|
||||
+ break;
|
||||
+ xmlParseElementEnd(ctxt);
|
||||
+ } else {
|
||||
+ xmlParseElementStart(ctxt);
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -9883,7 +9901,7 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
||||
* xmlParseElement:
|
||||
* @ctxt: an XML parser context
|
||||
*
|
||||
- * parse an XML element, this is highly recursive
|
||||
+ * parse an XML element
|
||||
*
|
||||
* [39] element ::= EmptyElemTag | STag content ETag
|
||||
*
|
||||
@@ -9895,6 +9913,23 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
||||
|
||||
void
|
||||
xmlParseElement(xmlParserCtxtPtr ctxt) {
|
||||
+ if (xmlParseElementStart(ctxt) != 0)
|
||||
+ return;
|
||||
+ xmlParseContent(ctxt);
|
||||
+ if (ctxt->instate == XML_PARSER_EOF)
|
||||
+ return;
|
||||
+ xmlParseElementEnd(ctxt);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * xmlParseElementStart:
|
||||
+ * @ctxt: an XML parser context
|
||||
+ *
|
||||
+ * Parse the start of an XML element. Returns -1 in case of error, 0 if an
|
||||
+ * opening tag was parsed, 1 if an empty element was parsed.
|
||||
+ */
|
||||
+static int
|
||||
+xmlParseElementStart(xmlParserCtxtPtr ctxt) {
|
||||
const xmlChar *name;
|
||||
const xmlChar *prefix = NULL;
|
||||
const xmlChar *URI = NULL;
|
||||
@@ -9909,7 +9944,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
||||
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
|
||||
xmlParserMaxDepth);
|
||||
xmlHaltParser(ctxt);
|
||||
- return;
|
||||
+ return(-1);
|
||||
}
|
||||
|
||||
/* Capture start position */
|
||||
@@ -9936,12 +9971,17 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
||||
name = xmlParseStartTag(ctxt);
|
||||
#endif /* LIBXML_SAX1_ENABLED */
|
||||
if (ctxt->instate == XML_PARSER_EOF)
|
||||
- return;
|
||||
+ return(-1);
|
||||
if (name == NULL) {
|
||||
spacePop(ctxt);
|
||||
- return;
|
||||
+ return(-1);
|
||||
}
|
||||
- namePush(ctxt, name);
|
||||
+ if (ctxt->sax2)
|
||||
+ nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
|
||||
+#ifdef LIBXML_SAX1_ENABLED
|
||||
+ else
|
||||
+ namePush(ctxt, name);
|
||||
+#endif /* LIBXML_SAX1_ENABLED */
|
||||
ret = ctxt->node;
|
||||
|
||||
#ifdef LIBXML_VALID_ENABLED
|
||||
@@ -9982,7 +10022,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
||||
node_info.node = ret;
|
||||
xmlParserAddNodeInfo(ctxt, &node_info);
|
||||
}
|
||||
- return;
|
||||
+ return(1);
|
||||
}
|
||||
if (RAW == '>') {
|
||||
NEXT1;
|
||||
@@ -10010,41 +10050,39 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
|
||||
node_info.node = ret;
|
||||
xmlParserAddNodeInfo(ctxt, &node_info);
|
||||
}
|
||||
- return;
|
||||
+ return(-1);
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Parse the content of the element:
|
||||
- */
|
||||
- xmlParseContent(ctxt);
|
||||
- if (ctxt->instate == XML_PARSER_EOF)
|
||||
- return;
|
||||
- if (!IS_BYTE_CHAR(RAW)) {
|
||||
- xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
|
||||
- "Premature end of data in tag %s line %d\n",
|
||||
- name, line, NULL);
|
||||
+ return(0);
|
||||
+}
|
||||
|
||||
- /*
|
||||
- * end of parsing of this node.
|
||||
- */
|
||||
- nodePop(ctxt);
|
||||
- namePop(ctxt);
|
||||
- spacePop(ctxt);
|
||||
- if (nsNr != ctxt->nsNr)
|
||||
- nsPop(ctxt, ctxt->nsNr - nsNr);
|
||||
- return;
|
||||
- }
|
||||
+/**
|
||||
+ * xmlParseElementEnd:
|
||||
+ * @ctxt: an XML parser context
|
||||
+ *
|
||||
+ * Parse the end of an XML element.
|
||||
+ */
|
||||
+static void
|
||||
+xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
|
||||
+ xmlParserNodeInfo node_info;
|
||||
+ xmlNodePtr ret = ctxt->node;
|
||||
+
|
||||
+ if (ctxt->nameNr <= 0)
|
||||
+ return;
|
||||
|
||||
/*
|
||||
* parse the end of tag: '</' should be here.
|
||||
*/
|
||||
if (ctxt->sax2) {
|
||||
- xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
|
||||
+ const xmlChar *prefix = ctxt->pushTab[ctxt->nameNr * 3 - 3];
|
||||
+ const xmlChar *URI = ctxt->pushTab[ctxt->nameNr * 3 - 2];
|
||||
+ int nsNr = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 3 - 1];
|
||||
+ xmlParseEndTag2(ctxt, prefix, URI, 0, nsNr, 0);
|
||||
namePop(ctxt);
|
||||
}
|
||||
#ifdef LIBXML_SAX1_ENABLED
|
||||
- else
|
||||
- xmlParseEndTag1(ctxt, line);
|
||||
+ else
|
||||
+ xmlParseEndTag1(ctxt, 0);
|
||||
#endif /* LIBXML_SAX1_ENABLED */
|
||||
|
||||
/*
|
||||
@@ -12361,13 +12399,6 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
|
||||
return(NULL);
|
||||
}
|
||||
ctxt->dictNames = 1;
|
||||
- ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
|
||||
- if (ctxt->pushTab == NULL) {
|
||||
- xmlErrMemory(ctxt, NULL);
|
||||
- xmlFreeParserInputBuffer(buf);
|
||||
- xmlFreeParserCtxt(ctxt);
|
||||
- return(NULL);
|
||||
- }
|
||||
if (sax != NULL) {
|
||||
#ifdef LIBXML_SAX1_ENABLED
|
||||
if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
|
||||
@@ -14949,16 +14980,6 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
|
||||
|
||||
xmlCtxtReset(ctxt);
|
||||
|
||||
- if (ctxt->pushTab == NULL) {
|
||||
- ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
|
||||
- sizeof(xmlChar *));
|
||||
- if (ctxt->pushTab == NULL) {
|
||||
- xmlErrMemory(ctxt, NULL);
|
||||
- xmlFreeParserInputBuffer(buf);
|
||||
- return(1);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (filename == NULL) {
|
||||
ctxt->directory = NULL;
|
||||
} else {
|
||||
diff --git a/result/errors/754947.xml.err b/result/errors/754947.xml.err
|
||||
index f45cb5a..51e9b4e 100644
|
||||
--- a/result/errors/754947.xml.err
|
||||
+++ b/result/errors/754947.xml.err
|
||||
@@ -2,6 +2,6 @@
|
||||
Bytes: 0xEE 0x5D 0x5D 0x3E
|
||||
<d><![CDATA[0000000000000î]]>
|
||||
^
|
||||
-./test/errors/754947.xml:1: parser error : Premature end of data in tag d line 1
|
||||
+./test/errors/754947.xml:1: parser error : EndTag: '</' not found
|
||||
<d><![CDATA[0000000000000î]]>
|
||||
^
|
||||
diff --git a/result/errors/759398.xml.err b/result/errors/759398.xml.err
|
||||
index f6036a3..bc9e5e0 100644
|
||||
--- a/result/errors/759398.xml.err
|
||||
+++ b/result/errors/759398.xml.err
|
||||
@@ -1,10 +1,10 @@
|
||||
./test/errors/759398.xml:210: parser error : StartTag: invalid element name
|
||||
need to worry about parsers whi<! don't expand PErefs finding
|
||||
^
|
||||
-./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–m line 308 and termdef
|
||||
+./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–â„–m line 205 and termdef
|
||||
and provide access to their content and structure.</termdef> <termdef
|
||||
^
|
||||
-./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 50 and p
|
||||
+./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 205 and p
|
||||
data and the information it must provide to the application.</p>
|
||||
^
|
||||
./test/errors/759398.xml:316: parser error : Extra content at the end of the document
|
||||
--
|
||||
1.7.12.4
|
||||
|
||||
77
backport-Make-xmlTextReaderFreeNodeList-non-recursive.patch
Normal file
77
backport-Make-xmlTextReaderFreeNodeList-non-recursive.patch
Normal file
@ -0,0 +1,77 @@
|
||||
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
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From 73060457de03c0dada603bdc6c6e1fc9b08fc94b Mon Sep 17 00:00:00 2001
|
||||
From: Zhipeng Xie <xiezhipeng1@huawei.com>
|
||||
Date: Thu, 12 Dec 2019 17:30:55 +0800
|
||||
Subject: [PATCH] Fix infinite loop in xmlStringLenDecodeEntities
|
||||
|
||||
When ctxt->instate == XML_PARSER_EOF,xmlParseStringEntityRef
|
||||
return NULL which cause a infinite loop in xmlStringLenDecodeEntities
|
||||
|
||||
Found with libFuzzer.
|
||||
|
||||
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
|
||||
---
|
||||
parser.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index 4696f916..3e09b3e9 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -2786,7 +2786,8 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
||||
else
|
||||
c = 0;
|
||||
while ((c != 0) && (c != end) && /* non input consuming loop */
|
||||
- (c != end2) && (c != end3)) {
|
||||
+ (c != end2) && (c != end3) &&
|
||||
+ (ctxt->instate != XML_PARSER_EOF)) {
|
||||
|
||||
if (c == 0) break;
|
||||
if ((c == '&') && (str[1] == '#')) {
|
||||
--
|
||||
2.19.1
|
||||
|
||||
16
libxml2.spec
16
libxml2.spec
@ -1,7 +1,7 @@
|
||||
Summary: Library providing XML and HTML support
|
||||
Name: libxml2
|
||||
Version: 2.9.8
|
||||
Release: 8
|
||||
Release: 9
|
||||
License: MIT
|
||||
Group: Development/Libraries
|
||||
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
|
||||
@ -42,9 +42,20 @@ Patch6015: 0031-Fix-parser-termination-from-Double-hyphen-within-com.patch
|
||||
Patch6016: 0032-Fix-return-value-of-xmlOutputBufferWrite.patch
|
||||
Patch6017: 0034-Fix-unsigned-integer-overflow.patch
|
||||
Patch6018: 0037-Fix-memory-leak-in-xmlAllocOutputBufferInternal-erro.patch
|
||||
Patch6019: backport-Make-xmlParseContent-and-xmlParseElement-non-recursi.patch
|
||||
Patch6020: backport-Make-xmlFreeNodeList-non-recursive.patch
|
||||
Patch6021: backport-Make-xmlTextReaderFreeNodeList-non-recursive.patch
|
||||
Patch6022: backport-Fix-use-after-free-in-xmlTextReaderFreeNodeList.patch
|
||||
Patch6023: backport-Make-xmlParseConditionalSections-non-recursive.patch
|
||||
Patch6024: backport-Fix-for-conditional-sections-at-end-of-document.patch
|
||||
Patch6025: backport-Another-fix-for-conditional-sections-at-end-of-docum.patch
|
||||
Patch6026: backport-Make-xmlDumpElementContent-non-recursive.patch
|
||||
|
||||
Patch9000: Fix-memory-leak-in-xmlParseBalancedChunkMemoryRecove.patch
|
||||
Patch9001: Fix-memory-leak-in-xmlSchemaValidateStream.patch
|
||||
Patch6027: backport-fix-infinite-loop-in-xmlStringLenDecodeEntities.patch
|
||||
Patch6028: backport-Annotate-functions-with-__attribute__-no_sanitize.patch
|
||||
Patch6029: backport-Avoid-ignored-attribute-warnings-under-GCC.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
||||
BuildRequires: python2-devel
|
||||
@ -234,6 +245,9 @@ rm -fr %{buildroot}
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Mar 17 2020 Leo Fang<leofang_94@163.com> - 2.9.8-9
|
||||
- Sync some patches from community
|
||||
|
||||
* Thu Dec 19 2019 openEuler Buildteam <buildteam@openEuler.org> - 2.9.8-8
|
||||
- Delete unused infomation
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user