fix problems detected by oss-fuzz test

This commit is contained in:
Liquor 2021-03-02 19:40:18 +08:00
parent f712b88ad5
commit 5a155f4191
12 changed files with 1548 additions and 1 deletions

View File

@ -0,0 +1,306 @@
From 32cb5dccda6d9c72aaa1717d7100277b755cca94 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 11 Feb 2020 13:16:10 +0100
Subject: [PATCH] Add test case for recursive external parsed entities
---
result/errors/rec_ext_ent.xml | 5 +
result/errors/rec_ext_ent.xml.ent | 243 ++++++++++++++++++++++++++++++
result/errors/rec_ext_ent.xml.err | 0
result/errors/rec_ext_ent.xml.str | 0
test/errors/rec_ext.ent | 1 +
test/errors/rec_ext_ent.xml | 4 +
6 files changed, 253 insertions(+)
create mode 100644 result/errors/rec_ext_ent.xml
create mode 100644 result/errors/rec_ext_ent.xml.ent
create mode 100644 result/errors/rec_ext_ent.xml.err
create mode 100644 result/errors/rec_ext_ent.xml.str
create mode 100644 test/errors/rec_ext.ent
create mode 100644 test/errors/rec_ext_ent.xml
diff --git a/result/errors/rec_ext_ent.xml b/result/errors/rec_ext_ent.xml
new file mode 100644
index 00000000..6a196cb5
--- /dev/null
+++ b/result/errors/rec_ext_ent.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ENTITY e SYSTEM "rec_ext.ent">
+]>
+<doc>&e; &e; &e; &e;</doc>
diff --git a/result/errors/rec_ext_ent.xml.ent b/result/errors/rec_ext_ent.xml.ent
new file mode 100644
index 00000000..30dd2854
--- /dev/null
+++ b/result/errors/rec_ext_ent.xml.ent
@@ -0,0 +1,243 @@
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
+<ent>&e; &e; &e; &e;</ent>
+ ^
+test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
+
+^
+./test/errors/rec_ext_ent.xml:4: parser error : Entity 'e' failed to parse
+<doc>&e; &e; &e; &e;</doc>
+ ^
diff --git a/result/errors/rec_ext_ent.xml.err b/result/errors/rec_ext_ent.xml.err
new file mode 100644
index 00000000..e69de29b
diff --git a/result/errors/rec_ext_ent.xml.str b/result/errors/rec_ext_ent.xml.str
new file mode 100644
index 00000000..e69de29b
diff --git a/test/errors/rec_ext.ent b/test/errors/rec_ext.ent
new file mode 100644
index 00000000..345f836f
--- /dev/null
+++ b/test/errors/rec_ext.ent
@@ -0,0 +1 @@
+<ent>&e; &e; &e; &e;</ent>
diff --git a/test/errors/rec_ext_ent.xml b/test/errors/rec_ext_ent.xml
new file mode 100644
index 00000000..b4e7e749
--- /dev/null
+++ b/test/errors/rec_ext_ent.xml
@@ -0,0 +1,4 @@
+<!DOCTYPE doc [
+ <!ENTITY e SYSTEM "rec_ext.ent">
+]>
+<doc>&e; &e; &e; &e;</doc>
--
2.27.0

View File

