Fixed some issues found in fuzzing testcases

This commit is contained in:
yang_zhuang_zhuang 2020-09-10 10:16:06 +08:00
parent 1368b5e2c0
commit 04bbcc0db4
22 changed files with 1599 additions and 1 deletions

View File

@ -0,0 +1,88 @@
From 11b5745927481d6a716acef5408da20899eab8a2 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Fri, 7 Aug 2020 18:39:19 +0200
Subject: [PATCH 108/139] Don't process siblings of root in xmlXIncludeProcess
xmlXIncludeDoProcess would follow the siblings of the tree root and
also expand these nodes. When using an XML reader, this could lead to
siblings of the current node being expanded without having been parsed
completely.
---
xinclude.c | 38 ++++++++++++++++++--------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/xinclude.c b/xinclude.c
index 0f1af9c..2917d45 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -1980,6 +1980,8 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
(ctxt == NULL))
return(-1);
if (fallback->children != NULL) {
+ xmlNodePtr child, next;
+
/*
* It's possible that the fallback also has 'includes'
* (Bug 129969), so we re-process the fallback just in case
@@ -1990,11 +1992,13 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
newctxt->_private = ctxt->_private;
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
- ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
+ for (child = fallback->children; child != NULL; child = next) {
+ next = child->next;
+ if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
+ ret = -1;
+ }
if (ctxt->nbErrors > oldNbErrors)
ret = -1;
- else if (ret > 0)
- ret = 0; /* xmlXIncludeDoProcess can return +ve number */
xmlXIncludeFreeContext(newctxt);
ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
@@ -2396,7 +2400,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
* First phase: lookup the elements in the document
*/
cur = tree;
- while ((cur != NULL) && (cur != tree->parent)) {
+ do {
/* TODO: need to work on entities -> stack */
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
xmlXIncludePreProcessNode(ctxt, cur);
@@ -2407,22 +2411,16 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
cur = cur->children;
continue;
}
- if (cur->next != NULL) {
- cur = cur->next;
- } else {
- if (cur == tree)
- break;
- do {
- cur = cur->parent;
- if ((cur == NULL) || (cur == tree->parent))
- break; /* do */
- if (cur->next != NULL) {
- cur = cur->next;
- break; /* do */
- }
- } while (cur != NULL);
- }
- }
+ do {
+ if (cur == tree)
+ break;
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
+ cur = cur->parent;
+ } while (cur != NULL);
+ } while ((cur != NULL) && (cur != tree));
/*
* Second Phase : collect the infosets fragments
--
1.8.3.1

View File

@ -0,0 +1,208 @@
From 0f9817c75b50a77c6aeb8f36801966fdadad229a Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 10 Jun 2020 16:34:52 +0200
Subject: [PATCH 107/139] Don't recurse into xi:include children in
xmlXIncludeDoProcess
Otherwise, nested xi:include nodes might result in a use-after-free
if XML_PARSE_NOXINCNODE is specified.
Found with libFuzzer and ASan.
---
result/XInclude/fallback3.xml | 8 ++++++++
result/XInclude/fallback3.xml.err | 0
result/XInclude/fallback3.xml.rdr | 25 +++++++++++++++++++++++++
result/XInclude/fallback4.xml | 10 ++++++++++
result/XInclude/fallback4.xml.err | 0
result/XInclude/fallback4.xml.rdr | 29 +++++++++++++++++++++++++++++
test/XInclude/docs/fallback3.xml | 9 +++++++++
test/XInclude/docs/fallback4.xml | 7 +++++++
xinclude.c | 24 ++++++++++--------------
9 files changed, 98 insertions(+), 14 deletions(-)
create mode 100644 result/XInclude/fallback3.xml
create mode 100644 result/XInclude/fallback3.xml.err
create mode 100644 result/XInclude/fallback3.xml.rdr
create mode 100644 result/XInclude/fallback4.xml
create mode 100644 result/XInclude/fallback4.xml.err
create mode 100644 result/XInclude/fallback4.xml.rdr
create mode 100644 test/XInclude/docs/fallback3.xml
create mode 100644 test/XInclude/docs/fallback4.xml
diff --git a/result/XInclude/fallback3.xml b/result/XInclude/fallback3.xml
new file mode 100644
index 0000000..b423551
--- /dev/null
+++ b/result/XInclude/fallback3.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<a>
+ <doc xml:base="../ents/something.xml">
+<p>something</p>
+<p>really</p>
+<p>simple</p>
+</doc>
+</a>
diff --git a/result/XInclude/fallback3.xml.err b/result/XInclude/fallback3.xml.err
new file mode 100644
index 0000000..e69de29
diff --git a/result/XInclude/fallback3.xml.rdr b/result/XInclude/fallback3.xml.rdr
new file mode 100644
index 0000000..aa2f137
--- /dev/null
+++ b/result/XInclude/fallback3.xml.rdr
@@ -0,0 +1,25 @@
+0 1 a 0 0
+1 14 #text 0 1
+
+1 1 doc 0 0
+2 14 #text 0 1
+
+2 1 p 0 0
+3 3 #text 0 1 something
+2 15 p 0 0
+2 14 #text 0 1
+
+2 1 p 0 0
+3 3 #text 0 1 really
+2 15 p 0 0
+2 14 #text 0 1
+
+2 1 p 0 0
+3 3 #text 0 1 simple
+2 15 p 0 0
+2 14 #text 0 1
+
+1 15 doc 0 0
+1 14 #text 0 1
+
+0 15 a 0 0
diff --git a/result/XInclude/fallback4.xml b/result/XInclude/fallback4.xml
new file mode 100644
index 0000000..9883fd5
--- /dev/null
+++ b/result/XInclude/fallback4.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<a>
+
+ <doc xml:base="../ents/something.xml">
+<p>something</p>
+<p>really</p>
+<p>simple</p>
+</doc>
+
+</a>
diff --git a/result/XInclude/fallback4.xml.err b/result/XInclude/fallback4.xml.err
new file mode 100644
index 0000000..e69de29
diff --git a/result/XInclude/fallback4.xml.rdr b/result/XInclude/fallback4.xml.rdr
new file mode 100644
index 0000000..628b951
--- /dev/null
+++ b/result/XInclude/fallback4.xml.rdr
@@ -0,0 +1,29 @@
+0 1 a 0 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 doc 0 0
+2 14 #text 0 1
+
+2 1 p 0 0
+3 3 #text 0 1 something
+2 15 p 0 0
+2 14 #text 0 1
+
+2 1 p 0 0
+3 3 #text 0 1 really
+2 15 p 0 0
+2 14 #text 0 1
+
+2 1 p 0 0
+3 3 #text 0 1 simple
+2 15 p 0 0
+2 14 #text 0 1
+
+1 15 doc 0 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+0 15 a 0 0
diff --git a/test/XInclude/docs/fallback3.xml b/test/XInclude/docs/fallback3.xml
new file mode 100644
index 0000000..0c8b6c9
--- /dev/null
+++ b/test/XInclude/docs/fallback3.xml
@@ -0,0 +1,9 @@
+<a>
+ <xi:include href="../ents/something.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:fallback>
+ <xi:include href="c.xml">
+ <xi:fallback>There is no c.xml ... </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+</a>
diff --git a/test/XInclude/docs/fallback4.xml b/test/XInclude/docs/fallback4.xml
new file mode 100644
index 0000000..b500a63
--- /dev/null
+++ b/test/XInclude/docs/fallback4.xml
@@ -0,0 +1,7 @@
+<a>
+ <xi:include href="c.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:fallback>
+ <xi:include href="../ents/something.xml"/>
+ </xi:fallback>
+ </xi:include>
+</a>
diff --git a/xinclude.c b/xinclude.c
index 461c1a5..0f1af9c 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -2396,21 +2396,19 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
* First phase: lookup the elements in the document
*/
cur = tree;
- if (xmlXIncludeTestNode(ctxt, cur) == 1)
- xmlXIncludePreProcessNode(ctxt, cur);
while ((cur != NULL) && (cur != tree->parent)) {
/* TODO: need to work on entities -> stack */
- if ((cur->children != NULL) &&
- (cur->children->type != XML_ENTITY_DECL) &&
- (cur->children->type != XML_XINCLUDE_START) &&
- (cur->children->type != XML_XINCLUDE_END)) {
- cur = cur->children;
- if (xmlXIncludeTestNode(ctxt, cur))
- xmlXIncludePreProcessNode(ctxt, cur);
- } else if (cur->next != NULL) {
+ if (xmlXIncludeTestNode(ctxt, cur) == 1) {
+ xmlXIncludePreProcessNode(ctxt, cur);
+ } else if ((cur->children != NULL) &&
+ (cur->children->type != XML_ENTITY_DECL) &&
+ (cur->children->type != XML_XINCLUDE_START) &&
+ (cur->children->type != XML_XINCLUDE_END)) {
+ cur = cur->children;
+ continue;
+ }
+ if (cur->next != NULL) {
cur = cur->next;
- if (xmlXIncludeTestNode(ctxt, cur))
- xmlXIncludePreProcessNode(ctxt, cur);
} else {
if (cur == tree)
break;
@@ -2420,8 +2418,6 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
break; /* do */
if (cur->next != NULL) {
cur = cur->next;
- if (xmlXIncludeTestNode(ctxt, cur))
- xmlXIncludePreProcessNode(ctxt, cur);
break; /* do */
}
} while (cur != NULL);
--
1.8.3.1

View File

@ -0,0 +1,115 @@
From 21ca8829a7366d72995adfeb21296d959fbb3777 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 25 Jul 2020 17:57:29 +0200
Subject: [PATCH 095/139] Don't try to handle namespaces when building HTML
documents
Don't try to resolve namespace in xmlSAX2StartElement when parsing
HTML documents. This useless operation could slow down the parser
considerably.
Found by OSS-Fuzz.
---
SAX2.c | 76 +++++++++++++++++++++++++++++++++---------------------------------
1 file changed, 38 insertions(+), 38 deletions(-)
diff --git a/SAX2.c b/SAX2.c
index 9df0184..4450a3f 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -1663,23 +1663,23 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
}
}
- /*
- * Insert all the defaulted attributes from the DTD especially namespaces
- */
- if ((!ctxt->html) &&
- ((ctxt->myDoc->intSubset != NULL) ||
- (ctxt->myDoc->extSubset != NULL))) {
- xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
- }
+ if (!ctxt->html) {
+ /*
+ * Insert all the defaulted attributes from the DTD especially
+ * namespaces
+ */
+ if ((ctxt->myDoc->intSubset != NULL) ||
+ (ctxt->myDoc->extSubset != NULL)) {
+ xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
+ }
- /*
- * process all the attributes whose name start with "xmlns"
- */
- if (atts != NULL) {
- i = 0;
- att = atts[i++];
- value = atts[i++];
- if (!ctxt->html) {
+ /*
+ * process all the attributes whose name start with "xmlns"
+ */
+ if (atts != NULL) {
+ i = 0;
+ att = atts[i++];
+ value = atts[i++];
while ((att != NULL) && (value != NULL)) {
if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
(att[3] == 'n') && (att[4] == 's'))
@@ -1688,30 +1688,30 @@ xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
att = atts[i++];
value = atts[i++];
}
- }
- }
+ }
- /*
- * Search the namespace, note that since the attributes have been
- * processed, the local namespaces are available.
- */
- ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
- if ((ns == NULL) && (parent != NULL))
- ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
- if ((prefix != NULL) && (ns == NULL)) {
- ns = xmlNewNs(ret, NULL, prefix);
- xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
- "Namespace prefix %s is not defined\n",
- prefix, NULL);
- }
+ /*
+ * Search the namespace, note that since the attributes have been
+ * processed, the local namespaces are available.
+ */
+ ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
+ if ((ns == NULL) && (parent != NULL))
+ ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
+ if ((prefix != NULL) && (ns == NULL)) {
+ ns = xmlNewNs(ret, NULL, prefix);
+ xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+ "Namespace prefix %s is not defined\n",
+ prefix, NULL);
+ }
- /*
- * set the namespace node, making sure that if the default namespace
- * is unbound on a parent we simply keep it NULL
- */
- if ((ns != NULL) && (ns->href != NULL) &&
- ((ns->href[0] != 0) || (ns->prefix != NULL)))
- xmlSetNs(ret, ns);
+ /*
+ * set the namespace node, making sure that if the default namespace
+ * is unbound on a parent we simply keep it NULL
+ */
+ if ((ns != NULL) && (ns->href != NULL) &&
+ ((ns->href[0] != 0) || (ns->prefix != NULL)))
+ xmlSetNs(ret, ns);
+ }
/*
* process all the other attributes
--
1.8.3.1

View File

@ -0,0 +1,58 @@
From 1493130ef24f8af2e1e70fdf12827374f670f7bf Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 15 Jul 2020 12:54:25 +0200
Subject: [PATCH 085/139] Fix UTF-8 decoder in HTML parser
Reject sequences starting with a continuation byte as well as overlong
sequences like the XML parser.
Also fixes an infinite loop in connection with previous commit 50078922
since htmlCurrentChar would return 0 even if not at the end of the
buffer.
Found by OSS-Fuzz.
---
HTMLparser.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/HTMLparser.c b/HTMLparser.c
index 26ed124..d31e2ec 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -439,6 +439,8 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
c = *cur;
if (c & 0x80) {
+ if ((c & 0x40) == 0)
+ goto encoding_error;
if (cur[1] == 0) {
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
cur = ctxt->input->cur;
@@ -467,18 +469,24 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
val |= (cur[1] & 0x3f) << 12;
val |= (cur[2] & 0x3f) << 6;
val |= cur[3] & 0x3f;
+ if (val < 0x10000)
+ goto encoding_error;
} else {
/* 3-byte code */
*len = 3;
val = (cur[0] & 0xf) << 12;
val |= (cur[1] & 0x3f) << 6;
val |= cur[2] & 0x3f;
+ if (val < 0x800)
+ goto encoding_error;
}
} else {
/* 2-byte code */
*len = 2;
val = (cur[0] & 0x1f) << 6;
val |= cur[1] & 0x3f;
+ if (val < 0x80)
+ goto encoding_error;
}
if (!IS_CHAR(val)) {
htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
--
1.8.3.1

View File

@ -0,0 +1,128 @@
From dba82a8c0453b7d4d138167a771c1c2988b889be Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 16 Aug 2020 23:02:20 +0200
Subject: [PATCH 121/139] Fix XInclude regression introduced with recent commit
The change to xmlXIncludeLoadFallback in commit 11b57459 could
process already freed nodes if text nodes were merged after deleting
nodes with an empty fallback.
Found by OSS-Fuzz.
---
xinclude.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/xinclude.c b/xinclude.c
index 41ff4e5..ff265eb 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -91,7 +91,8 @@ struct _xmlXIncludeCtxt {
};
static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
+ int skipRoot);
/************************************************************************
@@ -732,7 +733,7 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
*/
newctxt->parseFlags = ctxt->parseFlags;
newctxt->incTotal = ctxt->incTotal;
- xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
+ xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc), 0);
ctxt->incTotal = newctxt->incTotal;
for (i = 0;i < ctxt->incNr;i++) {
newctxt->incTab[i]->count--;
@@ -1984,8 +1985,6 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
(ctxt == NULL))
return(-1);
if (fallback->children != NULL) {
- xmlNodePtr child, next;
-
/*
* It's possible that the fallback also has 'includes'
* (Bug 129969), so we re-process the fallback just in case
@@ -1997,11 +1996,8 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
newctxt->incTotal = ctxt->incTotal;
- for (child = fallback->children; child != NULL; child = next) {
- next = child->next;
- if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
- ret = -1;
- }
+ if (xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback, 1) < 0)
+ ret = -1;
ctxt->incTotal = newctxt->incTotal;
if (ctxt->nbErrors > oldNbErrors)
ret = -1;
@@ -2386,6 +2382,7 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* @ctxt: the XInclude processing context
* @doc: an XML document
* @tree: the top of the tree to process
+ * @skipRoot: don't process the root node of the tree
*
* Implement the XInclude substitution on the XML document @doc
*
@@ -2393,13 +2390,16 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
* or the number of substitutions done.
*/
static int
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
+ int skipRoot) {
xmlNodePtr cur;
int ret = 0;
int i, start;
if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
return(-1);
+ if ((skipRoot) && (tree->children == NULL))
+ return(-1);
if (ctxt == NULL)
return(-1);
@@ -2413,7 +2413,10 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
/*
* First phase: lookup the elements in the document
*/
- cur = tree;
+ if (skipRoot)
+ cur = tree->children;
+ else
+ cur = tree;
do {
/* TODO: need to work on entities -> stack */
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
@@ -2521,7 +2524,7 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
ctxt->_private = data;
ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
xmlXIncludeSetFlags(ctxt, flags);
- ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
+ ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@@ -2605,7 +2608,7 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
return(-1);
ctxt->base = xmlNodeGetBase(tree->doc, tree);
xmlXIncludeSetFlags(ctxt, flags);
- ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
+ ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
@@ -2645,7 +2648,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
(node->doc == NULL) || (ctxt == NULL))
return(-1);
- ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
+ ret = xmlXIncludeDoProcess(ctxt, node->doc, node, 0);
if ((ret >= 0) && (ctxt->nbErrors > 0))
ret = -1;
return(ret);
--
1.8.3.1

View File

@ -0,0 +1,28 @@
From 50f18830e179f273c244d4969485c4154c81cc01 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 21 Jun 2020 15:21:45 +0200
Subject: [PATCH 058/139] Fix another memory leak in xmlSchemaValAtomicType
Don't collapse language IDs twice.
Found with libFuzzer and ASan.
---
xmlschemastypes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index 1a44052..35edfd6 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -2636,7 +2636,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
goto return0;
}
case XML_SCHEMAS_LANGUAGE:
- if (normOnTheFly) {
+ if ((norm == NULL) && (normOnTheFly)) {
norm = xmlSchemaCollapseString(value);
if (norm != NULL)
value = norm;
--
1.8.3.1

View File

@ -0,0 +1,29 @@
From ba589adc2f86c6be9ad7e0d771d4c9b09d059b89 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 25 Aug 2020 23:50:39 +0200
Subject: [PATCH 138/139] Fix double free in XML reader with XIncludes
An XInclude with empty fallback could lead to a double free in
xmlTextReaderRead.
Found by OSS-Fuzz.
---
xmlreader.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xmlreader.c b/xmlreader.c
index 6ae6e92..1ab15ba 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -1491,6 +1491,8 @@ get_next_node:
(reader->node->prev->type != XML_DTD_NODE)) {
xmlNodePtr tmp = reader->node->prev;
if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
+ if (oldnode == tmp)
+ oldnode = NULL;
xmlUnlinkNode(tmp);
xmlTextReaderFreeNode(reader, tmp);
}
--
1.8.3.1

View File

@ -0,0 +1,317 @@
From 1abf2967f955858764a6de5d7b7fe247cb637853 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 6 Aug 2020 17:51:57 +0200
Subject: [PATCH 109/139] Fix exponential runtime and memory in xi:fallback
processing
When creating XML_XINCLUDE_START nodes, the children of the original
xi:include node must be freed, otherwise fallback content is copied
twice, doubling runtime and memory consumption for each nested
xi:fallback/xi:include pair.
Found with libFuzzer.
---
result/XInclude/fallback5.xml | 51 +++++++++++++++++
result/XInclude/fallback5.xml.rdr | 116 ++++++++++++++++++++++++++++++++++++++
test/XInclude/docs/fallback5.xml | 83 +++++++++++++++++++++++++++
xinclude.c | 8 +++
4 files changed, 258 insertions(+)
create mode 100644 result/XInclude/fallback5.xml
create mode 100644 result/XInclude/fallback5.xml.rdr
create mode 100644 test/XInclude/docs/fallback5.xml
diff --git a/result/XInclude/fallback5.xml b/result/XInclude/fallback5.xml
new file mode 100644
index 0000000..0ba503d
--- /dev/null
+++ b/result/XInclude/fallback5.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<a>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+ <elem/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</a>
diff --git a/result/XInclude/fallback5.xml.rdr b/result/XInclude/fallback5.xml.rdr
new file mode 100644
index 0000000..0e1dab7
--- /dev/null
+++ b/result/XInclude/fallback5.xml.rdr
@@ -0,0 +1,116 @@
+0 1 a 0 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 1 elem 1 0
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+1 14 #text 0 1
+
+0 15 a 0 0
diff --git a/test/XInclude/docs/fallback5.xml b/test/XInclude/docs/fallback5.xml
new file mode 100644
index 0000000..d3ad424
--- /dev/null
+++ b/test/XInclude/docs/fallback5.xml
@@ -0,0 +1,83 @@
+<a>
+ <xi:include href="a01.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a02.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a03.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a04.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a05.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a06.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a07.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a08.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a09.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a10.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a11.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a12.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a13.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a14.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a15.xml">
+ <xi:fallback>
+ <elem/>
+ <xi:include href="a16.xml">
+ <xi:fallback>
+ <elem/>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+ </xi:fallback>
+ </xi:include>
+</a>
+
diff --git a/xinclude.c b/xinclude.c
index 2917d45..5ea87ad 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -2260,11 +2260,19 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlUnlinkNode(cur);
xmlFreeNode(cur);
} else {
+ xmlNodePtr child, next;
+
/*
* Change the current node as an XInclude start one, and add an
* XInclude end one
*/
cur->type = XML_XINCLUDE_START;
+ /* Remove fallback children */
+ for (child = cur->children; child != NULL; child = next) {
+ next = child->next;
+ xmlUnlinkNode(child);
+ xmlFreeNode(child);
+ }
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
if (end == NULL) {
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
--
1.8.3.1

View File

@ -0,0 +1,33 @@
From 18425d3ad5a9bbe5c6e7fd4a9a45691e6c8862d1 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 21 Jun 2020 19:14:23 +0200
Subject: [PATCH 060/139] Fix integer overflow in _xmlSchemaParseGYear
Found with libFuzzer and UBSan.
---
xmlschemastypes.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index 35edfd6..164db94 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -1222,7 +1222,14 @@ _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
firstChar = cur;
while ((*cur >= '0') && (*cur <= '9')) {
- dt->year = dt->year * 10 + (*cur - '0');
+ int digit = *cur - '0';
+
+ if (dt->year > LONG_MAX / 10)
+ return 2;
+ dt->year *= 10;
+ if (dt->year > LONG_MAX - digit)
+ return 2;
+ dt->year += digit;
cur++;
digcnt++;
}
--
1.8.3.1

View File

@ -0,0 +1,65 @@
From 31ca4a728cf96c9a341d0bfe489d2c0ba71dc6ff Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 15 Jun 2020 18:47:53 +0200
Subject: [PATCH 054/139] Fix integer overflow in htmlParseCharRef
Fixes #115.
---
HTMLparser.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 5dd62df..be7e14f 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -3400,13 +3400,16 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
((NXT(2) == 'x') || NXT(2) == 'X')) {
SKIP(3);
while (CUR != ';') {
- if ((CUR >= '0') && (CUR <= '9'))
- val = val * 16 + (CUR - '0');
- else if ((CUR >= 'a') && (CUR <= 'f'))
- val = val * 16 + (CUR - 'a') + 10;
- else if ((CUR >= 'A') && (CUR <= 'F'))
- val = val * 16 + (CUR - 'A') + 10;
- else {
+ if ((CUR >= '0') && (CUR <= '9')) {
+ if (val < 0x110000)
+ val = val * 16 + (CUR - '0');
+ } else if ((CUR >= 'a') && (CUR <= 'f')) {
+ if (val < 0x110000)
+ val = val * 16 + (CUR - 'a') + 10;
+ } else if ((CUR >= 'A') && (CUR <= 'F')) {
+ if (val < 0x110000)
+ val = val * 16 + (CUR - 'A') + 10;
+ } else {
htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF,
"htmlParseCharRef: missing semicolon\n",
NULL, NULL);
@@ -3419,9 +3422,10 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
} else if ((CUR == '&') && (NXT(1) == '#')) {
SKIP(2);
while (CUR != ';') {
- if ((CUR >= '0') && (CUR <= '9'))
- val = val * 10 + (CUR - '0');
- else {
+ if ((CUR >= '0') && (CUR <= '9')) {
+ if (val < 0x110000)
+ val = val * 10 + (CUR - '0');
+ } else {
htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF,
"htmlParseCharRef: missing semicolon\n",
NULL, NULL);
@@ -3440,6 +3444,9 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
*/
if (IS_CHAR(val)) {
return(val);
+ } else if (val >= 0x110000) {
+ htmlParseErr(ctxt, XML_ERR_INVALID_CHAR,
+ "htmlParseCharRef: value too large\n", NULL, NULL);
} else {
htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
"htmlParseCharRef: invalid xmlChar value %d\n",
--
1.8.3.1

View File

@ -0,0 +1,41 @@
From 8e7c20a1af8776677d7890f30b7a180567701a49 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 3 Aug 2020 17:30:41 +0200
Subject: [PATCH 103/139] Fix integer overflow when comparing schema dates
Found by OSS-Fuzz.
---
xmlschemastypes.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index 4249d70..d6b9f92 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -3691,6 +3691,8 @@ xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
minday = 0;
maxday = 0;
} else {
+ if (myear > LONG_MAX / 366)
+ return -2;
/* FIXME: This doesn't take leap year exceptions every 100/400 years
into account. */
maxday = 365 * myear + (myear + 3) / 4;
@@ -4079,6 +4081,14 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
if ((x == NULL) || (y == NULL))
return -2;
+ if ((x->value.date.year > LONG_MAX / 366) ||
+ (x->value.date.year < LONG_MIN / 366) ||
+ (y->value.date.year > LONG_MAX / 366) ||
+ (y->value.date.year < LONG_MIN / 366)) {
+ /* Possible overflow when converting to days. */
+ return -2;
+ }
+
if (x->value.date.tz_flag) {
if (!y->value.date.tz_flag) {
--
1.8.3.1

View File

@ -0,0 +1,55 @@
From 070d635e771a24f33e8480fa60689a881c9fa636 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 21 Jun 2020 16:26:38 +0200
Subject: [PATCH 059/139] Fix integer overflow when parsing {min,max}Occurs
Clamp value to INT_MAX.
Found with libFuzzer and UBSan.
---
xmlschemas.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/xmlschemas.c b/xmlschemas.c
index 81c47bc..cc20063 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -6074,7 +6074,16 @@ xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
return (def);
}
while ((*cur >= '0') && (*cur <= '9')) {
- ret = ret * 10 + (*cur - '0');
+ if (ret > INT_MAX / 10) {
+ ret = INT_MAX;
+ } else {
+ int digit = *cur - '0';
+ ret *= 10;
+ if (ret > INT_MAX - digit)
+ ret = INT_MAX;
+ else
+ ret += digit;
+ }
cur++;
}
while (IS_BLANK_CH(*cur))
@@ -6126,7 +6135,16 @@ xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
return (def);
}
while ((*cur >= '0') && (*cur <= '9')) {
- ret = ret * 10 + (*cur - '0');
+ if (ret > INT_MAX / 10) {
+ ret = INT_MAX;
+ } else {
+ int digit = *cur - '0';
+ ret *= 10;
+ if (ret > INT_MAX - digit)
+ ret = INT_MAX;
+ else
+ ret += digit;
+ }
cur++;
}
while (IS_BLANK_CH(*cur))
--
1.8.3.1

View File

@ -0,0 +1,37 @@
From e1c2d0adf02692fd668cfbb7025db437f1f5490b Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 16 Aug 2020 22:22:57 +0200
Subject: [PATCH 120/139] Fix memory leak in runtest.c
---
runtest.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/runtest.c b/runtest.c
index 19ed629..0f178cb 100644
--- a/runtest.c
+++ b/runtest.c
@@ -2108,16 +2108,16 @@ errParseTest(const char *filename, const char *result, const char *err,
xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
}
res = compareFileMem(result, base, size);
- if (res != 0) {
- fprintf(stderr, "Result for %s failed in %s\n", filename, result);
- return(-1);
- }
}
if (doc != NULL) {
if (base != NULL)
xmlFree((char *)base);
xmlFreeDoc(doc);
}
+ if (res != 0) {
+ fprintf(stderr, "Result for %s failed in %s\n", filename, result);
+ return(-1);
+ }
if (err != NULL) {
res = compareFileMem(err, testErrors, testErrorsSize);
if (res != 0) {
--
1.8.3.1

View File

@ -0,0 +1,52 @@
From fbb7fa9a9ad8269834d32ff872b1477ff7b9c705 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 19 Aug 2020 13:13:20 +0200
Subject: [PATCH 131/139] Fix memory leak in xmlXIncludeAddNode error paths
Found by OSS-Fuzz.
---
xinclude.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/xinclude.c b/xinclude.c
index 9024535..aac30d5 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -627,8 +627,8 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
"detected a local recursion with no xpointer in %s\n",
URL);
- if (fragment != NULL)
- xmlFree(fragment);
+ xmlFree(URL);
+ xmlFree(fragment);
return(-1);
}
@@ -640,12 +640,15 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
if (xmlStrEqual(URL, ctxt->urlTab[i])) {
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
"detected a recursion in %s\n", URL);
+ xmlFree(URL);
+ xmlFree(fragment);
return(-1);
}
}
}
ref = xmlXIncludeNewRef(ctxt, URL, cur);
+ xmlFree(URL);
if (ref == NULL) {
return(-1);
}
@@ -653,7 +656,6 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
ref->doc = NULL;
ref->xml = xml;
ref->count = 1;
- xmlFree(URL);
return(0);
}
--
1.8.3.1

View File

@ -0,0 +1,33 @@
From 5725c1153a74d997aa8ea8547574c049b040d5cb Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 10 Jun 2020 15:11:40 +0200
Subject: [PATCH 106/139] Fix memory leak in xmlXIncludeIncludeNode error paths
Found with libFuzzer and ASan.
---
xinclude.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xinclude.c b/xinclude.c
index baeb8db..461c1a5 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -2238,6 +2238,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
XML_XINCLUDE_MULTIPLE_ROOT,
"XInclude error: would result in multiple root nodes\n",
NULL);
+ xmlFreeNodeList(list);
return(-1);
}
}
@@ -2265,6 +2266,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
XML_XINCLUDE_BUILD_FAILED,
"failed to build node\n", NULL);
+ xmlFreeNodeList(list);
return(-1);
}
end->type = XML_XINCLUDE_END;
--
1.8.3.1

