From 8b04b2b5f087a735be511f64ba1bfe8423067f4b Mon Sep 17 00:00:00 2001 From: Liquor <1692257904@qq.com> Date: Tue, 2 Mar 2021 19:40:18 +0800 Subject: [PATCH] fix problems detected by oss-fuzz test --- ...r-recursive-external-parsed-entities.patch | 306 ++++++++++++++++++ ...-overflow-with-XML-reader-and-recurs.patch | 34 ++ backport-Fix-HTML-push-parser-lookahead.patch | 286 ++++++++++++++++ ...p-in-HTML-parser-introduced-with-rec.patch | 31 ++ ...flow-in-xmlSchemaGetParticleTotalRan.patch | 99 ++++++ ...Fix-quadratic-runtime-in-HTML-parser.patch | 225 +++++++++++++ ...ntime-in-HTML-push-parser-with-null-.patch | 33 ++ ...ntime-when-push-parsing-HTML-entity-.patch | 128 ++++++++ ...-regression-introduced-with-477c7f6a.patch | 48 +++ ...out-when-handling-recursive-entities.patch | 306 ++++++++++++++++++ ...r-input-before-reporting-encoding-er.patch | 36 +++ libxml2.spec | 17 +- 12 files changed, 1548 insertions(+), 1 deletion(-) create mode 100644 backport-Add-test-case-for-recursive-external-parsed-entities.patch create mode 100644 backport-Avoid-call-stack-overflow-with-XML-reader-and-recurs.patch create mode 100644 backport-Fix-HTML-push-parser-lookahead.patch create mode 100644 backport-Fix-infinite-loop-in-HTML-parser-introduced-with-rec.patch create mode 100644 backport-Fix-integer-overflow-in-xmlSchemaGetParticleTotalRan.patch create mode 100644 backport-Fix-quadratic-runtime-in-HTML-parser.patch create mode 100644 backport-Fix-quadratic-runtime-in-HTML-push-parser-with-null-.patch create mode 100644 backport-Fix-quadratic-runtime-when-push-parsing-HTML-entity-.patch create mode 100644 backport-Fix-regression-introduced-with-477c7f6a.patch create mode 100644 backport-Fix-timeout-when-handling-recursive-entities.patch create mode 100644 backport-Reset-HTML-parser-input-before-reporting-encoding-er.patch diff --git a/backport-Add-test-case-for-recursive-external-parsed-entities.patch b/backport-Add-test-case-for-recursive-external-parsed-entities.patch new file mode 100644 index 0000000..a51e07b --- /dev/null +++ b/backport-Add-test-case-for-recursive-external-parsed-entities.patch @@ -0,0 +1,306 @@ +From 32cb5dccda6d9c72aaa1717d7100277b755cca94 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 @@ ++ ++ ++]> ++&e; &e; &e; &e; +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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ ++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 ++&e; &e; &e; &e; ++ ^ +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 @@ ++&e; &e; &e; &e; +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 @@ ++ ++]> ++&e; &e; &e; &e; +-- +2.27.0 + diff --git a/backport-Avoid-call-stack-overflow-with-XML-reader-and-recurs.patch b/backport-Avoid-call-stack-overflow-with-XML-reader-and-recurs.patch new file mode 100644 index 0000000..493af36 --- /dev/null +++ b/backport-Avoid-call-stack-overflow-with-XML-reader-and-recurs.patch @@ -0,0 +1,34 @@ +From 31c6ce3b63f8a494ad9e31ca65187a73d8ad3508 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + diff --git a/backport-Fix-HTML-push-parser-lookahead.patch b/backport-Fix-HTML-push-parser-lookahead.patch new file mode 100644 index 0000000..88946a6 --- /dev/null +++ b/backport-Fix-HTML-push-parser-lookahead.patch @@ -0,0 +1,286 @@ +From 8e219b154e9b938af84c4b009aefa692020103f9 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 */ +- 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 */ +- 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 + diff --git a/backport-Fix-infinite-loop-in-HTML-parser-introduced-with-rec.patch b/backport-Fix-infinite-loop-in-HTML-parser-introduced-with-rec.patch new file mode 100644 index 0000000..7299487 --- /dev/null +++ b/backport-Fix-infinite-loop-in-HTML-parser-introduced-with-rec.patch @@ -0,0 +1,31 @@ +From 954696e7cf236c3aa71dc0b7f9e70d3f51e5cb07 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + diff --git a/backport-Fix-integer-overflow-in-xmlSchemaGetParticleTotalRan.patch b/backport-Fix-integer-overflow-in-xmlSchemaGetParticleTotalRan.patch new file mode 100644 index 0000000..b86e82a --- /dev/null +++ b/backport-Fix-integer-overflow-in-xmlSchemaGetParticleTotalRan.patch @@ -0,0 +1,99 @@ +From 8ca3a59b2ee57e2f30272272bb232c84d03b9edc Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 { ++ /* and */ ++ 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 + diff --git a/backport-Fix-quadratic-runtime-in-HTML-parser.patch b/backport-Fix-quadratic-runtime-in-HTML-parser.patch new file mode 100644 index 0000000..3e85aab --- /dev/null +++ b/backport-Fix-quadratic-runtime-in-HTML-parser.patch @@ -0,0 +1,225 @@ +From 477c7f6affcb665305b333f92ce0a782325b4156 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Sun, 28 Jun 2020 15:54:23 +0200 +Subject: [PATCH] Fix quadratic runtime in HTML parser + +Commit eeb99329 removed an important optimization avoiding quadratic +runtime when repeatedly scanning the input buffer for terminating +characters in the HTML push parser. The related bug is + + https://bugzilla.gnome.org/show_bug.cgi?id=444994 + +Make sure that ctxt->checkIndex is always written and store additional +parser state in ctxt->inSubset which is unused in the HTML parser. + +Found by OSS-Fuzz. +--- + HTMLparser.c | 15 +++++++-- + result/HTML/chunked_attr.html | 46 +++++++++++++++++++++++++++ + result/HTML/chunked_attr.html.err | 0 + result/HTML/chunked_attr.html.sax | 41 ++++++++++++++++++++++++ + test/HTML/chunked_attr.html | 53 +++++++++++++++++++++++++++++++ + 5 files changed, 152 insertions(+), 3 deletions(-) + create mode 100644 result/HTML/chunked_attr.html + create mode 100644 result/HTML/chunked_attr.html.err + create mode 100644 result/HTML/chunked_attr.html.sax + create mode 100644 test/HTML/chunked_attr.html + +diff --git a/HTMLparser.c b/HTMLparser.c +index 7fba9429..468db107 100644 +--- a/HTMLparser.c ++++ b/HTMLparser.c +@@ -5158,8 +5158,12 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first, + if (base < 0) + return (-1); + +- if (ctxt->checkIndex > base) ++ 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; ++ } + + if (in->buf == NULL) { + buf = in->base; +@@ -5235,8 +5239,13 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first, + return (base - (in->cur - in->base)); + } + } +- if ((!incomment) && (!invalue)) +- ctxt->checkIndex = base; ++ ctxt->checkIndex = base; ++ /* Abuse inSubset member to track current state. */ ++ ctxt->inSubset = 0; ++ if (incomment) ++ ctxt->inSubset |= 1; ++ if (invalue) ++ ctxt->inSubset |= 2; + #ifdef DEBUG_PUSH + if (next == 0) + xmlGenericError(xmlGenericErrorContext, +diff --git a/result/HTML/chunked_attr.html b/result/HTML/chunked_attr.html +new file mode 100644 +index 00000000..2fd71a6e +--- /dev/null ++++ b/result/HTML/chunked_attr.html +@@ -0,0 +1,46 @@ ++ ++ ++ ++ ++

++Filler bytes follow: ++ ++ 100 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 200 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 300 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 400 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 500 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 600 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 700 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 800 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 900 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 1000 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 100 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 200 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 300 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 400 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 500 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 600 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 700 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 800 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 900 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 2000 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 100 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 200 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 300 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 400 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 500 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 600 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 700 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 800 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++xxx ++

++
++
++ ++ +diff --git a/result/HTML/chunked_attr.html.err b/result/HTML/chunked_attr.html.err +new file mode 100644 +index 00000000..e69de29b +diff --git a/result/HTML/chunked_attr.html.sax b/result/HTML/chunked_attr.html.sax +new file mode 100644 +index 00000000..5f9e9702 +--- /dev/null ++++ b/result/HTML/chunked_attr.html.sax +@@ -0,0 +1,41 @@ ++SAX.setDocumentLocator() ++SAX.startDocument() ++SAX.startElement(html) ++SAX.characters( ++, 1) ++SAX.comment( ++This tests internal state tracking of the push parser and assumes a chunk ++size of 4096 (or a divisor of 4096) and an initial chunk of size 4. ++Make sure that the first '<' in the attribute value ends up near ++offset 4100. ++) ++SAX.characters( ++, 1) ++SAX.startElement(body) ++SAX.characters( ++, 1) ++SAX.startElement(p) ++SAX.characters( ++Filler bytes follow: ++ ++ 1, 1000) ++SAX.characters(89 123456789 123456789 ++ 1, 1000) ++SAX.characters(89 123456789 123456789 ++ 1, 827) ++SAX.endElement(p) ++SAX.characters( ++, 1) ++SAX.startElement(div, fill1='123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789', onmouseover='x<b>text</b>x', fill2='123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789', fill3='123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789', fill4='123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789', fill5='123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789', fill6='123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789') ++SAX.characters( ++, 1) ++SAX.endElement(div) ++SAX.characters( ++, 1) ++SAX.endElement(body) ++SAX.characters( ++, 1) ++SAX.endElement(html) ++SAX.characters( ++, 1) ++SAX.endDocument() +diff --git a/test/HTML/chunked_attr.html b/test/HTML/chunked_attr.html +new file mode 100644 +index 00000000..84d81796 +--- /dev/null ++++ b/test/HTML/chunked_attr.html +@@ -0,0 +1,53 @@ ++ ++ ++ ++

++Filler bytes follow: ++ ++ 100 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 200 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 300 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 400 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 500 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 600 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 700 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 800 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 900 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 1000 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 100 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 200 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 300 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 400 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 500 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 600 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 700 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 800 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 900 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 2000 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 100 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 200 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 300 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 400 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 500 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 600 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 700 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++ 800 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ++xxx ++

++
++
++ ++ +-- +2.27.0 + diff --git a/backport-Fix-quadratic-runtime-in-HTML-push-parser-with-null-.patch b/backport-Fix-quadratic-runtime-in-HTML-push-parser-with-null-.patch new file mode 100644 index 0000000..e6480cb --- /dev/null +++ b/backport-Fix-quadratic-runtime-in-HTML-push-parser-with-null-.patch @@ -0,0 +1,33 @@ +From 94c2e415a9bc1b9e7b7210a9c73817106bb1f175 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + diff --git a/backport-Fix-quadratic-runtime-when-push-parsing-HTML-entity-.patch b/backport-Fix-quadratic-runtime-when-push-parsing-HTML-entity-.patch new file mode 100644 index 0000000..3f5c5cd --- /dev/null +++ b/backport-Fix-quadratic-runtime-when-push-parsing-HTML-entity-.patch @@ -0,0 +1,128 @@ +From 6995eed077899c64d34fe8f0d0b34d214cf586af Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + diff --git a/backport-Fix-regression-introduced-with-477c7f6a.patch b/backport-Fix-regression-introduced-with-477c7f6a.patch new file mode 100644 index 0000000..9a1f925 --- /dev/null +++ b/backport-Fix-regression-introduced-with-477c7f6a.patch @@ -0,0 +1,48 @@ +From 741b0d0a8b9bbee67d68af022cb3137c74e9cd0f Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + diff --git a/backport-Fix-timeout-when-handling-recursive-entities.patch b/backport-Fix-timeout-when-handling-recursive-entities.patch new file mode 100644 index 0000000..72ce1f7 --- /dev/null +++ b/backport-Fix-timeout-when-handling-recursive-entities.patch @@ -0,0 +1,306 @@ +From 79301d3d5e553d46fc3201f48dcec3a93068c5a2 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-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 + &e; &e; &e; &e; + ^ +-- +2.27.0 + diff --git a/backport-Reset-HTML-parser-input-before-reporting-encoding-er.patch b/backport-Reset-HTML-parser-input-before-reporting-encoding-er.patch new file mode 100644 index 0000000..c05d224 --- /dev/null +++ b/backport-Reset-HTML-parser-input-before-reporting-encoding-er.patch @@ -0,0 +1,36 @@ +From 13ba5b619a153f240320eb92b59158d657bdeb3a Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +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 + diff --git a/libxml2.spec b/libxml2.spec index 848c94b..a45f52b 100644 --- a/libxml2.spec +++ b/libxml2.spec @@ -1,7 +1,7 @@ Summary: Library providing XML and HTML support Name: libxml2 Version: 2.9.10 -Release: 11 +Release: 12 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: python2-devel BuildRequires: python3-devel @@ -248,6 +260,9 @@ rm -fr %{buildroot} %changelog +* Tue Mar 2 2020 Lirui - 2.9.10-12 +- fix problems detected by oss-fuzz test + * Thu Nov 12 2020 Liquor - 2.9.10-11 - fix problems detected by oss-fuzz test -- Gitee