upgrade to upstream v2.9.12
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
This commit is contained in:
parent
7c91ca8f90
commit
41b0da9246
@ -1,110 +0,0 @@
|
|||||||
From 6b4717d61ddd8499872ff7249b6712732c8b11cb Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Kilzer <ddkilzer@apple.com>
|
|
||||||
Date: Mon, 6 Jul 2020 12:36:27 +0200
|
|
||||||
Subject: [PATCH] Add regexp regression tests
|
|
||||||
|
|
||||||
- Bug 757711: heap-buffer-overflow in xmlFAParsePosCharGroup
|
|
||||||
<https://bugzilla.gnome.org/show_bug.cgi?id=757711>
|
|
||||||
- Bug 783015 - Integer-overflow in xmlFAParseQuantExact
|
|
||||||
<https://bugzilla.gnome.org/show_bug.cgi?id=783015>
|
|
||||||
|
|
||||||
(Regexptests): Add support for checking stderr output when
|
|
||||||
running regexp tests. This makes it possible to check in test
|
|
||||||
cases that fail and not see false-positive error output when
|
|
||||||
running the tests. Unlike other libxml2 test suites, if there
|
|
||||||
is no stderr output, no *.err file needs to be created.
|
|
||||||
---
|
|
||||||
Makefile.am | 12 +++++++-----
|
|
||||||
result/regexp/bug757711 | 2 ++
|
|
||||||
result/regexp/bug757711.err | 2 ++
|
|
||||||
result/regexp/bug783015 | 4 ++++
|
|
||||||
result/regexp/bug783015.err | 1 +
|
|
||||||
test/regexp/bug757711 | 1 +
|
|
||||||
test/regexp/bug783015 | 4 ++++
|
|
||||||
7 files changed, 21 insertions(+), 5 deletions(-)
|
|
||||||
create mode 100644 result/regexp/bug757711
|
|
||||||
create mode 100644 result/regexp/bug757711.err
|
|
||||||
create mode 100644 result/regexp/bug783015
|
|
||||||
create mode 100644 result/regexp/bug783015.err
|
|
||||||
create mode 100644 test/regexp/bug757711
|
|
||||||
create mode 100644 test/regexp/bug783015
|
|
||||||
|
|
||||||
diff --git a/Makefile.am b/Makefile.am
|
|
||||||
index 2a9d4709..76a834ef 100644
|
|
||||||
--- a/Makefile.am
|
|
||||||
+++ b/Makefile.am
|
|
||||||
@@ -907,14 +907,16 @@ Regexptests: testRegexp$(EXEEXT)
|
|
||||||
if [ ! -d $$i ] ; then \
|
|
||||||
if [ ! -f $(srcdir)/result/regexp/$$name ] ; then \
|
|
||||||
echo New test file $$name ; \
|
|
||||||
- $(CHECKER) $(top_builddir)/testRegexp -i $$i > $(srcdir)/result/regexp/$$name; \
|
|
||||||
+ $(CHECKER) $(top_builddir)/testRegexp -i $$i > $(srcdir)/result/regexp/$$name 2> $(srcdir)/result/regexp/$$name.err ; \
|
|
||||||
+ if [ ! -s "$(srcdir)/result/regexp/$$name.err" ] ; then rm $(srcdir)/result/regexp/$$name.err; fi ; \
|
|
||||||
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
|
||||||
else \
|
|
||||||
- log=`$(CHECKER) $(top_builddir)/testRegexp -i $$i 2>&1 > result.$$name ; \
|
|
||||||
+ log=`$(CHECKER) $(top_builddir)/testRegexp -i $$i > result.$$name 2> error.$$name ; \
|
|
||||||
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
|
||||||
- diff $(srcdir)/result/regexp/$$name result.$$name` ; \
|
|
||||||
- if [ -n "$$log" ] ; then echo $$name result ; echo "$$log" ; fi ; \
|
|
||||||
- rm result.$$name ; \
|
|
||||||
+ diff $(srcdir)/result/regexp/$$name result.$$name ; \
|
|
||||||
+ if [ -s "$(srcdir)/result/regexp/$$name.err" -o -s "error.$$name" ] ; then diff $(srcdir)/result/regexp/$$name.err error.$$name ; fi` ; \
|
|
||||||
+ if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \
|
|
||||||
+ rm result.$$name error.$$name ; \
|
|
||||||
fi ; fi ; done)
|
|
||||||
|
|
||||||
# Disabled for now
|
|
||||||
diff --git a/result/regexp/bug757711 b/result/regexp/bug757711
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..0991e4e2
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/regexp/bug757711
|
|
||||||
@@ -0,0 +1,2 @@
|
|
||||||
+Regexp: [;^((-
|
|
||||||
+ failed to compile
|
|
||||||
diff --git a/result/regexp/bug757711.err b/result/regexp/bug757711.err
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..f1cae806
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/regexp/bug757711.err
|
|
||||||
@@ -0,0 +1,2 @@
|
|
||||||
+regexp error : failed to compile: Expecting the end of a char range
|
|
||||||
+regexp error : failed to compile: xmlFAParseCharClass: ']' expected
|
|
||||||
diff --git a/result/regexp/bug783015 b/result/regexp/bug783015
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..653f6f09
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/regexp/bug783015
|
|
||||||
@@ -0,0 +1,4 @@
|
|
||||||
+Regexp: .{2147483647}
|
|
||||||
+input: Fail
|
|
||||||
+Regexp: .{2147483648}
|
|
||||||
+ failed to compile
|
|
||||||
diff --git a/result/regexp/bug783015.err b/result/regexp/bug783015.err
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..a00edc98
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/regexp/bug783015.err
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+regexp error : failed to compile: Improper quantifier
|
|
||||||
diff --git a/test/regexp/bug757711 b/test/regexp/bug757711
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..29098354
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/regexp/bug757711
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+=>[;^((-
|
|
||||||
diff --git a/test/regexp/bug783015 b/test/regexp/bug783015
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..5c91a0f1
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/regexp/bug783015
|
|
||||||
@@ -0,0 +1,4 @@
|
|
||||||
+# This assumes 32-bit ints.
|
|
||||||
+=>.{2147483647}
|
|
||||||
+input
|
|
||||||
+=>.{2147483648}
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
From bf22713507fe1fc3a2c4b525cf0a88c2dc87a3a2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Joel Hockey <joel.hockey@gmail.com>
|
|
||||||
Date: Sun, 16 Aug 2020 17:19:35 -0700
|
|
||||||
Subject: [PATCH] Validate UTF8 in xmlEncodeEntities
|
|
||||||
|
|
||||||
Code is currently assuming UTF-8 without validating. Truncated UTF-8
|
|
||||||
input can cause out-of-bounds array access.
|
|
||||||
|
|
||||||
Adds further checks to partial fix in 50f06b3e.
|
|
||||||
|
|
||||||
Fixes #178
|
|
||||||
|
|
||||||
Signed-off-by: guoxiaoqi <guoxiaoqi2@huawei.com>
|
|
||||||
---
|
|
||||||
entities.c | 16 +++++++++++++++-
|
|
||||||
1 file changed, 15 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/entities.c b/entities.c
|
|
||||||
index 37b99a5..1a8f86f 100644
|
|
||||||
--- a/entities.c
|
|
||||||
+++ b/entities.c
|
|
||||||
@@ -704,11 +704,25 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* We assume we have UTF-8 input.
|
|
||||||
+ * It must match either:
|
|
||||||
+ * 110xxxxx 10xxxxxx
|
|
||||||
+ * 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
+ * That is:
|
|
||||||
+ * cur[0] is 11xxxxxx
|
|
||||||
+ * cur[1] is 10xxxxxx
|
|
||||||
+ * cur[2] is 10xxxxxx if cur[0] is 111xxxxx
|
|
||||||
+ * cur[3] is 10xxxxxx if cur[0] is 1111xxxx
|
|
||||||
+ * cur[0] is not 11111xxx
|
|
||||||
*/
|
|
||||||
char buf[11], *ptr;
|
|
||||||
int val = 0, l = 1;
|
|
||||||
|
|
||||||
- if (*cur < 0xC0) {
|
|
||||||
+ if (((cur[0] & 0xC0) != 0xC0) ||
|
|
||||||
+ ((cur[1] & 0xC0) != 0x80) ||
|
|
||||||
+ (((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) ||
|
|
||||||
+ (((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) ||
|
|
||||||
+ (((cur[0] & 0xF8) == 0xF8))) {
|
|
||||||
xmlEntitiesErr(XML_CHECK_NOT_UTF8,
|
|
||||||
"xmlEncodeEntities: input not UTF-8");
|
|
||||||
if (doc != NULL)
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
From 1098c30a040e72a4654968547f415be4e4c40fe7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 22 Apr 2021 19:26:28 +0200
|
|
||||||
Subject: [PATCH] Fix user-after-free with `xmllint --xinclude --dropdtd`
|
|
||||||
|
|
||||||
The --dropdtd option can leave dangling pointers in entity reference
|
|
||||||
nodes. Make sure to skip these nodes when processing XIncludes.
|
|
||||||
|
|
||||||
This also avoids scanning entity declarations and even modifying
|
|
||||||
them inadvertently during XInclude processing.
|
|
||||||
|
|
||||||
Move from a block list to an allow list approach to avoid descending
|
|
||||||
into other node types that can't contain elements.
|
|
||||||
|
|
||||||
Fixes #237.
|
|
||||||
|
|
||||||
Signed-off-by: guoxiaoqi <guoxiaoqi2@huawei.com>
|
|
||||||
---
|
|
||||||
xinclude.c | 5 ++---
|
|
||||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 1636caf..b2e6ea1 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -2430,9 +2430,8 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
|
|
||||||
ctxt->incTotal++;
|
|
||||||
xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
} else if ((cur->children != NULL) &&
|
|
||||||
- (cur->children->type != XML_ENTITY_DECL) &&
|
|
||||||
- (cur->children->type != XML_XINCLUDE_START) &&
|
|
||||||
- (cur->children->type != XML_XINCLUDE_END)) {
|
|
||||||
+ ((cur->type == XML_DOCUMENT_NODE) ||
|
|
||||||
+ (cur->type == XML_ELEMENT_NODE))) {
|
|
||||||
cur = cur->children;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
From 8598060bacada41a0eb09d95c97744ff4e428f8e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Veillard <veillard@redhat.com>
|
|
||||||
Date: Thu, 13 May 2021 14:55:12 +0200
|
|
||||||
Subject: [PATCH] Patch for security issue CVE-2021-3541
|
|
||||||
|
|
||||||
This is relapted to parameter entities expansion and following
|
|
||||||
the line of the billion laugh attack. Somehow in that path the
|
|
||||||
counting of parameters was missed and the normal algorithm based
|
|
||||||
on entities "density" was useless.
|
|
||||||
---
|
|
||||||
parser.c | 26 ++++++++++++++++++++++++++
|
|
||||||
1 file changed, 26 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index f5e5e169..c9312fa4 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -140,6 +140,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
|
|
||||||
xmlEntityPtr ent, size_t replacement)
|
|
||||||
{
|
|
||||||
size_t consumed = 0;
|
|
||||||
+ int i;
|
|
||||||
|
|
||||||
if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
|
|
||||||
return (0);
|
|
||||||
@@ -177,6 +178,28 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
|
|
||||||
rep = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Prevent entity exponential check, not just replacement while
|
|
||||||
+ * parsing the DTD
|
|
||||||
+ * The check is potentially costly so do that only once in a thousand
|
|
||||||
+ */
|
|
||||||
+ if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
|
|
||||||
+ (ctxt->nbentities % 1024 == 0)) {
|
|
||||||
+ for (i = 0;i < ctxt->inputNr;i++) {
|
|
||||||
+ consumed += ctxt->inputTab[i]->consumed +
|
|
||||||
+ (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
|
|
||||||
+ }
|
|
||||||
+ if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
|
|
||||||
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
|
||||||
+ ctxt->instate = XML_PARSER_EOF;
|
|
||||||
+ return (1);
|
|
||||||
+ }
|
|
||||||
+ consumed = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
if (replacement != 0) {
|
|
||||||
if (replacement < XML_MAX_TEXT_LENGTH)
|
|
||||||
return(0);
|
|
||||||
@@ -7963,6 +7986,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
|
|
||||||
xmlChar start[4];
|
|
||||||
xmlCharEncoding enc;
|
|
||||||
|
|
||||||
+ if (xmlParserEntityCheck(ctxt, 0, entity, 0))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
|
|
||||||
((ctxt->options & XML_PARSE_NOENT) == 0) &&
|
|
||||||
((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
|
|
||||||
--
|
|
||||||
GitLab
|
|
||||||
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
From 52649b63ebd0dc45df0c5e6b209af6f6d96515ca Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 2 Jan 2020 14:45:28 +0100
|
|
||||||
Subject: [PATCH] Check for overflow when allocating two-dimensional arrays
|
|
||||||
|
|
||||||
Found by lgtm.com
|
|
||||||
---
|
|
||||||
xmlregexp.c | 46 +++++++++++++++++++++++++++++++++++++---------
|
|
||||||
1 file changed, 37 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlregexp.c b/xmlregexp.c
|
|
||||||
index 5a2deb9..0bd938f 100644
|
|
||||||
--- a/xmlregexp.c
|
|
||||||
+++ b/xmlregexp.c
|
|
||||||
@@ -26,6 +26,9 @@
|
|
||||||
#ifdef HAVE_LIMITS_H
|
|
||||||
#include <limits.h>
|
|
||||||
#endif
|
|
||||||
+#ifdef HAVE_STDINT_H
|
|
||||||
+#include <stdint.h>
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#include <libxml/tree.h>
|
|
||||||
#include <libxml/parserInternals.h>
|
|
||||||
@@ -36,6 +39,9 @@
|
|
||||||
#ifndef INT_MAX
|
|
||||||
#define INT_MAX 123456789 /* easy to flag and big enough for our needs */
|
|
||||||
#endif
|
|
||||||
+#ifndef SIZE_MAX
|
|
||||||
+#define SIZE_MAX ((size_t) -1)
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/* #define DEBUG_REGEXP_GRAPH */
|
|
||||||
/* #define DEBUG_REGEXP_EXEC */
|
|
||||||
@@ -418,6 +424,32 @@ xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra)
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt);
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * xmlRegCalloc2:
|
|
||||||
+ * @dim1: size of first dimension
|
|
||||||
+ * @dim2: size of second dimension
|
|
||||||
+ * @elemSize: size of element
|
|
||||||
+ *
|
|
||||||
+ * Allocate a two-dimensional array and set all elements to zero.
|
|
||||||
+ *
|
|
||||||
+ * Returns the new array or NULL in case of error.
|
|
||||||
+ */
|
|
||||||
+static void*
|
|
||||||
+xmlRegCalloc2(size_t dim1, size_t dim2, size_t elemSize) {
|
|
||||||
+ size_t totalSize;
|
|
||||||
+ void *ret;
|
|
||||||
+
|
|
||||||
+ /* Check for overflow */
|
|
||||||
+ if (dim1 > SIZE_MAX / dim2 / elemSize)
|
|
||||||
+ return (NULL);
|
|
||||||
+ totalSize = dim1 * dim2 * elemSize;
|
|
||||||
+ ret = xmlMalloc(totalSize);
|
|
||||||
+ if (ret != NULL)
|
|
||||||
+ memset(ret, 0, totalSize);
|
|
||||||
+ return (ret);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* xmlRegEpxFromParse:
|
|
||||||
* @ctxt: the parser context used to build it
|
|
||||||
@@ -540,8 +572,8 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
#ifdef DEBUG_COMPACTION
|
|
||||||
printf("Final: %d atoms\n", nbatoms);
|
|
||||||
#endif
|
|
||||||
- transitions = (int *) xmlMalloc((nbstates + 1) *
|
|
||||||
- (nbatoms + 1) * sizeof(int));
|
|
||||||
+ transitions = (int *) xmlRegCalloc2(nbstates + 1, nbatoms + 1,
|
|
||||||
+ sizeof(int));
|
|
||||||
if (transitions == NULL) {
|
|
||||||
xmlFree(stateRemap);
|
|
||||||
xmlFree(stringRemap);
|
|
||||||
@@ -551,7 +583,6 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
xmlFree(ret);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
- memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate the transition table. The first entry for each
|
|
||||||
@@ -577,12 +608,9 @@ xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
continue;
|
|
||||||
atomno = stringRemap[trans->atom->no];
|
|
||||||
if ((trans->atom->data != NULL) && (transdata == NULL)) {
|
|
||||||
- transdata = (void **) xmlMalloc(nbstates * nbatoms *
|
|
||||||
- sizeof(void *));
|
|
||||||
- if (transdata != NULL)
|
|
||||||
- memset(transdata, 0,
|
|
||||||
- nbstates * nbatoms * sizeof(void *));
|
|
||||||
- else {
|
|
||||||
+ transdata = (void **) xmlRegCalloc2(nbstates, nbatoms,
|
|
||||||
+ sizeof(void *));
|
|
||||||
+ if (transdata == NULL) {
|
|
||||||
xmlRegexpErrMemory(ctxt, "compiling regexp");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
From 5c7e0a9a4608ac442e727f6e479cf2a6dea368ec Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 11 Feb 2020 16:29:30 +0100
|
|
||||||
Subject: [PATCH] Copy some XMLReader option flags to parser context
|
|
||||||
|
|
||||||
The parser context stores some options both in the "options" bits and
|
|
||||||
extra members like "validate" or "replaceEntities". Which of these
|
|
||||||
are actually read is inconsistent, so make sure to also update the
|
|
||||||
bit field.
|
|
||||||
---
|
|
||||||
xmlreader.c | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xmlreader.c b/xmlreader.c
|
|
||||||
index f3891e4..e336bc7 100644
|
|
||||||
--- a/xmlreader.c
|
|
||||||
+++ b/xmlreader.c
|
|
||||||
@@ -3848,16 +3848,20 @@ xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
|
|
||||||
return(0);
|
|
||||||
case XML_PARSER_VALIDATE:
|
|
||||||
if (value != 0) {
|
|
||||||
+ ctxt->options |= XML_PARSE_DTDVALID;
|
|
||||||
ctxt->validate = 1;
|
|
||||||
reader->validate = XML_TEXTREADER_VALIDATE_DTD;
|
|
||||||
} else {
|
|
||||||
+ ctxt->options &= ~XML_PARSE_DTDVALID;
|
|
||||||
ctxt->validate = 0;
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
case XML_PARSER_SUBST_ENTITIES:
|
|
||||||
if (value != 0) {
|
|
||||||
+ ctxt->options |= XML_PARSE_NOENT;
|
|
||||||
ctxt->replaceEntities = 1;
|
|
||||||
} else {
|
|
||||||
+ ctxt->options &= ~XML_PARSE_NOENT;
|
|
||||||
ctxt->replaceEntities = 0;
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
From 00a86d414ba9a9e1cd588182b87518e4e3af9466 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 16 Aug 2020 23:38:00 +0200
|
|
||||||
Subject: [PATCH] Don't add formatting newlines to XInclude nodes
|
|
||||||
|
|
||||||
---
|
|
||||||
xmlsave.c | 8 ++++++--
|
|
||||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlsave.c b/xmlsave.c
|
|
||||||
index f1d40b9..2225628 100644
|
|
||||||
--- a/xmlsave.c
|
|
||||||
+++ b/xmlsave.c
|
|
||||||
@@ -1049,7 +1049,9 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
while (1) {
|
|
||||||
if (cur == root)
|
|
||||||
return;
|
|
||||||
- if (ctxt->format == 1) {
|
|
||||||
+ if ((ctxt->format == 1) &&
|
|
||||||
+ (cur->type != XML_XINCLUDE_START) &&
|
|
||||||
+ (cur->type != XML_XINCLUDE_END)) {
|
|
||||||
xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
}
|
|
||||||
if (cur->next != NULL) {
|
|
||||||
@@ -1224,7 +1226,9 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
xmlNodeDumpOutputInternal(ctxt, child);
|
|
||||||
- xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
+ if ((child->type != XML_XINCLUDE_START) &&
|
|
||||||
+ (child->type != XML_XINCLUDE_END))
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
child = child->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
From eddfbc38fa7e84ccd480eab3738e40d1b2c83979 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 22 Jan 2020 22:03:45 +0100
|
|
||||||
Subject: [PATCH] Don't load external entity from xmlSAX2GetEntity
|
|
||||||
|
|
||||||
Despite the comment, I can't see a reason why external entities must be
|
|
||||||
loaded in the SAX handler. For external entities, the handler is
|
|
||||||
typically first invoked via xmlParseReference which will later load the
|
|
||||||
entity on its own if it wasn't loaded yet.
|
|
||||||
|
|
||||||
The old code also lead to duplicated SAX events which makes it
|
|
||||||
basically impossible to reuse xmlSAX2GetEntity for a custom SAX parser.
|
|
||||||
See the change to the expected test output.
|
|
||||||
|
|
||||||
Note that xmlSAX2GetEntity was loading the entity via
|
|
||||||
xmlParseCtxtExternalEntity while xmlParseReference uses
|
|
||||||
xmlParseExternalEntityPrivate. In the previous commit, the two
|
|
||||||
functions were merged, trying to compensate for some slight differences
|
|
||||||
between the two mostly identical implementations.
|
|
||||||
|
|
||||||
But the more urgent reason for this change is that xmlParseReference
|
|
||||||
has the facility to abort early when recursive entities are detected,
|
|
||||||
avoiding what could practically amount to an infinite loop.
|
|
||||||
|
|
||||||
If you want to backport this change, note that the previous three
|
|
||||||
commits are required as well:
|
|
||||||
|
|
||||||
f9ea1a24 Fix copying of entities in xmlParseReference
|
|
||||||
5c7e0a9a Copy some XMLReader option flags to parser context
|
|
||||||
1a3e584a Merge code paths loading external entities
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
SAX2.c | 30 ------------------------------
|
|
||||||
result/noent/ent2.sax2 | 7 -------
|
|
||||||
2 files changed, 37 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/SAX2.c b/SAX2.c
|
|
||||||
index 5f141f9..6045ca1 100644
|
|
||||||
--- a/SAX2.c
|
|
||||||
+++ b/SAX2.c
|
|
||||||
@@ -590,36 +590,6 @@ xmlSAX2GetEntity(void *ctx, const xmlChar *name)
|
|
||||||
} else {
|
|
||||||
ret = xmlGetDocEntity(ctxt->myDoc, name);
|
|
||||||
}
|
|
||||||
- if ((ret != NULL) &&
|
|
||||||
- ((ctxt->validate) || (ctxt->replaceEntities)) &&
|
|
||||||
- (ret->children == NULL) &&
|
|
||||||
- (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
|
|
||||||
- int val;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * for validation purposes we really need to fetch and
|
|
||||||
- * parse the external entity
|
|
||||||
- */
|
|
||||||
- xmlNodePtr children;
|
|
||||||
- unsigned long oldnbent = ctxt->nbentities;
|
|
||||||
-
|
|
||||||
- val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
|
|
||||||
- ret->ExternalID, &children);
|
|
||||||
- if (val == 0) {
|
|
||||||
- xmlAddChildList((xmlNodePtr) ret, children);
|
|
||||||
- } else {
|
|
||||||
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
|
|
||||||
- "Failure to process entity %s\n", name, NULL);
|
|
||||||
- ctxt->validate = 0;
|
|
||||||
- return(NULL);
|
|
||||||
- }
|
|
||||||
- ret->owner = 1;
|
|
||||||
- if (ret->checked == 0) {
|
|
||||||
- ret->checked = (ctxt->nbentities - oldnbent + 1) * 2;
|
|
||||||
- if ((ret->content != NULL) && (xmlStrchr(ret->content, '<')))
|
|
||||||
- ret->checked |= 1;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/result/noent/ent2.sax2 b/result/noent/ent2.sax2
|
|
||||||
index 88c6aa6..d17f2ff 100644
|
|
||||||
--- a/result/noent/ent2.sax2
|
|
||||||
+++ b/result/noent/ent2.sax2
|
|
||||||
@@ -17,13 +17,6 @@ SAX.characters(my title, 8)
|
|
||||||
SAX.endElementNs(title, NULL, NULL)
|
|
||||||
SAX.characters(
|
|
||||||
, 1)
|
|
||||||
-SAX.ignorableWhitespace(
|
|
||||||
-, 1)
|
|
||||||
-SAX.startElementNs(title, NULL, NULL, 0, 0, 0)
|
|
||||||
-SAX.characters(my title, 8)
|
|
||||||
-SAX.endElementNs(title, NULL, NULL)
|
|
||||||
-SAX.characters(
|
|
||||||
-, 1)
|
|
||||||
SAX.characters(
|
|
||||||
This text is about XML, the, 31)
|
|
||||||
SAX.getEntity(xml)
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
From 11b5745927481d6a716acef5408da20899eab8a2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Fri, 7 Aug 2020 18:39:19 +0200
|
|
||||||
Subject: [PATCH 108/139] Don't process siblings of root in xmlXIncludeProcess
|
|
||||||
|
|
||||||
xmlXIncludeDoProcess would follow the siblings of the tree root and
|
|
||||||
also expand these nodes. When using an XML reader, this could lead to
|
|
||||||
siblings of the current node being expanded without having been parsed
|
|
||||||
completely.
|
|
||||||
---
|
|
||||||
xinclude.c | 38 ++++++++++++++++++--------------------
|
|
||||||
1 file changed, 18 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 0f1af9c..2917d45 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -1980,6 +1980,8 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
(ctxt == NULL))
|
|
||||||
return(-1);
|
|
||||||
if (fallback->children != NULL) {
|
|
||||||
+ xmlNodePtr child, next;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* It's possible that the fallback also has 'includes'
|
|
||||||
* (Bug 129969), so we re-process the fallback just in case
|
|
||||||
@@ -1990,11 +1992,13 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
newctxt->_private = ctxt->_private;
|
|
||||||
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
|
|
||||||
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
|
|
||||||
- ret = xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback->children);
|
|
||||||
+ for (child = fallback->children; child != NULL; child = next) {
|
|
||||||
+ next = child->next;
|
|
||||||
+ if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
|
|
||||||
+ ret = -1;
|
|
||||||
+ }
|
|
||||||
if (ctxt->nbErrors > oldNbErrors)
|
|
||||||
ret = -1;
|
|
||||||
- else if (ret > 0)
|
|
||||||
- ret = 0; /* xmlXIncludeDoProcess can return +ve number */
|
|
||||||
xmlXIncludeFreeContext(newctxt);
|
|
||||||
|
|
||||||
ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
|
|
||||||
@@ -2396,7 +2400,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
* First phase: lookup the elements in the document
|
|
||||||
*/
|
|
||||||
cur = tree;
|
|
||||||
- while ((cur != NULL) && (cur != tree->parent)) {
|
|
||||||
+ do {
|
|
||||||
/* TODO: need to work on entities -> stack */
|
|
||||||
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
|
|
||||||
xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
@@ -2407,22 +2411,16 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
cur = cur->children;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
- if (cur->next != NULL) {
|
|
||||||
- cur = cur->next;
|
|
||||||
- } else {
|
|
||||||
- if (cur == tree)
|
|
||||||
- break;
|
|
||||||
- do {
|
|
||||||
- cur = cur->parent;
|
|
||||||
- if ((cur == NULL) || (cur == tree->parent))
|
|
||||||
- break; /* do */
|
|
||||||
- if (cur->next != NULL) {
|
|
||||||
- cur = cur->next;
|
|
||||||
- break; /* do */
|
|
||||||
- }
|
|
||||||
- } while (cur != NULL);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ do {
|
|
||||||
+ if (cur == tree)
|
|
||||||
+ break;
|
|
||||||
+ if (cur->next != NULL) {
|
|
||||||
+ cur = cur->next;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ cur = cur->parent;
|
|
||||||
+ } while (cur != NULL);
|
|
||||||
+ } while ((cur != NULL) && (cur != tree));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Second Phase : collect the infosets fragments
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,208 +0,0 @@
|
|||||||
From 0f9817c75b50a77c6aeb8f36801966fdadad229a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 10 Jun 2020 16:34:52 +0200
|
|
||||||
Subject: [PATCH 107/139] Don't recurse into xi:include children in
|
|
||||||
xmlXIncludeDoProcess
|
|
||||||
|
|
||||||
Otherwise, nested xi:include nodes might result in a use-after-free
|
|
||||||
if XML_PARSE_NOXINCNODE is specified.
|
|
||||||
|
|
||||||
Found with libFuzzer and ASan.
|
|
||||||
---
|
|
||||||
result/XInclude/fallback3.xml | 8 ++++++++
|
|
||||||
result/XInclude/fallback3.xml.err | 0
|
|
||||||
result/XInclude/fallback3.xml.rdr | 25 +++++++++++++++++++++++++
|
|
||||||
result/XInclude/fallback4.xml | 10 ++++++++++
|
|
||||||
result/XInclude/fallback4.xml.err | 0
|
|
||||||
result/XInclude/fallback4.xml.rdr | 29 +++++++++++++++++++++++++++++
|
|
||||||
test/XInclude/docs/fallback3.xml | 9 +++++++++
|
|
||||||
test/XInclude/docs/fallback4.xml | 7 +++++++
|
|
||||||
xinclude.c | 24 ++++++++++--------------
|
|
||||||
9 files changed, 98 insertions(+), 14 deletions(-)
|
|
||||||
create mode 100644 result/XInclude/fallback3.xml
|
|
||||||
create mode 100644 result/XInclude/fallback3.xml.err
|
|
||||||
create mode 100644 result/XInclude/fallback3.xml.rdr
|
|
||||||
create mode 100644 result/XInclude/fallback4.xml
|
|
||||||
create mode 100644 result/XInclude/fallback4.xml.err
|
|
||||||
create mode 100644 result/XInclude/fallback4.xml.rdr
|
|
||||||
create mode 100644 test/XInclude/docs/fallback3.xml
|
|
||||||
create mode 100644 test/XInclude/docs/fallback4.xml
|
|
||||||
|
|
||||||
diff --git a/result/XInclude/fallback3.xml b/result/XInclude/fallback3.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..b423551
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback3.xml
|
|
||||||
@@ -0,0 +1,8 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
+<a>
|
|
||||||
+ <doc xml:base="../ents/something.xml">
|
|
||||||
+<p>something</p>
|
|
||||||
+<p>really</p>
|
|
||||||
+<p>simple</p>
|
|
||||||
+</doc>
|
|
||||||
+</a>
|
|
||||||
diff --git a/result/XInclude/fallback3.xml.err b/result/XInclude/fallback3.xml.err
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..e69de29
|
|
||||||
diff --git a/result/XInclude/fallback3.xml.rdr b/result/XInclude/fallback3.xml.rdr
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..aa2f137
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback3.xml.rdr
|
|
||||||
@@ -0,0 +1,25 @@
|
|
||||||
+0 1 a 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 doc 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 p 0 0
|
|
||||||
+3 3 #text 0 1 something
|
|
||||||
+2 15 p 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 p 0 0
|
|
||||||
+3 3 #text 0 1 really
|
|
||||||
+2 15 p 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 p 0 0
|
|
||||||
+3 3 #text 0 1 simple
|
|
||||||
+2 15 p 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 15 doc 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+0 15 a 0 0
|
|
||||||
diff --git a/result/XInclude/fallback4.xml b/result/XInclude/fallback4.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..9883fd5
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback4.xml
|
|
||||||
@@ -0,0 +1,10 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
+<a>
|
|
||||||
+
|
|
||||||
+ <doc xml:base="../ents/something.xml">
|
|
||||||
+<p>something</p>
|
|
||||||
+<p>really</p>
|
|
||||||
+<p>simple</p>
|
|
||||||
+</doc>
|
|
||||||
+
|
|
||||||
+</a>
|
|
||||||
diff --git a/result/XInclude/fallback4.xml.err b/result/XInclude/fallback4.xml.err
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..e69de29
|
|
||||||
diff --git a/result/XInclude/fallback4.xml.rdr b/result/XInclude/fallback4.xml.rdr
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..628b951
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback4.xml.rdr
|
|
||||||
@@ -0,0 +1,29 @@
|
|
||||||
+0 1 a 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 doc 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 p 0 0
|
|
||||||
+3 3 #text 0 1 something
|
|
||||||
+2 15 p 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 p 0 0
|
|
||||||
+3 3 #text 0 1 really
|
|
||||||
+2 15 p 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 p 0 0
|
|
||||||
+3 3 #text 0 1 simple
|
|
||||||
+2 15 p 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 15 doc 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+0 15 a 0 0
|
|
||||||
diff --git a/test/XInclude/docs/fallback3.xml b/test/XInclude/docs/fallback3.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..0c8b6c9
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/XInclude/docs/fallback3.xml
|
|
||||||
@@ -0,0 +1,9 @@
|
|
||||||
+<a>
|
|
||||||
+ <xi:include href="../ents/something.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <xi:include href="c.xml">
|
|
||||||
+ <xi:fallback>There is no c.xml ... </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+</a>
|
|
||||||
diff --git a/test/XInclude/docs/fallback4.xml b/test/XInclude/docs/fallback4.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..b500a63
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/XInclude/docs/fallback4.xml
|
|
||||||
@@ -0,0 +1,7 @@
|
|
||||||
+<a>
|
|
||||||
+ <xi:include href="c.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <xi:include href="../ents/something.xml"/>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+</a>
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 461c1a5..0f1af9c 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -2396,21 +2396,19 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
* First phase: lookup the elements in the document
|
|
||||||
*/
|
|
||||||
cur = tree;
|
|
||||||
- if (xmlXIncludeTestNode(ctxt, cur) == 1)
|
|
||||||
- xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
while ((cur != NULL) && (cur != tree->parent)) {
|
|
||||||
/* TODO: need to work on entities -> stack */
|
|
||||||
- if ((cur->children != NULL) &&
|
|
||||||
- (cur->children->type != XML_ENTITY_DECL) &&
|
|
||||||
- (cur->children->type != XML_XINCLUDE_START) &&
|
|
||||||
- (cur->children->type != XML_XINCLUDE_END)) {
|
|
||||||
- cur = cur->children;
|
|
||||||
- if (xmlXIncludeTestNode(ctxt, cur))
|
|
||||||
- xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
- } else if (cur->next != NULL) {
|
|
||||||
+ if (xmlXIncludeTestNode(ctxt, cur) == 1) {
|
|
||||||
+ xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
+ } else if ((cur->children != NULL) &&
|
|
||||||
+ (cur->children->type != XML_ENTITY_DECL) &&
|
|
||||||
+ (cur->children->type != XML_XINCLUDE_START) &&
|
|
||||||
+ (cur->children->type != XML_XINCLUDE_END)) {
|
|
||||||
+ cur = cur->children;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if (cur->next != NULL) {
|
|
||||||
cur = cur->next;
|
|
||||||
- if (xmlXIncludeTestNode(ctxt, cur))
|
|
||||||
- xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
} else {
|
|
||||||
if (cur == tree)
|
|
||||||
break;
|
|
||||||
@@ -2420,8 +2418,6 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
break; /* do */
|
|
||||||
if (cur->next != NULL) {
|
|
||||||
cur = cur->next;
|
|
||||||
- if (xmlXIncludeTestNode(ctxt, cur))
|
|
||||||
- xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
break; /* do */
|
|
||||||
}
|
|
||||||
} while (cur != NULL);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
From 1493130ef24f8af2e1e70fdf12827374f670f7bf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 15 Jul 2020 12:54:25 +0200
|
|
||||||
Subject: [PATCH 085/139] Fix UTF-8 decoder in HTML parser
|
|
||||||
|
|
||||||
Reject sequences starting with a continuation byte as well as overlong
|
|
||||||
sequences like the XML parser.
|
|
||||||
|
|
||||||
Also fixes an infinite loop in connection with previous commit 50078922
|
|
||||||
since htmlCurrentChar would return 0 even if not at the end of the
|
|
||||||
buffer.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
HTMLparser.c | 8 ++++++++
|
|
||||||
1 file changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
|
||||||
index 26ed124..d31e2ec 100644
|
|
||||||
--- a/HTMLparser.c
|
|
||||||
+++ b/HTMLparser.c
|
|
||||||
@@ -439,6 +439,8 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
|
|
||||||
|
|
||||||
c = *cur;
|
|
||||||
if (c & 0x80) {
|
|
||||||
+ if ((c & 0x40) == 0)
|
|
||||||
+ goto encoding_error;
|
|
||||||
if (cur[1] == 0) {
|
|
||||||
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
|
|
||||||
cur = ctxt->input->cur;
|
|
||||||
@@ -467,18 +469,24 @@ htmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
|
|
||||||
val |= (cur[1] & 0x3f) << 12;
|
|
||||||
val |= (cur[2] & 0x3f) << 6;
|
|
||||||
val |= cur[3] & 0x3f;
|
|
||||||
+ if (val < 0x10000)
|
|
||||||
+ goto encoding_error;
|
|
||||||
} else {
|
|
||||||
/* 3-byte code */
|
|
||||||
*len = 3;
|
|
||||||
val = (cur[0] & 0xf) << 12;
|
|
||||||
val |= (cur[1] & 0x3f) << 6;
|
|
||||||
val |= cur[2] & 0x3f;
|
|
||||||
+ if (val < 0x800)
|
|
||||||
+ goto encoding_error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* 2-byte code */
|
|
||||||
*len = 2;
|
|
||||||
val = (cur[0] & 0x1f) << 6;
|
|
||||||
val |= cur[1] & 0x3f;
|
|
||||||
+ if (val < 0x80)
|
|
||||||
+ goto encoding_error;
|
|
||||||
}
|
|
||||||
if (!IS_CHAR(val)) {
|
|
||||||
htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
From dba82a8c0453b7d4d138167a771c1c2988b889be Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 16 Aug 2020 23:02:20 +0200
|
|
||||||
Subject: [PATCH 121/139] Fix XInclude regression introduced with recent commit
|
|
||||||
|
|
||||||
The change to xmlXIncludeLoadFallback in commit 11b57459 could
|
|
||||||
process already freed nodes if text nodes were merged after deleting
|
|
||||||
nodes with an empty fallback.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xinclude.c | 31 +++++++++++++++++--------------
|
|
||||||
1 file changed, 17 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 41ff4e5..ff265eb 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -91,7 +91,8 @@ struct _xmlXIncludeCtxt {
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree);
|
|
||||||
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
|
|
||||||
+ int skipRoot);
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
@@ -732,7 +733,7 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
|
|
||||||
*/
|
|
||||||
newctxt->parseFlags = ctxt->parseFlags;
|
|
||||||
newctxt->incTotal = ctxt->incTotal;
|
|
||||||
- xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
|
|
||||||
+ xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc), 0);
|
|
||||||
ctxt->incTotal = newctxt->incTotal;
|
|
||||||
for (i = 0;i < ctxt->incNr;i++) {
|
|
||||||
newctxt->incTab[i]->count--;
|
|
||||||
@@ -1984,8 +1985,6 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
(ctxt == NULL))
|
|
||||||
return(-1);
|
|
||||||
if (fallback->children != NULL) {
|
|
||||||
- xmlNodePtr child, next;
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* It's possible that the fallback also has 'includes'
|
|
||||||
* (Bug 129969), so we re-process the fallback just in case
|
|
||||||
@@ -1997,11 +1996,8 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
|
|
||||||
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
|
|
||||||
newctxt->incTotal = ctxt->incTotal;
|
|
||||||
- for (child = fallback->children; child != NULL; child = next) {
|
|
||||||
- next = child->next;
|
|
||||||
- if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
|
|
||||||
- ret = -1;
|
|
||||||
- }
|
|
||||||
+ if (xmlXIncludeDoProcess(newctxt, ctxt->doc, fallback, 1) < 0)
|
|
||||||
+ ret = -1;
|
|
||||||
ctxt->incTotal = newctxt->incTotal;
|
|
||||||
if (ctxt->nbErrors > oldNbErrors)
|
|
||||||
ret = -1;
|
|
||||||
@@ -2386,6 +2382,7 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
|
|
||||||
* @ctxt: the XInclude processing context
|
|
||||||
* @doc: an XML document
|
|
||||||
* @tree: the top of the tree to process
|
|
||||||
+ * @skipRoot: don't process the root node of the tree
|
|
||||||
*
|
|
||||||
* Implement the XInclude substitution on the XML document @doc
|
|
||||||
*
|
|
||||||
@@ -2393,13 +2390,16 @@ xmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
|
|
||||||
* or the number of substitutions done.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
-xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
+xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
|
|
||||||
+ int skipRoot) {
|
|
||||||
xmlNodePtr cur;
|
|
||||||
int ret = 0;
|
|
||||||
int i, start;
|
|
||||||
|
|
||||||
if ((doc == NULL) || (tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
|
|
||||||
return(-1);
|
|
||||||
+ if ((skipRoot) && (tree->children == NULL))
|
|
||||||
+ return(-1);
|
|
||||||
if (ctxt == NULL)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
@@ -2413,7 +2413,10 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
/*
|
|
||||||
* First phase: lookup the elements in the document
|
|
||||||
*/
|
|
||||||
- cur = tree;
|
|
||||||
+ if (skipRoot)
|
|
||||||
+ cur = tree->children;
|
|
||||||
+ else
|
|
||||||
+ cur = tree;
|
|
||||||
do {
|
|
||||||
/* TODO: need to work on entities -> stack */
|
|
||||||
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
|
|
||||||
@@ -2521,7 +2524,7 @@ xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data) {
|
|
||||||
ctxt->_private = data;
|
|
||||||
ctxt->base = xmlStrdup((xmlChar *)tree->doc->URL);
|
|
||||||
xmlXIncludeSetFlags(ctxt, flags);
|
|
||||||
- ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
|
|
||||||
+ ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
|
|
||||||
if ((ret >= 0) && (ctxt->nbErrors > 0))
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
@@ -2605,7 +2608,7 @@ xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) {
|
|
||||||
return(-1);
|
|
||||||
ctxt->base = xmlNodeGetBase(tree->doc, tree);
|
|
||||||
xmlXIncludeSetFlags(ctxt, flags);
|
|
||||||
- ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree);
|
|
||||||
+ ret = xmlXIncludeDoProcess(ctxt, tree->doc, tree, 0);
|
|
||||||
if ((ret >= 0) && (ctxt->nbErrors > 0))
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
@@ -2645,7 +2648,7 @@ xmlXIncludeProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
|
|
||||||
if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
|
|
||||||
(node->doc == NULL) || (ctxt == NULL))
|
|
||||||
return(-1);
|
|
||||||
- ret = xmlXIncludeDoProcess(ctxt, node->doc, node);
|
|
||||||
+ ret = xmlXIncludeDoProcess(ctxt, node->doc, node, 0);
|
|
||||||
if ((ret >= 0) && (ctxt->nbErrors > 0))
|
|
||||||
ret = -1;
|
|
||||||
return(ret);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
From 50f18830e179f273c244d4969485c4154c81cc01 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 21 Jun 2020 15:21:45 +0200
|
|
||||||
Subject: [PATCH 058/139] Fix another memory leak in xmlSchemaValAtomicType
|
|
||||||
|
|
||||||
Don't collapse language IDs twice.
|
|
||||||
|
|
||||||
Found with libFuzzer and ASan.
|
|
||||||
---
|
|
||||||
xmlschemastypes.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
|
|
||||||
index 1a44052..35edfd6 100644
|
|
||||||
--- a/xmlschemastypes.c
|
|
||||||
+++ b/xmlschemastypes.c
|
|
||||||
@@ -2636,7 +2636,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
|
||||||
goto return0;
|
|
||||||
}
|
|
||||||
case XML_SCHEMAS_LANGUAGE:
|
|
||||||
- if (normOnTheFly) {
|
|
||||||
+ if ((norm == NULL) && (normOnTheFly)) {
|
|
||||||
norm = xmlSchemaCollapseString(value);
|
|
||||||
if (norm != NULL)
|
|
||||||
value = norm;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
From b215c270fa3b1436314cc56654718bd12182cfec Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 13 Sep 2020 12:19:48 +0200
|
|
||||||
Subject: [PATCH] Fix cleanup of attributes in XML reader
|
|
||||||
|
|
||||||
xml:id creates ID attributes even in documents without a DTD, so the
|
|
||||||
check in xmlTextReaderFreeProp must be changed to avoid use after free.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xmlreader.c | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlreader.c b/xmlreader.c
|
|
||||||
index a9b9ef93..01adf74f 100644
|
|
||||||
--- a/xmlreader.c
|
|
||||||
+++ b/xmlreader.c
|
|
||||||
@@ -359,12 +359,12 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
|
|
||||||
xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);
|
|
||||||
|
|
||||||
/* Check for ID removal -> leading to invalid references ! */
|
|
||||||
- if ((cur->parent != NULL) && (cur->parent->doc != NULL) &&
|
|
||||||
- ((cur->parent->doc->intSubset != NULL) ||
|
|
||||||
- (cur->parent->doc->extSubset != NULL))) {
|
|
||||||
+ if ((cur->parent != NULL) && (cur->parent->doc != NULL)) {
|
|
||||||
if (xmlIsID(cur->parent->doc, cur->parent, cur))
|
|
||||||
xmlTextReaderRemoveID(cur->parent->doc, cur);
|
|
||||||
- if (xmlIsRef(cur->parent->doc, cur->parent, cur))
|
|
||||||
+ if (((cur->parent->doc->intSubset != NULL) ||
|
|
||||||
+ (cur->parent->doc->extSubset != NULL)) &&
|
|
||||||
+ (xmlIsRef(cur->parent->doc, cur->parent, cur)))
|
|
||||||
xmlTextReaderRemoveRef(cur->parent->doc, cur);
|
|
||||||
}
|
|
||||||
if (cur->children != NULL)
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
From f9ea1a24ed0fd2fd051bb01b0d08cdff60887938 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 11 Feb 2020 16:17:34 +0100
|
|
||||||
Subject: [PATCH] Fix copying of entities in xmlParseReference
|
|
||||||
|
|
||||||
Before, reader mode would end up in a branch that didn't handle
|
|
||||||
entities with multiple children and failed to update ent->last, so the
|
|
||||||
hack copying the "extra" reader data wouldn't trigger. Consequently,
|
|
||||||
some empty nodes in entities are correctly detected now in the test
|
|
||||||
suite. (The detection of empty nodes in entities is still buggy,
|
|
||||||
though.)
|
|
||||||
---
|
|
||||||
parser.c | 64 +++++++++++++++++++++++++++------------------------------
|
|
||||||
result/att7.rde | 3 +--
|
|
||||||
result/ent9.rde | 6 ++----
|
|
||||||
3 files changed, 33 insertions(+), 40 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 1ba988c..5ff8592 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -7159,42 +7159,38 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|
||||||
(ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
|
|
||||||
(ent->children == NULL)) {
|
|
||||||
ent->children = list;
|
|
||||||
- if (ctxt->replaceEntities) {
|
|
||||||
- /*
|
|
||||||
- * Prune it directly in the generated document
|
|
||||||
- * except for single text nodes.
|
|
||||||
- */
|
|
||||||
- if (((list->type == XML_TEXT_NODE) &&
|
|
||||||
- (list->next == NULL)) ||
|
|
||||||
- (ctxt->parseMode == XML_PARSE_READER)) {
|
|
||||||
- list->parent = (xmlNodePtr) ent;
|
|
||||||
- list = NULL;
|
|
||||||
- ent->owner = 1;
|
|
||||||
- } else {
|
|
||||||
- ent->owner = 0;
|
|
||||||
- while (list != NULL) {
|
|
||||||
- list->parent = (xmlNodePtr) ctxt->node;
|
|
||||||
- list->doc = ctxt->myDoc;
|
|
||||||
- if (list->next == NULL)
|
|
||||||
- ent->last = list;
|
|
||||||
- list = list->next;
|
|
||||||
- }
|
|
||||||
- list = ent->children;
|
|
||||||
+ /*
|
|
||||||
+ * Prune it directly in the generated document
|
|
||||||
+ * except for single text nodes.
|
|
||||||
+ */
|
|
||||||
+ if ((ctxt->replaceEntities == 0) ||
|
|
||||||
+ (ctxt->parseMode == XML_PARSE_READER) ||
|
|
||||||
+ ((list->type == XML_TEXT_NODE) &&
|
|
||||||
+ (list->next == NULL))) {
|
|
||||||
+ ent->owner = 1;
|
|
||||||
+ while (list != NULL) {
|
|
||||||
+ list->parent = (xmlNodePtr) ent;
|
|
||||||
+ xmlSetTreeDoc(list, ent->doc);
|
|
||||||
+ if (list->next == NULL)
|
|
||||||
+ ent->last = list;
|
|
||||||
+ list = list->next;
|
|
||||||
+ }
|
|
||||||
+ list = NULL;
|
|
||||||
+ } else {
|
|
||||||
+ ent->owner = 0;
|
|
||||||
+ while (list != NULL) {
|
|
||||||
+ list->parent = (xmlNodePtr) ctxt->node;
|
|
||||||
+ list->doc = ctxt->myDoc;
|
|
||||||
+ if (list->next == NULL)
|
|
||||||
+ ent->last = list;
|
|
||||||
+ list = list->next;
|
|
||||||
+ }
|
|
||||||
+ list = ent->children;
|
|
||||||
#ifdef LIBXML_LEGACY_ENABLED
|
|
||||||
- if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
|
|
||||||
- xmlAddEntityReference(ent, list, NULL);
|
|
||||||
+ if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
|
|
||||||
+ xmlAddEntityReference(ent, list, NULL);
|
|
||||||
#endif /* LIBXML_LEGACY_ENABLED */
|
|
||||||
- }
|
|
||||||
- } else {
|
|
||||||
- ent->owner = 1;
|
|
||||||
- while (list != NULL) {
|
|
||||||
- list->parent = (xmlNodePtr) ent;
|
|
||||||
- xmlSetTreeDoc(list, ent->doc);
|
|
||||||
- if (list->next == NULL)
|
|
||||||
- ent->last = list;
|
|
||||||
- list = list->next;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
xmlFreeNodeList(list);
|
|
||||||
list = NULL;
|
|
||||||
diff --git a/result/att7.rde b/result/att7.rde
|
|
||||||
index afcef5f..6079637 100644
|
|
||||||
--- a/result/att7.rde
|
|
||||||
+++ b/result/att7.rde
|
|
||||||
@@ -5,8 +5,7 @@
|
|
||||||
1 1 test 1 0
|
|
||||||
1 14 #text 0 1
|
|
||||||
|
|
||||||
-1 1 test 0 0
|
|
||||||
-1 15 test 0 0
|
|
||||||
+1 1 test 1 0
|
|
||||||
1 14 #text 0 1
|
|
||||||
|
|
||||||
0 15 x 0 0
|
|
||||||
diff --git a/result/ent9.rde b/result/ent9.rde
|
|
||||||
index 38b9f43..2206146 100644
|
|
||||||
--- a/result/ent9.rde
|
|
||||||
+++ b/result/ent9.rde
|
|
||||||
@@ -12,8 +12,7 @@
|
|
||||||
2 1 c 0 0
|
|
||||||
2 15 c 0 0
|
|
||||||
2 3 #text 0 1 ,
|
|
||||||
-2 1 d 0 0
|
|
||||||
-2 15 d 0 0
|
|
||||||
+2 1 d 1 0
|
|
||||||
1 15 ent 0 0
|
|
||||||
1 14 #text 0 1
|
|
||||||
|
|
||||||
@@ -292,8 +291,7 @@
|
|
||||||
2 1 c 0 0
|
|
||||||
2 15 c 0 0
|
|
||||||
2 3 #text 0 1 ,
|
|
||||||
-2 1 d 0 0
|
|
||||||
-2 15 d 0 0
|
|
||||||
+2 1 d 1 0
|
|
||||||
1 15 ent 0 0
|
|
||||||
1 14 #text 0 1
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
From d88df4bd48ba4ce9a68040a2427b4a665d5ff891 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 16 Aug 2020 23:38:48 +0200
|
|
||||||
Subject: [PATCH] Fix corner case with empty xi:fallback
|
|
||||||
|
|
||||||
xi:fallback could become empty after recursive expansion. Use a flag
|
|
||||||
to track whether nodes should be skipped.
|
|
||||||
---
|
|
||||||
result/XInclude/fallback6.xml | 1 +
|
|
||||||
result/XInclude/fallback6.xml.rdr | 0
|
|
||||||
test/XInclude/docs/fallback6.xml | 6 ++++++
|
|
||||||
xinclude.c | 11 ++++-------
|
|
||||||
4 files changed, 11 insertions(+), 7 deletions(-)
|
|
||||||
create mode 100644 result/XInclude/fallback6.xml
|
|
||||||
create mode 100644 result/XInclude/fallback6.xml.rdr
|
|
||||||
create mode 100644 test/XInclude/docs/fallback6.xml
|
|
||||||
|
|
||||||
diff --git a/result/XInclude/fallback6.xml b/result/XInclude/fallback6.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..2b5d411
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback6.xml
|
|
||||||
@@ -0,0 +1 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
diff --git a/result/XInclude/fallback6.xml.rdr b/result/XInclude/fallback6.xml.rdr
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..e69de29
|
|
||||||
diff --git a/test/XInclude/docs/fallback6.xml b/test/XInclude/docs/fallback6.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..fd00a03
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/XInclude/docs/fallback6.xml
|
|
||||||
@@ -0,0 +1,6 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="b.xml">
|
|
||||||
+ <xi:fallback><xi:include href="c.xml">
|
|
||||||
+ <xi:fallback/>
|
|
||||||
+ </xi:include></xi:fallback>
|
|
||||||
+</xi:include>
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index ff265eb..e9d3af5 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -60,7 +60,7 @@ struct _xmlXIncludeRef {
|
|
||||||
int xml; /* xml or txt */
|
|
||||||
int count; /* how many refs use that specific doc */
|
|
||||||
xmlXPathObjectPtr xptr; /* the xpointer if needed */
|
|
||||||
- int emptyFb; /* flag to show fallback empty */
|
|
||||||
+ int skip; /* skip in case of errors */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _xmlXIncludeCtxt {
|
|
||||||
@@ -2007,7 +2007,6 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
fallback->children);
|
|
||||||
} else {
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
- ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
|
|
||||||
}
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
@@ -2164,13 +2163,13 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
((xmlStrEqual(children->ns->href, XINCLUDE_NS)) ||
|
|
||||||
(xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) {
|
|
||||||
ret = xmlXIncludeLoadFallback(ctxt, children, nr);
|
|
||||||
- if (ret == 0)
|
|
||||||
- break;
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
children = children->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ret < 0) {
|
|
||||||
+ ctxt->incTab[nr]->skip = 1;
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
XML_XINCLUDE_NO_FALLBACK,
|
|
||||||
"could not load %s, and no fallback was found\n",
|
|
||||||
@@ -2468,9 +2467,7 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
|
|
||||||
- if ((ctxt->incTab[i]->inc != NULL) ||
|
|
||||||
- (ctxt->incTab[i]->xptr != NULL) ||
|
|
||||||
- (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
|
|
||||||
+ if (ctxt->incTab[i]->skip == 0)
|
|
||||||
xmlXIncludeIncludeNode(ctxt, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
From 72b3c067cedbb80dbbac755cca79ff502c858ad5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 22 Apr 2021 19:24:50 +0200
|
|
||||||
Subject: [PATCH] Fix dangling pointer with `xmllint --dropdtd`
|
|
||||||
|
|
||||||
Reset doc->intSubset when dropping the DTD.
|
|
||||||
---
|
|
||||||
xmllint.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/xmllint.c b/xmllint.c
|
|
||||||
index dbef273..a3fe10a 100644
|
|
||||||
--- a/xmllint.c
|
|
||||||
+++ b/xmllint.c
|
|
||||||
@@ -2426,6 +2426,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
|
|
||||||
dtd = xmlGetIntSubset(doc);
|
|
||||||
if (dtd != NULL) {
|
|
||||||
xmlUnlinkNode((xmlNodePtr)dtd);
|
|
||||||
+ doc->intSubset = NULL;
|
|
||||||
xmlFreeDtd(dtd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
From ba589adc2f86c6be9ad7e0d771d4c9b09d059b89 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 25 Aug 2020 23:50:39 +0200
|
|
||||||
Subject: [PATCH 138/139] Fix double free in XML reader with XIncludes
|
|
||||||
|
|
||||||
An XInclude with empty fallback could lead to a double free in
|
|
||||||
xmlTextReaderRead.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xmlreader.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xmlreader.c b/xmlreader.c
|
|
||||||
index 6ae6e92..1ab15ba 100644
|
|
||||||
--- a/xmlreader.c
|
|
||||||
+++ b/xmlreader.c
|
|
||||||
@@ -1491,6 +1491,8 @@ get_next_node:
|
|
||||||
(reader->node->prev->type != XML_DTD_NODE)) {
|
|
||||||
xmlNodePtr tmp = reader->node->prev;
|
|
||||||
if ((tmp->extra & NODE_IS_PRESERVED) == 0) {
|
|
||||||
+ if (oldnode == tmp)
|
|
||||||
+ oldnode = NULL;
|
|
||||||
xmlUnlinkNode(tmp);
|
|
||||||
xmlTextReaderFreeNode(reader, tmp);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From 683de7efe4a4178d62fab85d8c5f4c3bed36b984 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 4 Mar 2021 19:06:04 +0100
|
|
||||||
Subject: [PATCH] Fix duplicate xmlStrEqual calls in htmlParseEndTag
|
|
||||||
|
|
||||||
---
|
|
||||||
HTMLparser.c | 10 ++++------
|
|
||||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
|
||||||
index e63e9b7..adefb3b 100644
|
|
||||||
--- a/HTMLparser.c
|
|
||||||
+++ b/HTMLparser.c
|
|
||||||
@@ -4207,12 +4207,10 @@ htmlParseEndTag(htmlParserCtxtPtr ctxt)
|
|
||||||
* With the exception that the autoclose may have popped stuff out
|
|
||||||
* of the stack.
|
|
||||||
*/
|
|
||||||
- if (!xmlStrEqual(name, ctxt->name)) {
|
|
||||||
- if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
|
|
||||||
- htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
|
|
||||||
- "Opening and ending tag mismatch: %s and %s\n",
|
|
||||||
- name, ctxt->name);
|
|
||||||
- }
|
|
||||||
+ if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
|
|
||||||
+ htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
|
|
||||||
+ "Opening and ending tag mismatch: %s and %s\n",
|
|
||||||
+ name, ctxt->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
From 2c747129779be9e3ce84a2f98ce5052a68d41098 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 17 Aug 2020 00:54:12 +0200
|
|
||||||
Subject: [PATCH] Fix error reporting with xi:fallback
|
|
||||||
|
|
||||||
When reporting errors, don't use href of xi:include if xi:fallback
|
|
||||||
was used. I think this can only be reproduced with
|
|
||||||
"xmllint --postvalid", see the original bug report:
|
|
||||||
|
|
||||||
https://bugzilla.gnome.org/show_bug.cgi?id=152623
|
|
||||||
---
|
|
||||||
error.c | 22 +++++++++++-----------
|
|
||||||
xinclude.c | 4 ++++
|
|
||||||
2 files changed, 15 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/error.c b/error.c
|
|
||||||
index 3e41e17..9ff1c2b 100644
|
|
||||||
--- a/error.c
|
|
||||||
+++ b/error.c
|
|
||||||
@@ -557,6 +557,7 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel,
|
|
||||||
* of the usual "base" (doc->URL) for the node (bug 152623).
|
|
||||||
*/
|
|
||||||
xmlNodePtr prev = baseptr;
|
|
||||||
+ char *href = NULL;
|
|
||||||
int inclcount = 0;
|
|
||||||
while (prev != NULL) {
|
|
||||||
if (prev->prev == NULL)
|
|
||||||
@@ -564,21 +565,20 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel,
|
|
||||||
else {
|
|
||||||
prev = prev->prev;
|
|
||||||
if (prev->type == XML_XINCLUDE_START) {
|
|
||||||
- if (--inclcount < 0)
|
|
||||||
- break;
|
|
||||||
+ if (inclcount > 0) {
|
|
||||||
+ --inclcount;
|
|
||||||
+ } else {
|
|
||||||
+ href = (char *) xmlGetProp(prev, BAD_CAST "href");
|
|
||||||
+ if (href != NULL)
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
} else if (prev->type == XML_XINCLUDE_END)
|
|
||||||
inclcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- if (prev != NULL) {
|
|
||||||
- if (prev->type == XML_XINCLUDE_START) {
|
|
||||||
- prev->type = XML_ELEMENT_NODE;
|
|
||||||
- to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
|
|
||||||
- prev->type = XML_XINCLUDE_START;
|
|
||||||
- } else {
|
|
||||||
- to->file = (char *) xmlGetProp(prev, BAD_CAST "href");
|
|
||||||
- }
|
|
||||||
- } else
|
|
||||||
+ if (href != NULL)
|
|
||||||
+ to->file = href;
|
|
||||||
+ else
|
|
||||||
#endif
|
|
||||||
to->file = (char *) xmlStrdup(baseptr->doc->URL);
|
|
||||||
if ((to->file == NULL) && (node != NULL) && (node->doc != NULL)) {
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 9a65ee5..2423a93 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -61,6 +61,7 @@ struct _xmlXIncludeRef {
|
|
||||||
int count; /* how many refs use that specific doc */
|
|
||||||
xmlXPathObjectPtr xptr; /* the xpointer if needed */
|
|
||||||
int skip; /* skip in case of errors */
|
|
||||||
+ int fallback; /* fallback was loaded */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _xmlXIncludeCtxt {
|
|
||||||
@@ -2007,6 +2008,7 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
} else {
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
}
|
|
||||||
+ ctxt->incTab[nr]->fallback = 1;
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2266,6 +2268,8 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
* Change the current node as an XInclude start one, and add an
|
|
||||||
* XInclude end one
|
|
||||||
*/
|
|
||||||
+ if (ctxt->incTab[nr]->fallback)
|
|
||||||
+ xmlUnsetProp(cur, BAD_CAST "href");
|
|
||||||
cur->type = XML_XINCLUDE_START;
|
|
||||||
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
|
|
||||||
if (end == NULL) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
From c3fd8c429591e06eb847c11bc9273d13b3450d53 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 13 Mar 2021 17:19:32 +0100
|
|
||||||
Subject: [PATCH] Fix exponential behavior with recursive entities
|
|
||||||
|
|
||||||
Fix another case where only recursion depth was limited, but entities
|
|
||||||
would still be expanded over and over again.
|
|
||||||
|
|
||||||
The test case discovered by fuzzing only affected parsing in recovery
|
|
||||||
mode with XML_PARSE_RECOVER.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
parser.c | 9 +++++++--
|
|
||||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index efde672..b42e604 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -2684,8 +2684,10 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|
||||||
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
|
|
||||||
0, 0, 0);
|
|
||||||
ctxt->depth--;
|
|
||||||
- if (rep == NULL)
|
|
||||||
+ if (rep == NULL) {
|
|
||||||
+ ent->content[0] = 0;
|
|
||||||
goto int_error;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
current = rep;
|
|
||||||
while (*current != 0) { /* non input consuming loop */
|
|
||||||
@@ -2740,8 +2742,11 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|
||||||
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
|
|
||||||
0, 0, 0);
|
|
||||||
ctxt->depth--;
|
|
||||||
- if (rep == NULL)
|
|
||||||
+ if (rep == NULL) {
|
|
||||||
+ if (ent->content != NULL)
|
|
||||||
+ ent->content[0] = 0;
|
|
||||||
goto int_error;
|
|
||||||
+ }
|
|
||||||
current = rep;
|
|
||||||
while (*current != 0) { /* non input consuming loop */
|
|
||||||
buffer[nbchars++] = *current++;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,317 +0,0 @@
|
|||||||
From 1abf2967f955858764a6de5d7b7fe247cb637853 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 6 Aug 2020 17:51:57 +0200
|
|
||||||
Subject: [PATCH 109/139] Fix exponential runtime and memory in xi:fallback
|
|
||||||
processing
|
|
||||||
|
|
||||||
When creating XML_XINCLUDE_START nodes, the children of the original
|
|
||||||
xi:include node must be freed, otherwise fallback content is copied
|
|
||||||
twice, doubling runtime and memory consumption for each nested
|
|
||||||
xi:fallback/xi:include pair.
|
|
||||||
|
|
||||||
Found with libFuzzer.
|
|
||||||
---
|
|
||||||
result/XInclude/fallback5.xml | 51 +++++++++++++++++
|
|
||||||
result/XInclude/fallback5.xml.rdr | 116 ++++++++++++++++++++++++++++++++++++++
|
|
||||||
test/XInclude/docs/fallback5.xml | 83 +++++++++++++++++++++++++++
|
|
||||||
xinclude.c | 8 +++
|
|
||||||
4 files changed, 258 insertions(+)
|
|
||||||
create mode 100644 result/XInclude/fallback5.xml
|
|
||||||
create mode 100644 result/XInclude/fallback5.xml.rdr
|
|
||||||
create mode 100644 test/XInclude/docs/fallback5.xml
|
|
||||||
|
|
||||||
diff --git a/result/XInclude/fallback5.xml b/result/XInclude/fallback5.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..0ba503d
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback5.xml
|
|
||||||
@@ -0,0 +1,51 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
+<a>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+ <elem/>
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+</a>
|
|
||||||
diff --git a/result/XInclude/fallback5.xml.rdr b/result/XInclude/fallback5.xml.rdr
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..0e1dab7
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/fallback5.xml.rdr
|
|
||||||
@@ -0,0 +1,116 @@
|
|
||||||
+0 1 a 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+0 15 a 0 0
|
|
||||||
diff --git a/test/XInclude/docs/fallback5.xml b/test/XInclude/docs/fallback5.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..d3ad424
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/XInclude/docs/fallback5.xml
|
|
||||||
@@ -0,0 +1,83 @@
|
|
||||||
+<a>
|
|
||||||
+ <xi:include href="a01.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a02.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a03.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a04.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a05.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a06.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a07.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a08.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a09.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a10.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a11.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a12.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a13.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a14.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a15.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ <xi:include href="a16.xml">
|
|
||||||
+ <xi:fallback>
|
|
||||||
+ <elem/>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+</a>
|
|
||||||
+
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 2917d45..5ea87ad 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -2260,11 +2260,19 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
xmlUnlinkNode(cur);
|
|
||||||
xmlFreeNode(cur);
|
|
||||||
} else {
|
|
||||||
+ xmlNodePtr child, next;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Change the current node as an XInclude start one, and add an
|
|
||||||
* XInclude end one
|
|
||||||
*/
|
|
||||||
cur->type = XML_XINCLUDE_START;
|
|
||||||
+ /* Remove fallback children */
|
|
||||||
+ for (child = cur->children; child != NULL; child = next) {
|
|
||||||
+ next = child->next;
|
|
||||||
+ xmlUnlinkNode(child);
|
|
||||||
+ xmlFreeNode(child);
|
|
||||||
+ }
|
|
||||||
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
|
|
||||||
if (end == NULL) {
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
From 68eadabd0055cba39c4ea1acfa8931d0d10a44e5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 11 Jul 2020 21:32:10 +0200
|
|
||||||
Subject: [PATCH] Fix exponential runtime in xmlFARecurseDeterminism
|
|
||||||
|
|
||||||
In order to prevent visiting a state twice, states must be marked as
|
|
||||||
visited for the whole duration of graph traversal because states might
|
|
||||||
be reached by different paths. Otherwise state graphs like the
|
|
||||||
following can lead to exponential runtime:
|
|
||||||
|
|
||||||
->O-->O-->O-->O-->O->
|
|
||||||
\ / \ / \ / \ /
|
|
||||||
O O O O
|
|
||||||
|
|
||||||
Reset the "visited" flag only after the graph was traversed.
|
|
||||||
|
|
||||||
xmlFAComputesDeterminism still has massive performance problems when
|
|
||||||
handling fuzzed input. By design, it has quadratic time complexity in
|
|
||||||
the number of reachable states. Some issues might also stem from
|
|
||||||
redundant epsilon transitions. With this fix, fuzzing regexes with a
|
|
||||||
maximum length of 100 becomes feasible at least.
|
|
||||||
|
|
||||||
Found with libFuzzer.
|
|
||||||
---
|
|
||||||
xmlregexp.c | 26 +++++++++++++++++++++++++-
|
|
||||||
1 file changed, 25 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmlregexp.c b/xmlregexp.c
|
|
||||||
index dbf3bf2c..f971f0c8 100644
|
|
||||||
--- a/xmlregexp.c
|
|
||||||
+++ b/xmlregexp.c
|
|
||||||
@@ -2658,7 +2658,6 @@ xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
|
|
||||||
state->markd = XML_REGEXP_MARK_VISITED;
|
|
||||||
res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
|
|
||||||
to, atom);
|
|
||||||
- state->markd = 0;
|
|
||||||
if (res == 0) {
|
|
||||||
ret = 0;
|
|
||||||
/* t1->nd = 1; */
|
|
||||||
@@ -2676,6 +2675,30 @@ xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * xmlFAFinishRecurseDeterminism:
|
|
||||||
+ * @ctxt: a regexp parser context
|
|
||||||
+ *
|
|
||||||
+ * Reset flags after checking determinism.
|
|
||||||
+ */
|
|
||||||
+static void
|
|
||||||
+xmlFAFinishRecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
|
|
||||||
+ int transnr, nbTrans;
|
|
||||||
+
|
|
||||||
+ if (state == NULL)
|
|
||||||
+ return;
|
|
||||||
+ if (state->markd != XML_REGEXP_MARK_VISITED)
|
|
||||||
+ return;
|
|
||||||
+ state->markd = 0;
|
|
||||||
+
|
|
||||||
+ nbTrans = state->nbTrans;
|
|
||||||
+ for (transnr = 0; transnr < nbTrans; transnr++) {
|
|
||||||
+ xmlRegTransPtr t1 = &state->trans[transnr];
|
|
||||||
+ if ((t1->atom == NULL) && (t1->to >= 0))
|
|
||||||
+ xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* xmlFAComputesDeterminism:
|
|
||||||
* @ctxt: a regexp parser context
|
|
||||||
@@ -2789,6 +2812,7 @@ xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
*/
|
|
||||||
ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
|
|
||||||
t2->to, t2->atom);
|
|
||||||
+ xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]);
|
|
||||||
/* don't shortcut the computation so all non deterministic
|
|
||||||
transition get marked down
|
|
||||||
if (ret == 0)
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From 0815302dee2b78139832c2080348086a0564836b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Fri, 6 Dec 2019 12:27:29 +0100
|
|
||||||
Subject: [PATCH] Fix freeing of nested documents
|
|
||||||
|
|
||||||
Apparently, some libxslt RVTs can contain nested document nodes, see
|
|
||||||
issue #132. I'm not sure how this happens exactly but it can cause a
|
|
||||||
segfault in xmlFreeNodeList after the changes in commit 0762c9b6.
|
|
||||||
|
|
||||||
Make sure not to touch the (nonexistent) `content` member of xmlDocs.
|
|
||||||
---
|
|
||||||
tree.c | 5 +++++
|
|
||||||
1 file changed, 5 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/tree.c b/tree.c
|
|
||||||
index 070670f..0d7fc98 100644
|
|
||||||
--- a/tree.c
|
|
||||||
+++ b/tree.c
|
|
||||||
@@ -3708,6 +3708,11 @@ xmlFreeNodeList(xmlNodePtr cur) {
|
|
||||||
(cur->type != XML_XINCLUDE_START) &&
|
|
||||||
(cur->type != XML_XINCLUDE_END) &&
|
|
||||||
(cur->type != XML_ENTITY_REF_NODE) &&
|
|
||||||
+ (cur->type != XML_DOCUMENT_NODE) &&
|
|
||||||
+#ifdef LIBXML_DOCB_ENABLED
|
|
||||||
+ (cur->type != XML_DOCB_DOCUMENT_NODE) &&
|
|
||||||
+#endif
|
|
||||||
+ (cur->type != XML_HTML_DOCUMENT_NODE) &&
|
|
||||||
(cur->content != (xmlChar *) &(cur->properties))) {
|
|
||||||
DICT_FREE(cur->content)
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,125 +0,0 @@
|
|||||||
From de5b624f10e9d29ff1b3bbc07358774a3725898e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 8 May 2021 20:21:29 +0200
|
|
||||||
Subject: [PATCH] Fix handling of unexpected EOF in xmlParseContent
|
|
||||||
|
|
||||||
Readd the XML_ERR_TAG_NOT_FINISHED error on unexpected EOF which was
|
|
||||||
removed in commit 62150ed2.
|
|
||||||
|
|
||||||
This commit also introduced a regression for direct users of
|
|
||||||
xmlParseContent. Unclosed tags weren't checked.
|
|
||||||
---
|
|
||||||
parser.c | 48 +++++++++++++++++++++++++++++++++++++-------
|
|
||||||
python/tests/tstLastError.py | 4 ++--
|
|
||||||
result/errors/754947.xml.err | 2 +-
|
|
||||||
3 files changed, 44 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index c2948ca..dd58282 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -9837,16 +9837,15 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
- * xmlParseContent:
|
|
||||||
+ * xmlParseContentInternal:
|
|
||||||
* @ctxt: an XML parser context
|
|
||||||
*
|
|
||||||
- * Parse a content:
|
|
||||||
- *
|
|
||||||
- * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
|
|
||||||
+ * Parse a content sequence. Stops at EOF or '</'. Leaves checking of
|
|
||||||
+ * unexpected EOF to the caller.
|
|
||||||
*/
|
|
||||||
|
|
||||||
-void
|
|
||||||
-xmlParseContent(xmlParserCtxtPtr ctxt) {
|
|
||||||
+static void
|
|
||||||
+xmlParseContentInternal(xmlParserCtxtPtr ctxt) {
|
|
||||||
int nameNr = ctxt->nameNr;
|
|
||||||
|
|
||||||
GROW;
|
|
||||||
@@ -9922,6 +9921,30 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
+ * xmlParseContent:
|
|
||||||
+ * @ctxt: an XML parser context
|
|
||||||
+ *
|
|
||||||
+ * Parse a content sequence. Stops at EOF or '</'.
|
|
||||||
+ *
|
|
||||||
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+xmlParseContent(xmlParserCtxtPtr ctxt) {
|
|
||||||
+ int nameNr = ctxt->nameNr;
|
|
||||||
+
|
|
||||||
+ xmlParseContentInternal(ctxt);
|
|
||||||
+
|
|
||||||
+ if ((ctxt->instate != XML_PARSER_EOF) && (ctxt->nameNr > nameNr)) {
|
|
||||||
+ const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
|
|
||||||
+ int line = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 4 - 2];
|
|
||||||
+ xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
|
|
||||||
+ "Premature end of data in tag %s line %d\n",
|
|
||||||
+ name, line, NULL);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
* xmlParseElement:
|
|
||||||
* @ctxt: an XML parser context
|
|
||||||
*
|
|
||||||
@@ -9939,9 +9962,20 @@ void
|
|
||||||
xmlParseElement(xmlParserCtxtPtr ctxt) {
|
|
||||||
if (xmlParseElementStart(ctxt) != 0)
|
|
||||||
return;
|
|
||||||
- xmlParseContent(ctxt);
|
|
||||||
+
|
|
||||||
+ xmlParseContentInternal(ctxt);
|
|
||||||
if (ctxt->instate == XML_PARSER_EOF)
|
|
||||||
return;
|
|
||||||
+
|
|
||||||
+ if (CUR == 0) {
|
|
||||||
+ const xmlChar *name = ctxt->nameTab[ctxt->nameNr - 1];
|
|
||||||
+ int line = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 4 - 2];
|
|
||||||
+ xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
|
|
||||||
+ "Premature end of data in tag %s line %d\n",
|
|
||||||
+ name, line, NULL);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
xmlParseElementEnd(ctxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/python/tests/tstLastError.py b/python/tests/tstLastError.py
|
|
||||||
index 1758a9f..36ffe5f 100755
|
|
||||||
--- a/python/tests/tstLastError.py
|
|
||||||
+++ b/python/tests/tstLastError.py
|
|
||||||
@@ -71,8 +71,8 @@ class TestCase(unittest.TestCase):
|
|
||||||
(s,len(s),"dummy.xml",None,0),
|
|
||||||
libxml2.treeError,
|
|
||||||
domain=libxml2.XML_FROM_PARSER,
|
|
||||||
- code=libxml2.XML_ERR_LTSLASH_REQUIRED,
|
|
||||||
- message='EndTag: \'</\' not found\n',
|
|
||||||
+ code=libxml2.XML_ERR_TAG_NOT_FINISHED,
|
|
||||||
+ message='Premature end of data in tag x line 1\n',
|
|
||||||
level=libxml2.XML_ERR_FATAL,
|
|
||||||
file='dummy.xml',
|
|
||||||
line=3)
|
|
||||||
diff --git a/result/errors/754947.xml.err b/result/errors/754947.xml.err
|
|
||||||
index 51e9b4e..f45cb5a 100644
|
|
||||||
--- a/result/errors/754947.xml.err
|
|
||||||
+++ b/result/errors/754947.xml.err
|
|
||||||
@@ -2,6 +2,6 @@
|
|
||||||
Bytes: 0xEE 0x5D 0x5D 0x3E
|
|
||||||
<d><![CDATA[0000000000000î]]>
|
|
||||||
^
|
|
||||||
-./test/errors/754947.xml:1: parser error : EndTag: '</' not found
|
|
||||||
+./test/errors/754947.xml:1: parser error : Premature end of data in tag d line 1
|
|
||||||
<d><![CDATA[0000000000000î]]>
|
|
||||||
^
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From 18425d3ad5a9bbe5c6e7fd4a9a45691e6c8862d1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 21 Jun 2020 19:14:23 +0200
|
|
||||||
Subject: [PATCH 060/139] Fix integer overflow in _xmlSchemaParseGYear
|
|
||||||
|
|
||||||
Found with libFuzzer and UBSan.
|
|
||||||
---
|
|
||||||
xmlschemastypes.c | 9 ++++++++-
|
|
||||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
|
|
||||||
index 35edfd6..164db94 100644
|
|
||||||
--- a/xmlschemastypes.c
|
|
||||||
+++ b/xmlschemastypes.c
|
|
||||||
@@ -1222,7 +1222,14 @@ _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
|
|
||||||
firstChar = cur;
|
|
||||||
|
|
||||||
while ((*cur >= '0') && (*cur <= '9')) {
|
|
||||||
- dt->year = dt->year * 10 + (*cur - '0');
|
|
||||||
+ int digit = *cur - '0';
|
|
||||||
+
|
|
||||||
+ if (dt->year > LONG_MAX / 10)
|
|
||||||
+ return 2;
|
|
||||||
+ dt->year *= 10;
|
|
||||||
+ if (dt->year > LONG_MAX - digit)
|
|
||||||
+ return 2;
|
|
||||||
+ dt->year += digit;
|
|
||||||
cur++;
|
|
||||||
digcnt++;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
From 31ca4a728cf96c9a341d0bfe489d2c0ba71dc6ff Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 15 Jun 2020 18:47:53 +0200
|
|
||||||
Subject: [PATCH 054/139] Fix integer overflow in htmlParseCharRef
|
|
||||||
|
|
||||||
Fixes #115.
|
|
||||||
---
|
|
||||||
HTMLparser.c | 27 +++++++++++++++++----------
|
|
||||||
1 file changed, 17 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
|
||||||
index 5dd62df..be7e14f 100644
|
|
||||||
--- a/HTMLparser.c
|
|
||||||
+++ b/HTMLparser.c
|
|
||||||
@@ -3400,13 +3400,16 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
|
|
||||||
((NXT(2) == 'x') || NXT(2) == 'X')) {
|
|
||||||
SKIP(3);
|
|
||||||
while (CUR != ';') {
|
|
||||||
- if ((CUR >= '0') && (CUR <= '9'))
|
|
||||||
- val = val * 16 + (CUR - '0');
|
|
||||||
- else if ((CUR >= 'a') && (CUR <= 'f'))
|
|
||||||
- val = val * 16 + (CUR - 'a') + 10;
|
|
||||||
- else if ((CUR >= 'A') && (CUR <= 'F'))
|
|
||||||
- val = val * 16 + (CUR - 'A') + 10;
|
|
||||||
- else {
|
|
||||||
+ if ((CUR >= '0') && (CUR <= '9')) {
|
|
||||||
+ if (val < 0x110000)
|
|
||||||
+ val = val * 16 + (CUR - '0');
|
|
||||||
+ } else if ((CUR >= 'a') && (CUR <= 'f')) {
|
|
||||||
+ if (val < 0x110000)
|
|
||||||
+ val = val * 16 + (CUR - 'a') + 10;
|
|
||||||
+ } else if ((CUR >= 'A') && (CUR <= 'F')) {
|
|
||||||
+ if (val < 0x110000)
|
|
||||||
+ val = val * 16 + (CUR - 'A') + 10;
|
|
||||||
+ } else {
|
|
||||||
htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF,
|
|
||||||
"htmlParseCharRef: missing semicolon\n",
|
|
||||||
NULL, NULL);
|
|
||||||
@@ -3419,9 +3422,10 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
|
|
||||||
} else if ((CUR == '&') && (NXT(1) == '#')) {
|
|
||||||
SKIP(2);
|
|
||||||
while (CUR != ';') {
|
|
||||||
- if ((CUR >= '0') && (CUR <= '9'))
|
|
||||||
- val = val * 10 + (CUR - '0');
|
|
||||||
- else {
|
|
||||||
+ if ((CUR >= '0') && (CUR <= '9')) {
|
|
||||||
+ if (val < 0x110000)
|
|
||||||
+ val = val * 10 + (CUR - '0');
|
|
||||||
+ } else {
|
|
||||||
htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF,
|
|
||||||
"htmlParseCharRef: missing semicolon\n",
|
|
||||||
NULL, NULL);
|
|
||||||
@@ -3440,6 +3444,9 @@ htmlParseCharRef(htmlParserCtxtPtr ctxt) {
|
|
||||||
*/
|
|
||||||
if (IS_CHAR(val)) {
|
|
||||||
return(val);
|
|
||||||
+ } else if (val >= 0x110000) {
|
|
||||||
+ htmlParseErr(ctxt, XML_ERR_INVALID_CHAR,
|
|
||||||
+ "htmlParseCharRef: value too large\n", NULL, NULL);
|
|
||||||
} else {
|
|
||||||
htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
|
|
||||||
"htmlParseCharRef: invalid xmlChar value %d\n",
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
From b07251215ef48c70c6e56f7351406c47cfca4d5b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Fri, 10 Jan 2020 15:55:07 +0100
|
|
||||||
Subject: [PATCH] Fix integer overflow in xmlBufferResize
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
tree.c | 9 +++++++--
|
|
||||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/tree.c b/tree.c
|
|
||||||
index 0d7fc98..f43f6de 100644
|
|
||||||
--- a/tree.c
|
|
||||||
+++ b/tree.c
|
|
||||||
@@ -7424,12 +7424,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
|
|
||||||
if (size < buf->size)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
+ if (size > UINT_MAX - 10) {
|
|
||||||
+ xmlTreeErrMemory("growing buffer");
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* figure out new size */
|
|
||||||
switch (buf->alloc){
|
|
||||||
case XML_BUFFER_ALLOC_IO:
|
|
||||||
case XML_BUFFER_ALLOC_DOUBLEIT:
|
|
||||||
/*take care of empty case*/
|
|
||||||
- newSize = (buf->size ? buf->size*2 : size + 10);
|
|
||||||
+ newSize = (buf->size ? buf->size : size + 10);
|
|
||||||
while (size > newSize) {
|
|
||||||
if (newSize > UINT_MAX / 2) {
|
|
||||||
xmlTreeErrMemory("growing buffer");
|
|
||||||
@@ -7445,7 +7450,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
|
|
||||||
if (buf->use < BASE_BUFFER_SIZE)
|
|
||||||
newSize = size;
|
|
||||||
else {
|
|
||||||
- newSize = buf->size * 2;
|
|
||||||
+ newSize = buf->size;
|
|
||||||
while (size > newSize) {
|
|
||||||
if (newSize > UINT_MAX / 2) {
|
|
||||||
xmlTreeErrMemory("growing buffer");
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
From 1e7851b5aea4b2d8b9a6b6c02187fc4786f7a8b7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 25 Jun 2020 12:17:50 +0200
|
|
||||||
Subject: [PATCH] Fix integer overflow in xmlFAParseQuantExact
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xmlregexp.c | 15 +++++++++++++--
|
|
||||||
1 file changed, 13 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlregexp.c b/xmlregexp.c
|
|
||||||
index 53fa145c..0272dcab 100644
|
|
||||||
--- a/xmlregexp.c
|
|
||||||
+++ b/xmlregexp.c
|
|
||||||
@@ -5211,13 +5211,24 @@ static int
|
|
||||||
xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
int ret = 0;
|
|
||||||
int ok = 0;
|
|
||||||
+ int overflow = 0;
|
|
||||||
|
|
||||||
while ((CUR >= '0') && (CUR <= '9')) {
|
|
||||||
- ret = ret * 10 + (CUR - '0');
|
|
||||||
+ if (ret > INT_MAX / 10) {
|
|
||||||
+ overflow = 1;
|
|
||||||
+ } else {
|
|
||||||
+ int digit = CUR - '0';
|
|
||||||
+
|
|
||||||
+ ret *= 10;
|
|
||||||
+ if (ret > INT_MAX - digit)
|
|
||||||
+ overflow = 1;
|
|
||||||
+ else
|
|
||||||
+ ret += digit;
|
|
||||||
+ }
|
|
||||||
ok = 1;
|
|
||||||
NEXT;
|
|
||||||
}
|
|
||||||
- if (ok != 1) {
|
|
||||||
+ if ((ok != 1) || (overflow == 1)) {
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
return(ret);
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
From 8e7c20a1af8776677d7890f30b7a180567701a49 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 3 Aug 2020 17:30:41 +0200
|
|
||||||
Subject: [PATCH 103/139] Fix integer overflow when comparing schema dates
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xmlschemastypes.c | 10 ++++++++++
|
|
||||||
1 file changed, 10 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
|
|
||||||
index 4249d70..d6b9f92 100644
|
|
||||||
--- a/xmlschemastypes.c
|
|
||||||
+++ b/xmlschemastypes.c
|
|
||||||
@@ -3691,6 +3691,8 @@ xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
|
|
||||||
minday = 0;
|
|
||||||
maxday = 0;
|
|
||||||
} else {
|
|
||||||
+ if (myear > LONG_MAX / 366)
|
|
||||||
+ return -2;
|
|
||||||
/* FIXME: This doesn't take leap year exceptions every 100/400 years
|
|
||||||
into account. */
|
|
||||||
maxday = 365 * myear + (myear + 3) / 4;
|
|
||||||
@@ -4079,6 +4081,14 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
|
|
||||||
if ((x == NULL) || (y == NULL))
|
|
||||||
return -2;
|
|
||||||
|
|
||||||
+ if ((x->value.date.year > LONG_MAX / 366) ||
|
|
||||||
+ (x->value.date.year < LONG_MIN / 366) ||
|
|
||||||
+ (y->value.date.year > LONG_MAX / 366) ||
|
|
||||||
+ (y->value.date.year < LONG_MIN / 366)) {
|
|
||||||
+ /* Possible overflow when converting to days. */
|
|
||||||
+ return -2;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (x->value.date.tz_flag) {
|
|
||||||
|
|
||||||
if (!y->value.date.tz_flag) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
From 070d635e771a24f33e8480fa60689a881c9fa636 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 21 Jun 2020 16:26:38 +0200
|
|
||||||
Subject: [PATCH 059/139] Fix integer overflow when parsing {min,max}Occurs
|
|
||||||
|
|
||||||
Clamp value to INT_MAX.
|
|
||||||
|
|
||||||
Found with libFuzzer and UBSan.
|
|
||||||
---
|
|
||||||
xmlschemas.c | 22 ++++++++++++++++++++--
|
|
||||||
1 file changed, 20 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlschemas.c b/xmlschemas.c
|
|
||||||
index 81c47bc..cc20063 100644
|
|
||||||
--- a/xmlschemas.c
|
|
||||||
+++ b/xmlschemas.c
|
|
||||||
@@ -6074,7 +6074,16 @@ xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
|
|
||||||
return (def);
|
|
||||||
}
|
|
||||||
while ((*cur >= '0') && (*cur <= '9')) {
|
|
||||||
- ret = ret * 10 + (*cur - '0');
|
|
||||||
+ if (ret > INT_MAX / 10) {
|
|
||||||
+ ret = INT_MAX;
|
|
||||||
+ } else {
|
|
||||||
+ int digit = *cur - '0';
|
|
||||||
+ ret *= 10;
|
|
||||||
+ if (ret > INT_MAX - digit)
|
|
||||||
+ ret = INT_MAX;
|
|
||||||
+ else
|
|
||||||
+ ret += digit;
|
|
||||||
+ }
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
while (IS_BLANK_CH(*cur))
|
|
||||||
@@ -6126,7 +6135,16 @@ xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
|
|
||||||
return (def);
|
|
||||||
}
|
|
||||||
while ((*cur >= '0') && (*cur <= '9')) {
|
|
||||||
- ret = ret * 10 + (*cur - '0');
|
|
||||||
+ if (ret > INT_MAX / 10) {
|
|
||||||
+ ret = INT_MAX;
|
|
||||||
+ } else {
|
|
||||||
+ int digit = *cur - '0';
|
|
||||||
+ ret *= 10;
|
|
||||||
+ if (ret > INT_MAX - digit)
|
|
||||||
+ ret = INT_MAX;
|
|
||||||
+ else
|
|
||||||
+ ret += digit;
|
|
||||||
+ }
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
while (IS_BLANK_CH(*cur))
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,162 +0,0 @@
|
|||||||
From 3e80560d4bbf2768c90b9a017743ec45f26c3c1c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Fri, 7 May 2021 10:51:38 +0200
|
|
||||||
Subject: [PATCH] Fix line numbers in error messages for mismatched tags
|
|
||||||
|
|
||||||
Commit 62150ed2 introduced a small regression in the error messages for
|
|
||||||
mismatched tags. This typically only affected messages after the first
|
|
||||||
mismatch, but with custom SAX handlers all line numbers would be off.
|
|
||||||
|
|
||||||
This also fixes line numbers in the SAX push parser which were never
|
|
||||||
handled correctly.
|
|
||||||
---
|
|
||||||
parser.c | 38 +++++++++++++++++++++++---------------
|
|
||||||
python/tests/ctxterror.py | 2 +-
|
|
||||||
result/errors/759398.xml.err | 4 ++--
|
|
||||||
3 files changed, 26 insertions(+), 18 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 73c27ed..c2948ca 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -1838,6 +1838,8 @@ nodePop(xmlParserCtxtPtr ctxt)
|
|
||||||
* @value: the element name
|
|
||||||
* @prefix: the element prefix
|
|
||||||
* @URI: the element namespace name
|
|
||||||
+ * @line: the current line number for error messages
|
|
||||||
+ * @nsNr: the number of namespaces pushed on the namespace table
|
|
||||||
*
|
|
||||||
* Pushes a new element name/prefix/URL on top of the name stack
|
|
||||||
*
|
|
||||||
@@ -1845,7 +1847,7 @@ nodePop(xmlParserCtxtPtr ctxt)
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
|
|
||||||
- const xmlChar *prefix, const xmlChar *URI, int nsNr)
|
|
||||||
+ const xmlChar *prefix, const xmlChar *URI, int line, int nsNr)
|
|
||||||
{
|
|
||||||
if (ctxt->nameNr >= ctxt->nameMax) {
|
|
||||||
const xmlChar * *tmp;
|
|
||||||
@@ -1860,7 +1862,7 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
|
|
||||||
}
|
|
||||||
ctxt->nameTab = tmp;
|
|
||||||
tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
|
|
||||||
- ctxt->nameMax * 3 *
|
|
||||||
+ ctxt->nameMax * 4 *
|
|
||||||
sizeof(ctxt->pushTab[0]));
|
|
||||||
if (tmp2 == NULL) {
|
|
||||||
ctxt->nameMax /= 2;
|
|
||||||
@@ -1868,16 +1870,17 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
|
|
||||||
}
|
|
||||||
ctxt->pushTab = tmp2;
|
|
||||||
} else if (ctxt->pushTab == NULL) {
|
|
||||||
- ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
|
|
||||||
+ ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 4 *
|
|
||||||
sizeof(ctxt->pushTab[0]));
|
|
||||||
if (ctxt->pushTab == NULL)
|
|
||||||
goto mem_error;
|
|
||||||
}
|
|
||||||
ctxt->nameTab[ctxt->nameNr] = value;
|
|
||||||
ctxt->name = value;
|
|
||||||
- ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
|
|
||||||
- ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
|
|
||||||
- ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (ptrdiff_t) nsNr;
|
|
||||||
+ ctxt->pushTab[ctxt->nameNr * 4] = (void *) prefix;
|
|
||||||
+ ctxt->pushTab[ctxt->nameNr * 4 + 1] = (void *) URI;
|
|
||||||
+ ctxt->pushTab[ctxt->nameNr * 4 + 2] = (void *) (ptrdiff_t) line;
|
|
||||||
+ ctxt->pushTab[ctxt->nameNr * 4 + 3] = (void *) (ptrdiff_t) nsNr;
|
|
||||||
return (ctxt->nameNr++);
|
|
||||||
mem_error:
|
|
||||||
xmlErrMemory(ctxt, NULL);
|
|
||||||
@@ -9998,7 +10001,7 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
if (ctxt->sax2)
|
|
||||||
- nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
|
|
||||||
+ nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
|
|
||||||
#ifdef LIBXML_SAX1_ENABLED
|
|
||||||
else
|
|
||||||
namePush(ctxt, name);
|
|
||||||
@@ -10095,10 +10098,11 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
|
|
||||||
* parse the end of tag: '</' should be here.
|
|
||||||
*/
|
|
||||||
if (ctxt->sax2) {
|
|
||||||
- const xmlChar *prefix = ctxt->pushTab[ctxt->nameNr * 3 - 3];
|
|
||||||
- const xmlChar *URI = ctxt->pushTab[ctxt->nameNr * 3 - 2];
|
|
||||||
- int nsNr = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 3 - 1];
|
|
||||||
- xmlParseEndTag2(ctxt, prefix, URI, 0, nsNr, 0);
|
|
||||||
+ const xmlChar *prefix = ctxt->pushTab[ctxt->nameNr * 4 - 4];
|
|
||||||
+ const xmlChar *URI = ctxt->pushTab[ctxt->nameNr * 4 - 3];
|
|
||||||
+ int line = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 4 - 2];
|
|
||||||
+ int nsNr = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 4 - 1];
|
|
||||||
+ xmlParseEndTag2(ctxt, prefix, URI, line, nsNr, 0);
|
|
||||||
namePop(ctxt);
|
|
||||||
}
|
|
||||||
#ifdef LIBXML_SAX1_ENABLED
|
|
||||||
@@ -11373,6 +11377,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
|
|
||||||
const xmlChar *name;
|
|
||||||
const xmlChar *prefix = NULL;
|
|
||||||
const xmlChar *URI = NULL;
|
|
||||||
+ int line = ctxt->input->line;
|
|
||||||
int nsNr = ctxt->nsNr;
|
|
||||||
|
|
||||||
if ((avail < 2) && (ctxt->inputNr == 1))
|
|
||||||
@@ -11471,7 +11476,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
|
|
||||||
spacePop(ctxt);
|
|
||||||
}
|
|
||||||
if (ctxt->sax2)
|
|
||||||
- nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
|
|
||||||
+ nameNsPush(ctxt, name, prefix, URI, line,
|
|
||||||
+ ctxt->nsNr - nsNr);
|
|
||||||
#ifdef LIBXML_SAX1_ENABLED
|
|
||||||
else
|
|
||||||
namePush(ctxt, name);
|
|
||||||
@@ -11593,10 +11599,12 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
|
|
||||||
}
|
|
||||||
if (ctxt->sax2) {
|
|
||||||
xmlParseEndTag2(ctxt,
|
|
||||||
- (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
|
|
||||||
- (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
|
|
||||||
+ (void *) ctxt->pushTab[ctxt->nameNr * 4 - 4],
|
|
||||||
+ (void *) ctxt->pushTab[ctxt->nameNr * 4 - 3],
|
|
||||||
+ (int) (ptrdiff_t)
|
|
||||||
+ ctxt->pushTab[ctxt->nameNr * 4 - 2],
|
|
||||||
(int) (ptrdiff_t)
|
|
||||||
- ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
|
|
||||||
+ ctxt->pushTab[ctxt->nameNr * 4 - 1], 0);
|
|
||||||
nameNsPop(ctxt);
|
|
||||||
}
|
|
||||||
#ifdef LIBXML_SAX1_ENABLED
|
|
||||||
diff --git a/python/tests/ctxterror.py b/python/tests/ctxterror.py
|
|
||||||
index 416e384..ac64624 100755
|
|
||||||
--- a/python/tests/ctxterror.py
|
|
||||||
+++ b/python/tests/ctxterror.py
|
|
||||||
@@ -10,7 +10,7 @@ import libxml2
|
|
||||||
libxml2.debugMemory(1)
|
|
||||||
|
|
||||||
expect="""--> (3) xmlns: URI foo is not absolute
|
|
||||||
---> (4) Opening and ending tag mismatch: x line 0 and y
|
|
||||||
+--> (4) Opening and ending tag mismatch: x line 1 and y
|
|
||||||
"""
|
|
||||||
|
|
||||||
err=""
|
|
||||||
diff --git a/result/errors/759398.xml.err b/result/errors/759398.xml.err
|
|
||||||
index bc9e5e0..f6036a3 100644
|
|
||||||
--- a/result/errors/759398.xml.err
|
|
||||||
+++ b/result/errors/759398.xml.err
|
|
||||||
@@ -1,10 +1,10 @@
|
|
||||||
./test/errors/759398.xml:210: parser error : StartTag: invalid element name
|
|
||||||
need to worry about parsers whi<! don't expand PErefs finding
|
|
||||||
^
|
|
||||||
-./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№m line 205 and termdef
|
|
||||||
+./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: №№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№№m line 308 and termdef
|
|
||||||
and provide access to their content and structure.</termdef> <termdef
|
|
||||||
^
|
|
||||||
-./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 205 and p
|
|
||||||
+./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 50 and p
|
|
||||||
data and the information it must provide to the application.</p>
|
|
||||||
^
|
|
||||||
./test/errors/759398.xml:316: parser error : Extra content at the end of the document
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
From d5f2f74d0f0e7906eabb32c57e09a13ac3e578a2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 11 Nov 2019 11:27:40 +0100
|
|
||||||
Subject: [PATCH] Fix memory leak in error path of XPath expr parser
|
|
||||||
|
|
||||||
Also propagate memory errors.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xpath.c | 20 ++++++++++++++++----
|
|
||||||
1 file changed, 16 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpath.c b/xpath.c
|
|
||||||
index 9f64ab9..ff1137f 100644
|
|
||||||
--- a/xpath.c
|
|
||||||
+++ b/xpath.c
|
|
||||||
@@ -10088,6 +10088,7 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
|
|
||||||
int ok = 0;
|
|
||||||
int exponent = 0;
|
|
||||||
int is_exponent_negative = 0;
|
|
||||||
+ xmlXPathObjectPtr num;
|
|
||||||
#ifdef __GNUC__
|
|
||||||
unsigned long tmp = 0;
|
|
||||||
double temp;
|
|
||||||
@@ -10160,8 +10161,13 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
|
|
||||||
exponent = -exponent;
|
|
||||||
ret *= pow(10.0, (double) exponent);
|
|
||||||
}
|
|
||||||
- PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
|
|
||||||
- xmlXPathCacheNewFloat(ctxt->context, ret), NULL);
|
|
||||||
+ num = xmlXPathCacheNewFloat(ctxt->context, ret);
|
|
||||||
+ if (num == NULL) {
|
|
||||||
+ ctxt->error = XPATH_MEMORY_ERROR;
|
|
||||||
+ } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num,
|
|
||||||
+ NULL) == -1) {
|
|
||||||
+ xmlXPathReleaseObject(ctxt->context, num);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -10223,6 +10229,7 @@ static void
|
|
||||||
xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
|
|
||||||
const xmlChar *q;
|
|
||||||
xmlChar *ret = NULL;
|
|
||||||
+ xmlXPathObjectPtr lit;
|
|
||||||
|
|
||||||
if (CUR == '"') {
|
|
||||||
NEXT;
|
|
||||||
@@ -10250,8 +10257,13 @@ xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
|
|
||||||
XP_ERROR(XPATH_START_LITERAL_ERROR);
|
|
||||||
}
|
|
||||||
if (ret == NULL) return;
|
|
||||||
- PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
|
|
||||||
- xmlXPathCacheNewString(ctxt->context, ret), NULL);
|
|
||||||
+ lit = xmlXPathCacheNewString(ctxt->context, ret);
|
|
||||||
+ if (lit == NULL) {
|
|
||||||
+ ctxt->error = XPATH_MEMORY_ERROR;
|
|
||||||
+ } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit,
|
|
||||||
+ NULL) == -1) {
|
|
||||||
+ xmlXPathReleaseObject(ctxt->context, lit);
|
|
||||||
+ }
|
|
||||||
xmlFree(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
From e1c2d0adf02692fd668cfbb7025db437f1f5490b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 16 Aug 2020 22:22:57 +0200
|
|
||||||
Subject: [PATCH 120/139] Fix memory leak in runtest.c
|
|
||||||
|
|
||||||
---
|
|
||||||
runtest.c | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/runtest.c b/runtest.c
|
|
||||||
index 19ed629..0f178cb 100644
|
|
||||||
--- a/runtest.c
|
|
||||||
+++ b/runtest.c
|
|
||||||
@@ -2108,16 +2108,16 @@ errParseTest(const char *filename, const char *result, const char *err,
|
|
||||||
xmlDocDumpMemory(doc, (xmlChar **) &base, &size);
|
|
||||||
}
|
|
||||||
res = compareFileMem(result, base, size);
|
|
||||||
- if (res != 0) {
|
|
||||||
- fprintf(stderr, "Result for %s failed in %s\n", filename, result);
|
|
||||||
- return(-1);
|
|
||||||
- }
|
|
||||||
}
|
|
||||||
if (doc != NULL) {
|
|
||||||
if (base != NULL)
|
|
||||||
xmlFree((char *)base);
|
|
||||||
xmlFreeDoc(doc);
|
|
||||||
}
|
|
||||||
+ if (res != 0) {
|
|
||||||
+ fprintf(stderr, "Result for %s failed in %s\n", filename, result);
|
|
||||||
+ return(-1);
|
|
||||||
+ }
|
|
||||||
if (err != NULL) {
|
|
||||||
res = compareFileMem(err, testErrors, testErrorsSize);
|
|
||||||
if (res != 0) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
From fbb7fa9a9ad8269834d32ff872b1477ff7b9c705 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 19 Aug 2020 13:13:20 +0200
|
|
||||||
Subject: [PATCH 131/139] Fix memory leak in xmlXIncludeAddNode error paths
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xinclude.c | 8 +++++---
|
|
||||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 9024535..aac30d5 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -627,8 +627,8 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
|
|
||||||
"detected a local recursion with no xpointer in %s\n",
|
|
||||||
URL);
|
|
||||||
- if (fragment != NULL)
|
|
||||||
- xmlFree(fragment);
|
|
||||||
+ xmlFree(URL);
|
|
||||||
+ xmlFree(fragment);
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -640,12 +640,15 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
if (xmlStrEqual(URL, ctxt->urlTab[i])) {
|
|
||||||
xmlXIncludeErr(ctxt, cur, XML_XINCLUDE_RECURSION,
|
|
||||||
"detected a recursion in %s\n", URL);
|
|
||||||
+ xmlFree(URL);
|
|
||||||
+ xmlFree(fragment);
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ref = xmlXIncludeNewRef(ctxt, URL, cur);
|
|
||||||
+ xmlFree(URL);
|
|
||||||
if (ref == NULL) {
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
@@ -653,7 +656,6 @@ xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
ref->doc = NULL;
|
|
||||||
ref->xml = xml;
|
|
||||||
ref->count = 1;
|
|
||||||
- xmlFree(URL);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From 5725c1153a74d997aa8ea8547574c049b040d5cb Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 10 Jun 2020 15:11:40 +0200
|
|
||||||
Subject: [PATCH 106/139] Fix memory leak in xmlXIncludeIncludeNode error paths
|
|
||||||
|
|
||||||
Found with libFuzzer and ASan.
|
|
||||||
---
|
|
||||||
xinclude.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index baeb8db..461c1a5 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -2238,6 +2238,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
XML_XINCLUDE_MULTIPLE_ROOT,
|
|
||||||
"XInclude error: would result in multiple root nodes\n",
|
|
||||||
NULL);
|
|
||||||
+ xmlFreeNodeList(list);
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2265,6 +2266,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
XML_XINCLUDE_BUILD_FAILED,
|
|
||||||
"failed to build node\n", NULL);
|
|
||||||
+ xmlFreeNodeList(list);
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
end->type = XML_XINCLUDE_END;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From ff009f991314ce8711f8a6a7f99107c10fb0a807 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 30 May 2020 15:32:25 +0200
|
|
||||||
Subject: [PATCH 042/139] Fix memory leak in xmlXIncludeLoadDoc error path
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xinclude.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 5d44df4..baeb8db 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -1608,6 +1608,7 @@ loaded:
|
|
||||||
XML_XINCLUDE_XPTR_RESULT,
|
|
||||||
"XPointer is not a range: #%s\n",
|
|
||||||
fragment);
|
|
||||||
+ xmlXPathFreeObject(xptr);
|
|
||||||
xmlXPathFreeContext(xptrctxt);
|
|
||||||
xmlFree(URL);
|
|
||||||
xmlFree(fragment);
|
|
||||||
@@ -1615,6 +1616,7 @@ loaded:
|
|
||||||
case XPATH_NODESET:
|
|
||||||
if ((xptr->nodesetval == NULL) ||
|
|
||||||
(xptr->nodesetval->nodeNr <= 0)) {
|
|
||||||
+ xmlXPathFreeObject(xptr);
|
|
||||||
xmlXPathFreeContext(xptrctxt);
|
|
||||||
xmlFree(URL);
|
|
||||||
xmlFree(fragment);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
From c7c526d6d0f605ed090f8fc1bbede9e439d3185c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Puetz <PuetzKevinA@JohnDeere.com>
|
|
||||||
Date: Mon, 13 Jan 2020 18:49:01 -0600
|
|
||||||
Subject: [PATCH 021/139] Fix memory leak when shared libxml.dll is unloaded
|
|
||||||
|
|
||||||
When a multiple modules (process/plugins) all link to libxml2.dll
|
|
||||||
they will in fact share a single loaded instance of it.
|
|
||||||
It is unsafe for any of them to call xmlCleanupParser,
|
|
||||||
as this would deinitialize the shared state and break others that might
|
|
||||||
still have ongoing use.
|
|
||||||
|
|
||||||
However, on windows atexit is per-module (rather process-wide), so if used
|
|
||||||
*within* libxml2 it is possible to register a clean up when all users
|
|
||||||
are done and libxml2.dll is about to actually unload.
|
|
||||||
|
|
||||||
This allows multiple plugins to link with and share libxml2 without
|
|
||||||
a premature cleanup if one is unloaded, while still cleaning up if *all*
|
|
||||||
such callers are themselves unloaded.
|
|
||||||
---
|
|
||||||
parser.c | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 43a1a0a..1ba988c 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -14741,6 +14741,10 @@ xmlInitParser(void) {
|
|
||||||
if (xmlParserInitialized != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
+#if defined(WIN32) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
|
|
||||||
+ atexit(xmlCleanupParser);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#ifdef LIBXML_THREAD_ENABLED
|
|
||||||
__xmlGlobalInitMutexLock();
|
|
||||||
if (xmlParserInitialized == 0) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
From 46837d47d59c7b8c9bd1d08a6a717a90a7f1ceb6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 3 Oct 2020 01:13:35 +0200
|
|
||||||
Subject: [PATCH] Fix memory leaks in XPointer string-range function
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xpointer.c | 41 +++++++++++++++++++++++++++--------------
|
|
||||||
1 file changed, 27 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpointer.c b/xpointer.c
|
|
||||||
index 53def72..ad2c288 100644
|
|
||||||
--- a/xpointer.c
|
|
||||||
+++ b/xpointer.c
|
|
||||||
@@ -2706,10 +2706,10 @@ static void
|
|
||||||
xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|
||||||
int i, startindex, endindex = 0, fendindex;
|
|
||||||
xmlNodePtr start, end = 0, fend;
|
|
||||||
- xmlXPathObjectPtr set;
|
|
||||||
+ xmlXPathObjectPtr set = NULL;
|
|
||||||
xmlLocationSetPtr oldset;
|
|
||||||
- xmlLocationSetPtr newset;
|
|
||||||
- xmlXPathObjectPtr string;
|
|
||||||
+ xmlLocationSetPtr newset = NULL;
|
|
||||||
+ xmlXPathObjectPtr string = NULL;
|
|
||||||
xmlXPathObjectPtr position = NULL;
|
|
||||||
xmlXPathObjectPtr number = NULL;
|
|
||||||
int found, pos = 0, num = 0;
|
|
||||||
@@ -2721,29 +2721,39 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|
||||||
XP_ERROR(XPATH_INVALID_ARITY);
|
|
||||||
|
|
||||||
if (nargs >= 4) {
|
|
||||||
- CHECK_TYPE(XPATH_NUMBER);
|
|
||||||
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
|
|
||||||
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
number = valuePop(ctxt);
|
|
||||||
if (number != NULL)
|
|
||||||
num = (int) number->floatval;
|
|
||||||
}
|
|
||||||
if (nargs >= 3) {
|
|
||||||
- CHECK_TYPE(XPATH_NUMBER);
|
|
||||||
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
|
|
||||||
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
position = valuePop(ctxt);
|
|
||||||
if (position != NULL)
|
|
||||||
pos = (int) position->floatval;
|
|
||||||
}
|
|
||||||
- CHECK_TYPE(XPATH_STRING);
|
|
||||||
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
|
|
||||||
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
string = valuePop(ctxt);
|
|
||||||
if ((ctxt->value == NULL) ||
|
|
||||||
((ctxt->value->type != XPATH_LOCATIONSET) &&
|
|
||||||
- (ctxt->value->type != XPATH_NODESET)))
|
|
||||||
- XP_ERROR(XPATH_INVALID_TYPE)
|
|
||||||
-
|
|
||||||
+ (ctxt->value->type != XPATH_NODESET))) {
|
|
||||||
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
set = valuePop(ctxt);
|
|
||||||
newset = xmlXPtrLocationSetCreate(NULL);
|
|
||||||
if (newset == NULL) {
|
|
||||||
- xmlXPathFreeObject(set);
|
|
||||||
- XP_ERROR(XPATH_MEMORY_ERROR);
|
|
||||||
+ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
|
|
||||||
+ goto error;
|
|
||||||
}
|
|
||||||
if (set->nodesetval == NULL) {
|
|
||||||
goto error;
|
|
||||||
@@ -2756,8 +2766,10 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|
||||||
*/
|
|
||||||
tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
|
|
||||||
xmlXPathFreeObject(set);
|
|
||||||
- if (tmp == NULL)
|
|
||||||
- XP_ERROR(XPATH_MEMORY_ERROR)
|
|
||||||
+ if (tmp == NULL) {
|
|
||||||
+ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
|
|
||||||
+ goto error;
|
|
||||||
+ }
|
|
||||||
set = tmp;
|
|
||||||
}
|
|
||||||
oldset = (xmlLocationSetPtr) set->user;
|
|
||||||
@@ -2830,7 +2842,8 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|
||||||
* Save the new value and cleanup
|
|
||||||
*/
|
|
||||||
error:
|
|
||||||
- valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
|
||||||
+ if (newset != NULL)
|
|
||||||
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
|
||||||
xmlXPathFreeObject(set);
|
|
||||||
xmlXPathFreeObject(string);
|
|
||||||
if (position) xmlXPathFreeObject(position);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
From 42942066e1f6422e26cd162a6014b19ac215083f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 11 Nov 2019 13:49:11 +0100
|
|
||||||
Subject: [PATCH] Fix memory leaks of encoding handlers in xmlsave.c
|
|
||||||
|
|
||||||
Fix leak of iconv/ICU encoding handler in xmlSaveToBuffer.
|
|
||||||
|
|
||||||
Fix leaks of iconv/ICU encoding handlers in xmlSaveTo* error paths.
|
|
||||||
|
|
||||||
Closes #127.
|
|
||||||
---
|
|
||||||
xmlsave.c | 26 ++++++++------------------
|
|
||||||
1 file changed, 8 insertions(+), 18 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlsave.c b/xmlsave.c
|
|
||||||
index fa00915..7158c26 100644
|
|
||||||
--- a/xmlsave.c
|
|
||||||
+++ b/xmlsave.c
|
|
||||||
@@ -1802,6 +1802,7 @@ xmlSaveToFd(int fd, const char *encoding, int options)
|
|
||||||
if (ret == NULL) return(NULL);
|
|
||||||
ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
|
|
||||||
if (ret->buf == NULL) {
|
|
||||||
+ xmlCharEncCloseFunc(ret->handler);
|
|
||||||
xmlFreeSaveCtxt(ret);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
@@ -1831,6 +1832,7 @@ xmlSaveToFilename(const char *filename, const char *encoding, int options)
|
|
||||||
ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
|
|
||||||
compression);
|
|
||||||
if (ret->buf == NULL) {
|
|
||||||
+ xmlCharEncCloseFunc(ret->handler);
|
|
||||||
xmlFreeSaveCtxt(ret);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
@@ -1853,28 +1855,15 @@ xmlSaveCtxtPtr
|
|
||||||
xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
|
|
||||||
{
|
|
||||||
xmlSaveCtxtPtr ret;
|
|
||||||
- xmlOutputBufferPtr out_buff;
|
|
||||||
- xmlCharEncodingHandlerPtr handler;
|
|
||||||
|
|
||||||
ret = xmlNewSaveCtxt(encoding, options);
|
|
||||||
if (ret == NULL) return(NULL);
|
|
||||||
-
|
|
||||||
- if (encoding != NULL) {
|
|
||||||
- handler = xmlFindCharEncodingHandler(encoding);
|
|
||||||
- if (handler == NULL) {
|
|
||||||
- xmlFree(ret);
|
|
||||||
- return(NULL);
|
|
||||||
- }
|
|
||||||
- } else
|
|
||||||
- handler = NULL;
|
|
||||||
- out_buff = xmlOutputBufferCreateBuffer(buffer, handler);
|
|
||||||
- if (out_buff == NULL) {
|
|
||||||
- xmlFree(ret);
|
|
||||||
- if (handler) xmlCharEncCloseFunc(handler);
|
|
||||||
- return(NULL);
|
|
||||||
+ ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler);
|
|
||||||
+ if (ret->buf == NULL) {
|
|
||||||
+ xmlCharEncCloseFunc(ret->handler);
|
|
||||||
+ xmlFreeSaveCtxt(ret);
|
|
||||||
+ return(NULL);
|
|
||||||
}
|
|
||||||
-
|
|
||||||
- ret->buf = out_buff;
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1902,6 +1891,7 @@ xmlSaveToIO(xmlOutputWriteCallback iowrite,
|
|
||||||
if (ret == NULL) return(NULL);
|
|
||||||
ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
|
|
||||||
if (ret->buf == NULL) {
|
|
||||||
+ xmlCharEncCloseFunc(ret->handler);
|
|
||||||
xmlFreeSaveCtxt(ret);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
From 2c80fc911678adc9dcf252b3bc71cce101c8728e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 2 Dec 2019 11:30:30 +0100
|
|
||||||
Subject: [PATCH] Fix more memory leaks in error paths of XPath parser
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xpath.c | 24 +++++++++++++++---------
|
|
||||||
1 file changed, 15 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpath.c b/xpath.c
|
|
||||||
index ff1137f..030bab3 100644
|
|
||||||
--- a/xpath.c
|
|
||||||
+++ b/xpath.c
|
|
||||||
@@ -10300,8 +10300,10 @@ xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
|
|
||||||
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
|
|
||||||
}
|
|
||||||
ctxt->comp->last = -1;
|
|
||||||
- PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
|
|
||||||
- name, prefix);
|
|
||||||
+ if (PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, name, prefix) == -1) {
|
|
||||||
+ xmlFree(prefix);
|
|
||||||
+ xmlFree(name);
|
|
||||||
+ }
|
|
||||||
SKIP_BLANKS;
|
|
||||||
if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
|
|
||||||
XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
|
|
||||||
@@ -10408,8 +10410,10 @@ xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
|
|
||||||
SKIP_BLANKS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
|
|
||||||
- name, prefix);
|
|
||||||
+ if (PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, name, prefix) == -1) {
|
|
||||||
+ xmlFree(prefix);
|
|
||||||
+ xmlFree(name);
|
|
||||||
+ }
|
|
||||||
NEXT;
|
|
||||||
SKIP_BLANKS;
|
|
||||||
}
|
|
||||||
@@ -11050,7 +11054,7 @@ xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
|
|
||||||
*/
|
|
||||||
static xmlChar *
|
|
||||||
xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
|
|
||||||
- xmlXPathTypeVal *type, const xmlChar **prefix,
|
|
||||||
+ xmlXPathTypeVal *type, xmlChar **prefix,
|
|
||||||
xmlChar *name) {
|
|
||||||
int blanks;
|
|
||||||
|
|
||||||
@@ -11281,7 +11285,7 @@ xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
|
|
||||||
SKIP_BLANKS;
|
|
||||||
} else {
|
|
||||||
xmlChar *name = NULL;
|
|
||||||
- const xmlChar *prefix = NULL;
|
|
||||||
+ xmlChar *prefix = NULL;
|
|
||||||
xmlXPathTestVal test = (xmlXPathTestVal) 0;
|
|
||||||
xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
|
|
||||||
xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
|
|
||||||
@@ -11391,9 +11395,11 @@ eval_predicates:
|
|
||||||
PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
- PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
|
|
||||||
- test, type, (void *)prefix, (void *)name);
|
|
||||||
-
|
|
||||||
+ if (PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
|
|
||||||
+ test, type, (void *)prefix, (void *)name) == -1) {
|
|
||||||
+ xmlFree(prefix);
|
|
||||||
+ xmlFree(name);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_STEP
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "Step : ");
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
From 3da8d947df1f84e54b12145ca2cfa1ff6456f532 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 9 Jul 2020 16:08:38 +0200
|
|
||||||
Subject: [PATCH] Fix more quadratic runtime issues in HTML push parser
|
|
||||||
|
|
||||||
Make sure that checkIndex is set when returning without match from
|
|
||||||
inside a comment. Also track parser state in htmlParseLookupChars.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
|
|
||||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
|
||||||
index 366c19b..9b12dd1 100644
|
|
||||||
--- a/HTMLparser.c
|
|
||||||
+++ b/HTMLparser.c
|
|
||||||
@@ -5205,7 +5205,7 @@ htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
|
|
||||||
}
|
|
||||||
if (incomment) {
|
|
||||||
if (base + 3 > len)
|
|
||||||
- return (-1);
|
|
||||||
+ break;
|
|
||||||
if ((buf[base] == '-') && (buf[base + 1] == '-') &&
|
|
||||||
(buf[base + 2] == '>')) {
|
|
||||||
incomment = 0;
|
|
||||||
@@ -5294,8 +5294,11 @@ 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;
|
|
||||||
@@ -5316,7 +5319,7 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
|
|
||||||
}
|
|
||||||
if (incomment) {
|
|
||||||
if (base + 3 > len)
|
|
||||||
- return (-1);
|
|
||||||
+ break;
|
|
||||||
if ((buf[base] == '-') && (buf[base + 1] == '-') &&
|
|
||||||
(buf[base + 2] == '>')) {
|
|
||||||
incomment = 0;
|
|
||||||
@@ -5332,6 +5335,8 @@ htmlParseLookupChars(htmlParserCtxtPtr ctxt, const xmlChar * stop,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctxt->checkIndex = base;
|
|
||||||
+ /* Abuse hasPErefs member to track current state. */
|
|
||||||
+ ctxt->hasPErefs = incomment;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
From e6ec58ecf7adf73335cfb40f0d5bc673681f766b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 21 Sep 2020 12:49:36 +0200
|
|
||||||
Subject: [PATCH] Fix null deref in XPointer expression error path
|
|
||||||
|
|
||||||
Make sure that the filter functions introduced with commit c2f4da1a
|
|
||||||
return node-sets without NULL pointers also in the error case.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xpath.c | 38 +++++++++++++++++++-------------------
|
|
||||||
1 file changed, 19 insertions(+), 19 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpath.c b/xpath.c
|
|
||||||
index 311997fe..6ee7e57e 100644
|
|
||||||
--- a/xpath.c
|
|
||||||
+++ b/xpath.c
|
|
||||||
@@ -11677,11 +11677,11 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
|
|
||||||
|
|
||||||
if (ctxt->error != XPATH_EXPRESSION_OK)
|
|
||||||
- goto exit;
|
|
||||||
+ break;
|
|
||||||
if (res < 0) {
|
|
||||||
/* Shouldn't happen */
|
|
||||||
xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
|
|
||||||
- goto exit;
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
|
|
||||||
@@ -11700,15 +11700,7 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
if (pos == maxPos) {
|
|
||||||
- /* Clear remaining nodes and exit loop. */
|
|
||||||
- if (hasNsNodes) {
|
|
||||||
- for (i++; i < set->nodeNr; i++) {
|
|
||||||
- node = set->nodeTab[i];
|
|
||||||
- if ((node != NULL) &&
|
|
||||||
- (node->type == XML_NAMESPACE_DECL))
|
|
||||||
- xmlXPathNodeSetFreeNs((xmlNsPtr) node);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ i += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -11716,6 +11708,15 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Free remaining nodes. */
|
|
||||||
+ if (hasNsNodes) {
|
|
||||||
+ for (; i < set->nodeNr; i++) {
|
|
||||||
+ xmlNodePtr node = set->nodeTab[i];
|
|
||||||
+ if ((node != NULL) && (node->type == XML_NAMESPACE_DECL))
|
|
||||||
+ xmlXPathNodeSetFreeNs((xmlNsPtr) node);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
set->nodeNr = j;
|
|
||||||
|
|
||||||
/* If too many elements were removed, shrink table to preserve memory. */
|
|
||||||
@@ -11736,7 +11737,6 @@ xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-exit:
|
|
||||||
xpctxt->node = oldnode;
|
|
||||||
xpctxt->doc = olddoc;
|
|
||||||
xpctxt->contextSize = oldcs;
|
|
||||||
@@ -11801,11 +11801,11 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
|
|
||||||
|
|
||||||
if (ctxt->error != XPATH_EXPRESSION_OK)
|
|
||||||
- goto exit;
|
|
||||||
+ break;
|
|
||||||
if (res < 0) {
|
|
||||||
/* Shouldn't happen */
|
|
||||||
xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
|
|
||||||
- goto exit;
|
|
||||||
+ break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
|
|
||||||
@@ -11823,10 +11823,7 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
if (pos == maxPos) {
|
|
||||||
- /* Clear remaining nodes and exit loop. */
|
|
||||||
- for (i++; i < locset->locNr; i++) {
|
|
||||||
- xmlXPathFreeObject(locset->locTab[i]);
|
|
||||||
- }
|
|
||||||
+ i += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -11834,6 +11831,10 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Free remaining nodes. */
|
|
||||||
+ for (; i < locset->locNr; i++)
|
|
||||||
+ xmlXPathFreeObject(locset->locTab[i]);
|
|
||||||
+
|
|
||||||
locset->locNr = j;
|
|
||||||
|
|
||||||
/* If too many elements were removed, shrink table to preserve memory. */
|
|
||||||
@@ -11854,7 +11855,6 @@ xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-exit:
|
|
||||||
xpctxt->node = oldnode;
|
|
||||||
xpctxt->doc = olddoc;
|
|
||||||
xpctxt->contextSize = oldcs;
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
From bfd2f4300fb348a0fb8265a17546a0eb8bdec719 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 9 May 2021 18:56:57 +0200
|
|
||||||
Subject: [PATCH] Fix null deref in legacy SAX1 parser
|
|
||||||
|
|
||||||
Always call nameNsPush instead of namePush. The latter is unused now
|
|
||||||
and should probably be removed from the public API. I can't see how
|
|
||||||
it could be used reasonably from client code and the unprefixed name
|
|
||||||
has always polluted the global namespace.
|
|
||||||
|
|
||||||
Fixes a null pointer dereference introduced with de5b624f when parsing
|
|
||||||
in SAX1 mode.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
parser.c | 15 ++-------------
|
|
||||||
1 file changed, 2 insertions(+), 13 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 9bda945..f5e5e16 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -10025,12 +10025,7 @@ xmlParseElementStart(xmlParserCtxtPtr ctxt) {
|
|
||||||
spacePop(ctxt);
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
- if (ctxt->sax2)
|
|
||||||
- nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
|
|
||||||
-#ifdef LIBXML_SAX1_ENABLED
|
|
||||||
- else
|
|
||||||
- namePush(ctxt, name);
|
|
||||||
-#endif /* LIBXML_SAX1_ENABLED */
|
|
||||||
+ nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
|
|
||||||
ret = ctxt->node;
|
|
||||||
|
|
||||||
#ifdef LIBXML_VALID_ENABLED
|
|
||||||
@@ -11496,13 +11491,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
|
|
||||||
nodePop(ctxt);
|
|
||||||
spacePop(ctxt);
|
|
||||||
}
|
|
||||||
- if (ctxt->sax2)
|
|
||||||
- nameNsPush(ctxt, name, prefix, URI, line,
|
|
||||||
- ctxt->nsNr - nsNr);
|
|
||||||
-#ifdef LIBXML_SAX1_ENABLED
|
|
||||||
- else
|
|
||||||
- namePush(ctxt, name);
|
|
||||||
-#endif /* LIBXML_SAX1_ENABLED */
|
|
||||||
+ nameNsPush(ctxt, name, prefix, URI, line, ctxt->nsNr - nsNr);
|
|
||||||
|
|
||||||
ctxt->instate = XML_PARSER_CONTENT;
|
|
||||||
ctxt->progressive = 1;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
From a218ff0ec0ca6da74236b1419e841848a249f011 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 6 Dec 2020 17:26:36 +0100
|
|
||||||
Subject: [PATCH] Fix null pointer deref in xmlXPtrRangeInsideFunction
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xpointer.c | 10 ++++++----
|
|
||||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpointer.c b/xpointer.c
|
|
||||||
index ad2c288..3e3c8b8 100644
|
|
||||||
--- a/xpointer.c
|
|
||||||
+++ b/xpointer.c
|
|
||||||
@@ -2200,7 +2200,6 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|
||||||
XP_ERROR(XPATH_MEMORY_ERROR)
|
|
||||||
set = tmp;
|
|
||||||
}
|
|
||||||
- oldset = (xmlLocationSetPtr) set->user;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The loop is to compute the covering range for each item and add it
|
|
||||||
@@ -2210,9 +2209,12 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|
||||||
xmlXPathFreeObject(set);
|
|
||||||
XP_ERROR(XPATH_MEMORY_ERROR);
|
|
||||||
}
|
|
||||||
- for (i = 0;i < oldset->locNr;i++) {
|
|
||||||
- xmlXPtrLocationSetAdd(newset,
|
|
||||||
- xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
|
|
||||||
+ oldset = (xmlLocationSetPtr) set->user;
|
|
||||||
+ if (oldset != NULL) {
|
|
||||||
+ for (i = 0;i < oldset->locNr;i++) {
|
|
||||||
+ xmlXPtrLocationSetAdd(newset,
|
|
||||||
+ xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
From c9faa29259ac23b5fbf945f61056288e413dae81 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 2 Jan 2020 14:12:39 +0100
|
|
||||||
Subject: [PATCH] Fix overflow check in xmlNodeDump
|
|
||||||
|
|
||||||
Store return value of xmlBufNodeDump in a size_t before checking for
|
|
||||||
integer overflow.
|
|
||||||
|
|
||||||
Found by lgtm.com
|
|
||||||
---
|
|
||||||
xmlsave.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmlsave.c b/xmlsave.c
|
|
||||||
index 7158c26..b06e24d 100644
|
|
||||||
--- a/xmlsave.c
|
|
||||||
+++ b/xmlsave.c
|
|
||||||
@@ -2187,7 +2187,7 @@ xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
|
|
||||||
int format)
|
|
||||||
{
|
|
||||||
xmlBufPtr buffer;
|
|
||||||
- int ret;
|
|
||||||
+ size_t ret;
|
|
||||||
|
|
||||||
if ((buf == NULL) || (cur == NULL))
|
|
||||||
return(-1);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
From bf2e96173d4f78f564015a925970077501586fbe Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 7 Nov 2019 12:54:01 +0100
|
|
||||||
Subject: [PATCH] Fix overflow handling in xmlBufBackToBuffer
|
|
||||||
|
|
||||||
Don't overwrite 'use' and 'size' members after clamping to INT_MAX.
|
|
||||||
|
|
||||||
Thanks to Ranier Vilela for pointing this out in merge request !56.
|
|
||||||
---
|
|
||||||
buf.c | 6 ++++--
|
|
||||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/buf.c b/buf.c
|
|
||||||
index d46da36..3b212fc 100644
|
|
||||||
--- a/buf.c
|
|
||||||
+++ b/buf.c
|
|
||||||
@@ -1233,10 +1233,12 @@ xmlBufBackToBuffer(xmlBufPtr buf) {
|
|
||||||
* Keep the buffer but provide a truncated size value.
|
|
||||||
*/
|
|
||||||
xmlBufOverflowError(buf, "Allocated size too big for xmlBuffer");
|
|
||||||
+ ret->use = (int) buf->use;
|
|
||||||
ret->size = INT_MAX;
|
|
||||||
+ } else {
|
|
||||||
+ ret->use = (int) buf->use;
|
|
||||||
+ ret->size = (int) buf->size;
|
|
||||||
}
|
|
||||||
- ret->use = (int) buf->use;
|
|
||||||
- ret->size = (int) buf->size;
|
|
||||||
ret->alloc = buf->alloc;
|
|
||||||
ret->content = buf->content;
|
|
||||||
ret->contentIO = buf->contentIO;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
From 688b41a0fb06cf1ab5173308f6a8db5089ba6e14 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 1 Mar 2021 14:17:42 +0100
|
|
||||||
Subject: [PATCH] Fix quadratic behavior when looking up xml:* attributes
|
|
||||||
|
|
||||||
Add a special case for the predefined XML namespace when looking up DTD
|
|
||||||
attribute defaults in xmlGetPropNodeInternal to avoid calling
|
|
||||||
xmlGetNsList.
|
|
||||||
|
|
||||||
This fixes quadratic behavior in
|
|
||||||
|
|
||||||
- xmlNodeGetBase
|
|
||||||
- xmlNodeGetLang
|
|
||||||
- xmlNodeGetSpacePreserve
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
tree.c | 10 ++++++++++
|
|
||||||
1 file changed, 10 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/tree.c b/tree.c
|
|
||||||
index d6ea704..617e818 100644
|
|
||||||
--- a/tree.c
|
|
||||||
+++ b/tree.c
|
|
||||||
@@ -6589,6 +6589,16 @@ xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,
|
|
||||||
attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
|
|
||||||
elemQName, name, NULL);
|
|
||||||
}
|
|
||||||
+ } else if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
|
|
||||||
+ /*
|
|
||||||
+ * The XML namespace must be bound to prefix 'xml'.
|
|
||||||
+ */
|
|
||||||
+ attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
|
|
||||||
+ elemQName, name, BAD_CAST "xml");
|
|
||||||
+ if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
|
|
||||||
+ attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
|
|
||||||
+ elemQName, name, BAD_CAST "xml");
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
xmlNsPtr *nsList, *cur;
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
From 27119ec33c9f6b9830efa1e0da0acfa353dfa55a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 17 Aug 2020 00:05:19 +0200
|
|
||||||
Subject: [PATCH] Fix quadratic runtime in xi:fallback processing
|
|
||||||
|
|
||||||
Copying the tree would lead to runtime quadratic in nested fallback
|
|
||||||
depth, similar to naive string concatenation.
|
|
||||||
---
|
|
||||||
xinclude.c | 23 +++++++++++------------
|
|
||||||
1 file changed, 11 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index e9d3af5..9a65ee5 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -2003,8 +2003,7 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
ret = -1;
|
|
||||||
xmlXIncludeFreeContext(newctxt);
|
|
||||||
|
|
||||||
- ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
|
|
||||||
- fallback->children);
|
|
||||||
+ ctxt->incTab[nr]->inc = fallback->children;
|
|
||||||
} else {
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
}
|
|
||||||
@@ -2268,12 +2267,6 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
* XInclude end one
|
|
||||||
*/
|
|
||||||
cur->type = XML_XINCLUDE_START;
|
|
||||||
- /* Remove fallback children */
|
|
||||||
- for (child = cur->children; child != NULL; child = next) {
|
|
||||||
- next = child->next;
|
|
||||||
- xmlUnlinkNode(child);
|
|
||||||
- xmlFreeNode(child);
|
|
||||||
- }
|
|
||||||
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
|
|
||||||
if (end == NULL) {
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
@@ -2289,11 +2282,17 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
* Add the list of nodes
|
|
||||||
*/
|
|
||||||
while (list != NULL) {
|
|
||||||
- cur = list;
|
|
||||||
- list = list->next;
|
|
||||||
-
|
|
||||||
- xmlAddPrevSibling(end, cur);
|
|
||||||
+ next = list->next;
|
|
||||||
+ xmlAddPrevSibling(end, list);
|
|
||||||
+ list = next;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* Remove fallback node */
|
|
||||||
+ for (child = cur->children; child != NULL; child = next) {
|
|
||||||
+ next = child->next;
|
|
||||||
+ xmlUnlinkNode(child);
|
|
||||||
+ xmlFreeNode(child);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
From 500789224b59fa70d6837be5cd1edb8e2f1eccb6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sun, 12 Jul 2020 20:28:47 +0200
|
|
||||||
Subject: [PATCH 083/139] Fix quadratic runtime when parsing HTML script
|
|
||||||
content
|
|
||||||
|
|
||||||
If htmlParseScript returns upon hitting an invalid character,
|
|
||||||
htmlParseLookupSequence will be called again with checkIndex reset to
|
|
||||||
zero, potentially resulting in quadratic runtime. Make sure that
|
|
||||||
htmlParseScript consumes all input in one go and simply skips over
|
|
||||||
invalid characters similar to htmlParseCharDataInternal.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
HTMLparser.c | 17 +++++++----------
|
|
||||||
1 file changed, 7 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
|
||||||
index 1dea794..26ed124 100644
|
|
||||||
--- a/HTMLparser.c
|
|
||||||
+++ b/HTMLparser.c
|
|
||||||
@@ -2928,7 +2928,7 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
|
|
||||||
|
|
||||||
SHRINK;
|
|
||||||
cur = CUR_CHAR(l);
|
|
||||||
- while (IS_CHAR_CH(cur)) {
|
|
||||||
+ while (cur != 0) {
|
|
||||||
if ((cur == '<') && (NXT(1) == '/')) {
|
|
||||||
/*
|
|
||||||
* One should break here, the specification is clear:
|
|
||||||
@@ -2959,7 +2959,12 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- COPY_BUF(l,buf,nbchar,cur);
|
|
||||||
+ if (IS_CHAR_CH(cur)) {
|
|
||||||
+ COPY_BUF(l,buf,nbchar,cur);
|
|
||||||
+ } else {
|
|
||||||
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
|
|
||||||
+ "Invalid char in CDATA 0x%X\n", cur);
|
|
||||||
+ }
|
|
||||||
if (nbchar >= HTML_PARSER_BIG_BUFFER_SIZE) {
|
|
||||||
buf[nbchar] = 0;
|
|
||||||
if (ctxt->sax->cdataBlock!= NULL) {
|
|
||||||
@@ -2977,14 +2982,6 @@ htmlParseScript(htmlParserCtxtPtr ctxt) {
|
|
||||||
cur = CUR_CHAR(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((!(IS_CHAR_CH(cur))) && (!((cur == 0) && (ctxt->progressive)))) {
|
|
||||||
- htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
|
|
||||||
- "Invalid char in CDATA 0x%X\n", cur);
|
|
||||||
- if (ctxt->input->cur < ctxt->input->end) {
|
|
||||||
- NEXT;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
if ((nbchar != 0) && (ctxt->sax != NULL) && (!ctxt->disableSAX)) {
|
|
||||||
buf[nbchar] = 0;
|
|
||||||
if (ctxt->sax->cdataBlock!= NULL) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
From 87d20b554c6a90e7ece1cc7391c005089bf85b78 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 19 Aug 2020 13:52:08 +0200
|
|
||||||
Subject: [PATCH] Fix regression introduced with commit 74dcc10b
|
|
||||||
|
|
||||||
The code wasn't dead after all, but I can see no reason in delaying
|
|
||||||
the XPointer evaluation. This could lead to nodes included earlier
|
|
||||||
appearing in XPointer results.
|
|
||||||
---
|
|
||||||
result/XInclude/ns1.xml | 10 ++++++++++
|
|
||||||
result/XInclude/ns1.xml.rdr | 23 +++++++++++++++++++++++
|
|
||||||
test/XInclude/docs/ns1.xml | 12 ++++++++++++
|
|
||||||
xinclude.c | 2 +-
|
|
||||||
4 files changed, 46 insertions(+), 1 deletion(-)
|
|
||||||
create mode 100644 result/XInclude/ns1.xml
|
|
||||||
create mode 100644 result/XInclude/ns1.xml.rdr
|
|
||||||
create mode 100644 test/XInclude/docs/ns1.xml
|
|
||||||
|
|
||||||
diff --git a/result/XInclude/ns1.xml b/result/XInclude/ns1.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..ab41fb7
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/ns1.xml
|
|
||||||
@@ -0,0 +1,10 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
+<doc xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
||||||
+ <ns:elem xmlns:ns="urn:foo" xml:id="a"/>
|
|
||||||
+ <elem xmlns:ns="urn:foo">
|
|
||||||
+ <ns:elem xml:id="a"/>
|
|
||||||
+ </elem>
|
|
||||||
+
|
|
||||||
+ <ns:elem xmlns:ns="urn:bar"/>
|
|
||||||
+
|
|
||||||
+</doc>
|
|
||||||
diff --git a/result/XInclude/ns1.xml.rdr b/result/XInclude/ns1.xml.rdr
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..f23702f
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/result/XInclude/ns1.xml.rdr
|
|
||||||
@@ -0,0 +1,23 @@
|
|
||||||
+0 1 doc 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 ns:elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 elem 0 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+2 1 ns:elem 1 0
|
|
||||||
+2 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 15 elem 0 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 1 ns:elem 1 0
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+1 14 #text 0 1
|
|
||||||
+
|
|
||||||
+0 15 doc 0 0
|
|
||||||
diff --git a/test/XInclude/docs/ns1.xml b/test/XInclude/docs/ns1.xml
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..7523f4a
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/XInclude/docs/ns1.xml
|
|
||||||
@@ -0,0 +1,12 @@
|
|
||||||
+<?xml version="1.0"?>
|
|
||||||
+<doc xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
||||||
+ <xi:include href="#a"/>
|
|
||||||
+ <elem xmlns:ns="urn:foo">
|
|
||||||
+ <ns:elem xml:id="a"/>
|
|
||||||
+ </elem>
|
|
||||||
+ <xi:include href="b.xml">
|
|
||||||
+ <xi:fallback xmlns:ns="urn:bar">
|
|
||||||
+ <ns:elem/>
|
|
||||||
+ </xi:fallback>
|
|
||||||
+ </xi:include>
|
|
||||||
+</doc>
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index aac30d5..c92b32b 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -1464,7 +1464,7 @@ xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
|
|
||||||
*/
|
|
||||||
if ((URL[0] == 0) || (URL[0] == '#') ||
|
|
||||||
((ctxt->doc != NULL) && (xmlStrEqual(URL, ctxt->doc->URL)))) {
|
|
||||||
- doc = NULL;
|
|
||||||
+ doc = ctxt->doc;
|
|
||||||
goto loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
From 3fcf319378f9396a9ca840cd63b96a441818e1f1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 22 Aug 2020 00:43:18 +0200
|
|
||||||
Subject: [PATCH] Fix regression introduced with commit d88df4b
|
|
||||||
|
|
||||||
Revert the commit and use a different approach.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xinclude.c | 10 +++++++---
|
|
||||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index c92b32b..f48e0af 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -59,8 +59,8 @@ struct _xmlXIncludeRef {
|
|
||||||
xmlNodePtr inc; /* the included copy */
|
|
||||||
int xml; /* xml or txt */
|
|
||||||
int count; /* how many refs use that specific doc */
|
|
||||||
- int skip; /* skip in case of errors */
|
|
||||||
int fallback; /* fallback was loaded */
|
|
||||||
+ int emptyFb; /* flag to show fallback empty */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _xmlXIncludeCtxt {
|
|
||||||
@@ -1988,8 +1988,11 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
|
|
||||||
ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
|
|
||||||
fallback->children);
|
|
||||||
+ if (ctxt->incTab[nr]->inc == NULL)
|
|
||||||
+ ctxt->incTab[nr]->emptyFb = 1;
|
|
||||||
} else {
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
+ ctxt->incTab[nr]->emptyFb = 1; /* flag empty callback */
|
|
||||||
}
|
|
||||||
ctxt->incTab[nr]->fallback = 1;
|
|
||||||
return(ret);
|
|
||||||
@@ -2153,7 +2156,6 @@ xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ret < 0) {
|
|
||||||
- ctxt->incTab[nr]->skip = 1;
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
XML_XINCLUDE_NO_FALLBACK,
|
|
||||||
"could not load %s, and no fallback was found\n",
|
|
||||||
@@ -2197,6 +2199,7 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
|
|
||||||
list = ctxt->incTab[nr]->inc;
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
+ ctxt->incTab[nr]->emptyFb = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check against the risk of generating a multi-rooted document
|
|
||||||
@@ -2459,7 +2462,8 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree,
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
for (i = ctxt->incBase;i < ctxt->incNr; i++) {
|
|
||||||
- if (ctxt->incTab[i]->skip == 0)
|
|
||||||
+ if ((ctxt->incTab[i]->inc != NULL) ||
|
|
||||||
+ (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */
|
|
||||||
xmlXIncludeIncludeNode(ctxt, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
From 487871b0e39bcc69ec0c1f69c30e2697712c6829 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 10 Jun 2020 13:23:43 +0200
|
|
||||||
Subject: [PATCH 048/139] Fix undefined behavior in xmlXPathTryStreamCompile
|
|
||||||
|
|
||||||
&NULL[0] is undefined behavior.
|
|
||||||
---
|
|
||||||
xpath.c | 3 +--
|
|
||||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpath.c b/xpath.c
|
|
||||||
index 1510d69..74848cd 100644
|
|
||||||
--- a/xpath.c
|
|
||||||
+++ b/xpath.c
|
|
||||||
@@ -14104,8 +14104,7 @@ xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
|
|
||||||
- &namespaces[0]);
|
|
||||||
+ stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH, namespaces);
|
|
||||||
if (namespaces != NULL) {
|
|
||||||
xmlFree((xmlChar **)namespaces);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
From 847a3a1181d59dc49c1b446d646d344d0543af3e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 28 Sep 2020 12:28:29 +0200
|
|
||||||
Subject: [PATCH] Fix use-after-free when XIncluding text from Reader
|
|
||||||
|
|
||||||
The XML Reader can free text nodes coming from the XInclude engine
|
|
||||||
before parsing has finished. Cache a copy of the text string, not the
|
|
||||||
included node to avoid use after free.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xinclude.c | 31 ++++++++++++++++++-------------
|
|
||||||
1 file changed, 18 insertions(+), 13 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index f48e0af5..1636caff 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -72,7 +72,7 @@ struct _xmlXIncludeCtxt {
|
|
||||||
|
|
||||||
int txtNr; /* number of unparsed documents */
|
|
||||||
int txtMax; /* size of unparsed documents tab */
|
|
||||||
- xmlNodePtr *txtTab; /* array of unparsed text nodes */
|
|
||||||
+ xmlChar * *txtTab; /* array of unparsed text strings */
|
|
||||||
xmlURL *txturlTab; /* array of unparsed text URLs */
|
|
||||||
|
|
||||||
xmlChar * url; /* the current URL processed */
|
|
||||||
@@ -393,18 +393,22 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
|
|
||||||
if (ctxt->incTab[i] != NULL)
|
|
||||||
xmlXIncludeFreeRef(ctxt->incTab[i]);
|
|
||||||
}
|
|
||||||
+ if (ctxt->incTab != NULL)
|
|
||||||
+ xmlFree(ctxt->incTab);
|
|
||||||
+ if (ctxt->txtTab != NULL) {
|
|
||||||
+ for (i = 0;i < ctxt->txtNr;i++) {
|
|
||||||
+ if (ctxt->txtTab[i] != NULL)
|
|
||||||
+ xmlFree(ctxt->txtTab[i]);
|
|
||||||
+ }
|
|
||||||
+ xmlFree(ctxt->txtTab);
|
|
||||||
+ }
|
|
||||||
if (ctxt->txturlTab != NULL) {
|
|
||||||
for (i = 0;i < ctxt->txtNr;i++) {
|
|
||||||
if (ctxt->txturlTab[i] != NULL)
|
|
||||||
xmlFree(ctxt->txturlTab[i]);
|
|
||||||
}
|
|
||||||
- }
|
|
||||||
- if (ctxt->incTab != NULL)
|
|
||||||
- xmlFree(ctxt->incTab);
|
|
||||||
- if (ctxt->txtTab != NULL)
|
|
||||||
- xmlFree(ctxt->txtTab);
|
|
||||||
- if (ctxt->txturlTab != NULL)
|
|
||||||
xmlFree(ctxt->txturlTab);
|
|
||||||
+ }
|
|
||||||
if (ctxt->base != NULL) {
|
|
||||||
xmlFree(ctxt->base);
|
|
||||||
}
|
|
||||||
@@ -764,13 +768,14 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
|
|
||||||
* Add a new text node to the list
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
-xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
|
|
||||||
+xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *txt,
|
|
||||||
+ const xmlURL url) {
|
|
||||||
#ifdef DEBUG_XINCLUDE
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "Adding text %s\n", url);
|
|
||||||
#endif
|
|
||||||
if (ctxt->txtMax == 0) {
|
|
||||||
ctxt->txtMax = 4;
|
|
||||||
- ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
|
|
||||||
+ ctxt->txtTab = (xmlChar **) xmlMalloc(ctxt->txtMax *
|
|
||||||
sizeof(ctxt->txtTab[0]));
|
|
||||||
if (ctxt->txtTab == NULL) {
|
|
||||||
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
|
|
||||||
@@ -785,7 +790,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
|
|
||||||
}
|
|
||||||
if (ctxt->txtNr >= ctxt->txtMax) {
|
|
||||||
ctxt->txtMax *= 2;
|
|
||||||
- ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
|
|
||||||
+ ctxt->txtTab = (xmlChar **) xmlRealloc(ctxt->txtTab,
|
|
||||||
ctxt->txtMax * sizeof(ctxt->txtTab[0]));
|
|
||||||
if (ctxt->txtTab == NULL) {
|
|
||||||
xmlXIncludeErrMemory(ctxt, NULL, "processing text");
|
|
||||||
@@ -798,7 +803,7 @@ xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt, const xmlURL url) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- ctxt->txtTab[ctxt->txtNr] = txt;
|
|
||||||
+ ctxt->txtTab[ctxt->txtNr] = xmlStrdup(txt);
|
|
||||||
ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
|
|
||||||
ctxt->txtNr++;
|
|
||||||
}
|
|
||||||
@@ -1845,7 +1850,7 @@ xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt, const xmlChar *url, int nr) {
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ctxt->txtNr; i++) {
|
|
||||||
if (xmlStrEqual(URL, ctxt->txturlTab[i])) {
|
|
||||||
- node = xmlCopyNode(ctxt->txtTab[i], 1);
|
|
||||||
+ node = xmlNewText(ctxt->txtTab[i]);
|
|
||||||
goto loaded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1935,7 +1940,7 @@ xinclude_multibyte_fallback:
|
|
||||||
xmlBufShrink(buf->buffer, len);
|
|
||||||
}
|
|
||||||
xmlFreeParserCtxt(pctxt);
|
|
||||||
- xmlXIncludeAddTxt(ctxt, node, URL);
|
|
||||||
+ xmlXIncludeAddTxt(ctxt, node->content, URL);
|
|
||||||
xmlFreeInputStream(inputStream);
|
|
||||||
|
|
||||||
loaded:
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
From 2af3c2a8b974cb5896cd3beb74561ba979de9f34 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 8 Jun 2020 12:49:51 +0200
|
|
||||||
Subject: [PATCH] Fix use-after-free with validating reader
|
|
||||||
|
|
||||||
Just like IDs, IDREF attributes must be removed from the document's
|
|
||||||
refs table when they're freed by a reader. This bug is often hidden
|
|
||||||
because xmlAttr structs are reused and strings are stored in a
|
|
||||||
dictionary unless XML_PARSE_NODICT is specified.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xmlreader.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
1 file changed, 55 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xmlreader.c b/xmlreader.c
|
|
||||||
index 3fd9aa4c0..6ae6e9229 100644
|
|
||||||
--- a/xmlreader.c
|
|
||||||
+++ b/xmlreader.c
|
|
||||||
@@ -278,6 +278,59 @@ xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * xmlTextReaderWalkRemoveRef:
|
|
||||||
+ * @data: Contents of current link
|
|
||||||
+ * @user: Value supplied by the user
|
|
||||||
+ *
|
|
||||||
+ * Returns 0 to abort the walk or 1 to continue
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+xmlTextReaderWalkRemoveRef(const void *data, void *user)
|
|
||||||
+{
|
|
||||||
+ xmlRefPtr ref = (xmlRefPtr)data;
|
|
||||||
+ xmlAttrPtr attr = (xmlAttrPtr)user;
|
|
||||||
+
|
|
||||||
+ if (ref->attr == attr) { /* Matched: remove and terminate walk */
|
|
||||||
+ ref->name = xmlStrdup(attr->name);
|
|
||||||
+ ref->attr = NULL;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * xmlTextReaderRemoveRef:
|
|
||||||
+ * @doc: the document
|
|
||||||
+ * @attr: the attribute
|
|
||||||
+ *
|
|
||||||
+ * Remove the given attribute from the Ref table maintained internally.
|
|
||||||
+ *
|
|
||||||
+ * Returns -1 if the lookup failed and 0 otherwise
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+xmlTextReaderRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
|
|
||||||
+ xmlListPtr ref_list;
|
|
||||||
+ xmlRefTablePtr table;
|
|
||||||
+ xmlChar *ID;
|
|
||||||
+
|
|
||||||
+ if (doc == NULL) return(-1);
|
|
||||||
+ if (attr == NULL) return(-1);
|
|
||||||
+ table = (xmlRefTablePtr) doc->refs;
|
|
||||||
+ if (table == NULL)
|
|
||||||
+ return(-1);
|
|
||||||
+
|
|
||||||
+ ID = xmlNodeListGetString(doc, attr->children, 1);
|
|
||||||
+ if (ID == NULL)
|
|
||||||
+ return(-1);
|
|
||||||
+ ref_list = xmlHashLookup(table, ID);
|
|
||||||
+ xmlFree(ID);
|
|
||||||
+ if(ref_list == NULL)
|
|
||||||
+ return (-1);
|
|
||||||
+ xmlListWalk(ref_list, xmlTextReaderWalkRemoveRef, attr);
|
|
||||||
+ return(0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* xmlTextReaderFreeProp:
|
|
||||||
* @reader: the xmlTextReaderPtr used
|
|
||||||
@@ -304,6 +357,8 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
|
|
||||||
(cur->parent->doc->extSubset != NULL))) {
|
|
||||||
if (xmlIsID(cur->parent->doc, cur->parent, cur))
|
|
||||||
xmlTextReaderRemoveID(cur->parent->doc, cur);
|
|
||||||
+ if (xmlIsRef(cur->parent->doc, cur->parent, cur))
|
|
||||||
+ xmlTextReaderRemoveRef(cur->parent->doc, cur);
|
|
||||||
}
|
|
||||||
if (cur->children != NULL)
|
|
||||||
xmlTextReaderFreeNodeList(reader, cur->children);
|
|
||||||
--
|
|
||||||
GitLab
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
From 1358d157d0bd83be1dfe356a69213df9fac0b539 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 21 Apr 2021 13:23:27 +0200
|
|
||||||
Subject: [PATCH] Fix use-after-free with `xmllint --html --push`
|
|
||||||
|
|
||||||
Call htmlCtxtUseOptions to make sure that names aren't stored in
|
|
||||||
dictionaries.
|
|
||||||
|
|
||||||
Note that this issue only affects xmllint using the HTML push parser.
|
|
||||||
|
|
||||||
Fixes #230.
|
|
||||||
---
|
|
||||||
xmllint.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmllint.c b/xmllint.c
|
|
||||||
index 6ca1bf5..dbef273 100644
|
|
||||||
--- a/xmllint.c
|
|
||||||
+++ b/xmllint.c
|
|
||||||
@@ -2213,7 +2213,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
|
|
||||||
if (res > 0) {
|
|
||||||
ctxt = htmlCreatePushParserCtxt(NULL, NULL,
|
|
||||||
chars, res, filename, XML_CHAR_ENCODING_NONE);
|
|
||||||
- xmlCtxtUseOptions(ctxt, options);
|
|
||||||
+ htmlCtxtUseOptions(ctxt, options);
|
|
||||||
while ((res = fread(chars, 1, pushsize, f)) > 0) {
|
|
||||||
htmlParseChunk(ctxt, chars, res, 0);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
From e20c9c148c725e2933efa143ee6a543a5cae4204 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 13 Mar 2021 18:41:47 +0100
|
|
||||||
Subject: [PATCH] Fix xmlGetNodePath with invalid node types
|
|
||||||
|
|
||||||
Make xmlGetNodePath return NULL instead of invalid XPath when hitting
|
|
||||||
unsupported node types like DTD content.
|
|
||||||
|
|
||||||
Reported here:
|
|
||||||
https://mail.gnome.org/archives/xml/2021-January/msg00012.html
|
|
||||||
|
|
||||||
Original report:
|
|
||||||
https://bugs.php.net/bug.php?id=80680
|
|
||||||
---
|
|
||||||
tree.c | 4 +++-
|
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/tree.c b/tree.c
|
|
||||||
index dbc87aa..c707f59 100644
|
|
||||||
--- a/tree.c
|
|
||||||
+++ b/tree.c
|
|
||||||
@@ -4893,7 +4893,9 @@ xmlGetNodePath(const xmlNode *node)
|
|
||||||
}
|
|
||||||
next = ((xmlAttrPtr) cur)->parent;
|
|
||||||
} else {
|
|
||||||
- next = cur->parent;
|
|
||||||
+ xmlFree(buf);
|
|
||||||
+ xmlFree(buffer);
|
|
||||||
+ return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
From 6c128fd58a0e4641c23a345d413672494622db1b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Fri, 5 Jun 2020 13:43:45 +0200
|
|
||||||
Subject: [PATCH 111/139] Fuzz XInclude engine
|
|
||||||
|
|
||||||
---
|
|
||||||
xinclude.c | 15 +++++++++++++++
|
|
||||||
1 files changed, 15 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 5ea87ad..41ff4e5 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -86,6 +86,8 @@ struct _xmlXIncludeCtxt {
|
|
||||||
xmlChar * base; /* the current xml:base */
|
|
||||||
|
|
||||||
void *_private; /* application data */
|
|
||||||
+
|
|
||||||
+ unsigned long incTotal; /* total number of processed inclusions */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
@@ -729,7 +731,9 @@ xmlXIncludeRecurseDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
|
|
||||||
* (bug 132597)
|
|
||||||
*/
|
|
||||||
newctxt->parseFlags = ctxt->parseFlags;
|
|
||||||
+ newctxt->incTotal = ctxt->incTotal;
|
|
||||||
xmlXIncludeDoProcess(newctxt, doc, xmlDocGetRootElement(doc));
|
|
||||||
+ ctxt->incTotal = newctxt->incTotal;
|
|
||||||
for (i = 0;i < ctxt->incNr;i++) {
|
|
||||||
newctxt->incTab[i]->count--;
|
|
||||||
newctxt->incTab[i] = NULL;
|
|
||||||
@@ -1992,11 +1996,13 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
newctxt->_private = ctxt->_private;
|
|
||||||
newctxt->base = xmlStrdup(ctxt->base); /* Inherit the base from the existing context */
|
|
||||||
xmlXIncludeSetFlags(newctxt, ctxt->parseFlags);
|
|
||||||
+ newctxt->incTotal = ctxt->incTotal;
|
|
||||||
for (child = fallback->children; child != NULL; child = next) {
|
|
||||||
next = child->next;
|
|
||||||
if (xmlXIncludeDoProcess(newctxt, ctxt->doc, child) < 0)
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
+ ctxt->incTotal = newctxt->incTotal;
|
|
||||||
if (ctxt->nbErrors > oldNbErrors)
|
|
||||||
ret = -1;
|
|
||||||
xmlXIncludeFreeContext(newctxt);
|
|
||||||
@@ -2411,6 +2417,15 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
|
|
||||||
do {
|
|
||||||
/* TODO: need to work on entities -> stack */
|
|
||||||
if (xmlXIncludeTestNode(ctxt, cur) == 1) {
|
|
||||||
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
||||||
+ /*
|
|
||||||
+ * Avoid superlinear expansion by limiting the total number
|
|
||||||
+ * of replacements.
|
|
||||||
+ */
|
|
||||||
+ if (ctxt->incTotal >= 20)
|
|
||||||
+ return(-1);
|
|
||||||
+#endif
|
|
||||||
+ ctxt->incTotal++;
|
|
||||||
xmlXIncludePreProcessNode(ctxt, cur);
|
|
||||||
} else if ((cur->children != NULL) &&
|
|
||||||
(cur->children->type != XML_ENTITY_DECL) &&
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
From 6f1470a5d6e3e369fe93f52d5760ba7c947f0cd1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 25 Aug 2020 18:50:45 +0200
|
|
||||||
Subject: [PATCH] Hardcode maximum XPath recursion depth
|
|
||||||
|
|
||||||
Always limit nested functions calls to 5000. This avoids call stack
|
|
||||||
overflows with deeply nested expressions.
|
|
||||||
|
|
||||||
The expression parser produces about 10 nested function calls when
|
|
||||||
parsing a subexpression in parentheses, so the effective nesting limit
|
|
||||||
is about 500 which should be more than enough.
|
|
||||||
|
|
||||||
Use a lower limit when fuzzing to account for increased memory usage
|
|
||||||
when using sanitizers.
|
|
||||||
|
|
||||||
Conflict:delete contents of fuzz/xpath.c
|
|
||||||
---
|
|
||||||
xpath.c | 25 +++++++++++++++++--------
|
|
||||||
1 file changed, 17 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpath.c b/xpath.c
|
|
||||||
index c018d03..2850a1a 100644
|
|
||||||
--- a/xpath.c
|
|
||||||
+++ b/xpath.c
|
|
||||||
@@ -136,6 +136,17 @@
|
|
||||||
#define XPATH_MAX_NODESET_LENGTH 10000000
|
|
||||||
|
|
||||||
/*
|
|
||||||
+ * XPATH_MAX_RECRUSION_DEPTH:
|
|
||||||
+ * Maximum amount of nested functions calls when parsing or evaluating
|
|
||||||
+ * expressions
|
|
||||||
+ */
|
|
||||||
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
||||||
+#define XPATH_MAX_RECURSION_DEPTH 500
|
|
||||||
+#else
|
|
||||||
+#define XPATH_MAX_RECURSION_DEPTH 5000
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
* TODO:
|
|
||||||
* There are a few spots where some tests are done which depend upon ascii
|
|
||||||
* data. These should be enhanced for full UTF8 support (see particularly
|
|
||||||
@@ -6118,8 +6129,6 @@ xmlXPathNewContext(xmlDocPtr doc) {
|
|
||||||
ret->contextSize = -1;
|
|
||||||
ret->proximityPosition = -1;
|
|
||||||
|
|
||||||
- ret->maxDepth = INT_MAX;
|
|
||||||
-
|
|
||||||
#ifdef XP_DEFAULT_CACHE_ON
|
|
||||||
if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
|
|
||||||
xmlXPathFreeContext(ret);
|
|
||||||
@@ -10947,7 +10956,7 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
|
|
||||||
xmlXPathContextPtr xpctxt = ctxt->context;
|
|
||||||
|
|
||||||
if (xpctxt != NULL) {
|
|
||||||
- if (xpctxt->depth >= xpctxt->maxDepth)
|
|
||||||
+ if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
|
|
||||||
XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
|
|
||||||
/*
|
|
||||||
* Parsing a single '(' pushes about 10 functions on the call stack
|
|
||||||
@@ -11883,7 +11892,7 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
|
|
||||||
"xmlXPathCompOpEvalPredicate: Expected a predicate\n");
|
|
||||||
XP_ERROR(XPATH_INVALID_OPERAND);
|
|
||||||
}
|
|
||||||
- if (ctxt->context->depth >= ctxt->context->maxDepth)
|
|
||||||
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
|
|
||||||
XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
|
|
||||||
ctxt->context->depth += 1;
|
|
||||||
xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set,
|
|
||||||
@@ -12599,7 +12608,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
|
|
||||||
CHECK_ERROR0;
|
|
||||||
if (OP_LIMIT_EXCEEDED(ctxt, 1))
|
|
||||||
return(0);
|
|
||||||
- if (ctxt->context->depth >= ctxt->context->maxDepth)
|
|
||||||
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
|
|
||||||
XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
|
|
||||||
ctxt->context->depth += 1;
|
|
||||||
comp = ctxt->comp;
|
|
||||||
@@ -12740,7 +12749,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
|
|
||||||
CHECK_ERROR0;
|
|
||||||
if (OP_LIMIT_EXCEEDED(ctxt, 1))
|
|
||||||
return(0);
|
|
||||||
- if (ctxt->context->depth >= ctxt->context->maxDepth)
|
|
||||||
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
|
|
||||||
XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
|
|
||||||
ctxt->context->depth += 1;
|
|
||||||
comp = ctxt->comp;
|
|
||||||
@@ -12958,7 +12967,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
|
||||||
CHECK_ERROR0;
|
|
||||||
if (OP_LIMIT_EXCEEDED(ctxt, 1))
|
|
||||||
return(0);
|
|
||||||
- if (ctxt->context->depth >= ctxt->context->maxDepth)
|
|
||||||
+ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
|
|
||||||
XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
|
|
||||||
ctxt->context->depth += 1;
|
|
||||||
comp = ctxt->comp;
|
|
||||||
@@ -14192,7 +14201,7 @@ xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,
|
|
||||||
/* Recurse */
|
|
||||||
ctxt = pctxt->context;
|
|
||||||
if (ctxt != NULL) {
|
|
||||||
- if (ctxt->depth >= ctxt->maxDepth)
|
|
||||||
+ if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
|
|
||||||
return;
|
|
||||||
ctxt->depth += 1;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
From fc842f6eba81f3b630e1ff1ffea69c6f4dd66ccc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 6 Jul 2020 15:22:12 +0200
|
|
||||||
Subject: [PATCH] Limit regexp nesting depth
|
|
||||||
|
|
||||||
Enforce a maximum nesting depth of 50 for regular expressions. Avoids
|
|
||||||
stack overflows with deeply nested regexes.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xmlregexp.c | 8 ++++++++
|
|
||||||
1 file changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xmlregexp.c b/xmlregexp.c
|
|
||||||
index 687290e2..dbf3bf2c 100644
|
|
||||||
--- a/xmlregexp.c
|
|
||||||
+++ b/xmlregexp.c
|
|
||||||
@@ -273,6 +273,8 @@ struct _xmlAutomata {
|
|
||||||
int determinist;
|
|
||||||
int negs;
|
|
||||||
int flags;
|
|
||||||
+
|
|
||||||
+ int depth;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _xmlRegexp {
|
|
||||||
@@ -5330,6 +5332,10 @@ xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
xmlRegStatePtr start, oldend, start0;
|
|
||||||
|
|
||||||
NEXT;
|
|
||||||
+ if (ctxt->depth >= 50) {
|
|
||||||
+ ERROR("xmlFAParseAtom: maximum nesting depth exceeded");
|
|
||||||
+ return(-1);
|
|
||||||
+ }
|
|
||||||
/*
|
|
||||||
* this extra Epsilon transition is needed if we count with 0 allowed
|
|
||||||
* unfortunately this can't be known at that point
|
|
||||||
@@ -5341,7 +5347,9 @@ xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
oldend = ctxt->end;
|
|
||||||
ctxt->end = NULL;
|
|
||||||
ctxt->atom = NULL;
|
|
||||||
+ ctxt->depth++;
|
|
||||||
xmlFAParseRegExp(ctxt, 0);
|
|
||||||
+ ctxt->depth--;
|
|
||||||
if (CUR == ')') {
|
|
||||||
NEXT;
|
|
||||||
} else {
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
From f0fd1b67fc883a24cdd039abb3d4fe4696104d72 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 26 Aug 2020 00:16:38 +0200
|
|
||||||
Subject: [PATCH 139/139] Limit size of free lists in XML reader when fuzzing
|
|
||||||
|
|
||||||
Keeping objects on a free list can hide memory errors. Only allow a
|
|
||||||
single node on free lists used by the XML reader when fuzzing. This
|
|
||||||
should hide fewer errors while still exercising the free list logic.
|
|
||||||
---
|
|
||||||
xmlreader.c | 13 ++++++++++---
|
|
||||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlreader.c b/xmlreader.c
|
|
||||||
index 1ab15ba..a9b9ef9 100644
|
|
||||||
--- a/xmlreader.c
|
|
||||||
+++ b/xmlreader.c
|
|
||||||
@@ -48,6 +48,13 @@
|
|
||||||
|
|
||||||
#define MAX_ERR_MSG_SIZE 64000
|
|
||||||
|
|
||||||
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
||||||
+/* Keeping free objects can hide memory errors. */
|
|
||||||
+#define MAX_FREE_NODES 1
|
|
||||||
+#else
|
|
||||||
+#define MAX_FREE_NODES 100
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* The following VA_COPY was coded following an example in
|
|
||||||
* the Samba project. It may not be sufficient for some
|
|
||||||
@@ -365,7 +372,7 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
|
|
||||||
|
|
||||||
DICT_FREE(cur->name);
|
|
||||||
if ((reader != NULL) && (reader->ctxt != NULL) &&
|
|
||||||
- (reader->ctxt->freeAttrsNr < 100)) {
|
|
||||||
+ (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
|
|
||||||
cur->next = reader->ctxt->freeAttrs;
|
|
||||||
reader->ctxt->freeAttrs = cur;
|
|
||||||
reader->ctxt->freeAttrsNr++;
|
|
||||||
@@ -466,7 +473,7 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
|
|
||||||
if (((cur->type == XML_ELEMENT_NODE) ||
|
|
||||||
(cur->type == XML_TEXT_NODE)) &&
|
|
||||||
(reader != NULL) && (reader->ctxt != NULL) &&
|
|
||||||
- (reader->ctxt->freeElemsNr < 100)) {
|
|
||||||
+ (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
|
|
||||||
cur->next = reader->ctxt->freeElems;
|
|
||||||
reader->ctxt->freeElems = cur;
|
|
||||||
reader->ctxt->freeElemsNr++;
|
|
||||||
@@ -554,7 +561,7 @@ xmlTextReaderFreeNode(xmlTextReaderPtr reader, xmlNodePtr cur) {
|
|
||||||
if (((cur->type == XML_ELEMENT_NODE) ||
|
|
||||||
(cur->type == XML_TEXT_NODE)) &&
|
|
||||||
(reader != NULL) && (reader->ctxt != NULL) &&
|
|
||||||
- (reader->ctxt->freeElemsNr < 100)) {
|
|
||||||
+ (reader->ctxt->freeElemsNr < MAX_FREE_NODES)) {
|
|
||||||
cur->next = reader->ctxt->freeElems;
|
|
||||||
reader->ctxt->freeElems = cur;
|
|
||||||
reader->ctxt->freeElemsNr++;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,470 +0,0 @@
|
|||||||
From b79ab6e6d9270666c5dcd2fd85e4c8563d13f922 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 28 Jul 2020 02:42:37 +0200
|
|
||||||
Subject: [PATCH] Make htmlNodeDumpFormatOutput non-recursive
|
|
||||||
|
|
||||||
Fixes stack overflow with deeply nested HTML documents.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
HTMLtree.c | 410 ++++++++++++++++++++++++++++---------------------------------
|
|
||||||
1 file changed, 185 insertions(+), 225 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/HTMLtree.c b/HTMLtree.c
|
|
||||||
index fe5d086..8d236bb 100644
|
|
||||||
--- a/HTMLtree.c
|
|
||||||
+++ b/HTMLtree.c
|
|
||||||
@@ -760,50 +760,6 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
- * htmlAttrListDumpOutput:
|
|
||||||
- * @buf: the HTML buffer output
|
|
||||||
- * @doc: the document
|
|
||||||
- * @cur: the first attribute pointer
|
|
||||||
- * @encoding: the encoding string
|
|
||||||
- *
|
|
||||||
- * Dump a list of HTML attributes
|
|
||||||
- */
|
|
||||||
-static void
|
|
||||||
-htmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, const char *encoding) {
|
|
||||||
- if (cur == NULL) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- while (cur != NULL) {
|
|
||||||
- htmlAttrDumpOutput(buf, doc, cur, encoding);
|
|
||||||
- cur = cur->next;
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-/**
|
|
||||||
- * htmlNodeListDumpOutput:
|
|
||||||
- * @buf: the HTML buffer output
|
|
||||||
- * @doc: the document
|
|
||||||
- * @cur: the first node
|
|
||||||
- * @encoding: the encoding string
|
|
||||||
- * @format: should formatting spaces been added
|
|
||||||
- *
|
|
||||||
- * Dump an HTML node list, recursive behaviour,children are printed too.
|
|
||||||
- */
|
|
||||||
-static void
|
|
||||||
-htmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
|
|
||||||
- xmlNodePtr cur, const char *encoding, int format) {
|
|
||||||
- if (cur == NULL) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- while (cur != NULL) {
|
|
||||||
- htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
|
|
||||||
- cur = cur->next;
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-/**
|
|
||||||
* htmlNodeDumpFormatOutput:
|
|
||||||
* @buf: the HTML buffer output
|
|
||||||
* @doc: the document
|
|
||||||
@@ -816,6 +772,8 @@ htmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
|
|
||||||
void
|
|
||||||
htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
|
|
||||||
xmlNodePtr cur, const char *encoding, int format) {
|
|
||||||
+ xmlNodePtr root;
|
|
||||||
+ xmlAttrPtr attr;
|
|
||||||
const htmlElemDesc * info;
|
|
||||||
|
|
||||||
xmlInitParser();
|
|
||||||
@@ -823,172 +781,193 @@ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
|
|
||||||
if ((cur == NULL) || (buf == NULL)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
- /*
|
|
||||||
- * Special cases.
|
|
||||||
- */
|
|
||||||
- if (cur->type == XML_DTD_NODE)
|
|
||||||
- return;
|
|
||||||
- if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
|
|
||||||
- (cur->type == XML_DOCUMENT_NODE)){
|
|
||||||
- htmlDocContentDumpOutput(buf, (xmlDocPtr) cur, encoding);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_ATTRIBUTE_NODE) {
|
|
||||||
- htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur, encoding);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == HTML_TEXT_NODE) {
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- if (((cur->name == (const xmlChar *)xmlStringText) ||
|
|
||||||
- (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
|
|
||||||
- ((cur->parent == NULL) ||
|
|
||||||
- ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
|
|
||||||
- (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
|
|
||||||
- xmlChar *buffer;
|
|
||||||
-
|
|
||||||
- buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
|
|
||||||
- if (buffer != NULL) {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)buffer);
|
|
||||||
- xmlFree(buffer);
|
|
||||||
- }
|
|
||||||
- } else {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == HTML_COMMENT_NODE) {
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- xmlOutputBufferWriteString(buf, "<!--");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
- xmlOutputBufferWriteString(buf, "-->");
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == HTML_PI_NODE) {
|
|
||||||
- if (cur->name == NULL)
|
|
||||||
- return;
|
|
||||||
- xmlOutputBufferWriteString(buf, "<?");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- xmlOutputBufferWriteString(buf, " ");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWriteString(buf, ">");
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == HTML_ENTITY_REF_NODE) {
|
|
||||||
- xmlOutputBufferWriteString(buf, "&");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- xmlOutputBufferWriteString(buf, ";");
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == HTML_PRESERVE_NODE) {
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
|
|
||||||
- /*
|
|
||||||
- * Get specific HTML info for that node.
|
|
||||||
- */
|
|
||||||
- if (cur->ns == NULL)
|
|
||||||
- info = htmlTagLookup(cur->name);
|
|
||||||
- else
|
|
||||||
- info = NULL;
|
|
||||||
+ root = cur;
|
|
||||||
+ while (1) {
|
|
||||||
+ switch (cur->type) {
|
|
||||||
+ case XML_HTML_DOCUMENT_NODE:
|
|
||||||
+ case XML_DOCUMENT_NODE:
|
|
||||||
+ if (((xmlDocPtr) cur)->intSubset != NULL) {
|
|
||||||
+ htmlDtdDumpOutput(buf, (xmlDocPtr) cur, NULL);
|
|
||||||
+ }
|
|
||||||
+ if (cur->children != NULL) {
|
|
||||||
+ cur = cur->children;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
|
|
||||||
- xmlOutputBufferWriteString(buf, "<");
|
|
||||||
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
- xmlOutputBufferWriteString(buf, ":");
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- if (cur->nsDef)
|
|
||||||
- xmlNsListDumpOutput(buf, cur->nsDef);
|
|
||||||
- if (cur->properties != NULL)
|
|
||||||
- htmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
|
|
||||||
-
|
|
||||||
- if ((info != NULL) && (info->empty)) {
|
|
||||||
- xmlOutputBufferWriteString(buf, ">");
|
|
||||||
- if ((format) && (!info->isinline) && (cur->next != NULL)) {
|
|
||||||
- if ((cur->next->type != HTML_TEXT_NODE) &&
|
|
||||||
- (cur->next->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
- (cur->parent != NULL) &&
|
|
||||||
- (cur->parent->name != NULL) &&
|
|
||||||
- (cur->parent->name[0] != 'p')) /* p, pre, param */
|
|
||||||
- xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
|
|
||||||
- (cur->children == NULL)) {
|
|
||||||
- if ((info != NULL) && (info->saveEndTag != 0) &&
|
|
||||||
- (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
|
|
||||||
- (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
|
|
||||||
- xmlOutputBufferWriteString(buf, ">");
|
|
||||||
- } else {
|
|
||||||
- xmlOutputBufferWriteString(buf, "></");
|
|
||||||
+ case XML_ELEMENT_NODE:
|
|
||||||
+ /*
|
|
||||||
+ * Get specific HTML info for that node.
|
|
||||||
+ */
|
|
||||||
+ if (cur->ns == NULL)
|
|
||||||
+ info = htmlTagLookup(cur->name);
|
|
||||||
+ else
|
|
||||||
+ info = NULL;
|
|
||||||
+
|
|
||||||
+ xmlOutputBufferWriteString(buf, "<");
|
|
||||||
if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
xmlOutputBufferWriteString(buf, ":");
|
|
||||||
}
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- xmlOutputBufferWriteString(buf, ">");
|
|
||||||
- }
|
|
||||||
- if ((format) && (cur->next != NULL) &&
|
|
||||||
- (info != NULL) && (!info->isinline)) {
|
|
||||||
- if ((cur->next->type != HTML_TEXT_NODE) &&
|
|
||||||
- (cur->next->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
- (cur->parent != NULL) &&
|
|
||||||
- (cur->parent->name != NULL) &&
|
|
||||||
- (cur->parent->name[0] != 'p')) /* p, pre, param */
|
|
||||||
- xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWriteString(buf, ">");
|
|
||||||
- if ((cur->type != XML_ELEMENT_NODE) &&
|
|
||||||
- (cur->content != NULL)) {
|
|
||||||
- /*
|
|
||||||
- * Uses the OutputBuffer property to automatically convert
|
|
||||||
- * invalids to charrefs
|
|
||||||
- */
|
|
||||||
-
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *) cur->content);
|
|
||||||
- }
|
|
||||||
- if (cur->children != NULL) {
|
|
||||||
- if ((format) && (info != NULL) && (!info->isinline) &&
|
|
||||||
- (cur->children->type != HTML_TEXT_NODE) &&
|
|
||||||
- (cur->children->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
- (cur->children != cur->last) &&
|
|
||||||
- (cur->name != NULL) &&
|
|
||||||
- (cur->name[0] != 'p')) /* p, pre, param */
|
|
||||||
- xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
- htmlNodeListDumpOutput(buf, doc, cur->children, encoding, format);
|
|
||||||
- if ((format) && (info != NULL) && (!info->isinline) &&
|
|
||||||
- (cur->last->type != HTML_TEXT_NODE) &&
|
|
||||||
- (cur->last->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
- (cur->children != cur->last) &&
|
|
||||||
- (cur->name != NULL) &&
|
|
||||||
- (cur->name[0] != 'p')) /* p, pre, param */
|
|
||||||
- xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWriteString(buf, "</");
|
|
||||||
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
- xmlOutputBufferWriteString(buf, ":");
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- xmlOutputBufferWriteString(buf, ">");
|
|
||||||
- if ((format) && (info != NULL) && (!info->isinline) &&
|
|
||||||
- (cur->next != NULL)) {
|
|
||||||
- if ((cur->next->type != HTML_TEXT_NODE) &&
|
|
||||||
- (cur->next->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
- (cur->parent != NULL) &&
|
|
||||||
- (cur->parent->name != NULL) &&
|
|
||||||
- (cur->parent->name[0] != 'p')) /* p, pre, param */
|
|
||||||
- xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (cur->nsDef)
|
|
||||||
+ xmlNsListDumpOutput(buf, cur->nsDef);
|
|
||||||
+ attr = cur->properties;
|
|
||||||
+ while (attr != NULL) {
|
|
||||||
+ htmlAttrDumpOutput(buf, doc, attr, encoding);
|
|
||||||
+ attr = attr->next;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((info != NULL) && (info->empty)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, ">");
|
|
||||||
+ } else if (cur->children == NULL) {
|
|
||||||
+ if ((info != NULL) && (info->saveEndTag != 0) &&
|
|
||||||
+ (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
|
|
||||||
+ (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, ">");
|
|
||||||
+ } else {
|
|
||||||
+ xmlOutputBufferWriteString(buf, "></");
|
|
||||||
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf,
|
|
||||||
+ (const char *)cur->ns->prefix);
|
|
||||||
+ xmlOutputBufferWriteString(buf, ":");
|
|
||||||
+ }
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ xmlOutputBufferWriteString(buf, ">");
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ xmlOutputBufferWriteString(buf, ">");
|
|
||||||
+ if ((format) && (info != NULL) && (!info->isinline) &&
|
|
||||||
+ (cur->children->type != HTML_TEXT_NODE) &&
|
|
||||||
+ (cur->children->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
+ (cur->children != cur->last) &&
|
|
||||||
+ (cur->name != NULL) &&
|
|
||||||
+ (cur->name[0] != 'p')) /* p, pre, param */
|
|
||||||
+ xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
+ cur = cur->children;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((format) && (cur->next != NULL) &&
|
|
||||||
+ (info != NULL) && (!info->isinline)) {
|
|
||||||
+ if ((cur->next->type != HTML_TEXT_NODE) &&
|
|
||||||
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
+ (cur->parent != NULL) &&
|
|
||||||
+ (cur->parent->name != NULL) &&
|
|
||||||
+ (cur->parent->name[0] != 'p')) /* p, pre, param */
|
|
||||||
+ xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ATTRIBUTE_NODE:
|
|
||||||
+ htmlAttrDumpOutput(buf, doc, (xmlAttrPtr) cur, encoding);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case HTML_TEXT_NODE:
|
|
||||||
+ if (cur->content == NULL)
|
|
||||||
+ break;
|
|
||||||
+ if (((cur->name == (const xmlChar *)xmlStringText) ||
|
|
||||||
+ (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
|
|
||||||
+ ((cur->parent == NULL) ||
|
|
||||||
+ ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
|
|
||||||
+ (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
|
|
||||||
+ xmlChar *buffer;
|
|
||||||
+
|
|
||||||
+ buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
|
|
||||||
+ if (buffer != NULL) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)buffer);
|
|
||||||
+ xmlFree(buffer);
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case HTML_COMMENT_NODE:
|
|
||||||
+ if (cur->content != NULL) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, "<!--");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
+ xmlOutputBufferWriteString(buf, "-->");
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case HTML_PI_NODE:
|
|
||||||
+ if (cur->name != NULL) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, "<?");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (cur->content != NULL) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, " ");
|
|
||||||
+ xmlOutputBufferWriteString(buf,
|
|
||||||
+ (const char *)cur->content);
|
|
||||||
+ }
|
|
||||||
+ xmlOutputBufferWriteString(buf, ">");
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case HTML_ENTITY_REF_NODE:
|
|
||||||
+ xmlOutputBufferWriteString(buf, "&");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ xmlOutputBufferWriteString(buf, ";");
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case HTML_PRESERVE_NODE:
|
|
||||||
+ if (cur->content != NULL) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (1) {
|
|
||||||
+ if (cur == root)
|
|
||||||
+ return;
|
|
||||||
+ if (cur->next != NULL) {
|
|
||||||
+ cur = cur->next;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ cur = cur->parent;
|
|
||||||
+
|
|
||||||
+ if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
|
|
||||||
+ (cur->type == XML_DOCUMENT_NODE)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
+ } else {
|
|
||||||
+ if ((format) && (cur->ns == NULL))
|
|
||||||
+ info = htmlTagLookup(cur->name);
|
|
||||||
+ else
|
|
||||||
+ info = NULL;
|
|
||||||
+
|
|
||||||
+ if ((format) && (info != NULL) && (!info->isinline) &&
|
|
||||||
+ (cur->last->type != HTML_TEXT_NODE) &&
|
|
||||||
+ (cur->last->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
+ (cur->children != cur->last) &&
|
|
||||||
+ (cur->name != NULL) &&
|
|
||||||
+ (cur->name[0] != 'p')) /* p, pre, param */
|
|
||||||
+ xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
+
|
|
||||||
+ xmlOutputBufferWriteString(buf, "</");
|
|
||||||
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
+ xmlOutputBufferWriteString(buf, ":");
|
|
||||||
+ }
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ xmlOutputBufferWriteString(buf, ">");
|
|
||||||
+
|
|
||||||
+ if ((format) && (info != NULL) && (!info->isinline) &&
|
|
||||||
+ (cur->next != NULL)) {
|
|
||||||
+ if ((cur->next->type != HTML_TEXT_NODE) &&
|
|
||||||
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
|
|
||||||
+ (cur->parent != NULL) &&
|
|
||||||
+ (cur->parent->name != NULL) &&
|
|
||||||
+ (cur->parent->name[0] != 'p')) /* p, pre, param */
|
|
||||||
+ xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1020,26 +999,7 @@ htmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
|
|
||||||
void
|
|
||||||
htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
|
|
||||||
const char *encoding, int format) {
|
|
||||||
- int type;
|
|
||||||
-
|
|
||||||
- xmlInitParser();
|
|
||||||
-
|
|
||||||
- if ((buf == NULL) || (cur == NULL))
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * force to output the stuff as HTML, especially for entities
|
|
||||||
- */
|
|
||||||
- type = cur->type;
|
|
||||||
- cur->type = XML_HTML_DOCUMENT_NODE;
|
|
||||||
- if (cur->intSubset != NULL) {
|
|
||||||
- htmlDtdDumpOutput(buf, cur, NULL);
|
|
||||||
- }
|
|
||||||
- if (cur->children != NULL) {
|
|
||||||
- htmlNodeListDumpOutput(buf, cur, cur->children, encoding, format);
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWriteString(buf, "\n");
|
|
||||||
- cur->type = (xmlElementType) type;
|
|
||||||
+ htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, encoding, format);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -1053,7 +1013,7 @@ htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
|
|
||||||
void
|
|
||||||
htmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
|
|
||||||
const char *encoding) {
|
|
||||||
- htmlDocContentDumpFormatOutput(buf, cur, encoding, 1);
|
|
||||||
+ htmlNodeDumpFormatOutput(buf, cur, (xmlNodePtr) cur, encoding, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,550 +0,0 @@
|
|||||||
From dc6f009280e6108fe25f4c4ce32e18fb69cf496e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 28 Jul 2020 19:07:19 +0200
|
|
||||||
Subject: [PATCH] Make xmlNodeDumpOutputInternal non-recursive
|
|
||||||
|
|
||||||
Fixes stack overflow with deeply nested documents.
|
|
||||||
---
|
|
||||||
xmlsave.c | 470 ++++++++++++++++++++++++++++++++------------------------------
|
|
||||||
1 file changed, 240 insertions(+), 230 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xmlsave.c b/xmlsave.c
|
|
||||||
index cf32d69..2235c8f 100644
|
|
||||||
--- a/xmlsave.c
|
|
||||||
+++ b/xmlsave.c
|
|
||||||
@@ -590,7 +590,6 @@ static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
|
|
||||||
static void
|
|
||||||
xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
|
|
||||||
#endif
|
|
||||||
-static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
|
|
||||||
static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
|
|
||||||
void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
|
|
||||||
static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
|
|
||||||
@@ -705,6 +704,7 @@ xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
|
|
||||||
static void
|
|
||||||
xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
|
|
||||||
xmlOutputBufferPtr buf;
|
|
||||||
+ xmlNodePtr cur;
|
|
||||||
int format, level;
|
|
||||||
|
|
||||||
if (dtd == NULL) return;
|
|
||||||
@@ -742,7 +742,9 @@ xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
|
|
||||||
level = ctxt->level;
|
|
||||||
ctxt->format = 0;
|
|
||||||
ctxt->level = -1;
|
|
||||||
- xmlNodeListDumpOutput(ctxt, dtd->children);
|
|
||||||
+ for (cur = dtd->children; cur != NULL; cur = cur->next) {
|
|
||||||
+ xmlNodeDumpOutputInternal(ctxt, cur);
|
|
||||||
+ }
|
|
||||||
ctxt->format = format;
|
|
||||||
ctxt->level = level;
|
|
||||||
xmlOutputBufferWrite(buf, 2, "]>");
|
|
||||||
@@ -776,58 +778,9 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
|
|
||||||
xmlOutputBufferWrite(buf, 1, "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
-/**
|
|
||||||
- * xmlAttrListDumpOutput:
|
|
||||||
- * @buf: the XML buffer output
|
|
||||||
- * @doc: the document
|
|
||||||
- * @cur: the first attribute pointer
|
|
||||||
- * @encoding: an optional encoding string
|
|
||||||
- *
|
|
||||||
- * Dump a list of XML attributes
|
|
||||||
- */
|
|
||||||
-static void
|
|
||||||
-xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
|
|
||||||
- if (cur == NULL) return;
|
|
||||||
- while (cur != NULL) {
|
|
||||||
- xmlAttrDumpOutput(ctxt, cur);
|
|
||||||
- cur = cur->next;
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-/**
|
|
||||||
- * xmlNodeListDumpOutput:
|
|
||||||
- * @cur: the first node
|
|
||||||
- *
|
|
||||||
- * Dump an XML node list, recursive behaviour, children are printed too.
|
|
||||||
- */
|
|
||||||
-static void
|
|
||||||
-xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
- xmlOutputBufferPtr buf;
|
|
||||||
-
|
|
||||||
- if (cur == NULL) return;
|
|
||||||
- buf = ctxt->buf;
|
|
||||||
- while (cur != NULL) {
|
|
||||||
- if ((ctxt->format == 1) && (xmlIndentTreeOutput) &&
|
|
||||||
- ((cur->type == XML_ELEMENT_NODE) ||
|
|
||||||
- (cur->type == XML_COMMENT_NODE) ||
|
|
||||||
- (cur->type == XML_PI_NODE)))
|
|
||||||
- xmlOutputBufferWrite(buf, ctxt->indent_size *
|
|
||||||
- (ctxt->level > ctxt->indent_nr ?
|
|
||||||
- ctxt->indent_nr : ctxt->level),
|
|
||||||
- ctxt->indent);
|
|
||||||
- xmlNodeDumpOutputInternal(ctxt, cur);
|
|
||||||
- if (ctxt->format == 1) {
|
|
||||||
- xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
- }
|
|
||||||
- cur = cur->next;
|
|
||||||
- }
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
#ifdef LIBXML_HTML_ENABLED
|
|
||||||
/**
|
|
||||||
- * xmlNodeDumpOutputInternal:
|
|
||||||
+ * htmlNodeDumpOutputInternal:
|
|
||||||
* @cur: the current node
|
|
||||||
*
|
|
||||||
* Dump an HTML node, recursive behaviour, children are printed too.
|
|
||||||
@@ -893,57 +846,111 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
- int format;
|
|
||||||
- xmlNodePtr tmp;
|
|
||||||
+ int format = ctxt->format;
|
|
||||||
+ xmlNodePtr tmp, root, unformattedNode = NULL;
|
|
||||||
+ xmlAttrPtr attr;
|
|
||||||
xmlChar *start, *end;
|
|
||||||
xmlOutputBufferPtr buf;
|
|
||||||
|
|
||||||
if (cur == NULL) return;
|
|
||||||
buf = ctxt->buf;
|
|
||||||
- if (cur->type == XML_XINCLUDE_START)
|
|
||||||
- return;
|
|
||||||
- if (cur->type == XML_XINCLUDE_END)
|
|
||||||
- return;
|
|
||||||
- if ((cur->type == XML_DOCUMENT_NODE) ||
|
|
||||||
- (cur->type == XML_HTML_DOCUMENT_NODE)) {
|
|
||||||
- xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-#ifdef LIBXML_HTML_ENABLED
|
|
||||||
- if (ctxt->options & XML_SAVE_XHTML) {
|
|
||||||
- xhtmlNodeDumpOutput(ctxt, cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
|
|
||||||
- (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
|
|
||||||
- ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
|
|
||||||
- (ctxt->options & XML_SAVE_AS_HTML)) {
|
|
||||||
- htmlNodeDumpOutputInternal(ctxt, cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
- if (cur->type == XML_DTD_NODE) {
|
|
||||||
- xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_DOCUMENT_FRAG_NODE) {
|
|
||||||
- xmlNodeListDumpOutput(ctxt, cur->children);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_ELEMENT_DECL) {
|
|
||||||
- xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_ATTRIBUTE_DECL) {
|
|
||||||
- xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_ENTITY_DECL) {
|
|
||||||
- xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_TEXT_NODE) {
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
+
|
|
||||||
+ root = cur;
|
|
||||||
+ while (1) {
|
|
||||||
+ switch (cur->type) {
|
|
||||||
+ case XML_DOCUMENT_NODE:
|
|
||||||
+ case XML_HTML_DOCUMENT_NODE:
|
|
||||||
+ xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_DTD_NODE:
|
|
||||||
+ xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_DOCUMENT_FRAG_NODE:
|
|
||||||
+ if (cur->children != NULL) {
|
|
||||||
+ cur = cur->children;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ELEMENT_DECL:
|
|
||||||
+ xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ATTRIBUTE_DECL:
|
|
||||||
+ xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ENTITY_DECL:
|
|
||||||
+ xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ELEMENT_NODE:
|
|
||||||
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
|
|
||||||
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
|
|
||||||
+ (ctxt->level > ctxt->indent_nr ?
|
|
||||||
+ ctxt->indent_nr : ctxt->level),
|
|
||||||
+ ctxt->indent);
|
|
||||||
+
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, "<");
|
|
||||||
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ":");
|
|
||||||
+ }
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (cur->nsDef)
|
|
||||||
+ xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
|
|
||||||
+ for (attr = cur->properties; attr != NULL; attr = attr->next)
|
|
||||||
+ xmlAttrDumpOutput(ctxt, attr);
|
|
||||||
+
|
|
||||||
+ if (cur->children == NULL) {
|
|
||||||
+ if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) {
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
+ xmlOutputBufferWrite(buf, 2, "/>");
|
|
||||||
+ } else {
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 1);
|
|
||||||
+ xmlOutputBufferWrite(buf, 3, "></");
|
|
||||||
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf,
|
|
||||||
+ (const char *)cur->ns->prefix);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ":");
|
|
||||||
+ }
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ">");
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ if (ctxt->format == 1) {
|
|
||||||
+ tmp = cur->children;
|
|
||||||
+ while (tmp != NULL) {
|
|
||||||
+ if ((tmp->type == XML_TEXT_NODE) ||
|
|
||||||
+ (tmp->type == XML_CDATA_SECTION_NODE) ||
|
|
||||||
+ (tmp->type == XML_ENTITY_REF_NODE)) {
|
|
||||||
+ ctxt->format = 0;
|
|
||||||
+ unformattedNode = cur;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ tmp = tmp->next;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 1);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ">");
|
|
||||||
+ if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
+ if (ctxt->level >= 0) ctxt->level++;
|
|
||||||
+ cur = cur->children;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_TEXT_NODE:
|
|
||||||
+ if (cur->content == NULL)
|
|
||||||
+ break;
|
|
||||||
if (cur->name != xmlStringTextNoenc) {
|
|
||||||
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
|
|
||||||
} else {
|
|
||||||
@@ -952,139 +959,129 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
|
||||||
*/
|
|
||||||
xmlOutputBufferWriteString(buf, (const char *) cur->content);
|
|
||||||
}
|
|
||||||
- }
|
|
||||||
+ break;
|
|
||||||
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_PI_NODE) {
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- xmlOutputBufferWrite(buf, 2, "<?");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- if (ctxt->format == 2)
|
|
||||||
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
- else
|
|
||||||
- xmlOutputBufferWrite(buf, 1, " ");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWrite(buf, 2, "?>");
|
|
||||||
- } else {
|
|
||||||
- xmlOutputBufferWrite(buf, 2, "<?");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- if (ctxt->format == 2)
|
|
||||||
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
- xmlOutputBufferWrite(buf, 2, "?>");
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_COMMENT_NODE) {
|
|
||||||
- if (cur->content != NULL) {
|
|
||||||
- xmlOutputBufferWrite(buf, 4, "<!--");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
- xmlOutputBufferWrite(buf, 3, "-->");
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_ENTITY_REF_NODE) {
|
|
||||||
- xmlOutputBufferWrite(buf, 1, "&");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- xmlOutputBufferWrite(buf, 1, ";");
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_CDATA_SECTION_NODE) {
|
|
||||||
- if (cur->content == NULL || *cur->content == '\0') {
|
|
||||||
- xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
|
|
||||||
- } else {
|
|
||||||
- start = end = cur->content;
|
|
||||||
- while (*end != '\0') {
|
|
||||||
- if ((*end == ']') && (*(end + 1) == ']') &&
|
|
||||||
- (*(end + 2) == '>')) {
|
|
||||||
- end = end + 2;
|
|
||||||
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
|
|
||||||
- xmlOutputBufferWrite(buf, end - start, (const char *)start);
|
|
||||||
- xmlOutputBufferWrite(buf, 3, "]]>");
|
|
||||||
- start = end;
|
|
||||||
- }
|
|
||||||
- end++;
|
|
||||||
- }
|
|
||||||
- if (start != end) {
|
|
||||||
- xmlOutputBufferWrite(buf, 9, "<![CDATA[");
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)start);
|
|
||||||
- xmlOutputBufferWrite(buf, 3, "]]>");
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_ATTRIBUTE_NODE) {
|
|
||||||
- xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (cur->type == XML_NAMESPACE_DECL) {
|
|
||||||
- xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
+ case XML_PI_NODE:
|
|
||||||
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
|
|
||||||
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
|
|
||||||
+ (ctxt->level > ctxt->indent_nr ?
|
|
||||||
+ ctxt->indent_nr : ctxt->level),
|
|
||||||
+ ctxt->indent);
|
|
||||||
|
|
||||||
- format = ctxt->format;
|
|
||||||
- if (format == 1) {
|
|
||||||
- tmp = cur->children;
|
|
||||||
- while (tmp != NULL) {
|
|
||||||
- if ((tmp->type == XML_TEXT_NODE) ||
|
|
||||||
- (tmp->type == XML_CDATA_SECTION_NODE) ||
|
|
||||||
- (tmp->type == XML_ENTITY_REF_NODE)) {
|
|
||||||
- ctxt->format = 0;
|
|
||||||
- break;
|
|
||||||
- }
|
|
||||||
- tmp = tmp->next;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWrite(buf, 1, "<");
|
|
||||||
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
- xmlOutputBufferWrite(buf, 1, ":");
|
|
||||||
- }
|
|
||||||
+ if (cur->content != NULL) {
|
|
||||||
+ xmlOutputBufferWrite(buf, 2, "<?");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (cur->content != NULL) {
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
+ else
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, " ");
|
|
||||||
+ xmlOutputBufferWriteString(buf,
|
|
||||||
+ (const char *)cur->content);
|
|
||||||
+ }
|
|
||||||
+ xmlOutputBufferWrite(buf, 2, "?>");
|
|
||||||
+ } else {
|
|
||||||
+ xmlOutputBufferWrite(buf, 2, "<?");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
+ xmlOutputBufferWrite(buf, 2, "?>");
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- if (cur->nsDef)
|
|
||||||
- xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
|
|
||||||
- if (cur->properties != NULL)
|
|
||||||
- xmlAttrListDumpOutput(ctxt, cur->properties);
|
|
||||||
-
|
|
||||||
- if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
|
|
||||||
- (cur->children == NULL) && ((ctxt->options & XML_SAVE_NO_EMPTY) == 0)) {
|
|
||||||
- if (ctxt->format == 2)
|
|
||||||
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
- xmlOutputBufferWrite(buf, 2, "/>");
|
|
||||||
- ctxt->format = format;
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
- if (ctxt->format == 2)
|
|
||||||
- xmlOutputBufferWriteWSNonSig(ctxt, 1);
|
|
||||||
- xmlOutputBufferWrite(buf, 1, ">");
|
|
||||||
- if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
|
|
||||||
- xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
|
|
||||||
- }
|
|
||||||
- if (cur->children != NULL) {
|
|
||||||
- if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
- if (ctxt->level >= 0) ctxt->level++;
|
|
||||||
- xmlNodeListDumpOutput(ctxt, cur->children);
|
|
||||||
- if (ctxt->level > 0) ctxt->level--;
|
|
||||||
- if ((xmlIndentTreeOutput) && (ctxt->format == 1))
|
|
||||||
- xmlOutputBufferWrite(buf, ctxt->indent_size *
|
|
||||||
- (ctxt->level > ctxt->indent_nr ?
|
|
||||||
- ctxt->indent_nr : ctxt->level),
|
|
||||||
- ctxt->indent);
|
|
||||||
- }
|
|
||||||
- xmlOutputBufferWrite(buf, 2, "</");
|
|
||||||
- if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
- xmlOutputBufferWrite(buf, 1, ":");
|
|
||||||
- }
|
|
||||||
+ case XML_COMMENT_NODE:
|
|
||||||
+ if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
|
|
||||||
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
|
|
||||||
+ (ctxt->level > ctxt->indent_nr ?
|
|
||||||
+ ctxt->indent_nr : ctxt->level),
|
|
||||||
+ ctxt->indent);
|
|
||||||
|
|
||||||
- xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
- if (ctxt->format == 2)
|
|
||||||
- xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
- xmlOutputBufferWrite(buf, 1, ">");
|
|
||||||
- ctxt->format = format;
|
|
||||||
+ if (cur->content != NULL) {
|
|
||||||
+ xmlOutputBufferWrite(buf, 4, "<!--");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
|
|
||||||
+ xmlOutputBufferWrite(buf, 3, "-->");
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ENTITY_REF_NODE:
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, "&");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ";");
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_CDATA_SECTION_NODE:
|
|
||||||
+ if (cur->content == NULL || *cur->content == '\0') {
|
|
||||||
+ xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
|
|
||||||
+ } else {
|
|
||||||
+ start = end = cur->content;
|
|
||||||
+ while (*end != '\0') {
|
|
||||||
+ if ((*end == ']') && (*(end + 1) == ']') &&
|
|
||||||
+ (*(end + 2) == '>')) {
|
|
||||||
+ end = end + 2;
|
|
||||||
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
|
|
||||||
+ xmlOutputBufferWrite(buf, end - start,
|
|
||||||
+ (const char *)start);
|
|
||||||
+ xmlOutputBufferWrite(buf, 3, "]]>");
|
|
||||||
+ start = end;
|
|
||||||
+ }
|
|
||||||
+ end++;
|
|
||||||
+ }
|
|
||||||
+ if (start != end) {
|
|
||||||
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)start);
|
|
||||||
+ xmlOutputBufferWrite(buf, 3, "]]>");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_ATTRIBUTE_NODE:
|
|
||||||
+ xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case XML_NAMESPACE_DECL:
|
|
||||||
+ xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (1) {
|
|
||||||
+ if (cur == root)
|
|
||||||
+ return;
|
|
||||||
+ if (ctxt->format == 1) {
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, "\n");
|
|
||||||
+ }
|
|
||||||
+ if (cur->next != NULL) {
|
|
||||||
+ cur = cur->next;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ cur = cur->parent;
|
|
||||||
+
|
|
||||||
+ if (ctxt->level > 0) ctxt->level--;
|
|
||||||
+ if ((xmlIndentTreeOutput) && (ctxt->format == 1))
|
|
||||||
+ xmlOutputBufferWrite(buf, ctxt->indent_size *
|
|
||||||
+ (ctxt->level > ctxt->indent_nr ?
|
|
||||||
+ ctxt->indent_nr : ctxt->level),
|
|
||||||
+ ctxt->indent);
|
|
||||||
+ if (cur == unformattedNode) {
|
|
||||||
+ ctxt->format = format;
|
|
||||||
+ unformattedNode = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xmlOutputBufferWrite(buf, 2, "</");
|
|
||||||
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ":");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
|
||||||
+ if (ctxt->format == 2)
|
|
||||||
+ xmlOutputBufferWriteWSNonSig(ctxt, 0);
|
|
||||||
+ xmlOutputBufferWrite(buf, 1, ">");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -1865,12 +1862,25 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
|
|
||||||
* Returns the number of byte written or -1 in case of error
|
|
||||||
*/
|
|
||||||
long
|
|
||||||
-xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr node)
|
|
||||||
+xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
|
|
||||||
{
|
|
||||||
long ret = 0;
|
|
||||||
|
|
||||||
- if ((ctxt == NULL) || (node == NULL)) return(-1);
|
|
||||||
- xmlNodeDumpOutputInternal(ctxt, node);
|
|
||||||
+ if ((ctxt == NULL) || (cur == NULL)) return(-1);
|
|
||||||
+#ifdef LIBXML_HTML_ENABLED
|
|
||||||
+ if (ctxt->options & XML_SAVE_XHTML) {
|
|
||||||
+ xhtmlNodeDumpOutput(ctxt, cur);
|
|
||||||
+ return(ret);
|
|
||||||
+ }
|
|
||||||
+ if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
|
|
||||||
+ (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
|
|
||||||
+ ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
|
|
||||||
+ (ctxt->options & XML_SAVE_AS_HTML)) {
|
|
||||||
+ htmlNodeDumpOutputInternal(ctxt, cur);
|
|
||||||
+ return(ret);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ xmlNodeDumpOutputInternal(ctxt, cur);
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,361 +0,0 @@
|
|||||||
From 1a3e584a5af0f6ffc6f80a3caa192eb8c0389611 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 21 Jan 2020 22:12:42 +0100
|
|
||||||
Subject: [PATCH] Merge code paths loading external entities
|
|
||||||
|
|
||||||
Merge xmlParseCtxtExternalEntity into xmlParseExternalEntityPrivate.
|
|
||||||
---
|
|
||||||
parser.c | 282 ++++++++++++++++-----------------------------------------------
|
|
||||||
1 file changed, 72 insertions(+), 210 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 5ff8592..0ca58e8 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -12891,189 +12891,21 @@ xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
|
|
||||||
int
|
|
||||||
xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
|
|
||||||
const xmlChar *ID, xmlNodePtr *lst) {
|
|
||||||
- xmlParserCtxtPtr ctxt;
|
|
||||||
- xmlDocPtr newDoc;
|
|
||||||
- xmlNodePtr newRoot;
|
|
||||||
- xmlSAXHandlerPtr oldsax = NULL;
|
|
||||||
- int ret = 0;
|
|
||||||
- xmlChar start[4];
|
|
||||||
- xmlCharEncoding enc;
|
|
||||||
+ void *userData;
|
|
||||||
|
|
||||||
if (ctx == NULL) return(-1);
|
|
||||||
-
|
|
||||||
- if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
|
|
||||||
- (ctx->depth > 1024)) {
|
|
||||||
- return(XML_ERR_ENTITY_LOOP);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (lst != NULL)
|
|
||||||
- *lst = NULL;
|
|
||||||
- if ((URL == NULL) && (ID == NULL))
|
|
||||||
- return(-1);
|
|
||||||
- if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
|
|
||||||
- return(-1);
|
|
||||||
-
|
|
||||||
- ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
|
|
||||||
- if (ctxt == NULL) {
|
|
||||||
- return(-1);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- oldsax = ctxt->sax;
|
|
||||||
- ctxt->sax = ctx->sax;
|
|
||||||
- xmlDetectSAX2(ctxt);
|
|
||||||
- newDoc = xmlNewDoc(BAD_CAST "1.0");
|
|
||||||
- if (newDoc == NULL) {
|
|
||||||
- xmlFreeParserCtxt(ctxt);
|
|
||||||
- return(-1);
|
|
||||||
- }
|
|
||||||
- newDoc->properties = XML_DOC_INTERNAL;
|
|
||||||
- if (ctx->myDoc->dict) {
|
|
||||||
- newDoc->dict = ctx->myDoc->dict;
|
|
||||||
- xmlDictReference(newDoc->dict);
|
|
||||||
- }
|
|
||||||
- if (ctx->myDoc != NULL) {
|
|
||||||
- newDoc->intSubset = ctx->myDoc->intSubset;
|
|
||||||
- newDoc->extSubset = ctx->myDoc->extSubset;
|
|
||||||
- }
|
|
||||||
- if (ctx->myDoc->URL != NULL) {
|
|
||||||
- newDoc->URL = xmlStrdup(ctx->myDoc->URL);
|
|
||||||
- }
|
|
||||||
- newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
|
|
||||||
- if (newRoot == NULL) {
|
|
||||||
- ctxt->sax = oldsax;
|
|
||||||
- xmlFreeParserCtxt(ctxt);
|
|
||||||
- newDoc->intSubset = NULL;
|
|
||||||
- newDoc->extSubset = NULL;
|
|
||||||
- xmlFreeDoc(newDoc);
|
|
||||||
- return(-1);
|
|
||||||
- }
|
|
||||||
- xmlAddChild((xmlNodePtr) newDoc, newRoot);
|
|
||||||
- nodePush(ctxt, newDoc->children);
|
|
||||||
- if (ctx->myDoc == NULL) {
|
|
||||||
- ctxt->myDoc = newDoc;
|
|
||||||
- } else {
|
|
||||||
- ctxt->myDoc = ctx->myDoc;
|
|
||||||
- newDoc->children->doc = ctx->myDoc;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
- * Get the 4 first bytes and decode the charset
|
|
||||||
- * if enc != XML_CHAR_ENCODING_NONE
|
|
||||||
- * plug some encoding conversion routines.
|
|
||||||
- */
|
|
||||||
- GROW
|
|
||||||
- if ((ctxt->input->end - ctxt->input->cur) >= 4) {
|
|
||||||
- start[0] = RAW;
|
|
||||||
- start[1] = NXT(1);
|
|
||||||
- start[2] = NXT(2);
|
|
||||||
- start[3] = NXT(3);
|
|
||||||
- enc = xmlDetectCharEncoding(start, 4);
|
|
||||||
- if (enc != XML_CHAR_ENCODING_NONE) {
|
|
||||||
- xmlSwitchEncoding(ctxt, enc);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * Parse a possible text declaration first
|
|
||||||
- */
|
|
||||||
- if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
|
|
||||||
- xmlParseTextDecl(ctxt);
|
|
||||||
- /*
|
|
||||||
- * An XML-1.0 document can't reference an entity not XML-1.0
|
|
||||||
- */
|
|
||||||
- if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
|
|
||||||
- (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
|
|
||||||
- xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
|
|
||||||
- "Version mismatch between document and entity\n");
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * If the user provided its own SAX callbacks then reuse the
|
|
||||||
- * useData callback field, otherwise the expected setup in a
|
|
||||||
+ * If the user provided their own SAX callbacks, then reuse the
|
|
||||||
+ * userData callback field, otherwise the expected setup in a
|
|
||||||
* DOM builder is to have userData == ctxt
|
|
||||||
*/
|
|
||||||
if (ctx->userData == ctx)
|
|
||||||
- ctxt->userData = ctxt;
|
|
||||||
+ userData = NULL;
|
|
||||||
else
|
|
||||||
- ctxt->userData = ctx->userData;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * Doing validity checking on chunk doesn't make sense
|
|
||||||
- */
|
|
||||||
- ctxt->instate = XML_PARSER_CONTENT;
|
|
||||||
- ctxt->validate = ctx->validate;
|
|
||||||
- ctxt->valid = ctx->valid;
|
|
||||||
- ctxt->loadsubset = ctx->loadsubset;
|
|
||||||
- ctxt->depth = ctx->depth + 1;
|
|
||||||
- ctxt->replaceEntities = ctx->replaceEntities;
|
|
||||||
- if (ctxt->validate) {
|
|
||||||
- ctxt->vctxt.error = ctx->vctxt.error;
|
|
||||||
- ctxt->vctxt.warning = ctx->vctxt.warning;
|
|
||||||
- } else {
|
|
||||||
- ctxt->vctxt.error = NULL;
|
|
||||||
- ctxt->vctxt.warning = NULL;
|
|
||||||
- }
|
|
||||||
- ctxt->vctxt.nodeTab = NULL;
|
|
||||||
- ctxt->vctxt.nodeNr = 0;
|
|
||||||
- ctxt->vctxt.nodeMax = 0;
|
|
||||||
- ctxt->vctxt.node = NULL;
|
|
||||||
- if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
|
|
||||||
- ctxt->dict = ctx->dict;
|
|
||||||
- ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
|
|
||||||
- ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
|
|
||||||
- ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
|
|
||||||
- ctxt->dictNames = ctx->dictNames;
|
|
||||||
- ctxt->attsDefault = ctx->attsDefault;
|
|
||||||
- ctxt->attsSpecial = ctx->attsSpecial;
|
|
||||||
- ctxt->linenumbers = ctx->linenumbers;
|
|
||||||
-
|
|
||||||
- xmlParseContent(ctxt);
|
|
||||||
-
|
|
||||||
- ctx->validate = ctxt->validate;
|
|
||||||
- ctx->valid = ctxt->valid;
|
|
||||||
- if ((RAW == '<') && (NXT(1) == '/')) {
|
|
||||||
- xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
|
|
||||||
- } else if (RAW != 0) {
|
|
||||||
- xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
|
|
||||||
- }
|
|
||||||
- if (ctxt->node != newDoc->children) {
|
|
||||||
- xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (!ctxt->wellFormed) {
|
|
||||||
- if (ctxt->errNo == 0)
|
|
||||||
- ret = 1;
|
|
||||||
- else
|
|
||||||
- ret = ctxt->errNo;
|
|
||||||
- } else {
|
|
||||||
- if (lst != NULL) {
|
|
||||||
- xmlNodePtr cur;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * Return the newly created nodeset after unlinking it from
|
|
||||||
- * they pseudo parent.
|
|
||||||
- */
|
|
||||||
- cur = newDoc->children->children;
|
|
||||||
- *lst = cur;
|
|
||||||
- while (cur != NULL) {
|
|
||||||
- cur->parent = NULL;
|
|
||||||
- cur = cur->next;
|
|
||||||
- }
|
|
||||||
- newDoc->children->children = NULL;
|
|
||||||
- }
|
|
||||||
- ret = 0;
|
|
||||||
- }
|
|
||||||
- ctxt->sax = oldsax;
|
|
||||||
- ctxt->dict = NULL;
|
|
||||||
- ctxt->attsDefault = NULL;
|
|
||||||
- ctxt->attsSpecial = NULL;
|
|
||||||
- xmlFreeParserCtxt(ctxt);
|
|
||||||
- newDoc->intSubset = NULL;
|
|
||||||
- newDoc->extSubset = NULL;
|
|
||||||
- xmlFreeDoc(newDoc);
|
|
||||||
-
|
|
||||||
- return(ret);
|
|
||||||
+ userData = ctx->userData;
|
|
||||||
+ return xmlParseExternalEntityPrivate(ctx->myDoc, ctx, ctx->sax,
|
|
||||||
+ userData, ctx->depth + 1,
|
|
||||||
+ URL, ID, lst);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@@ -13123,25 +12955,6 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|
||||||
ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
|
|
||||||
if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
|
|
||||||
ctxt->userData = ctxt;
|
|
||||||
- if (oldctxt != NULL) {
|
|
||||||
- ctxt->_private = oldctxt->_private;
|
|
||||||
- ctxt->loadsubset = oldctxt->loadsubset;
|
|
||||||
- ctxt->validate = oldctxt->validate;
|
|
||||||
- ctxt->external = oldctxt->external;
|
|
||||||
- ctxt->record_info = oldctxt->record_info;
|
|
||||||
- ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
|
|
||||||
- ctxt->node_seq.length = oldctxt->node_seq.length;
|
|
||||||
- ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
|
|
||||||
- } else {
|
|
||||||
- /*
|
|
||||||
- * Doing validity checking on chunk without context
|
|
||||||
- * doesn't make sense
|
|
||||||
- */
|
|
||||||
- ctxt->_private = NULL;
|
|
||||||
- ctxt->validate = 0;
|
|
||||||
- ctxt->external = 2;
|
|
||||||
- ctxt->loadsubset = 0;
|
|
||||||
- }
|
|
||||||
if (sax != NULL) {
|
|
||||||
oldsax = ctxt->sax;
|
|
||||||
ctxt->sax = sax;
|
|
||||||
@@ -13151,28 +12964,25 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|
||||||
xmlDetectSAX2(ctxt);
|
|
||||||
newDoc = xmlNewDoc(BAD_CAST "1.0");
|
|
||||||
if (newDoc == NULL) {
|
|
||||||
- ctxt->node_seq.maximum = 0;
|
|
||||||
- ctxt->node_seq.length = 0;
|
|
||||||
- ctxt->node_seq.buffer = NULL;
|
|
||||||
xmlFreeParserCtxt(ctxt);
|
|
||||||
return(XML_ERR_INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
newDoc->properties = XML_DOC_INTERNAL;
|
|
||||||
- newDoc->intSubset = doc->intSubset;
|
|
||||||
- newDoc->extSubset = doc->extSubset;
|
|
||||||
- newDoc->dict = doc->dict;
|
|
||||||
- xmlDictReference(newDoc->dict);
|
|
||||||
-
|
|
||||||
- if (doc->URL != NULL) {
|
|
||||||
- newDoc->URL = xmlStrdup(doc->URL);
|
|
||||||
+ if (doc) {
|
|
||||||
+ newDoc->intSubset = doc->intSubset;
|
|
||||||
+ newDoc->extSubset = doc->extSubset;
|
|
||||||
+ if (doc->dict) {
|
|
||||||
+ newDoc->dict = doc->dict;
|
|
||||||
+ xmlDictReference(newDoc->dict);
|
|
||||||
+ }
|
|
||||||
+ if (doc->URL != NULL) {
|
|
||||||
+ newDoc->URL = xmlStrdup(doc->URL);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
|
|
||||||
if (newRoot == NULL) {
|
|
||||||
if (sax != NULL)
|
|
||||||
ctxt->sax = oldsax;
|
|
||||||
- ctxt->node_seq.maximum = 0;
|
|
||||||
- ctxt->node_seq.length = 0;
|
|
||||||
- ctxt->node_seq.buffer = NULL;
|
|
||||||
xmlFreeParserCtxt(ctxt);
|
|
||||||
newDoc->intSubset = NULL;
|
|
||||||
newDoc->extSubset = NULL;
|
|
||||||
@@ -13181,8 +12991,12 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|
||||||
}
|
|
||||||
xmlAddChild((xmlNodePtr) newDoc, newRoot);
|
|
||||||
nodePush(ctxt, newDoc->children);
|
|
||||||
- ctxt->myDoc = doc;
|
|
||||||
- newRoot->doc = doc;
|
|
||||||
+ if (doc == NULL) {
|
|
||||||
+ ctxt->myDoc = newDoc;
|
|
||||||
+ } else {
|
|
||||||
+ ctxt->myDoc = doc;
|
|
||||||
+ newRoot->doc = doc;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the 4 first bytes and decode the charset
|
|
||||||
@@ -13206,10 +13020,53 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|
||||||
*/
|
|
||||||
if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
|
|
||||||
xmlParseTextDecl(ctxt);
|
|
||||||
+ /*
|
|
||||||
+ * An XML-1.0 document can't reference an entity not XML-1.0
|
|
||||||
+ */
|
|
||||||
+ if ((xmlStrEqual(oldctxt->version, BAD_CAST "1.0")) &&
|
|
||||||
+ (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
|
|
||||||
+ xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
|
|
||||||
+ "Version mismatch between document and entity\n");
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt->instate = XML_PARSER_CONTENT;
|
|
||||||
ctxt->depth = depth;
|
|
||||||
+ if (oldctxt != NULL) {
|
|
||||||
+ ctxt->_private = oldctxt->_private;
|
|
||||||
+ ctxt->loadsubset = oldctxt->loadsubset;
|
|
||||||
+ ctxt->validate = oldctxt->validate;
|
|
||||||
+ ctxt->valid = oldctxt->valid;
|
|
||||||
+ ctxt->replaceEntities = oldctxt->replaceEntities;
|
|
||||||
+ if (oldctxt->validate) {
|
|
||||||
+ ctxt->vctxt.error = oldctxt->vctxt.error;
|
|
||||||
+ ctxt->vctxt.warning = oldctxt->vctxt.warning;
|
|
||||||
+ ctxt->vctxt.userData = oldctxt->vctxt.userData;
|
|
||||||
+ }
|
|
||||||
+ ctxt->external = oldctxt->external;
|
|
||||||
+ if (ctxt->dict) xmlDictFree(ctxt->dict);
|
|
||||||
+ ctxt->dict = oldctxt->dict;
|
|
||||||
+ ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
|
|
||||||
+ ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
|
|
||||||
+ ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
|
|
||||||
+ ctxt->dictNames = oldctxt->dictNames;
|
|
||||||
+ ctxt->attsDefault = oldctxt->attsDefault;
|
|
||||||
+ ctxt->attsSpecial = oldctxt->attsSpecial;
|
|
||||||
+ ctxt->linenumbers = oldctxt->linenumbers;
|
|
||||||
+ ctxt->record_info = oldctxt->record_info;
|
|
||||||
+ ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
|
|
||||||
+ ctxt->node_seq.length = oldctxt->node_seq.length;
|
|
||||||
+ ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
|
|
||||||
+ } else {
|
|
||||||
+ /*
|
|
||||||
+ * Doing validity checking on chunk without context
|
|
||||||
+ * doesn't make sense
|
|
||||||
+ */
|
|
||||||
+ ctxt->_private = NULL;
|
|
||||||
+ ctxt->validate = 0;
|
|
||||||
+ ctxt->external = 2;
|
|
||||||
+ ctxt->loadsubset = 0;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
xmlParseContent(ctxt);
|
|
||||||
|
|
||||||
@@ -13269,6 +13126,11 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|
||||||
if (sax != NULL)
|
|
||||||
ctxt->sax = oldsax;
|
|
||||||
if (oldctxt != NULL) {
|
|
||||||
+ ctxt->dict = NULL;
|
|
||||||
+ ctxt->attsDefault = NULL;
|
|
||||||
+ ctxt->attsSpecial = NULL;
|
|
||||||
+ oldctxt->validate = ctxt->validate;
|
|
||||||
+ oldctxt->valid = ctxt->valid;
|
|
||||||
oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
|
|
||||||
oldctxt->node_seq.length = ctxt->node_seq.length;
|
|
||||||
oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
From a28f7d8789e63f5e2ac63b42083754cba58f1a0e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 10 Jun 2020 13:41:13 +0200
|
|
||||||
Subject: [PATCH] Never expand parameter entities in text declaration
|
|
||||||
|
|
||||||
When parsing the text declaration of external DTDs or entities, make
|
|
||||||
sure that parameter entities are not expanded. This also fixes a memory
|
|
||||||
leak in certain error cases.
|
|
||||||
|
|
||||||
The change to xmlSkipBlankChars assumes that the parser state is
|
|
||||||
maintained correctly when parsing external DTDs or parameter entities,
|
|
||||||
and might expose bugs in the code that were hidden previously.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
parser.c | 10 +++++++++-
|
|
||||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 046f1cec3..3559aaaec 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -2156,7 +2156,7 @@ xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
|
|
||||||
* It's Okay to use CUR/NEXT here since all the blanks are on
|
|
||||||
* the ASCII range.
|
|
||||||
*/
|
|
||||||
- if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
|
|
||||||
+ if (ctxt->instate != XML_PARSER_DTD) {
|
|
||||||
const xmlChar *cur;
|
|
||||||
/*
|
|
||||||
* if we are in the document content, go really fast
|
|
||||||
@@ -6852,6 +6852,7 @@ void
|
|
||||||
xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
|
|
||||||
xmlChar *version;
|
|
||||||
const xmlChar *encoding;
|
|
||||||
+ int oldstate;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We know that '<?xml' is here.
|
|
||||||
@@ -6863,6 +6864,10 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Avoid expansion of parameter entities when skipping blanks. */
|
|
||||||
+ oldstate = ctxt->instate;
|
|
||||||
+ ctxt->instate = XML_PARSER_START;
|
|
||||||
+
|
|
||||||
if (SKIP_BLANKS == 0) {
|
|
||||||
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
|
|
||||||
"Space needed after '<?xml'\n");
|
|
||||||
@@ -6890,6 +6895,7 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
|
|
||||||
/*
|
|
||||||
* The XML REC instructs us to stop parsing right here
|
|
||||||
*/
|
|
||||||
+ ctxt->instate = oldstate;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
|
|
||||||
@@ -6909,6 +6915,8 @@ xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
|
|
||||||
MOVETO_ENDTAG(CUR_PTR);
|
|
||||||
NEXT;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ ctxt->instate = oldstate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
--
|
|
||||||
GitLab
|
|
||||||
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
From d724861536f3cfb82750176aa45e655634bbbbcc Mon Sep 17 00:00:00 2001
|
|
||||||
From: raniervf <ranier_gyn@hotmail.com>
|
|
||||||
Date: Mon, 4 Nov 2019 23:19:28 -0300
|
|
||||||
Subject: [PATCH] Null pointer handling in catalog.c
|
|
||||||
|
|
||||||
Fix potential deferencing potential null pointers;
|
|
||||||
Small optimizations.
|
|
||||||
|
|
||||||
Closes #123.
|
|
||||||
---
|
|
||||||
catalog.c | 14 +++++++-------
|
|
||||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/catalog.c b/catalog.c
|
|
||||||
index 7328fd3..b471e8a 100644
|
|
||||||
--- a/catalog.c
|
|
||||||
+++ b/catalog.c
|
|
||||||
@@ -924,7 +924,7 @@ xmlParseCatalogFile(const char *filename) {
|
|
||||||
xmlBufResetInput(buf->buffer, inputStream);
|
|
||||||
|
|
||||||
inputPush(ctxt, inputStream);
|
|
||||||
- if ((ctxt->directory == NULL) && (directory == NULL))
|
|
||||||
+ if (ctxt->directory == NULL)
|
|
||||||
directory = xmlParserGetDirectory(filename);
|
|
||||||
if ((ctxt->directory == NULL) && (directory != NULL))
|
|
||||||
ctxt->directory = directory;
|
|
||||||
@@ -2069,8 +2069,7 @@ xmlCatalogListXMLResolve(xmlCatalogEntryPtr catal, const xmlChar *pubID,
|
|
||||||
ret = xmlCatalogXMLResolve(catal->children, pubID, sysID);
|
|
||||||
if (ret != NULL) {
|
|
||||||
break;
|
|
||||||
- } else if ((catal->children != NULL) &&
|
|
||||||
- (catal->children->depth > MAX_CATAL_DEPTH)) {
|
|
||||||
+ } else if (catal->children->depth > MAX_CATAL_DEPTH) {
|
|
||||||
ret = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
@@ -2353,7 +2352,7 @@ xmlParseSGMLCatalog(xmlCatalogPtr catal, const xmlChar *value,
|
|
||||||
xmlCatalogEntryType type = XML_CATA_NONE;
|
|
||||||
|
|
||||||
cur = xmlParseSGMLCatalogName(cur, &name);
|
|
||||||
- if (name == NULL) {
|
|
||||||
+ if (cur == NULL || name == NULL) {
|
|
||||||
/* error */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
@@ -3254,6 +3253,7 @@ xmlLoadCatalogs(const char *pathss) {
|
|
||||||
while ((*cur != 0) && (*cur != PATH_SEPARATOR) && (!xmlIsBlank_ch(*cur)))
|
|
||||||
cur++;
|
|
||||||
path = xmlStrndup((const xmlChar *)paths, cur - paths);
|
|
||||||
+ if (path != NULL) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
iLen = strlen((const char*)path);
|
|
||||||
for(i = 0; i < iLen; i++) {
|
|
||||||
@@ -3262,7 +3262,6 @@ xmlLoadCatalogs(const char *pathss) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
- if (path != NULL) {
|
|
||||||
xmlLoadCatalog((const char *) path);
|
|
||||||
xmlFree(path);
|
|
||||||
}
|
|
||||||
@@ -3427,9 +3426,10 @@ xmlCatalogAdd(const xmlChar *type, const xmlChar *orig, const xmlChar *replace)
|
|
||||||
(xmlStrEqual(type, BAD_CAST "catalog"))) {
|
|
||||||
xmlDefaultCatalog = xmlCreateNewCatalog(XML_XML_CATALOG_TYPE,
|
|
||||||
xmlCatalogDefaultPrefer);
|
|
||||||
- xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
|
|
||||||
+ if (xmlDefaultCatalog != NULL) {
|
|
||||||
+ xmlDefaultCatalog->xml = xmlNewCatalogEntry(XML_CATA_CATALOG, NULL,
|
|
||||||
orig, NULL, xmlCatalogDefaultPrefer, NULL);
|
|
||||||
-
|
|
||||||
+ }
|
|
||||||
xmlRMutexUnlock(xmlCatalogMutex);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
From 74dcc10b556cc4d1088a2496f7e93f8a8040447e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 17 Aug 2020 03:24:56 +0200
|
|
||||||
Subject: [PATCH] Remove dead code in xinclude.c
|
|
||||||
|
|
||||||
'doc' is checked for NULL in xmlXIncludeLoadDoc, so several code
|
|
||||||
paths can be eliminated.
|
|
||||||
---
|
|
||||||
xinclude.c | 43 ++++++-------------------------------------
|
|
||||||
1 file changed, 6 insertions(+), 37 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 2423a93..36bdfae 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -59,7 +59,6 @@ struct _xmlXIncludeRef {
|
|
||||||
xmlNodePtr inc; /* the included copy */
|
|
||||||
int xml; /* xml or txt */
|
|
||||||
int count; /* how many refs use that specific doc */
|
|
||||||
- xmlXPathObjectPtr xptr; /* the xpointer if needed */
|
|
||||||
int skip; /* skip in case of errors */
|
|
||||||
int fallback; /* fallback was loaded */
|
|
||||||
};
|
|
||||||
@@ -211,8 +210,6 @@ xmlXIncludeFreeRef(xmlXIncludeRefPtr ref) {
|
|
||||||
xmlFree(ref->URI);
|
|
||||||
if (ref->fragment != NULL)
|
|
||||||
xmlFree(ref->fragment);
|
|
||||||
- if (ref->xptr != NULL)
|
|
||||||
- xmlXPathFreeObject(ref->xptr);
|
|
||||||
xmlFree(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1557,15 +1554,8 @@ loaded:
|
|
||||||
/*
|
|
||||||
* Add the top children list as the replacement copy.
|
|
||||||
*/
|
|
||||||
- if (doc == NULL)
|
|
||||||
- {
|
|
||||||
- /* Hopefully a DTD declaration won't be copied from
|
|
||||||
- * the same document */
|
|
||||||
- ctxt->incTab[nr]->inc = xmlCopyNodeList(ctxt->doc->children);
|
|
||||||
- } else {
|
|
||||||
- ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
|
|
||||||
- doc, doc->children);
|
|
||||||
- }
|
|
||||||
+ ctxt->incTab[nr]->inc = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
|
|
||||||
+ doc, doc->children);
|
|
||||||
}
|
|
||||||
#ifdef LIBXML_XPTR_ENABLED
|
|
||||||
else {
|
|
||||||
@@ -1577,12 +1567,7 @@ loaded:
|
|
||||||
xmlXPathContextPtr xptrctxt;
|
|
||||||
xmlNodeSetPtr set;
|
|
||||||
|
|
||||||
- if (doc == NULL) {
|
|
||||||
- xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr]->ref,
|
|
||||||
- NULL);
|
|
||||||
- } else {
|
|
||||||
- xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
|
|
||||||
- }
|
|
||||||
+ xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
|
|
||||||
if (xptrctxt == NULL) {
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
XML_XINCLUDE_XPTR_FAILED,
|
|
||||||
@@ -1686,14 +1671,9 @@ loaded:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- if (doc == NULL) {
|
|
||||||
- ctxt->incTab[nr]->xptr = xptr;
|
|
||||||
- ctxt->incTab[nr]->inc = NULL;
|
|
||||||
- } else {
|
|
||||||
- ctxt->incTab[nr]->inc =
|
|
||||||
- xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
|
|
||||||
- xmlXPathFreeObject(xptr);
|
|
||||||
- }
|
|
||||||
+ ctxt->incTab[nr]->inc =
|
|
||||||
+ xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
|
|
||||||
+ xmlXPathFreeObject(xptr);
|
|
||||||
xmlXPathFreeContext(xptrctxt);
|
|
||||||
xmlFree(fragment);
|
|
||||||
}
|
|
||||||
@@ -2212,17 +2192,6 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
- /*
|
|
||||||
- * If we stored an XPointer a late computation may be needed
|
|
||||||
- */
|
|
||||||
- if ((ctxt->incTab[nr]->inc == NULL) &&
|
|
||||||
- (ctxt->incTab[nr]->xptr != NULL)) {
|
|
||||||
- ctxt->incTab[nr]->inc =
|
|
||||||
- xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc,
|
|
||||||
- ctxt->incTab[nr]->xptr);
|
|
||||||
- xmlXPathFreeObject(ctxt->incTab[nr]->xptr);
|
|
||||||
- ctxt->incTab[nr]->xptr = NULL;
|
|
||||||
- }
|
|
||||||
list = ctxt->incTab[nr]->inc;
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
From f8329fdc234a43b858271acc75ea70881e35fcae Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Thu, 2 Jul 2020 11:51:31 +0200
|
|
||||||
Subject: [PATCH] Report error for invalid regexp quantifiers
|
|
||||||
|
|
||||||
---
|
|
||||||
xmlregexp.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/xmlregexp.c b/xmlregexp.c
|
|
||||||
index 0272dcab..687290e2 100644
|
|
||||||
--- a/xmlregexp.c
|
|
||||||
+++ b/xmlregexp.c
|
|
||||||
@@ -5268,6 +5268,9 @@ xmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt) {
|
|
||||||
cur = xmlFAParseQuantExact(ctxt);
|
|
||||||
if (cur >= 0)
|
|
||||||
min = cur;
|
|
||||||
+ else {
|
|
||||||
+ ERROR("Improper quantifier");
|
|
||||||
+ }
|
|
||||||
if (CUR == ',') {
|
|
||||||
NEXT;
|
|
||||||
if (CUR == '}')
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
From 3f18e7486d5feb8ae41911ce3c122e05641a4c3d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 11 Jul 2020 14:34:57 +0200
|
|
||||||
Subject: [PATCH] Reset HTML parser input before reporting error
|
|
||||||
|
|
||||||
Avoid use-after-free, similar to 13ba5b61. Also make sure that
|
|
||||||
xmlBufSetInputBaseCur sets valid pointers in case of buffer errors.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
|
|
||||||
diff --git a/HTMLparser.c b/HTMLparser.c
|
|
||||||
index 9b12dd1..1dea794 100644
|
|
||||||
--- a/HTMLparser.c
|
|
||||||
+++ b/HTMLparser.c
|
|
||||||
@@ -6150,12 +6150,12 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size,
|
|
||||||
int res;
|
|
||||||
|
|
||||||
res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
|
|
||||||
+ xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
|
|
||||||
if (res < 0) {
|
|
||||||
ctxt->errNo = XML_PARSER_EOF;
|
|
||||||
ctxt->disableSAX = 1;
|
|
||||||
return (XML_PARSER_EOF);
|
|
||||||
}
|
|
||||||
- xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
|
|
||||||
#ifdef DEBUG_PUSH
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "HPP: pushed %d\n", size);
|
|
||||||
#endif
|
|
||||||
diff --git a/buf.c b/buf.c
|
|
||||||
index 8ad18a1..24368d3 100644
|
|
||||||
--- a/buf.c
|
|
||||||
+++ b/buf.c
|
|
||||||
@@ -1334,8 +1334,12 @@ xmlBufGetInputBase(xmlBufPtr buf, xmlParserInputPtr input) {
|
|
||||||
int
|
|
||||||
xmlBufSetInputBaseCur(xmlBufPtr buf, xmlParserInputPtr input,
|
|
||||||
size_t base, size_t cur) {
|
|
||||||
- if ((input == NULL) || (buf == NULL) || (buf->error))
|
|
||||||
+ if (input == NULL)
|
|
||||||
+ return(-1);
|
|
||||||
+ if ((buf == NULL) || (buf->error)) {
|
|
||||||
+ input->base = input->cur = input->end = BAD_CAST "";
|
|
||||||
return(-1);
|
|
||||||
+ }
|
|
||||||
CHECK_COMPAT(buf)
|
|
||||||
input->base = &buf->content[base];
|
|
||||||
input->cur = input->base + cur;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
From 19cae17f5a2acfbd5554d145bb87cd6bf2de244f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Wed, 19 Aug 2020 13:07:28 +0200
|
|
||||||
Subject: [PATCH] Revert "Fix quadratic runtime in xi:fallback processing"
|
|
||||||
|
|
||||||
This reverts commit 27119ec33c9f6b9830efa1e0da0acfa353dfa55a.
|
|
||||||
|
|
||||||
Not copying fallback children didn't fix up namespaces and could lead
|
|
||||||
to use-after-free errors.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
xinclude.c | 23 ++++++++++++-----------
|
|
||||||
1 file changed, 12 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xinclude.c b/xinclude.c
|
|
||||||
index 3c810ca..9024535 100644
|
|
||||||
--- a/xinclude.c
|
|
||||||
+++ b/xinclude.c
|
|
||||||
@@ -1984,7 +1984,8 @@ xmlXIncludeLoadFallback(xmlXIncludeCtxtPtr ctxt, xmlNodePtr fallback, int nr) {
|
|
||||||
ret = -1;
|
|
||||||
xmlXIncludeFreeContext(newctxt);
|
|
||||||
|
|
||||||
- ctxt->incTab[nr]->inc = fallback->children;
|
|
||||||
+ ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
|
|
||||||
+ fallback->children);
|
|
||||||
} else {
|
|
||||||
ctxt->incTab[nr]->inc = NULL;
|
|
||||||
}
|
|
||||||
@@ -2240,6 +2241,12 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
if (ctxt->incTab[nr]->fallback)
|
|
||||||
xmlUnsetProp(cur, BAD_CAST "href");
|
|
||||||
cur->type = XML_XINCLUDE_START;
|
|
||||||
+ /* Remove fallback children */
|
|
||||||
+ for (child = cur->children; child != NULL; child = next) {
|
|
||||||
+ next = child->next;
|
|
||||||
+ xmlUnlinkNode(child);
|
|
||||||
+ xmlFreeNode(child);
|
|
||||||
+ }
|
|
||||||
end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
|
|
||||||
if (end == NULL) {
|
|
||||||
xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
|
|
||||||
@@ -2255,17 +2262,11 @@ xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) {
|
|
||||||
* Add the list of nodes
|
|
||||||
*/
|
|
||||||
while (list != NULL) {
|
|
||||||
- next = list->next;
|
|
||||||
- xmlAddPrevSibling(end, list);
|
|
||||||
- list = next;
|
|
||||||
- }
|
|
||||||
+ cur = list;
|
|
||||||
+ list = list->next;
|
|
||||||
|
|
||||||
- /* Remove fallback node */
|
|
||||||
- for (child = cur->children; child != NULL; child = next) {
|
|
||||||
- next = child->next;
|
|
||||||
- xmlUnlinkNode(child);
|
|
||||||
- xmlFreeNode(child);
|
|
||||||
- }
|
|
||||||
+ xmlAddPrevSibling(end, cur);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
From a6e6498fb1d11f08c394ecbf69add6cfff815db0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Tue, 2 Mar 2021 13:09:06 +0100
|
|
||||||
Subject: [PATCH] Stop checking attributes for UTF-8 validity
|
|
||||||
|
|
||||||
I can't see a reason to check attribute content for UTF-8 validity.
|
|
||||||
Other parts of the API like xmlNewText have always assumed valid UTF-8
|
|
||||||
as extra checks only slow down processing.
|
|
||||||
|
|
||||||
Besides, setting doc->encoding to "ISO-8859-1" seems pointless, and not
|
|
||||||
freeing the old encoding would cause a memory leak.
|
|
||||||
|
|
||||||
Note that this was last changed in 2008 with commit 6f8611fd which
|
|
||||||
removed unnecessary encoding/decoding steps. Setting attributes should
|
|
||||||
be even faster now.
|
|
||||||
|
|
||||||
Found by OSS-Fuzz.
|
|
||||||
---
|
|
||||||
tree.c | 12 ------------
|
|
||||||
1 file changed, 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/tree.c b/tree.c
|
|
||||||
index 617e818..17db445 100644
|
|
||||||
--- a/tree.c
|
|
||||||
+++ b/tree.c
|
|
||||||
@@ -1901,12 +1901,6 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
|
|
||||||
if (value != NULL) {
|
|
||||||
xmlNodePtr tmp;
|
|
||||||
|
|
||||||
- if(!xmlCheckUTF8(value)) {
|
|
||||||
- xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) doc,
|
|
||||||
- NULL);
|
|
||||||
- if (doc != NULL)
|
|
||||||
- doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
|
|
||||||
- }
|
|
||||||
cur->children = xmlNewDocText(doc, value);
|
|
||||||
cur->last = NULL;
|
|
||||||
tmp = cur->children;
|
|
||||||
@@ -6945,12 +6939,6 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
|
||||||
if (value != NULL) {
|
|
||||||
xmlNodePtr tmp;
|
|
||||||
|
|
||||||
- if(!xmlCheckUTF8(value)) {
|
|
||||||
- xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) node->doc,
|
|
||||||
- NULL);
|
|
||||||
- if (node->doc != NULL)
|
|
||||||
- node->doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
|
|
||||||
- }
|
|
||||||
prop->children = xmlNewDocText(node->doc, value);
|
|
||||||
prop->last = NULL;
|
|
||||||
tmp = prop->children;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
From 804c52978fef3f18b8a634280bc5cc79a390c141 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Mon, 17 Aug 2020 03:37:18 +0200
|
|
||||||
Subject: [PATCH] Stop using maxParserDepth in xpath.c
|
|
||||||
|
|
||||||
Only use a single maxDepth value.
|
|
||||||
|
|
||||||
Conflict:delete contents of fuzz/xpath.c
|
|
||||||
---
|
|
||||||
xpath.c | 9 ++++++---
|
|
||||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/xpath.c b/xpath.c
|
|
||||||
index 673482a..c018d03 100644
|
|
||||||
--- a/xpath.c
|
|
||||||
+++ b/xpath.c
|
|
||||||
@@ -6119,7 +6119,6 @@ xmlXPathNewContext(xmlDocPtr doc) {
|
|
||||||
ret->proximityPosition = -1;
|
|
||||||
|
|
||||||
ret->maxDepth = INT_MAX;
|
|
||||||
- ret->maxParserDepth = INT_MAX;
|
|
||||||
|
|
||||||
#ifdef XP_DEFAULT_CACHE_ON
|
|
||||||
if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
|
|
||||||
@@ -10948,9 +10947,13 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
|
|
||||||
xmlXPathContextPtr xpctxt = ctxt->context;
|
|
||||||
|
|
||||||
if (xpctxt != NULL) {
|
|
||||||
- if (xpctxt->depth >= xpctxt->maxParserDepth)
|
|
||||||
+ if (xpctxt->depth >= xpctxt->maxDepth)
|
|
||||||
XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
|
|
||||||
- xpctxt->depth += 1;
|
|
||||||
+ /*
|
|
||||||
+ * Parsing a single '(' pushes about 10 functions on the call stack
|
|
||||||
+ * before recursing!
|
|
||||||
+ */
|
|
||||||
+ xpctxt->depth += 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlXPathCompAndExpr(ctxt);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
From 3c8a3e9922cb1203ab5998ec542ce1e4c7fd085a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ranier Vilela <ranier_gyn@hotmail.com>
|
|
||||||
Date: Thu, 7 Nov 2019 12:59:10 +0000
|
|
||||||
Subject: [PATCH] Use random seed in xmlDictComputeFastKey
|
|
||||||
|
|
||||||
xmlDictComputeFastKey is only used for small tables, so this shouldn't
|
|
||||||
be a security problem.
|
|
||||||
---
|
|
||||||
dict.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/dict.c b/dict.c
|
|
||||||
index 336e046..26ce516 100644
|
|
||||||
--- a/dict.c
|
|
||||||
+++ b/dict.c
|
|
||||||
@@ -452,7 +452,7 @@ xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
|
|
||||||
unsigned long value = seed;
|
|
||||||
|
|
||||||
if (name == NULL) return(0);
|
|
||||||
- value = *name;
|
|
||||||
+ value += *name;
|
|
||||||
value <<= 5;
|
|
||||||
if (namelen > 10) {
|
|
||||||
value += name[namelen - 1];
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,306 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
From babe75030c7f64a37826bb3342317134568bef61 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
|
||||||
Date: Sat, 1 May 2021 16:53:33 +0200
|
|
||||||
Subject: [PATCH] Propagate error in xmlParseElementChildrenContentDeclPriv
|
|
||||||
|
|
||||||
Check return value of recursive calls to
|
|
||||||
xmlParseElementChildrenContentDeclPriv and return immediately in case
|
|
||||||
of errors. Otherwise, struct xmlElementContent could contain unexpected
|
|
||||||
null pointers, leading to a null deref when post-validating documents
|
|
||||||
which aren't well-formed and parsed in recovery mode.
|
|
||||||
|
|
||||||
Fixes #243.
|
|
||||||
|
|
||||||
Reference:https://github.com/GNOME/libxml2/commit/babe75030c7f64a37826bb3342317134568bef61
|
|
||||||
Conflict:NA
|
|
||||||
|
|
||||||
---
|
|
||||||
parser.c | 7 +++++++
|
|
||||||
1 file changed, 7 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index b42e604..73c27ed 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -6208,6 +6208,8 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
|
|
||||||
SKIP_BLANKS;
|
|
||||||
cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
|
|
||||||
depth + 1);
|
|
||||||
+ if (cur == NULL)
|
|
||||||
+ return(NULL);
|
|
||||||
SKIP_BLANKS;
|
|
||||||
GROW;
|
|
||||||
} else {
|
|
||||||
@@ -6341,6 +6343,11 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
|
|
||||||
SKIP_BLANKS;
|
|
||||||
last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
|
|
||||||
depth + 1);
|
|
||||||
+ if (last == NULL) {
|
|
||||||
+ if (ret != NULL)
|
|
||||||
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
|
|
||||||
+ return(NULL);
|
|
||||||
+ }
|
|
||||||
SKIP_BLANKS;
|
|
||||||
} else {
|
|
||||||
elem = xmlParseName(ctxt);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,286 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
From b7520f8a61b48a9f265f711fa7a0bebf2175bed7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|
||||||
Date: Tue, 20 Aug 2019 16:33:06 +0800
|
|
||||||
Subject: [PATCH] Fix memory leak in xmlSchemaValidateStream
|
|
||||||
|
|
||||||
When ctxt->schema is NULL, xmlSchemaSAXPlug->xmlSchemaPreRun
|
|
||||||
alloc a new schema for ctxt->schema and set vctxt->xsiAssemble
|
|
||||||
to 1. Then xmlSchemaVStart->xmlSchemaPreRun initialize
|
|
||||||
vctxt->xsiAssemble to 0 again which cause the alloced schema
|
|
||||||
can not be freed anymore.
|
|
||||||
|
|
||||||
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|
||||||
---
|
|
||||||
xmlschemas.c | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmlschemas.c b/xmlschemas.c
|
|
||||||
index 019988a..005d8f1 100644
|
|
||||||
--- a/xmlschemas.c
|
|
||||||
+++ b/xmlschemas.c
|
|
||||||
@@ -28111,7 +28111,6 @@ xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
|
|
||||||
vctxt->nberrors = 0;
|
|
||||||
vctxt->depth = -1;
|
|
||||||
vctxt->skipDepth = -1;
|
|
||||||
- vctxt->xsiAssemble = 0;
|
|
||||||
vctxt->hasKeyrefs = 0;
|
|
||||||
#ifdef ENABLE_IDC_NODE_TABLES_TEST
|
|
||||||
vctxt->createIDCNodeTables = 1;
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,33 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,306 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
From ef4906c251b39a292c1e411e7b72d270768949c0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pieter van Oostrum <pieter@vanoostrum.org>
|
|
||||||
Date: Tue, 31 Dec 2019 21:49:58 +0100
|
|
||||||
Subject: [PATCH 1/1] Updated python/tests/tstLastError.py
|
|
||||||
|
|
||||||
libxml2.registerErrorHandler(None,None):
|
|
||||||
None is not acceptable as first argument
|
|
||||||
failUnlessEqual replaced by assertEqual
|
|
||||||
---
|
|
||||||
python/tests/tstLastError.py | 17 ++++++++++-------
|
|
||||||
1 file changed, 10 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/python/tests/tstLastError.py b/python/tests/tstLastError.py
|
|
||||||
index 81d0acc4..1758a9fb 100755
|
|
||||||
--- a/python/tests/tstLastError.py
|
|
||||||
+++ b/python/tests/tstLastError.py
|
|
||||||
@@ -25,7 +25,10 @@ class TestCase(unittest.TestCase):
|
|
||||||
when the exception is raised, check the libxml2.lastError for
|
|
||||||
expected values."""
|
|
||||||
# disable the default error handler
|
|
||||||
- libxml2.registerErrorHandler(None,None)
|
|
||||||
+ def noerr(ctx, str):
|
|
||||||
+ pass
|
|
||||||
+ # None is not acceptable as function.
|
|
||||||
+ libxml2.registerErrorHandler(noerr,None)
|
|
||||||
try:
|
|
||||||
f(*args)
|
|
||||||
except exc:
|
|
||||||
@@ -40,12 +43,12 @@ class TestCase(unittest.TestCase):
|
|
||||||
print("file =",e.file())
|
|
||||||
print("line =",e.line())
|
|
||||||
print()
|
|
||||||
- self.failUnlessEqual(domain,e.domain())
|
|
||||||
- self.failUnlessEqual(code,e.code())
|
|
||||||
- self.failUnlessEqual(message,e.message())
|
|
||||||
- self.failUnlessEqual(level,e.level())
|
|
||||||
- self.failUnlessEqual(file,e.file())
|
|
||||||
- self.failUnlessEqual(line,e.line())
|
|
||||||
+ self.assertEqual(domain,e.domain())
|
|
||||||
+ self.assertEqual(code,e.code())
|
|
||||||
+ self.assertEqual(message,e.message())
|
|
||||||
+ self.assertEqual(level,e.level())
|
|
||||||
+ self.assertEqual(file,e.file())
|
|
||||||
+ self.assertEqual(line,e.line())
|
|
||||||
else:
|
|
||||||
self.fail("exception %s should have been raised" % exc)
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
From 73060457de03c0dada603bdc6c6e1fc9b08fc94b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|
||||||
Date: Thu, 12 Dec 2019 17:30:55 +0800
|
|
||||||
Subject: [PATCH] Fix infinite loop in xmlStringLenDecodeEntities
|
|
||||||
|
|
||||||
When ctxt->instate == XML_PARSER_EOF,xmlParseStringEntityRef
|
|
||||||
return NULL which cause a infinite loop in xmlStringLenDecodeEntities
|
|
||||||
|
|
||||||
Found with libFuzzer.
|
|
||||||
|
|
||||||
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|
||||||
---
|
|
||||||
parser.c | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/parser.c b/parser.c
|
|
||||||
index 4696f916..3e09b3e9 100644
|
|
||||||
--- a/parser.c
|
|
||||||
+++ b/parser.c
|
|
||||||
@@ -2786,7 +2786,8 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|
||||||
else
|
|
||||||
c = 0;
|
|
||||||
while ((c != 0) && (c != end) && /* non input consuming loop */
|
|
||||||
- (c != end2) && (c != end3)) {
|
|
||||||
+ (c != end2) && (c != end3) &&
|
|
||||||
+ (ctxt->instate != XML_PARSER_EOF)) {
|
|
||||||
|
|
||||||
if (c == 0) break;
|
|
||||||
if ((c == '&') && (str[1] == '#')) {
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
|
|
||||||
Binary file not shown.
BIN
libxml2-2.9.12.tar.gz
Normal file
BIN
libxml2-2.9.12.tar.gz
Normal file
Binary file not shown.
@ -1,24 +1,18 @@
|
|||||||
*** XML/xml2-config.in.orig 2006-06-06 16:35:56.000000000 +0200
|
diff --git a/xml2-config.in b/xml2-config.in
|
||||||
--- XML/xml2-config.in 2006-06-06 16:36:24.000000000 +0200
|
index 5863ffa..47f205e 100644
|
||||||
***************
|
--- a/xml2-config.in
|
||||||
*** 3,9 ****
|
+++ b/xml2-config.in
|
||||||
prefix=@prefix@
|
@@ -3,7 +3,12 @@
|
||||||
exec_prefix=@exec_prefix@
|
prefix=@prefix@
|
||||||
includedir=@includedir@
|
exec_prefix=@exec_prefix@
|
||||||
! libdir=@libdir@
|
includedir=@includedir@
|
||||||
|
-libdir=@libdir@
|
||||||
|
+if [ "`ldd /bin/sh | grep lib64`" = "" ]
|
||||||
|
+then
|
||||||
|
+ libdir=${exec_prefix}/lib
|
||||||
|
+else
|
||||||
|
+ libdir=${exec_prefix}/lib64
|
||||||
|
+fi
|
||||||
|
cflags=
|
||||||
|
libs=
|
||||||
|
|
||||||
usage()
|
|
||||||
{
|
|
||||||
--- 3,14 ----
|
|
||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
includedir=@includedir@
|
|
||||||
! if [ "`ldd /bin/sh | grep lib64`" = "" ]
|
|
||||||
! then
|
|
||||||
! libdir=${exec_prefix}/lib
|
|
||||||
! else
|
|
||||||
! libdir=${exec_prefix}/lib64
|
|
||||||
! fi
|
|
||||||
|
|
||||||
usage()
|
|
||||||
{
|
|
||||||
|
|||||||
110
libxml2.spec
110
libxml2.spec
@ -1,107 +1,15 @@
|
|||||||
Summary: Library providing XML and HTML support
|
Summary: Library providing XML and HTML support
|
||||||
Name: libxml2
|
Name: libxml2
|
||||||
Version: 2.9.10
|
Version: 2.9.12
|
||||||
Release: 19
|
Release: 1
|
||||||
License: MIT
|
License: MIT
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
|
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
|
||||||
Patch0: libxml2-multilib.patch
|
|
||||||
# upstream patches
|
|
||||||
Patch1: backport-Fix-memory-leak-in-xmlSchemaValidateStream.patch
|
|
||||||
Patch2: backport-fix-infinite-loop-in-xmlStringLenDecodeEntities.patch
|
|
||||||
Patch3: backport-Updated-python-tests-tstLastError.py.patch
|
|
||||||
Patch4: Null-pointer-handling-in-catalog-c.patch
|
|
||||||
Patch5: Fix-overflow-handling-in-xmlBufBackToBuffer.patch
|
|
||||||
Patch6: Fix-memory-leak-in-error-path-of-XPath-expr-parser.patch
|
|
||||||
Patch7: Fix-memory-leaks-of-encoding-handlers-in-xmlsave-c.patch
|
|
||||||
Patch8: Use-random-seed-in-xmlDictComputeFastKey.patch
|
|
||||||
Patch9: Fix-more-memory-leaks-in-error-paths-of-XPath-parser.patch
|
|
||||||
Patch10: Fix-freeing-of-nested-documents.patch
|
|
||||||
Patch11: Fix-overflow-check-in-xmlNodeDump.patch
|
|
||||||
Patch12: Check-for-overflow-when-allocating-two-dimensional-arrays.patch
|
|
||||||
Patch13: Fix-integer-overflow-in-xmlBufferResize.patch
|
|
||||||
Patch14: Fix-copying-of-entities-in-xmlParseReference.patch
|
|
||||||
Patch15: Copy-some-XMLReader-option-flags-to-parser-context.patch
|
|
||||||
Patch16: Merge-code-paths-loading-external-entities.patch
|
|
||||||
Patch17: Don-t-load-external-entity-from-xmlSAX2GetEntity.patch
|
|
||||||
Patch18: Fix-use-after-free-with-validating-reader.patch
|
|
||||||
Patch19: Never-expand-parameter-entities-in-text-declaration.patch
|
|
||||||
Patch20: Fix-integer-overflow-in-xmlFAParseQuantExact.patch
|
|
||||||
Patch21: Report-error-for-invalid-regexp-quantifiers.patch
|
|
||||||
Patch22: Add-regexp-regression-tests.patch
|
|
||||||
Patch23: Limit-regexp-nesting-depth.patch
|
|
||||||
Patch24: Fix-exponential-runtime-in-xmlFARecurseDeterminism.patch
|
|
||||||
Patch25: Fix-more-quadratic-runtime-issues-in-HTML-push-parse.patch
|
|
||||||
Patch26: Reset-HTML-parser-input-before-reporting-error.patch
|
|
||||||
Patch27: Fix-memory-leak-when-shared-libxml-dll-is-unloaded.patch
|
|
||||||
Patch28: Fix-memory-leak-in-xmlXIncludeLoadDoc-error-path.patch
|
|
||||||
Patch29: Fix-undefined-behavior-in-xmlXPathTryStreamCompile.patch
|
|
||||||
Patch30: Fix-integer-overflow-in-htmlParseCharRef.patch
|
|
||||||
Patch31: Fix-another-memory-leak-in-xmlSchemaValAtomicType.patch
|
|
||||||
Patch32: Fix-integer-overflow-when-parsing-min-max-Occurs.patch
|
|
||||||
Patch33: Fix-integer-overflow-in-_xmlSchemaParseGYear.patch
|
|
||||||
Patch34: Fix-quadratic-runtime-when-parsing-HTML-script-conte.patch
|
|
||||||
Patch35: Fix-UTF-8-decoder-in-HTML-parser.patch
|
|
||||||
Patch36: Fix-integer-overflow-when-comparing-schema-dates.patch
|
|
||||||
Patch37: Fix-memory-leak-in-xmlXIncludeIncludeNode-error-path.patch
|
|
||||||
Patch38: Don-t-recurse-into-xi-include-children-in-xmlXInclud.patch
|
|
||||||
Patch39: Don-t-process-siblings-of-root-in-xmlXIncludeProcess.patch
|
|
||||||
Patch40: Fix-exponential-runtime-and-memory-in-xi-fallback-pr.patch
|
|
||||||
Patch41: Fuzz-XInclude-engine.patch
|
|
||||||
Patch42: Fix-memory-leak-in-runtest.c.patch
|
|
||||||
Patch43: Fix-XInclude-regression-introduced-with-recent-commi.patch
|
|
||||||
Patch44: Fix-memory-leak-in-xmlXIncludeAddNode-error-paths.patch
|
|
||||||
Patch45: Fix-double-free-in-XML-reader-with-XIncludes.patch
|
|
||||||
Patch46: Limit-size-of-free-lists-in-XML-reader-when-fuzzing.patch
|
|
||||||
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
|
Patch0: libxml2-multilib.patch
|
||||||
Patch51: backport-Fix-timeout-when-handling-recursive-entities.patch
|
Patch1: Fix-XPath-recursion-limit.patch
|
||||||
Patch52: backport-Avoid-call-stack-overflow-with-XML-reader-and-recurs.patch
|
Patch2: Fix-Null-deref-in-xmlSchemaGetComponentTargetNs.patch
|
||||||
Patch53: backport-Reset-HTML-parser-input-before-reporting-encoding-er.patch
|
Patch3: Fix-memleaks-in-xmlXIncludeProcessFlags.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
|
|
||||||
|
|
||||||
Patch61: backport-CVE-2021-3537.patch
|
|
||||||
Patch62: CVE-2021-3517.patch
|
|
||||||
Patch63: CVE-2021-3518.patch
|
|
||||||
Patch64: Fix-handling-of-unexpected-EOF-in-xmlParseContent.patch
|
|
||||||
Patch65: Fix-line-numbers-in-error-messages-for-mismatched-ta.patch
|
|
||||||
Patch66: Fix-null-deref-in-legacy-SAX1-parser.patch
|
|
||||||
Patch67: update-for-xsd-language-type-check.patch
|
|
||||||
Patch68: Fix-dangling-pointer-with-xmllint-dropdtd.patch
|
|
||||||
Patch69: Fix-duplicate-xmlStrEqual-calls-in-htmlParseEndTag.patch
|
|
||||||
Patch70: Fix-exponential-behavior-with-recursive-entities.patch
|
|
||||||
Patch71: Fix-quadratic-behavior-when-looking-up-xml-attribute.patch
|
|
||||||
Patch72: Fix-use-after-free-with-xmllint-html-push.patch
|
|
||||||
Patch73: Fix-xmlGetNodePath-with-invalid-node-types.patch
|
|
||||||
Patch74: Stop-checking-attributes-for-UTF-8-validity.patch
|
|
||||||
Patch75: CVE-2021-3541.patch
|
|
||||||
|
|
||||||
Patch76: Fix-corner-case-with-empty-xi-fallback.patch
|
|
||||||
Patch77: Fix-quadratic-runtime-in-xi-fallback-processing.patch
|
|
||||||
Patch78: Fix-error-reporting-with-xi-fallback.patch
|
|
||||||
Patch79: Revert-Fix-quadratic-runtime-in-xi-fallback-processi.patch
|
|
||||||
Patch80: Remove-dead-code-in-xinclude.c.patch
|
|
||||||
Patch81: Fix-regression-introduced-with-commit-74dcc10b.patch
|
|
||||||
Patch82: Fix-regression-introduced-with-commit-d88df4b.patch
|
|
||||||
Patch83: Make-xmlNodeDumpOutputInternal-non-recursive.patch
|
|
||||||
Patch84: Don-t-add-formatting-newlines-to-XInclude-nodes.patch
|
|
||||||
Patch85: Make-htmlNodeDumpFormatOutput-non-recursive.patch
|
|
||||||
Patch86: Fix-memory-leaks-in-XPointer-string-range-function.patch
|
|
||||||
Patch87: Fix-null-pointer-deref-in-xmlXPtrRangeInsideFunction.patch
|
|
||||||
Patch88: Stop-using-maxParserDepth-in-xpath.c.patch
|
|
||||||
Patch89: Hardcode-maximum-XPath-recursion-depth.patch
|
|
||||||
Patch90: Fix-XPath-recursion-limit.patch
|
|
||||||
Patch91: Fix-Null-deref-in-xmlSchemaGetComponentTargetNs.patch
|
|
||||||
Patch92: Fix-memleaks-in-xmlXIncludeProcessFlags.patch
|
|
||||||
|
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
BuildRoot: %{_tmppath}/%{name}-%{version}-root
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
@ -262,6 +170,12 @@ rm -fr %{buildroot}
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Nov 10 2021 Zhipeng Xie <xiezhipeng1@huawei.com> - 2.9.12-1
|
||||||
|
- Type:enhancement
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:upgrade to upstream v2.9.12
|
||||||
|
|
||||||
* Tue Nov 9 2021 panxiaohe <panxiaohe@huawei.com> - 2.9.10-19
|
* Tue Nov 9 2021 panxiaohe <panxiaohe@huawei.com> - 2.9.10-19
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- ID:NA
|
- ID:NA
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
From 33468d7e7080e384ad703a2369003cf18b2ad91d Mon Sep 17 00:00:00 2001
|
|
||||||
From: PaulHiggs <paul_higgs@hotmail.com>
|
|
||||||
Date: Mon, 3 May 2021 16:09:44 +0100
|
|
||||||
Subject: [PATCH] update for xsd:language type check
|
|
||||||
|
|
||||||
Fixes #242.
|
|
||||||
---
|
|
||||||
xmlschemastypes.c | 41 ++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
1 file changed, 40 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
|
|
||||||
index 07b5fd7..9c2dff0 100644
|
|
||||||
--- a/xmlschemastypes.c
|
|
||||||
+++ b/xmlschemastypes.c
|
|
||||||
@@ -2187,6 +2187,44 @@ xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * xmlSchemaCheckLanguageType
|
|
||||||
+ * @value: the value to check
|
|
||||||
+ *
|
|
||||||
+ * Check that a value conforms to the lexical space of the language datatype.
|
|
||||||
+ * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
|
|
||||||
+ *
|
|
||||||
+ * Returns 1 if this validates, 0 otherwise.
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+xmlSchemaCheckLanguageType(const xmlChar* value) {
|
|
||||||
+ int first = 1, len = 0;
|
|
||||||
+ const xmlChar* cur = value;
|
|
||||||
+
|
|
||||||
+ if (value == NULL)
|
|
||||||
+ return (0);
|
|
||||||
+
|
|
||||||
+ while (cur[0] != 0) {
|
|
||||||
+ if (!( ((cur[0] >= 'a') && (cur[0] <= 'z')) || ((cur[0] >= 'A') && (cur[0] <= 'Z'))
|
|
||||||
+ || (cur[0] == '-')
|
|
||||||
+ || ((first == 0) && (xmlIsDigit_ch(cur[0]))) ))
|
|
||||||
+ return (0);
|
|
||||||
+ if (cur[0] == '-') {
|
|
||||||
+ if ((len < 1) || (len > 8))
|
|
||||||
+ return (0);
|
|
||||||
+ len = 0;
|
|
||||||
+ first = 0;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ len++;
|
|
||||||
+ cur++;
|
|
||||||
+ }
|
|
||||||
+ if ((len < 1) || (len > 8))
|
|
||||||
+ return (0);
|
|
||||||
+
|
|
||||||
+ return (1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* xmlSchemaValAtomicType:
|
|
||||||
* @type: the predefined type
|
|
||||||
@@ -2704,7 +2742,8 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
|
||||||
if (norm != NULL)
|
|
||||||
value = norm;
|
|
||||||
}
|
|
||||||
- if (xmlCheckLanguageID(value) == 1) {
|
|
||||||
+
|
|
||||||
+ if (xmlSchemaCheckLanguageType(value) == 1) {
|
|
||||||
if (val != NULL) {
|
|
||||||
v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
|
|
||||||
if (v != NULL) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user