Sync some patches from community

This commit is contained in:
wsp1991 2020-03-17 21:03:10 +08:00
parent 7225a592c9
commit ebcc4287e9
12 changed files with 1453 additions and 1 deletions

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View 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 '&#37;<![INCLUDE[000&#37;&#3000;000&#37;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 '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
-./test/errors/759573.xml:1: parser error : DOCTYPE improperly terminated
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
-./test/errors/759573.xml:1: parser error : StartTag: invalid element name
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
-./test/errors/759573.xml:1: parser error : Extra content at the end of the document
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;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

View File

@ -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

View 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

View File

@ -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

View File

@ -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