View File

@ -0,0 +1,33 @@
From ff009f991314ce8711f8a6a7f99107c10fb0a807 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 30 May 2020 15:32:25 +0200
Subject: [PATCH 042/139] Fix memory leak in xmlXIncludeLoadDoc error path
Found by OSS-Fuzz.
---
xinclude.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xinclude.c b/xinclude.c
index 5d44df4..baeb8db 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -1608,6 +1608,7 @@ loaded:
XML_XINCLUDE_XPTR_RESULT,
"XPointer is not a range: #%s\n",
fragment);
+ xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
@@ -1615,6 +1616,7 @@ loaded:
case XPATH_NODESET:
if ((xptr->nodesetval == NULL) ||
(xptr->nodesetval->nodeNr <= 0)) {
+ xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
--
1.8.3.1

View File

@ -0,0 +1,40 @@
From c7c526d6d0f605ed090f8fc1bbede9e439d3185c Mon Sep 17 00:00:00 2001
From: Kevin Puetz <PuetzKevinA@JohnDeere.com>
Date: Mon, 13 Jan 2020 18:49:01 -0600
Subject: [PATCH 021/139] Fix memory leak when shared libxml.dll is unloaded
When a multiple modules (process/plugins) all link to libxml2.dll
they will in fact share a single loaded instance of it.
It is unsafe for any of them to call xmlCleanupParser,
as this would deinitialize the shared state and break others that might
still have ongoing use.
However, on windows atexit is per-module (rather process-wide), so if used
*within* libxml2 it is possible to register a clean up when all users
are done and libxml2.dll is about to actually unload.
This allows multiple plugins to link with and share libxml2 without
a premature cleanup if one is unloaded, while still cleaning up if *all*
such callers are themselves unloaded.
---
parser.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/parser.c b/parser.c
index 43a1a0a..1ba988c 100644
--- a/parser.c
+++ b/parser.c
@@ -14741,6 +14741,10 @@ xmlInitParser(void) {
if (xmlParserInitialized != 0)
return;
+#if defined(WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+ atexit(xmlCleanupParser);
+#endif
+
#ifdef LIBXML_THREAD_ENABLED
__xmlGlobalInitMutexLock();
if (xmlParserInitialized == 0) {
--
1.8.3.1

View File

@ -0,0 +1,62 @@
From 500789224b59fa70d6837be5cd1edb8e2f1eccb6 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 12 Jul 2020 20:28:47 +0200
Subject: [PATCH 083/139] Fix quadratic runtime when parsing HTML script
content
If htmlParseScript returns upon hitting an invalid character,
htmlParseLookupSequence will be called again with checkIndex reset to
zero, potentially resulting in quadratic runtime. Make sure that
htmlParseScript consumes all input in one go and simply skips over
invalid characters similar to htmlParseCharDataInternal.
Found by OSS-Fuzz.
---
HTMLparser.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 1dea794..26ed124 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -2928,7 +2928,7 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
SHRINK;
cur = CUR_CHAR(l);
- while (IS_CHAR_CH(cur)) {
+ while (cur != 0) {
if ((cur == '<') && (NXT(1) == '/')) {
/*
* One should break here, the specification is clear:
@@ -2959,7 +2959,12 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
}
}
}
- COPY_BUF(l,buf,nbchar,cur);
+ if (IS_CHAR_CH(cur)) {
+ COPY_BUF(l,buf,nbchar,cur);
+ } else {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Invalid char in CDATA 0x%X\n", cur);
+ }
if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
buf[nbchar] = 0;
if (ctxt->sax->cdataBlock!= NULL) {
@@ -2977,14 +2982,6 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
cur = CUR_CHAR(l);
}
- if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) {
- htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
- "Invalid char in CDATA 0x%X\n", cur);
- if (ctxt->input->cur < ctxt->input->end) {
- NEXT;
- }
- }
-
if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) {
buf[nbchar] = 0;
if (ctxt->sax->cdataBlock!= NULL) {
--
1.8.3.1

View File

@ -0,0 +1,27 @@
From 487871b0e39bcc69ec0c1f69c30e2697712c6829 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 10 Jun 2020 13:23:43 +0200
Subject: [PATCH 048/139] Fix undefined behavior in xmlXPathTryStreamCompile
&NULL[0] is undefined behavior.
---
xpath.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/xpath.c b/xpath.c
index 1510d69..74848cd 100644
--- a/xpath.c
+++ b/xpath.c
@@ -14104,8 +14104,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
}
}
- stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
- &namespaces[0]);
+ stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, namespaces);
if (namespaces != NULL) {
xmlFree((xmlChar **)namespaces);
}
--
1.8.3.1

View File

@ -0,0 +1,65 @@
From 6c128fd58a0e4641c23a345d413672494622db1b Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Fri, 5 Jun 2020 13:43:45 +0200
Subject: [PATCH 111/139] Fuzz XInclude engine
---
xinclude.c | 15 +++++++++++++++
1 files changed, 15 insertions(+)
diff --git a/xinclude.c b/xinclude.c
index 5ea87ad..41ff4e5 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -86,6 +86,8 @@ struct _xmlXIncludeCtxt {
xmlChar * base; /* the current xml:base */
void *_private; /* application data */
+
+ unsigned long incTotal; /* total number of processed inclusions */
};
static int
@@ -729,7 +731,9 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
* (bug 132597)
*/
newctxt->parseFlags = ctxt->parseFlags;
+ newctxt->incTotal = ctxt->incTotal;
xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
+ ctxt->incTotal = newctxt->incTotal;
for (i = 0;i < ctxt->incNr;i++) {
newctxt->incTab[i]->count--;
newctxt->incTab[i] = NULL;
@@ -1992,11 +1996,13 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
newctxt->_private = ctxt->_private;
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
+ newctxt->incTotal = ctxt->incTotal;
for (child = fallback->children; child != NULL; child = next) {
next = child->next;
if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
ret = -1;
}
+ ctxt->incTotal = newctxt->incTotal;
if (ctxt->nbErrors > oldNbErrors)
ret = -1;
xmlXIncludeFreeContext(newctxt);
@@ -2411,6 +2417,15 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
do {
/* TODO: need to work on entities -> stack */
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /*
+ * Avoid superlinear expansion by limiting the total number
+ * of replacements.
+ */
+ if (ctxt->incTotal >= 20)
+ return(-1);
+#endif
+ ctxt->incTotal++;
xmlXIncludePreProcessNode(ctxt, cur);
} else if ((cur->children != NULL) &&
(cur->children->type != XML_ENTITY_DECL) &&
--
1.8.3.1

View File

@ -0,0 +1,60 @@
From f0fd1b67fc883a24cdd039abb3d4fe4696104d72 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 26 Aug 2020 00:16:38 +0200
Subject: [PATCH 139/139] Limit size of free lists in XML reader when fuzzing
Keeping objects on a free list can hide memory errors. Only allow a
single node on free lists used by the XML reader when fuzzing. This
should hide fewer errors while still exercising the free list logic.
---
xmlreader.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/xmlreader.c b/xmlreader.c
index 1ab15ba..a9b9ef9 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -48,6 +48,13 @@
#define MAX_ERR_MSG_SIZE 64000
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/* Keeping free objects can hide memory errors. */
+#define MAX_FREE_NODES 1
+#else
+#define MAX_FREE_NODES 100
+#endif
+
/*
* The following VA_COPY was coded following an example in
* the Samba project. It may not be sufficient for some
@@ -365,7 +372,7 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
DICT_FREE(cur->name);
if ((reader != NULL) && (reader->ctxt != NULL) &&
- (reader->ctxt->freeAttrsNr < 100)) {
+ (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeAttrs;
reader->ctxt->freeAttrs = cur;
reader->ctxt->freeAttrsNr++;
@@ -466,7 +473,7 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_TEXT_NODE)) &&
(reader != NULL) && (reader->ctxt != NULL) &&
- (reader->ctxt->freeElemsNr < 100)) {
+ (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeElems;
reader->ctxt->freeElems = cur;
reader->ctxt->freeElemsNr++;
@@ -554,7 +561,7 @@ xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_TEXT_NODE)) &&
(reader != NULL) && (reader->ctxt != NULL) &&
- (reader->ctxt->freeElemsNr < 100)) {
+ (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeElems;
reader->ctxt->freeElems = cur;
reader->ctxt->freeElemsNr++;
--
1.8.3.1

View File

@ -1,7 +1,7 @@
Summary: Library providing XML and HTML support
Name: libxml2
Version: 2.9.10
Release: 6
Release: 7
License: MIT
Group: Development/Libraries
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
@ -33,6 +33,27 @@ Patch23: Limit-regexp-nesting-depth.patch
Patch24: Fix-exponential-runtime-in-xmlFARecurseDeterminism.patch
Patch25: Fix-more-quadratic-runtime-issues-in-HTML-push-parse.patch
Patch26: Reset-HTML-parser-input-before-reporting-error.patch
Patch27: Fix-memory-leak-when-shared-libxml-dll-is-unloaded.patch
Patch28: Fix-memory-leak-in-xmlXIncludeLoadDoc-error-path.patch
Patch29: Fix-undefined-behavior-in-xmlXPathTryStreamCompile.patch
Patch30: Fix-integer-overflow-in-htmlParseCharRef.patch
Patch31: Fix-another-memory-leak-in-xmlSchemaValAtomicType.patch
Patch32: Fix-integer-overflow-when-parsing-min-max-Occurs.patch
Patch33: Fix-integer-overflow-in-_xmlSchemaParseGYear.patch
Patch34: Fix-quadratic-runtime-when-parsing-HTML-script-conte.patch
Patch35: Fix-UTF-8-decoder-in-HTML-parser.patch
Patch36: Don-t-try-to-handle-namespaces-when-building-HTML-do.patch
Patch37: Fix-integer-overflow-when-comparing-schema-dates.patch
Patch38: Fix-memory-leak-in-xmlXIncludeIncludeNode-error-path.patch
Patch39: Don-t-recurse-into-xi-include-children-in-xmlXInclud.patch
Patch40: Don-t-process-siblings-of-root-in-xmlXIncludeProcess.patch
Patch41: Fix-exponential-runtime-and-memory-in-xi-fallback-pr.patch
Patch42: Fuzz-XInclude-engine.patch
Patch43: Fix-memory-leak-in-runtest.c.patch
Patch44: Fix-XInclude-regression-introduced-with-recent-commi.patch
Patch45: Fix-memory-leak-in-xmlXIncludeAddNode-error-paths.patch
Patch46: Fix-double-free-in-XML-reader-with-XIncludes.patch
Patch47: Limit-size-of-free-lists-in-XML-reader-when-fuzzing.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-root
BuildRequires: python2-devel
@ -224,6 +245,9 @@ rm -fr %{buildroot}
%changelog
* Thu Sep 10 2020 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 2.9.10-7
- Fixed some issues found in fuzzing testcases
* Fri Aug 28 2020 zoulin <zoulin13@huawei.com> - 2.9.10-6
- Fix more quadratic runtime issues in HTML push parse
- Fix reset HTML parser input before reporting error