@ -0,0 +1,34 @@
From 31c6ce3b63f8a494ad9e31ca65187a73d8ad3508 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 9 Nov 2020 17:55:44 +0100
Subject: [PATCH] Avoid call stack overflow with XML reader and recursive
XIncludes
Don't process XIncludes in the result of another inclusion to avoid
infinite recursion resulting in a call stack overflow.
This is something the XInclude engine shouldn't allow but correct
handling of intra-document includes would require major changes.
Found by OSS-Fuzz.
---
xmlreader.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/xmlreader.c b/xmlreader.c
index 01adf74f..72e40b03 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -1585,7 +1585,8 @@ node_found:
/*
* Handle XInclude if asked for
*/
- if ((reader->xinclude) && (reader->node != NULL) &&
+ if ((reader->xinclude) && (reader->in_xinclude == 0) &&
+ (reader->node != NULL) &&
(reader->node->type == XML_ELEMENT_NODE) &&
(reader->node->ns != NULL) &&
((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
--
2.27.0

View File

@ -0,0 +1,286 @@
From 8e219b154e9b938af84c4b009aefa692020103f9 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 12 Jul 2020 21:43:44 +0200
Subject: [PATCH] Fix HTML push parser lookahead
The parsing rules when looking for terminating chars or sequences in
the push parser differed from the actual parsing code. This could
result in the lookahead to overshoot and data being rescanned,
potentially leading to quadratic runtime.
Comments must never be handled during lookahead. Attribute values must
only be skipped for start tags and doctype declarations, not for end
tags, comments, PIs and script content.
---
HTMLparser.c | 88 +++++++++++++---------------------------------------
1 file changed, 21 insertions(+), 67 deletions(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 06d8c602..d10cf11f 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -5136,7 +5136,7 @@ htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
* @first: the first char to lookup
* @next: the next char to lookup or zero
* @third: the next char to lookup or zero
- * @comment: flag to force checking inside comments
+ * @ignoreattrval: skip over attribute values
*
* Try to find if a sequence (first, next, third) or just (first next) or
* (first) is available in the input stream.
@@ -5150,13 +5150,11 @@ htmlCreateDocParserCtxt(const xmlChar *cur, const char *encoding) {
*/
static int
htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
- xmlChar next, xmlChar third, int iscomment,
- int ignoreattrval)
+ xmlChar next, xmlChar third, int ignoreattrval)
{
int base, len;
htmlParserInputPtr in;
const xmlChar *buf;
- int incomment = 0;
int invalue = 0;
char valdellim = 0x0;
@@ -5171,8 +5169,7 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
if (ctxt->checkIndex > base) {
base = ctxt->checkIndex;
/* Abuse hasPErefs member to restore current state. */
- incomment = ctxt->hasPErefs & 1 ? 1 : 0;
- invalue = ctxt->hasPErefs & 2 ? 1 : 0;
+ invalue = ctxt->hasPErefs & 1 ? 1 : 0;
}
if (in->buf == NULL) {
@@ -5189,14 +5186,6 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
else if (next)
len--;
for (; base < len; base++) {
- if ((!incomment) && (base + 4 < len) && (!iscomment)) {
- if ((buf[base] == '<') && (buf[base + 1] == '!') &&
- (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
- incomment = 1;
- /* do not increment past <! - some people use <!--> */
- base += 2;
- }
- }
if (ignoreattrval) {
if (buf[base] == '"' || buf[base] == '\'') {
if (invalue) {
@@ -5213,16 +5202,6 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
continue;
}
}
- if (incomment) {
- if (base + 3 > len)
- break;
- if ((buf[base] == '-') && (buf[base + 1] == '-') &&
- (buf[base + 2] == '>')) {
- incomment = 0;
- base += 2;
- }
- continue;
- }
if (buf[base] == first) {
if (third != 0) {
if ((buf[base + 1] != next) || (buf[base + 2] != third))
@@ -5251,11 +5230,10 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
}
ctxt->checkIndex = base;
/* Abuse hasPErefs member to track current state. */
- ctxt->hasPErefs = 0;
- if (incomment)
- ctxt->hasPErefs |= 1;
if (invalue)
- ctxt->hasPErefs |= 2;
+ ctxt->hasPErefs |= 1;
+ else
+ ctxt->hasPErefs &= ~1;
#ifdef DEBUG_PUSH
if (next == 0)
xmlGenericError(xmlGenericErrorContext,
@@ -5293,7 +5271,6 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
int base, len;
htmlParserInputPtr in;
const xmlChar *buf;
- int incomment = 0;
int i;
in = ctxt->input;
@@ -5304,11 +5281,8 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
if (base < 0)
return (-1);
- if (ctxt->checkIndex > base) {
+ if (ctxt->checkIndex > base)
base = ctxt->checkIndex;
- /* Abuse hasPErefs member to restore current state. */
- incomment = ctxt->hasPErefs & 1 ? 1 : 0;
- }
if (in->buf == NULL) {
buf = in->base;
@@ -5319,24 +5293,6 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
}
for (; base < len; base++) {
- if (!incomment && (base + 4 < len)) {
- if ((buf[base] == '<') && (buf[base + 1] == '!') &&
- (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
- incomment = 1;
- /* do not increment past <! - some people use <!--> */
- base += 2;
- }
- }
- if (incomment) {
- if (base + 3 > len)
- break;
- if ((buf[base] == '-') && (buf[base + 1] == '-') &&
- (buf[base + 2] == '>')) {
- incomment = 0;
- base += 2;
- }
- continue;
- }
for (i = 0; i < stopLen; ++i) {
if (buf[base] == stop[i]) {
ctxt->checkIndex = 0;
@@ -5345,8 +5301,6 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
}
}
ctxt->checkIndex = base;
- /* Abuse hasPErefs member to track current state. */
- ctxt->hasPErefs = incomment;
return (-1);
}
@@ -5489,7 +5443,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(UPP(6) == 'Y') && (UPP(7) == 'P') &&
(UPP(8) == 'E')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5536,7 +5490,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '-', '-', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5546,7 +5500,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_MISC;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5560,7 +5514,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(UPP(6) == 'Y') && (UPP(7) == 'P') &&
(UPP(8) == 'E')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5597,7 +5551,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '-', '-', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5607,7 +5561,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_PROLOG;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5645,7 +5599,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if ((cur == '<') && (next == '!') &&
(in->cur[2] == '-') && (in->cur[3] == '-')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '-', '-', '>', 1, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '-', '-', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5655,7 +5609,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_EPILOG;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5719,7 +5673,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
break;
}
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
/* Capture start position */
@@ -5866,7 +5820,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
int idx;
xmlChar val;
- idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0, 0);
+ idx = htmlParseLookupSequence(ctxt, '<', '/', 0, 0);
if (idx < 0)
goto done;
val = in->cur[idx + 2];
@@ -5893,7 +5847,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(UPP(6) == 'Y') && (UPP(7) == 'P') &&
(UPP(8) == 'E')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 1) < 0))
goto done;
htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
"Misplaced DOCTYPE declaration\n",
@@ -5903,7 +5857,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
(in->cur[2] == '-') && (in->cur[3] == '-')) {
if ((!terminate) &&
(htmlParseLookupSequence(
- ctxt, '-', '-', '>', 1, 1) < 0))
+ ctxt, '-', '-', '>', 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5913,7 +5867,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
ctxt->instate = XML_PARSER_CONTENT;
} else if ((cur == '<') && (next == '?')) {
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
@@ -5984,7 +5938,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
if (avail < 2)
goto done;
if ((!terminate) &&
- (htmlParseLookupSequence(ctxt, '>', 0, 0, 0, 1) < 0))
+ (htmlParseLookupSequence(ctxt, '>', 0, 0, 0) < 0))
goto done;
htmlParseEndTag(ctxt);
if (ctxt->nameNr == 0) {
--
2.27.0

View File

@ -0,0 +1,31 @@
From 954696e7cf236c3aa71dc0b7f9e70d3f51e5cb07 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 7 Feb 2021 13:23:09 +0100
Subject: [PATCH] Fix infinite loop in HTML parser introduced with recent
commits
Check for XML_PARSER_EOF to avoid an infinite loop introduced with
recent changes to the HTML push parser.
Found by OSS-Fuzz.
---
HTMLparser.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 2877f4b7..14cc56fa 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -5872,7 +5872,8 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
xmlGenericError(xmlGenericErrorContext,
"HPP: Parsing char data\n");
#endif
- while ((cur != '<') && (in->cur < in->end)) {
+ while ((ctxt->instate != XML_PARSER_EOF) &&
+ (cur != '<') && (in->cur < in->end)) {
if (cur == '&') {
htmlParseReference(ctxt);
} else {
--
2.27.0

View File

@ -0,0 +1,99 @@
From 8ca3a59b2ee57e2f30272272bb232c84d03b9edc Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 15 Dec 2020 20:14:28 +0100
Subject: [PATCH] Fix integer overflow in xmlSchemaGetParticleTotalRangeMin
The function is only used once and its return value is only checked for
zero. Disable the function like its Max counterpart and add an
implementation for the special case.
Found by OSS-Fuzz.
---
xmlschemas.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 45 insertions(+), 5 deletions(-)
diff --git a/xmlschemas.c b/xmlschemas.c
index c455b4a3..1efd0962 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -14721,6 +14721,7 @@ xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
return (NULL);
}
+#if 0
/**
* xmlSchemaGetParticleTotalRangeMin:
* @particle: the particle
@@ -14776,7 +14777,6 @@ xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
}
}
-#if 0
/**
* xmlSchemaGetParticleTotalRangeMax:
* @particle: the particle
@@ -14838,6 +14838,48 @@ xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
}
#endif
+/**
+ * xmlSchemaGetParticleEmptiable:
+ * @particle: the particle
+ *
+ * Returns 1 if emptiable, 0 otherwise.
+ */
+static int
+xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
+{
+ xmlSchemaParticlePtr part;
+ int emptiable;
+
+ if ((particle->children == NULL) || (particle->minOccurs == 0))
+ return (1);
+
+ part = (xmlSchemaParticlePtr) particle->children->children;
+ if (part == NULL)
+ return (1);
+
+ while (part != NULL) {
+ if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
+ (part->children->type == XML_SCHEMA_TYPE_ANY))
+ emptiable = (part->minOccurs == 0);
+ else
+ emptiable = xmlSchemaGetParticleEmptiable(part);
+ if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
+ if (emptiable)
+ return (1);
+ } else {
+ /* <all> and <sequence> */
+ if (!emptiable)
+ return (0);
+ }
+ part = (xmlSchemaParticlePtr) part->next;
+ }
+
+ if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
+ return (0);
+ else
+ return (1);
+}
+
/**
* xmlSchemaIsParticleEmptiable:
* @particle: the particle
@@ -14860,10 +14902,8 @@ xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
* SPEC (2) "Its {term} is a group and the minimum part of the
* effective total range of that group, [...] is 0."
*/
- if (WXS_IS_MODEL_GROUP(particle->children)) {
- if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
- return (1);
- }
+ if (WXS_IS_MODEL_GROUP(particle->children))
+ return (xmlSchemaGetParticleEmptiable(particle));
return (0);
}
--
2.27.0

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
From 94c2e415a9bc1b9e7b7210a9c73817106bb1f175 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 6 Dec 2020 16:38:00 +0100
Subject: [PATCH] Fix quadratic runtime in HTML push parser with null bytes
Null bytes in the input stream do not necessarily signal an EOF
condition. Check the stream pointers for EOF to avoid quadratic
rescanning of input data.
Note that the CUR_CHAR macro used in functions like htmlParseCharData
calls htmlCurrentChar which translates null bytes.
Found by OSS-Fuzz.
---
HTMLparser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index de624f8d..26a1cdc2 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -5832,7 +5832,7 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
xmlGenericError(xmlGenericErrorContext,
"HPP: Parsing char data\n");
#endif
- while ((cur != '<') && (cur != 0)) {
+ while ((cur != '<') && (in->cur < in->end)) {
if (cur == '&') {
htmlParseReference(ctxt);
} else {
--
2.27.0

View File

@ -0,0 +1,128 @@
From 6995eed077899c64d34fe8f0d0b34d214cf586af Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 19 Jul 2020 13:54:52 +0200
Subject: [PATCH] Fix quadratic runtime when push parsing HTML entity refs
The HTML push parser would look ahead for characters in "; >/" to
terminate an entity reference but actual parsing could stop earlier,
potentially resulting in quadratic runtime.
Parse char data and references alternately in htmlParseTryOrFinish
and only look ahead once for a terminating '<' character.
Found by OSS-Fuzz.
---
HTMLparser.c | 77 ++++++----------------------------------------------
1 file changed, 9 insertions(+), 68 deletions(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index d10cf11f..ad9d7ccc 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -5249,61 +5249,6 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
return (-1);
}
-/**
- * htmlParseLookupChars:
- * @ctxt: an HTML parser context
- * @stop: Array of chars, which stop the lookup.
- * @stopLen: Length of stop-Array
- *
- * Try to find if any char of the stop-Array is available in the input
- * stream.
- * This function has a side effect of (possibly) incrementing ctxt->checkIndex
- * to avoid rescanning sequences of bytes, it DOES change the state of the
- * parser, do not use liberally.
- *
- * Returns the index to the current parsing point if a stopChar
- * is available, -1 otherwise.
- */
-static int
-htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
- int stopLen)
-{
- int base, len;
- htmlParserInputPtr in;
- const xmlChar *buf;
- int i;
-
- in = ctxt->input;
- if (in == NULL)
- return (-1);
-
- base = in->cur - in->base;
- if (base < 0)
- return (-1);
-
- if (ctxt->checkIndex > base)
- base = ctxt->checkIndex;
-
- if (in->buf == NULL) {
- buf = in->base;
- len = in->length;
- } else {
- buf = xmlBufContent(in->buf->buffer);
- len = xmlBufUse(in->buf->buffer);
- }
-
- for (; base < len; base++) {
- for (i = 0; i < stopLen; ++i) {
- if (buf[base] == stop[i]) {
- ctxt->checkIndex = 0;
- return (base - (in->cur - in->base));
- }
- }
- }
- ctxt->checkIndex = base;
- return (-1);
-}
-
/**
* htmlParseTryOrFinish:
* @ctxt: an HTML parser context
@@ -5893,17 +5838,6 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
"HPP: entering START_TAG\n");
#endif
break;
- } else if (cur == '&') {
- if ((!terminate) &&
- (htmlParseLookupChars(ctxt,
- BAD_CAST "; >/", 4) < 0))
- goto done;
-#ifdef DEBUG_PUSH
- xmlGenericError(xmlGenericErrorContext,
- "HPP: Parsing Reference\n");
-#endif
- /* TODO: check generation of subtrees if noent !!! */
- htmlParseReference(ctxt);
} else {
/*
* check that the text sequence is complete
@@ -5912,14 +5846,21 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) {
* data detection.
*/
if ((!terminate) &&
- (htmlParseLookupChars(ctxt, BAD_CAST "<&", 2) < 0))
+ (htmlParseLookupSequence(ctxt, '<', 0, 0, 0) < 0))
goto done;
ctxt->checkIndex = 0;
#ifdef DEBUG_PUSH
xmlGenericError(xmlGenericErrorContext,
"HPP: Parsing char data\n");
#endif
- htmlParseCharData(ctxt);
+ while ((cur != '<') && (cur != 0)) {
+ if (cur == '&') {
+ htmlParseReference(ctxt);
+ } else {
+ htmlParseCharData(ctxt);
+ }
+ cur = in->cur[0];
+ }
}
}
if (cons == ctxt->nbChars) {
--
2.27.0

View File

@ -0,0 +1,48 @@
From 741b0d0a8b9bbee67d68af022cb3137c74e9cd0f Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 7 Jul 2020 12:54:34 +0200
Subject: [PATCH] Fix regression introduced with 477c7f6a
The 'inSubset' member is actually used by the SAX2 handlers. Store
extra parser state in 'hasPErefs'.
---
HTMLparser.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 468db107..366c19b3 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -5160,9 +5160,9 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
if (ctxt->checkIndex > base) {
base = ctxt->checkIndex;
- /* Abuse inSubset member to restore current state. */
- incomment = ctxt->inSubset & 1 ? 1 : 0;
- invalue = ctxt->inSubset & 2 ? 1 : 0;
+ /* Abuse hasPErefs member to restore current state. */
+ incomment = ctxt->hasPErefs & 1 ? 1 : 0;
+ invalue = ctxt->hasPErefs & 2 ? 1 : 0;
}
if (in->buf == NULL) {
@@ -5240,12 +5240,12 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
}
}
ctxt->checkIndex = base;
- /* Abuse inSubset member to track current state. */
- ctxt->inSubset = 0;
+ /* Abuse hasPErefs member to track current state. */
+ ctxt->hasPErefs = 0;
if (incomment)
- ctxt->inSubset |= 1;
+ ctxt->hasPErefs |= 1;
if (invalue)
- ctxt->inSubset |= 2;
+ ctxt->hasPErefs |= 2;
#ifdef DEBUG_PUSH
if (next == 0)
xmlGenericError(xmlGenericErrorContext,
--
2.27.0

View File

@ -0,0 +1,306 @@
From 79301d3d5e553d46fc3201f48dcec3a93068c5a2 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Fri, 18 Dec 2020 12:50:21 +0100
Subject: [PATCH] Fix timeout when handling recursive entities
Abort parsing early to avoid an almost infinite loop in certain error
cases involving recursive entities.
Found with libFuzzer.
---
parser.c | 1 +
result/errors/rec_ext_ent.xml.ent | 178 +++++-------------------------
2 files changed, 30 insertions(+), 149 deletions(-)
diff --git a/parser.c b/parser.c
index 43b88358..a7bdc7f3 100644
--- a/parser.c
+++ b/parser.c
@@ -7158,6 +7158,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
ent->checked |= 1;
if (ret == XML_ERR_ENTITY_LOOP) {
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ xmlHaltParser(ctxt);
xmlFreeNodeList(list);
return;
}
diff --git a/result/errors/rec_ext_ent.xml.ent b/result/errors/rec_ext_ent.xml.ent
index 30dd2854..d8ccec14 100644
--- a/result/errors/rec_ext_ent.xml.ent
+++ b/result/errors/rec_ext_ent.xml.ent
@@ -1,243 +1,123 @@
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-test/errors/rec_ext.ent:1: parser error : Entity 'e' failed to parse
+test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
test/errors/rec_ext.ent:1: parser error : Detected an entity reference loop
<ent>&e; &e; &e; &e;</ent>
^
-test/errors/rec_ext.ent:2: parser error : chunk is not well balanced
-
-^
-./test/errors/rec_ext_ent.xml:4: parser error : Entity 'e' failed to parse
+./test/errors/rec_ext_ent.xml:4: parser error : Detected an entity reference loop
<doc>&e; &e; &e; &e;</doc>
^
--
2.27.0

View File

@ -0,0 +1,36 @@
From 13ba5b619a153f240320eb92b59158d657bdeb3a Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sun, 28 Jun 2020 13:16:46 +0200
Subject: [PATCH] Reset HTML parser input before reporting encoding error
If charset conversion fails, reset the input pointers before reporting
the error and bailing out. Otherwise, the input pointers are left in an
invalid state which could lead to use-after-free and other memory
errors.
Similar to f9e7997e. Found by OSS-Fuzz.
---
HTMLparser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 9ade6635..7fba9429 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -6160,12 +6160,12 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
size_t current = ctxt->input->cur - ctxt->input->base;
nbchars = xmlCharEncInput(in, terminate);
+ xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
if (nbchars < 0) {
htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
"encoder error\n", NULL, NULL);
return(XML_ERR_INVALID_ENCODING);
}
- xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
}
}
}
--
2.27.0

View File

@ -1,7 +1,7 @@
Summary: Library providing XML and HTML support
Name: libxml2
Version: 2.9.10
Release: 10
Release: 11
License: MIT
Group: Development/Libraries
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
@ -57,6 +57,18 @@ Patch47: Fix-cleanup-of-attributes-in-XML-reader.patch
Patch48: Fix-null-deref-in-XPointer-expression-error-path.patch
Patch49: Fix-use-after-free-when-XIncluding-text-from-Reader.patch
Patch50: backport-Add-test-case-for-recursive-external-parsed-entities.patch
Patch51: backport-Fix-timeout-when-handling-recursive-entities.patch
Patch52: backport-Avoid-call-stack-overflow-with-XML-reader-and-recurs.patch
Patch53: backport-Reset-HTML-parser-input-before-reporting-encoding-er.patch
Patch54: backport-Fix-quadratic-runtime-in-HTML-parser.patch
Patch55: backport-Fix-regression-introduced-with-477c7f6a.patch
Patch56: backport-Fix-HTML-push-parser-lookahead.patch
Patch57: backport-Fix-quadratic-runtime-when-push-parsing-HTML-entity-.patch
Patch58: backport-Fix-quadratic-runtime-in-HTML-push-parser-with-null-.patch
Patch59: backport-Fix-infinite-loop-in-HTML-parser-introduced-with-rec.patch
Patch60: backport-Fix-integer-overflow-in-xmlSchemaGetParticleTotalRan.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-root
BuildRequires: python3-devel
BuildRequires: zlib-devel
@ -216,6 +228,9 @@ rm -fr %{buildroot}
%changelog
* Tue Mar 2 2020 Lirui <lirui130@huawei.com> - 2.9.10-11
- fix problems detected by oss-fuzz test
* Thu Nov 12 2020 Liquor <lirui130@huawei.com> - 2.9.10-10
- fix problems detected by oss-fuzz test