!9 openEuler-libxml2

Merge pull request !9 from Liquor/master
This commit is contained in:
openeuler-ci-bot 2020-08-06 17:09:51 +08:00 committed by Gitee
commit c970c95d53
48 changed files with 188 additions and 3951 deletions

View File

@ -1,61 +0,0 @@
From 7abec671473b837f99181442d59edd0cc2ee01d1 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 15 Mar 2018 19:33:52 +0100
Subject: [PATCH 01/13] NaN and Inf fixes for pre-C99 compilers
On some pre-C99 compilers, the NAN and INFINITY macros don't expand to
constant expressions.
Some MSVC versions complain about floating point division by zero in
constants.
Thanks to Fabrice Manfroi for the report.
---
xpath.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/xpath.c b/xpath.c
index f4406967..89fab588 100644
--- a/xpath.c
+++ b/xpath.c
@@ -477,27 +477,28 @@ int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
* *
************************************************************************/
-#ifndef NAN
-#define NAN (0.0 / 0.0)
+#ifndef INFINITY
+#define INFINITY (DBL_MAX * DBL_MAX)
#endif
-#ifndef INFINITY
-#define INFINITY HUGE_VAL
+#ifndef NAN
+#define NAN (INFINITY / INFINITY)
#endif
-double xmlXPathNAN = NAN;
-double xmlXPathPINF = INFINITY;
-double xmlXPathNINF = -INFINITY;
+double xmlXPathNAN;
+double xmlXPathPINF;
+double xmlXPathNINF;
/**
* xmlXPathInit:
*
* Initialize the XPath environment
- *
- * Does nothing but must be kept as public function.
*/
void
xmlXPathInit(void) {
+ xmlXPathNAN = NAN;
+ xmlXPathPINF = INFINITY;
+ xmlXPathNINF = -INFINITY;
}
/**
--
2.18.0

View File

@ -1,67 +0,0 @@
From 7a1bd7f6497ac33a9023d556f6f47a48f01deac0 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 17 Mar 2018 00:03:24 +0100
Subject: [PATCH 02/13] Revert "Change calls to xmlCharEncInput to set flush
false"
This reverts commit 6e6ae5daa6cd9640c9a83c1070896273e9b30d14 which
broke decoding of larger documents with ICU.
See https://bugs.chromium.org/p/chromium/issues/detail?id=820163
---
HTMLparser.c | 2 +-
parserInternals.c | 2 +-
xmlIO.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 9adeb174..7e243e60 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -3635,7 +3635,7 @@ htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) {
*/
processed = ctxt->input->cur - ctxt->input->base;
xmlBufShrink(ctxt->input->buf->buffer, processed);
- nbchars = xmlCharEncInput(ctxt->input->buf, 0);
+ nbchars = xmlCharEncInput(ctxt->input->buf, 1);
if (nbchars < 0) {
htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
"htmlCheckEncoding: encoder error\n",
diff --git a/parserInternals.c b/parserInternals.c
index 8c0cd57a..09876ab4 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -1214,7 +1214,7 @@ xmlSwitchInputEncodingInt(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
/*
* convert as much as possible of the buffer
*/
- nbchars = xmlCharEncInput(input->buf, 0);
+ nbchars = xmlCharEncInput(input->buf, 1);
} else {
/*
* convert just enough to get
diff --git a/xmlIO.c b/xmlIO.c
index 82543477..f61dd05a 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -3157,7 +3157,7 @@ xmlParserInputBufferPush(xmlParserInputBufferPtr in,
* convert as much as possible to the parser reading buffer.
*/
use = xmlBufUse(in->raw);
- nbchars = xmlCharEncInput(in, 0);
+ nbchars = xmlCharEncInput(in, 1);
if (nbchars < 0) {
xmlIOErr(XML_IO_ENCODER, NULL);
in->error = XML_IO_ENCODER;
@@ -3273,7 +3273,7 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
* convert as much as possible to the parser reading buffer.
*/
use = xmlBufUse(in->raw);
- nbchars = xmlCharEncInput(in, 0);
+ nbchars = xmlCharEncInput(in, 1);
if (nbchars < 0) {
xmlIOErr(XML_IO_ENCODER, NULL);
in->error = XML_IO_ENCODER;
--
2.18.0

View File

@ -1,29 +0,0 @@
From ebe12882ee7e14fa6463bb07d7de5f5388f09573 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 16 Apr 2018 18:18:11 +0200
Subject: [PATCH 03/13] Fix inconsistency in xmlXPathIsInf
We don't use HUGE_VAL for INFINITY after the most recent fix.
---
xpath.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xpath.c b/xpath.c
index 89fab588..bd093643 100644
--- a/xpath.c
+++ b/xpath.c
@@ -527,9 +527,9 @@ xmlXPathIsInf(double val) {
#ifdef isinf
return isinf(val) ? (val > 0 ? 1 : -1) : 0;
#else
- if (val >= HUGE_VAL)
+ if (val >= INFINITY)
return 1;
- if (val <= -HUGE_VAL)
+ if (val <= -INFINITY)
return -1;
return 0;
#endif
--
2.18.0

View File

@ -1,104 +0,0 @@
From e22a83b1d095dac25ce05e1a2d9f263f41d11c68 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 25 May 2017 01:18:36 +0200
Subject: [PATCH 04/13] Stop using XPATH_OP_RESET
It only sets the context node to NULL which doesn't seem useful and can
even cause bugs like bug #795299:
https://bugzilla.gnome.org/show_bug.cgi?id=795299
---
xpath.c | 37 +++----------------------------------
1 file changed, 3 insertions(+), 34 deletions(-)
diff --git a/xpath.c b/xpath.c
index bd093643..601763ee 100644
--- a/xpath.c
+++ b/xpath.c
@@ -868,15 +868,14 @@ typedef enum {
XPATH_OP_UNION,
XPATH_OP_ROOT,
XPATH_OP_NODE,
- XPATH_OP_RESET, /* 10 */
XPATH_OP_COLLECT,
- XPATH_OP_VALUE, /* 12 */
+ XPATH_OP_VALUE, /* 11 */
XPATH_OP_VARIABLE,
XPATH_OP_FUNCTION,
XPATH_OP_ARG,
XPATH_OP_PREDICATE,
- XPATH_OP_FILTER, /* 17 */
- XPATH_OP_SORT /* 18 */
+ XPATH_OP_FILTER, /* 16 */
+ XPATH_OP_SORT /* 17 */
#ifdef LIBXML_XPTR_ENABLED
,XPATH_OP_RANGETO
#endif
@@ -1526,8 +1525,6 @@ xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
fprintf(output, "ROOT"); break;
case XPATH_OP_NODE:
fprintf(output, "NODE"); break;
- case XPATH_OP_RESET:
- fprintf(output, "RESET"); break;
case XPATH_OP_SORT:
fprintf(output, "SORT"); break;
case XPATH_OP_COLLECT: {
@@ -10735,7 +10732,6 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
- PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
xmlXPathCompRelativeLocationPath(ctxt);
} else if (CUR == '/') {
@@ -12779,15 +12775,6 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node));
return (total);
- case XPATH_OP_RESET:
- if (op->ch1 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- CHECK_ERROR0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- CHECK_ERROR0;
- ctxt->context->node = NULL;
- return (total);
case XPATH_OP_COLLECT:{
if (op->ch1 == -1)
return (total);
@@ -12918,15 +12905,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node));
return (total);
- case XPATH_OP_RESET:
- if (op->ch1 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- CHECK_ERROR0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- CHECK_ERROR0;
- ctxt->context->node = NULL;
- return (total);
case XPATH_OP_COLLECT:{
if (op->ch1 == -1)
return (0);
@@ -13457,15 +13435,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
ctxt->context->node));
return (total);
- case XPATH_OP_RESET:
- if (op->ch1 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- CHECK_ERROR0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- CHECK_ERROR0;
- ctxt->context->node = NULL;
- return (total);
case XPATH_OP_COLLECT:{
if (op->ch1 == -1)
return (total);
--
2.18.0

View File

@ -1,27 +0,0 @@
From 938835e763277684274ac31afc08fc40fa419aae Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 25 May 2017 01:21:57 +0200
Subject: [PATCH 05/13] Don't change context node in xmlXPathRoot
---
xpath.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/xpath.c b/xpath.c
index 601763ee..1e98ddc2 100644
--- a/xpath.c
+++ b/xpath.c
@@ -8477,9 +8477,8 @@ void
xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
if ((ctxt == NULL) || (ctxt->context == NULL))
return;
- ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt->context,
- ctxt->context->node));
+ (xmlNodePtr) ctxt->context->doc));
}
/************************************************************************
--
2.18.0

View File

@ -1,189 +0,0 @@
From 029d0e960c02d83111acb5ab057ee055821943f7 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 25 May 2017 01:28:27 +0200
Subject: [PATCH 06/13] Avoid unnecessary backups of the context node
---
xpath.c | 42 ------------------------------------------
1 file changed, 42 deletions(-)
diff --git a/xpath.c b/xpath.c
index 1e98ddc2..b1bd7e07 100644
--- a/xpath.c
+++ b/xpath.c
@@ -12829,8 +12829,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
int total = 0, cur;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr arg1, arg2;
- xmlNodePtr bak;
- xmlDocPtr bakd;
int pp;
int cs;
@@ -12840,8 +12838,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
case XPATH_OP_END:
return (0);
case XPATH_OP_UNION:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total =
@@ -12861,8 +12857,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
nodesetval->nodeNr -
1];
}
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
cur =
@@ -13244,8 +13238,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
int equal, ret;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr arg1, arg2;
- xmlNodePtr bak;
- xmlDocPtr bakd;
int pp;
int cs;
@@ -13255,8 +13247,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
case XPATH_OP_END:
return (0);
case XPATH_OP_AND:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
@@ -13265,8 +13255,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
return (total);
arg2 = valuePop(ctxt);
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13281,8 +13269,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_OR:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
@@ -13291,8 +13277,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
return (total);
arg2 = valuePop(ctxt);
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13307,14 +13291,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_EQUAL:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13326,14 +13306,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal));
return (total);
case XPATH_OP_CMP:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13342,15 +13318,11 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
return (total);
case XPATH_OP_PLUS:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
if (op->ch2 != -1) {
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13368,14 +13340,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
}
return (total);
case XPATH_OP_MULT:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13388,14 +13356,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathModValues(ctxt);
return (total);
case XPATH_OP_UNION:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
ctxt->context->proximityPosition = pp;
ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
@@ -13552,24 +13516,18 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
return (total);
}
case XPATH_OP_ARG:
- bakd = ctxt->context->doc;
- bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
if (op->ch1 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
ctxt->context->contextSize = cs;
ctxt->context->proximityPosition = pp;
- ctxt->context->node = bak;
- ctxt->context->doc = bakd;
CHECK_ERROR0;
}
if (op->ch2 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
ctxt->context->contextSize = cs;
ctxt->context->proximityPosition = pp;
- ctxt->context->node = bak;
- ctxt->context->doc = bakd;
CHECK_ERROR0;
}
return (total);
--
2.18.0

View File

@ -1,378 +0,0 @@
From 665df41dcc6c4c3a609907c979b6c16472593d0d Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 16 Apr 2018 19:37:34 +0200
Subject: [PATCH 07/13] Simplify and harden nodeset filtering
If a nodeset to be filtered is empty, it can be returned without popping
it from the stack.
Make sure to restore the context node in all error paths and never set
it to NULL.
Save and restore the context node in RANGETO operations.
---
xpath.c | 152 +++++++++++++++-----------------------------------------
1 file changed, 41 insertions(+), 111 deletions(-)
diff --git a/xpath.c b/xpath.c
index b1bd7e07..4b9faaf6 100644
--- a/xpath.c
+++ b/xpath.c
@@ -12993,7 +12993,6 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
return (total);
#ifdef LIBXML_XPTR_ENABLED
- oldnode = ctxt->context->node;
/*
* Hum are we filtering the result of an XPointer expression
*/
@@ -13008,23 +13007,15 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
+
+ if ((ctxt->value->user == NULL) ||
+ (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
+ return (total);
+
obj = valuePop(ctxt);
oldlocset = obj->user;
- ctxt->context->node = NULL;
+ oldnode = ctxt->context->node;
- if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- if (op->ch2 != -1)
- total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- res = valuePop(ctxt);
- if (res != NULL) {
- xmlXPathReleaseObject(ctxt->context, res);
- }
- valuePush(ctxt, obj);
- CHECK_ERROR0;
- return (total);
- }
newlocset = xmlXPtrLocationSetCreate(NULL);
for (i = 0; i < oldlocset->locNr; i++) {
@@ -13049,6 +13040,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeObject(obj);
+ ctxt->context->node = oldnode;
return(0);
}
/*
@@ -13077,7 +13069,6 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
/* OLD: xmlXPathFreeObject(res); */
} else
tmp = NULL;
- ctxt->context->node = NULL;
/*
* Only put the first node in the result, then leave.
*/
@@ -13093,7 +13084,6 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
* The result is used as the new evaluation locset.
*/
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
ctxt->context->contextSize = -1;
ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
@@ -13108,32 +13098,17 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
* up a new set.
*/
CHECK_TYPE0(XPATH_NODESET);
- obj = valuePop(ctxt);
- oldset = obj->nodesetval;
- oldnode = ctxt->context->node;
- oldDoc = ctxt->context->doc;
- ctxt->context->node = NULL;
-
- if ((oldset == NULL) || (oldset->nodeNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- /* QUESTION TODO: Why was this code commented out?
- if (op->ch2 != -1)
- total +=
- xmlXPathCompOpEval(ctxt,
- &comp->steps[op->ch2]);
- CHECK_ERROR0;
- res = valuePop(ctxt);
- if (res != NULL)
- xmlXPathFreeObject(res);
- */
- valuePush(ctxt, obj);
- ctxt->context->node = oldnode;
- CHECK_ERROR0;
- } else {
+ if ((ctxt->value->nodesetval != NULL) &&
+ (ctxt->value->nodesetval->nodeNr != 0)) {
xmlNodeSetPtr newset;
xmlXPathObjectPtr tmp = NULL;
+
+ obj = valuePop(ctxt);
+ oldset = obj->nodesetval;
+ oldnode = ctxt->context->node;
+ oldDoc = ctxt->context->doc;
+
/*
* Initialize the new set.
* Also set the xpath document in case things like
@@ -13168,6 +13143,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeNodeSet(newset);
xmlXPathFreeObject(obj);
+ ctxt->context->node = oldnode;
return(0);
}
/*
@@ -13195,7 +13171,6 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
xmlXPathNodeSetClear(tmp->nodesetval, 1);
} else
tmp = NULL;
- ctxt->context->node = NULL;
/*
* Only put the first node in the result, then leave.
*/
@@ -13211,14 +13186,12 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
* The result is used as the new evaluation set.
*/
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
ctxt->context->contextSize = -1;
ctxt->context->proximityPosition = -1;
- /* may want to move this past the '}' later */
+ ctxt->context->node = oldnode;
ctxt->context->doc = oldDoc;
valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
}
- ctxt->context->node = oldnode;
return(total);
}
#endif /* XP_OPTIMIZED_FILTER_FIRST */
@@ -13641,8 +13614,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
if (ctxt->value == NULL)
return (total);
- oldnode = ctxt->context->node;
-
#ifdef LIBXML_XPTR_ENABLED
/*
* Hum are we filtering the result of an XPointer expression
@@ -13657,25 +13628,15 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
+
+ if ((ctxt->value->user == NULL) ||
+ (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
+ return (total);
+
obj = valuePop(ctxt);
oldlocset = obj->user;
- ctxt->context->node = NULL;
+ oldnode = ctxt->context->node;
- if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- if (op->ch2 != -1)
- total +=
- xmlXPathCompOpEval(ctxt,
- &comp->steps[op->ch2]);
- res = valuePop(ctxt);
- if (res != NULL) {
- xmlXPathReleaseObject(ctxt->context, res);
- }
- valuePush(ctxt, obj);
- CHECK_ERROR0;
- return (total);
- }
newlocset = xmlXPtrLocationSetCreate(NULL);
for (i = 0; i < oldlocset->locNr; i++) {
@@ -13696,6 +13657,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeObject(obj);
+ ctxt->context->node = oldnode;
return(0);
}
@@ -13720,15 +13682,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
res = valuePop(ctxt);
xmlXPathReleaseObject(ctxt->context, res);
}
-
- ctxt->context->node = NULL;
}
/*
* The result is used as the new evaluation locset.
*/
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
ctxt->context->contextSize = -1;
ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
@@ -13743,30 +13702,13 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
* up a new set.
*/
CHECK_TYPE0(XPATH_NODESET);
- obj = valuePop(ctxt);
- oldset = obj->nodesetval;
-
- oldnode = ctxt->context->node;
- oldDoc = ctxt->context->doc;
- ctxt->context->node = NULL;
- if ((oldset == NULL) || (oldset->nodeNr == 0)) {
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
-/*
- if (op->ch2 != -1)
- total +=
- xmlXPathCompOpEval(ctxt,
- &comp->steps[op->ch2]);
- CHECK_ERROR0;
- res = valuePop(ctxt);
- if (res != NULL)
- xmlXPathFreeObject(res);
-*/
- valuePush(ctxt, obj);
- ctxt->context->node = oldnode;
- CHECK_ERROR0;
- } else {
+ if ((ctxt->value->nodesetval != NULL) &&
+ (ctxt->value->nodesetval->nodeNr != 0)) {
+ obj = valuePop(ctxt);
+ oldset = obj->nodesetval;
+ oldnode = ctxt->context->node;
+ oldDoc = ctxt->context->doc;
tmp = NULL;
/*
* Initialize the new set.
@@ -13833,6 +13775,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeNodeSet(newset);
xmlXPathFreeObject(obj);
+ ctxt->context->node = oldnode;
return(0);
}
@@ -13867,7 +13810,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
*/
} else
tmp = NULL;
- ctxt->context->node = NULL;
}
if (tmp != NULL)
xmlXPathReleaseObject(ctxt->context, tmp);
@@ -13875,15 +13817,13 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
* The result is used as the new evaluation set.
*/
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
ctxt->context->contextSize = -1;
ctxt->context->proximityPosition = -1;
- /* may want to move this past the '}' later */
+ ctxt->context->node = oldnode;
ctxt->context->doc = oldDoc;
valuePush(ctxt,
xmlXPathCacheWrapNodeSet(ctxt->context, newset));
}
- ctxt->context->node = oldnode;
return (total);
}
case XPATH_OP_SORT:
@@ -13906,6 +13846,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlLocationSetPtr newlocset = NULL;
xmlLocationSetPtr oldlocset;
xmlNodeSetPtr oldset;
+ xmlNodePtr oldnode = ctxt->context->node;
int i, j;
if (op->ch1 != -1) {
@@ -13926,22 +13867,14 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
+
+ if ((ctxt->value->user == NULL) ||
+ (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
+ return (total);
+
obj = valuePop(ctxt);
oldlocset = obj->user;
- if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
- ctxt->context->node = NULL;
- ctxt->context->contextSize = 0;
- ctxt->context->proximityPosition = 0;
- total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]);
- res = valuePop(ctxt);
- if (res != NULL) {
- xmlXPathReleaseObject(ctxt->context, res);
- }
- valuePush(ctxt, obj);
- CHECK_ERROR0;
- return (total);
- }
newlocset = xmlXPtrLocationSetCreate(NULL);
for (i = 0; i < oldlocset->locNr; i++) {
@@ -13962,6 +13895,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeObject(obj);
+ ctxt->context->node = oldnode;
return(0);
}
@@ -13997,14 +13931,11 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
res = valuePop(ctxt);
xmlXPathReleaseObject(ctxt->context, res);
}
-
- ctxt->context->node = NULL;
}
} else { /* Not a location set */
CHECK_TYPE0(XPATH_NODESET);
obj = valuePop(ctxt);
oldset = obj->nodesetval;
- ctxt->context->node = NULL;
newlocset = xmlXPtrLocationSetCreate(NULL);
@@ -14028,6 +13959,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeObject(obj);
+ ctxt->context->node = oldnode;
return(0);
}
@@ -14049,8 +13981,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
res = valuePop(ctxt);
xmlXPathReleaseObject(ctxt->context, res);
}
-
- ctxt->context->node = NULL;
}
}
}
@@ -14059,7 +13989,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
* The result is used as the new evaluation set.
*/
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->node = NULL;
+ ctxt->context->node = oldnode;
ctxt->context->contextSize = -1;
ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
--
2.18.0

View File

@ -1,443 +0,0 @@
From fa33bf317aa9b455e08b211252092dd9110c49fb Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 25 May 2017 00:45:10 +0200
Subject: [PATCH 08/13] Improve restoring of context size and position
Restore context size and position where it is modified, not in
seemingly random places.
---
xpath.c | 133 ++++++++++++++++++++++----------------------------------
1 file changed, 53 insertions(+), 80 deletions(-)
diff --git a/xpath.c b/xpath.c
index 4b9faaf6..9d223977 100644
--- a/xpath.c
+++ b/xpath.c
@@ -11661,6 +11661,7 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
xmlXPathContextPtr xpctxt = ctxt->context;
xmlNodePtr contextNode, oldContextNode;
xmlDocPtr oldContextDoc;
+ int oldcs, oldpp;
int i, res, contextPos = 0, newContextSize;
xmlXPathStepOpPtr exprOp;
xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
@@ -11697,6 +11698,8 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
*/
oldContextNode = xpctxt->node;
oldContextDoc = xpctxt->doc;
+ oldcs = xpctxt->contextSize;
+ oldpp = xpctxt->proximityPosition;
/*
* Get the expression of this predicate.
*/
@@ -11783,8 +11786,8 @@ evaluation_exit:
*/
xpctxt->node = oldContextNode;
xpctxt->doc = oldContextDoc;
- xpctxt->contextSize = -1;
- xpctxt->proximityPosition = -1;
+ xpctxt->contextSize = oldcs;
+ xpctxt->proximityPosition = oldpp;
return(newContextSize);
}
return(contextSize);
@@ -11827,6 +11830,7 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
return (contextSize);
} else {
xmlDocPtr oldContextDoc;
+ int oldcs, oldpp;
int i, pos = 0, newContextSize = 0, contextPos = 0, res;
xmlXPathStepOpPtr exprOp;
xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
@@ -11847,6 +11851,8 @@ xmlXPathCompOpEvalPositionalPredicate(xmlXPathParserContextPtr ctxt,
*/
oldContextNode = xpctxt->node;
oldContextDoc = xpctxt->doc;
+ oldcs = xpctxt->contextSize;
+ oldpp = xpctxt->proximityPosition;
/*
* Get the expression of this predicate.
*/
@@ -11983,8 +11989,8 @@ evaluation_exit:
*/
xpctxt->node = oldContextNode;
xpctxt->doc = oldContextDoc;
- xpctxt->contextSize = -1;
- xpctxt->proximityPosition = -1;
+ xpctxt->contextSize = oldcs;
+ xpctxt->proximityPosition = oldpp;
return(newContextSize);
}
return(contextSize);
@@ -12829,8 +12835,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
int total = 0, cur;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr arg1, arg2;
- int pp;
- int cs;
CHECK_ERROR0;
comp = ctxt->comp;
@@ -12838,8 +12842,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
case XPATH_OP_END:
return (0);
case XPATH_OP_UNION:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total =
xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
CHECK_ERROR0;
@@ -12857,8 +12859,6 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
nodesetval->nodeNr -
1];
}
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
cur =
xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
CHECK_ERROR0;
@@ -12942,6 +12942,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
xmlNodeSetPtr oldset;
xmlNodePtr oldnode;
xmlDocPtr oldDoc;
+ int oldcs, oldpp;
int i;
CHECK_ERROR0;
@@ -13015,6 +13016,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
obj = valuePop(ctxt);
oldlocset = obj->user;
oldnode = ctxt->context->node;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
newlocset = xmlXPtrLocationSetCreate(NULL);
@@ -13039,9 +13042,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
if (op->ch2 != -1)
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- ctxt->context->node = oldnode;
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto xptr_error;
}
/*
* The result of the evaluation need to be tested to
@@ -13083,11 +13085,12 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
/*
* The result is used as the new evaluation locset.
*/
- xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+xptr_error:
+ xmlXPathReleaseObject(ctxt->context, obj);
ctxt->context->node = oldnode;
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
return (total);
}
#endif /* LIBXML_XPTR_ENABLED */
@@ -13108,6 +13111,8 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
oldset = obj->nodesetval;
oldnode = ctxt->context->node;
oldDoc = ctxt->context->doc;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
/*
* Initialize the new set.
@@ -13142,9 +13147,7 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeNodeSet(newset);
- xmlXPathFreeObject(obj);
- ctxt->context->node = oldnode;
- return(0);
+ goto error;
}
/*
* The result of the evaluation needs to be tested to
@@ -13185,12 +13188,13 @@ xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
/*
* The result is used as the new evaluation set.
*/
+ valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+error:
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
ctxt->context->node = oldnode;
ctxt->context->doc = oldDoc;
- valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
}
return(total);
}
@@ -13211,8 +13215,6 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
int equal, ret;
xmlXPathCompExprPtr comp;
xmlXPathObjectPtr arg1, arg2;
- int pp;
- int cs;
CHECK_ERROR0;
comp = ctxt->comp;
@@ -13220,16 +13222,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
case XPATH_OP_END:
return (0);
case XPATH_OP_AND:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
xmlXPathBooleanFunction(ctxt, 1);
if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
return (total);
arg2 = valuePop(ctxt);
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error) {
xmlXPathFreeObject(arg2);
@@ -13242,16 +13240,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_OR:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
xmlXPathBooleanFunction(ctxt, 1);
if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
return (total);
arg2 = valuePop(ctxt);
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
if (ctxt->error) {
xmlXPathFreeObject(arg2);
@@ -13264,12 +13258,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_EQUAL:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
if (op->value)
@@ -13279,25 +13269,17 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, equal));
return (total);
case XPATH_OP_CMP:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, ret));
return (total);
case XPATH_OP_PLUS:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
if (op->ch2 != -1) {
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
}
CHECK_ERROR0;
@@ -13313,12 +13295,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
}
return (total);
case XPATH_OP_MULT:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
if (op->value == 0)
@@ -13329,12 +13307,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathModValues(ctxt);
return (total);
case XPATH_OP_UNION:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
CHECK_ERROR0;
- ctxt->context->proximityPosition = pp;
- ctxt->context->contextSize = cs;
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
CHECK_ERROR0;
@@ -13489,18 +13463,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
return (total);
}
case XPATH_OP_ARG:
- pp = ctxt->context->proximityPosition;
- cs = ctxt->context->contextSize;
if (op->ch1 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- ctxt->context->contextSize = cs;
- ctxt->context->proximityPosition = pp;
CHECK_ERROR0;
}
if (op->ch2 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- ctxt->context->contextSize = cs;
- ctxt->context->proximityPosition = pp;
CHECK_ERROR0;
}
return (total);
@@ -13512,6 +13480,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlNodeSetPtr oldset;
xmlNodePtr oldnode;
xmlDocPtr oldDoc;
+ int oldcs, oldpp;
int i;
/*
@@ -13636,6 +13605,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
obj = valuePop(ctxt);
oldlocset = obj->user;
oldnode = ctxt->context->node;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
newlocset = xmlXPtrLocationSetCreate(NULL);
@@ -13656,9 +13627,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- ctxt->context->node = oldnode;
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto filter_xptr_error;
}
/*
@@ -13687,11 +13657,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
/*
* The result is used as the new evaluation locset.
*/
- xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+filter_xptr_error:
+ xmlXPathReleaseObject(ctxt->context, obj);
ctxt->context->node = oldnode;
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
return (total);
}
#endif /* LIBXML_XPTR_ENABLED */
@@ -13709,6 +13680,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
oldset = obj->nodesetval;
oldnode = ctxt->context->node;
oldDoc = ctxt->context->doc;
+ oldcs = ctxt->context->contextSize;
+ oldpp = ctxt->context->proximityPosition;
tmp = NULL;
/*
* Initialize the new set.
@@ -13774,9 +13747,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
xmlXPathFreeNodeSet(newset);
- xmlXPathFreeObject(obj);
- ctxt->context->node = oldnode;
- return(0);
+ goto filter_error;
}
/*
@@ -13816,13 +13787,14 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
/*
* The result is used as the new evaluation set.
*/
+ valuePush(ctxt,
+ xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+filter_error:
xmlXPathReleaseObject(ctxt->context, obj);
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
ctxt->context->node = oldnode;
ctxt->context->doc = oldDoc;
- valuePush(ctxt,
- xmlXPathCacheWrapNodeSet(ctxt->context, newset));
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
}
return (total);
}
@@ -13847,6 +13819,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlLocationSetPtr oldlocset;
xmlNodeSetPtr oldset;
xmlNodePtr oldnode = ctxt->context->node;
+ int oldcs = ctxt->context->contextSize;
+ int oldpp = ctxt->context->proximityPosition;
int i, j;
if (op->ch1 != -1) {
@@ -13894,9 +13868,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- ctxt->context->node = oldnode;
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto rangeto_error;
}
res = valuePop(ctxt);
@@ -13958,9 +13931,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
if (ctxt->error != XPATH_EXPRESSION_OK) {
- xmlXPathFreeObject(obj);
- ctxt->context->node = oldnode;
- return(0);
+ xmlXPtrFreeLocationSet(newlocset);
+ goto rangeto_error;
}
res = valuePop(ctxt);
@@ -13988,11 +13960,12 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
/*
* The result is used as the new evaluation set.
*/
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+rangeto_error:
xmlXPathReleaseObject(ctxt->context, obj);
ctxt->context->node = oldnode;
- ctxt->context->contextSize = -1;
- ctxt->context->proximityPosition = -1;
- valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
+ ctxt->context->contextSize = oldcs;
+ ctxt->context->proximityPosition = oldpp;
return (total);
}
#endif /* LIBXML_XPTR_ENABLED */
--
2.18.0

View File

@ -1,26 +0,0 @@
From 09797c139e5b0168c87f41b2cea1078d7244638d Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 5 Mar 2019 15:14:34 +0100
Subject: [PATCH 09/37] Fix null deref in xmlregexp error path
Thanks to Shaobo He for the report.
---
xmlregexp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xmlregexp.c b/xmlregexp.c
index d255fbf..9e9c375 100644
--- a/xmlregexp.c
+++ b/xmlregexp.c
@@ -5537,6 +5537,8 @@ xmlRegexpIsDeterminist(xmlRegexpPtr comp) {
return(comp->determinist);
am = xmlNewAutomata();
+ if (am == NULL)
+ return(-1);
if (am->states != NULL) {
int i;
--
1.8.3.1

View File

@ -1,28 +0,0 @@
From 35e83488505d501864826125cfe6a7950d6cba78 Mon Sep 17 00:00:00 2001
From: Daniel Veillard <veillard@redhat.com>
Date: Wed, 18 Apr 2018 15:58:42 +0200
Subject: [PATCH 09/13] HTML noscript should not close p
For https://bugzilla.gnome.org/show_bug.cgi?id=795343
- HTMLparser.c: noscript should not close <p> but it should close <script>
---
HTMLparser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 7e243e60..96a1bf40 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -1084,7 +1084,7 @@ static const char * const htmlStartClose[] = {
"menu", "p", "head", "ul", NULL,
"p", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL,
"div", "p", "head", NULL,
-"noscript", "p", NULL,
+"noscript", "script", NULL,
"center", "font", "b", "i", "p", "head", NULL,
"a", "a", "head", NULL,
"caption", "p", NULL,
--
2.18.0

View File

@ -1,33 +0,0 @@
From d2293cdbc83b3ca79b9d7132c5a62dfd7e3751be Mon Sep 17 00:00:00 2001
From: Andrey Bienkowski <abenkovskii@gmail.com>
Date: Tue, 30 Jan 2018 15:04:11 +0300
Subject: [PATCH 10/13] Remove a misleading line from xmlCharEncOutput
Closes: https://bugzilla.gnome.org/show_bug.cgi?id=793028
It seams this line was accidentally copied over from xmlCharEncOutFunc.
In xmlCharEncOutput output is a pointer so incrementing it by ret can
point it where it wasn't supposed to be pointing. Luckily the current
implementation doesn't dereference the pointer after advancing it.
Signed-off-by: Daniel Veillard <veillard@redhat.com>
---
encoding.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/encoding.c b/encoding.c
index de7b511a..a3aaf10e 100644
--- a/encoding.c
+++ b/encoding.c
@@ -2460,8 +2460,6 @@ retry:
ret = -3;
}
- if (ret >= 0) output += ret;
-
/*
* Attempt to handle error cases
*/
--
2.18.0

View File

@ -1,28 +0,0 @@
From b7c50b8ddeae4662c639369360f34b832b6b2e49 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 17 Apr 2018 12:07:08 +0200
Subject: [PATCH 11/13] Remove stray character from comment
Fixes bug #795316:
https://bugzilla.gnome.org/show_bug.cgi?id=795316
---
xpath.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xpath.c b/xpath.c
index 9d223977..3fae0bf4 100644
--- a/xpath.c
+++ b/xpath.c
@@ -2,7 +2,7 @@
* xpath.c: XML Path Language implementation
* XPath is a language for addressing parts of an XML document,
* designed to be used by both XSLT and XPointer
- *f
+ *
* Reference: W3C Recommendation 16 November 1999
* http://www.w3.org/TR/1999/REC-xpath-19991116
* Public reference:
--
2.18.0

View File

@ -1,31 +0,0 @@
From 236dd6ab2e6129ece366117070c7c014500a00c1 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 13 Mar 2019 18:21:02 +0100
Subject: [PATCH 12/37] Check XPath stack after calling functions
Check that there's exactly one return value on the stack after calling
XPath functions. Otherwise, functions that corrupt the stack without
signaling an error could lead to memory errors.
Found with libFuzzer and UBSan.
---
xpath.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/xpath.c b/xpath.c
index 72c6338..facd641 100644
--- a/xpath.c
+++ b/xpath.c
@@ -13431,6 +13431,9 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
func(ctxt, op->value);
ctxt->context->function = oldFunc;
ctxt->context->functionURI = oldFuncURI;
+ if ((ctxt->error == XPATH_EXPRESSION_OK) &&
+ (ctxt->valueNr != ctxt->valueFrame + 1))
+ XP_ERROR0(XPATH_STACK_ERROR);
xmlXPathPopFrame(ctxt, frame);
return (total);
}
--
1.8.3.1

View File

@ -1,54 +0,0 @@
From a436374994c47b12d5de1b8b1d191a098fa23594 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 30 Jul 2018 12:54:38 +0200
Subject: [PATCH 12/13] Fix nullptr deref with XPath logic ops
If the XPath stack is corrupted, for example by a misbehaving extension
function, the "and" and "or" XPath operators could dereference NULL
pointers. Check that the XPath stack isn't empty and optimize the
logic operators slightly.
Closes: https://gitlab.gnome.org/GNOME/libxml2/issues/5
Also see
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=901817
https://bugzilla.redhat.com/show_bug.cgi?id=1595985
This is CVE-2018-14404.
Thanks to Guy Inbar for the report.
---
xpath.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/xpath.c b/xpath.c
index 3fae0bf4..5e3bb9ff 100644
--- a/xpath.c
+++ b/xpath.c
@@ -13234,9 +13234,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
return(0);
}
xmlXPathBooleanFunction(ctxt, 1);
- arg1 = valuePop(ctxt);
- arg1->boolval &= arg2->boolval;
- valuePush(ctxt, arg1);
+ if (ctxt->value != NULL)
+ ctxt->value->boolval &= arg2->boolval;
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_OR:
@@ -13252,9 +13251,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
return(0);
}
xmlXPathBooleanFunction(ctxt, 1);
- arg1 = valuePop(ctxt);
- arg1->boolval |= arg2->boolval;
- valuePush(ctxt, arg1);
+ if (ctxt->value != NULL)
+ ctxt->value->boolval |= arg2->boolval;
xmlXPathReleaseObject(ctxt->context, arg2);
return (total);
case XPATH_OP_EQUAL:
--
2.18.0

View File

@ -1,43 +0,0 @@
From b9bdb9dbfda8f591f1797ad90f900bf44ad39d45 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 19 Mar 2019 17:44:51 +0100
Subject: [PATCH 13/37] Check for integer overflow in xmlXPtrEvalChildSeq
Found with libFuzzer and UBSan.
---
xpointer.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/xpointer.c b/xpointer.c
index 6a41f07..0467411 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -1202,13 +1202,23 @@ xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) {
}
while (CUR == '/') {
- int child = 0;
+ int child = 0, overflow = 0;
NEXT;
while ((CUR >= '0') && (CUR <= '9')) {
- child = child * 10 + (CUR - '0');
+ int d = CUR - '0';
+ if (child > INT_MAX / 10)
+ overflow = 1;
+ else
+ child *= 10;
+ if (child > INT_MAX - d)
+ overflow = 1;
+ else
+ child += d;
NEXT;
}
+ if (overflow)
+ child = 0;
xmlXPtrGetChildNo(ctxt, child);
}
}
--
1.8.3.1

View File

@ -1,50 +0,0 @@
From 2240fbf5912054af025fb6e01e26375100275e74 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 30 Jul 2018 13:14:11 +0200
Subject: [PATCH 13/13] Fix infinite loop in LZMA decompression
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Check the liblzma error code more thoroughly to avoid infinite loops.
Closes: https://gitlab.gnome.org/GNOME/libxml2/issues/13
Closes: https://bugzilla.gnome.org/show_bug.cgi?id=794914
This is CVE-2018-9251 and CVE-2018-14567.
Thanks to Dongliang Mu and Simon Wörner for the reports.
---
xzlib.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/xzlib.c b/xzlib.c
index a839169e..0ba88cfa 100644
--- a/xzlib.c
+++ b/xzlib.c
@@ -562,6 +562,10 @@ xz_decomp(xz_statep state)
"internal error: inflate stream corrupt");
return -1;
}
+ /*
+ * FIXME: Remapping a couple of error codes and falling through
+ * to the LZMA error handling looks fragile.
+ */
if (ret == Z_MEM_ERROR)
ret = LZMA_MEM_ERROR;
if (ret == Z_DATA_ERROR)
@@ -587,6 +591,11 @@ xz_decomp(xz_statep state)
xz_error(state, LZMA_PROG_ERROR, "compression error");
return -1;
}
+ if ((state->how != GZIP) &&
+ (ret != LZMA_OK) && (ret != LZMA_STREAM_END)) {
+ xz_error(state, ret, "lzma error");
+ return -1;
+ }
} while (strm->avail_out && ret != LZMA_STREAM_END);
/* update available output and crc check value */
--
2.18.0

View File

@ -1,41 +0,0 @@
From 93a1d2238087c3acc650ba741067f34fb94905fc Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 16 Apr 2019 13:37:47 +0200
Subject: [PATCH 21/37] Fix memory leaks in xmlXPathParseNameComplex error
paths
Found by OSS-Fuzz.
---
xpath.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/xpath.c b/xpath.c
index a3a2aa6..1c567d7 100644
--- a/xpath.c
+++ b/xpath.c
@@ -10004,15 +10004,19 @@ xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
(IS_COMBINING(c)) ||
(IS_EXTENDER(c))) {
if (len + 10 > max) {
+ xmlChar *tmp;
if (max > XML_MAX_NAME_LENGTH) {
+ xmlFree(buffer);
XP_ERRORNULL(XPATH_EXPR_ERROR);
}
max *= 2;
- buffer = (xmlChar *) xmlRealloc(buffer,
- max * sizeof(xmlChar));
- if (buffer == NULL) {
+ tmp = (xmlChar *) xmlRealloc(buffer,
+ max * sizeof(xmlChar));
+ if (tmp == NULL) {
+ xmlFree(buffer);
XP_ERRORNULL(XPATH_MEMORY_ERROR);
}
+ buffer = tmp;
}
COPY_BUF(l,buffer,len,c);
NEXTL(l);
--
1.8.3.1

View File

@ -1,49 +0,0 @@
From 346febc6abbd63d1fa6a532c7429d2c11b5c269b Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 25 Apr 2019 11:34:08 +0200
Subject: [PATCH 26/37] Fix call stack overflow in xmlFreePattern
Since xmlFreePattern tried to free the next pattern recursively, its
behavior is identical to xmlFreePatternList. Make it call
xmlFreePatternList to avoid call stack overflows.
Found by OSS-Fuzz.
---
pattern.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/pattern.c b/pattern.c
index 0eb8d81..fdf5c79 100644
--- a/pattern.c
+++ b/pattern.c
@@ -229,13 +229,16 @@ xmlNewPattern(void) {
*/
void
xmlFreePattern(xmlPatternPtr comp) {
+ xmlFreePatternList(comp);
+}
+
+static void
+xmlFreePatternInternal(xmlPatternPtr comp) {
xmlStepOpPtr op;
int i;
if (comp == NULL)
return;
- if (comp->next != NULL)
- xmlFreePattern(comp->next);
if (comp->stream != NULL)
xmlFreeStreamComp(comp->stream);
if (comp->pattern != NULL)
@@ -273,7 +276,7 @@ xmlFreePatternList(xmlPatternPtr comp) {
cur = comp;
comp = comp->next;
cur->next = NULL;
- xmlFreePattern(cur);
+ xmlFreePatternInternal(cur);
}
}
--
1.8.3.1

View File

@ -1,36 +0,0 @@
From 3c0d62b4193c5c1fe15a143a138f76ffa1278779 Mon Sep 17 00:00:00 2001
From: David Warring <david.warring@gmail.com>
Date: Mon, 13 May 2019 07:15:44 +1200
Subject: [PATCH 31/37] Fix parser termination from "Double hyphen within
comment" error
The patch fixes the parser not halting immediately when the error
handler attempts to stop the parser.
Rather it was running on and continuing to reference the freed buffer
in the while loop termination test.
This is only a problem if xmlStopParser is called from an error
handler. Probably caused by commit 123234f2. Fixes #58.
---
parser.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/parser.c b/parser.c
index 5879d3b..2cab92c 100644
--- a/parser.c
+++ b/parser.c
@@ -4955,6 +4955,10 @@ get_more:
} else
xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
"Double hyphen within comment\n", NULL);
+ if (ctxt->instate == XML_PARSER_EOF) {
+ xmlFree(buf);
+ return;
+ }
in++;
ctxt->input->col++;
}
--
1.8.3.1

View File

@ -1,85 +0,0 @@
From 407b393d8023a6f20422fb3bf5806cf15ab750ad Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 15 May 2019 12:47:28 +0200
Subject: [PATCH 32/37] Fix return value of xmlOutputBufferWrite
When using memory buffers, the total size of the buffer was added
again and again, potentially leading to an integer overflow.
Found by OSS-Fuzz.
---
xmlIO.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/xmlIO.c b/xmlIO.c
index f61dd05..a0b4532 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -3372,20 +3372,26 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
out->error = XML_IO_ENCODER;
return(-1);
}
- nbchars = xmlBufUse(out->conv);
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->conv);
+ else
+ nbchars = ret;
} else {
ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
if (ret != 0)
return(-1);
- nbchars = xmlBufUse(out->buffer);
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->buffer);
+ else
+ nbchars = chunk;
}
buf += chunk;
len -= chunk;
- if ((nbchars < MINLEN) && (len <= 0))
- goto done;
-
if (out->writecallback) {
+ if ((nbchars < MINLEN) && (len <= 0))
+ goto done;
+
/*
* second write the stuff to the I/O channel
*/
@@ -3561,21 +3567,27 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
out->error = XML_IO_ENCODER;
return(-1);
}
- nbchars = xmlBufUse(out->conv);
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->conv);
+ else
+ nbchars = ret;
} else {
ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
return(-1);
xmlBufAddLen(out->buffer, chunk);
- nbchars = xmlBufUse(out->buffer);
+ if (out->writecallback)
+ nbchars = xmlBufUse(out->buffer);
+ else
+ nbchars = chunk;
}
str += cons;
len -= cons;
- if ((nbchars < MINLEN) && (len <= 0))
- goto done;
-
if (out->writecallback) {
+ if ((nbchars < MINLEN) && (len <= 0))
+ goto done;
+
/*
* second write the stuff to the I/O channel
*/
--
1.8.3.1

View File

@ -1,171 +0,0 @@
From f9fce963132b2a56a0f91bc19223a5c60f9786cb Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 16 May 2019 21:16:01 +0200
Subject: [PATCH 34/37] Fix unsigned integer overflow
It's defined behavior but -fsanitize=unsigned-integer-overflow is
useful to discover bugs.
---
parser.c | 34 ++++++++++++++++++++--------------
result/errors/charref1.xml.err | 2 +-
result/errors/charref1.xml.str | 2 +-
timsort.h | 3 ++-
uri.c | 6 ++++--
5 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/parser.c b/parser.c
index 2cab92c..459502b 100644
--- a/parser.c
+++ b/parser.c
@@ -2281,9 +2281,8 @@ xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
*/
int
xmlParseCharRef(xmlParserCtxtPtr ctxt) {
- unsigned int val = 0;
+ int val = 0;
int count = 0;
- unsigned int outofrange = 0;
/*
* Using RAW/CUR/NEXT is okay since we are working on ASCII range here
@@ -2310,8 +2309,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
val = 0;
break;
}
- if (val > 0x10FFFF)
- outofrange = val;
+ if (val > 0x110000)
+ val = 0x110000;
NEXT;
count++;
@@ -2339,8 +2338,8 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
val = 0;
break;
}
- if (val > 0x10FFFF)
- outofrange = val;
+ if (val > 0x110000)
+ val = 0x110000;
NEXT;
count++;
@@ -2360,7 +2359,11 @@ xmlParseCharRef(xmlParserCtxtPtr ctxt) {
* Characters referred to using character references must match the
* production for Char.
*/
- if ((IS_CHAR(val) && (outofrange == 0))) {
+ if (val >= 0x110000) {
+ xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+ "xmlParseCharRef: character reference out of bounds\n",
+ val);
+ } else if (IS_CHAR(val)) {
return(val);
} else {
xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
@@ -2392,8 +2395,7 @@ static int
xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
const xmlChar *ptr;
xmlChar cur;
- unsigned int val = 0;
- unsigned int outofrange = 0;
+ int val = 0;
if ((str == NULL) || (*str == NULL)) return(0);
ptr = *str;
@@ -2413,8 +2415,8 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
val = 0;
break;
}
- if (val > 0x10FFFF)
- outofrange = val;
+ if (val > 0x110000)
+ val = 0x110000;
ptr++;
cur = *ptr;
@@ -2432,8 +2434,8 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
val = 0;
break;
}
- if (val > 0x10FFFF)
- outofrange = val;
+ if (val > 0x110000)
+ val = 0x110000;
ptr++;
cur = *ptr;
@@ -2451,7 +2453,11 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
* Characters referred to using character references must match the
* production for Char.
*/
- if ((IS_CHAR(val) && (outofrange == 0))) {
+ if (val >= 0x110000) {
+ xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
+ "xmlParseStringCharRef: character reference out of bounds\n",
+ val);
+ } else if (IS_CHAR(val)) {
return(val);
} else {
xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
diff --git a/result/errors/charref1.xml.err b/result/errors/charref1.xml.err
index aa43bcf..dbf3005 100644
--- a/result/errors/charref1.xml.err
+++ b/result/errors/charref1.xml.err
@@ -1,3 +1,3 @@
-./test/errors/charref1.xml:1: parser error : xmlParseCharRef: invalid xmlChar value 60
+./test/errors/charref1.xml:1: parser error : xmlParseCharRef: character reference out of bounds
<bla>&#010100000000000000000000000000000000000000000000000060;</bla>
^
diff --git a/result/errors/charref1.xml.str b/result/errors/charref1.xml.str
index 467b4f6..692f614 100644
--- a/result/errors/charref1.xml.str
+++ b/result/errors/charref1.xml.str
@@ -1,4 +1,4 @@
-./test/errors/charref1.xml:1: parser error : xmlParseCharRef: invalid xmlChar value 60
+./test/errors/charref1.xml:1: parser error : xmlParseCharRef: character reference out of bounds
<bla>&#010100000000000000000000000000000000000000000000000060;</bla>
^
./test/errors/charref1.xml : failed to parse
diff --git a/timsort.h b/timsort.h
index e841bd9..622705b 100644
--- a/timsort.h
+++ b/timsort.h
@@ -404,7 +404,8 @@ static void TIM_SORT_MERGE(SORT_TYPE *dst, const TIM_SORT_RUN_T *stack, const in
j = curr + A;
k = curr + A + B;
- while (k-- > curr) {
+ while (k > curr) {
+ k--;
if ((i > 0) && (j > curr)) {
if (SORT_CMP(dst[j - 1], storage[i - 1]) > 0) {
dst[k] = dst[--j];
diff --git a/uri.c b/uri.c
index 2cf8d9f..9772aaf 100644
--- a/uri.c
+++ b/uri.c
@@ -325,16 +325,18 @@ static int
xmlParse3986Port(xmlURIPtr uri, const char **str)
{
const char *cur = *str;
- unsigned port = 0; /* unsigned for defined overflow behavior */
+ int port = 0;
if (ISA_DIGIT(cur)) {
while (ISA_DIGIT(cur)) {
port = port * 10 + (*cur - '0');
+ if (port > 99999999)
+ port = 99999999;
cur++;
}
if (uri != NULL)
- uri->port = port & INT_MAX; /* port value modulo INT_MAX+1 */
+ uri->port = port;
*str = cur;
return(0);
}
--
1.8.3.1

View File

@ -1,26 +0,0 @@
From f824a4bd4d341d765a0fb6102a03a733faa15cbb Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 20 May 2019 13:26:08 +0200
Subject: [PATCH 37/37] Fix memory leak in xmlAllocOutputBufferInternal error
path
Thanks to Anish K Kurian for the report. Closes #60.
---
xmlIO.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/xmlIO.c b/xmlIO.c
index a0b4532..299b6d2 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -2435,6 +2435,7 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
if (encoder != NULL) {
ret->conv = xmlBufCreateSize(4000);
if (ret->conv == NULL) {
+ xmlBufFree(ret->buffer);
xmlFree(ret);
return(NULL);
}
--
1.8.3.1

View File

@ -0,0 +1,110 @@
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

View File

@ -1,150 +0,0 @@
From d459831c1b308c2095a1b73800e0238269d4106a Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 13 Oct 2018 16:12:14 +0200
Subject: [PATCH 32/62] Fix HTML serialization with UTF-8 encoding
If the encoding is specified as UTF-8, make sure to use a NULL encoding
handler.
---
HTMLtree.c | 84 ++++++++++++++++++++++++++++++--------------------------------
1 file changed, 40 insertions(+), 44 deletions(-)
diff --git a/HTMLtree.c b/HTMLtree.c
index 6a2f43d..21cfcfe 100644
--- a/HTMLtree.c
+++ b/HTMLtree.c
@@ -502,17 +502,17 @@ htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
/*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
- /*
* save the content to a temp buffer.
*/
buf = xmlOutputBufferCreateFile(out, handler);
@@ -575,19 +575,17 @@ htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
- } else {
- handler = xmlFindCharEncodingHandler(encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
buf = xmlAllocOutputBufferInternal(handler);
if (buf == NULL) {
*mem = NULL;
@@ -1096,19 +1094,17 @@ htmlDocDump(FILE *f, xmlDocPtr cur) {
handler = xmlFindCharEncodingHandler(encoding);
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
- } else {
- handler = xmlFindCharEncodingHandler(encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
buf = xmlOutputBufferCreateFile(f, handler);
if (buf == NULL) return(-1);
htmlDocContentDumpOutput(buf, cur, NULL);
@@ -1149,17 +1145,17 @@ htmlSaveFile(const char *filename, xmlDocPtr cur) {
if (handler == NULL)
htmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
}
+ } else {
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
}
/*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
-
- /*
* save the content to a temp buffer.
*/
buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
@@ -1206,15 +1202,15 @@ htmlSaveFileFormat(const char *filename, xmlDocPtr cur,
htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
} else {
htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
- }
- /*
- * Fallback to HTML or ASCII when the encoding is unspecified
- */
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("HTML");
- if (handler == NULL)
- handler = xmlFindCharEncodingHandler("ascii");
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+ }
/*
* save the content to a temp buffer.
--
1.8.3.1

View File

@ -1,39 +0,0 @@
From 157cd3aed70845564e2ecc9754f3f826a3c9c65e Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 24 Nov 2018 15:46:00 +0100
Subject: [PATCH 50/62] Fix NULL pointer deref in xmlTextReaderValidateEntity
Found by OSS-Fuzz.
---
xmlreader.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/xmlreader.c b/xmlreader.c
index 4461b36..3acec75 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -1114,11 +1114,11 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
continue;
} else {
/*
- * The error has probably be raised already.
+ * The error has probably been raised already.
*/
if (node == oldnode)
break;
- node = node->next;
+ goto skip_children;
}
#ifdef LIBXML_REGEXP_ENABLED
} else if (node->type == XML_ELEMENT_NODE) {
@@ -1140,6 +1140,7 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
} else if (node->type == XML_ELEMENT_NODE) {
xmlTextReaderValidatePop(reader);
}
+skip_children:
if (node->next != NULL) {
node = node->next;
continue;
--
1.8.3.1

View File

@ -1,26 +0,0 @@
From 26828cb3a1294e09e42064f4769d4b3c0a8623b3 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 7 Jan 2019 16:52:42 +0100
Subject: [PATCH 59/62] Fix commit "Memory leak in xmlFreeID (xmlreader.c)"
The recent commit "Memory leak in xmlFreeID (xmlreader.c)" introduced
a double-free.
---
xmlreader.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/xmlreader.c b/xmlreader.c
index 3acec75..cd1fb5f 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -273,6 +273,7 @@ xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
return(-1);
}
id->name = attr->name;
+ attr->name = NULL;
id->attr = NULL;
return(0);
}
--
1.8.3.1

View File

@ -0,0 +1,44 @@
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

View File

@ -1,33 +0,0 @@
From f2bbca92d9dddca8807f6402b8fe0ac162a29269 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 7 Aug 2019 17:39:17 +0800
Subject: [PATCH] Fix memory leak in xmlParseBalancedChunkMemoryRecover
When doc is NULL, namespace created in xmlTreeEnsureXMLDecl
is bind to newDoc->oldNs, in this case, set newDoc->oldNs to
NULL and free newDoc will cause a memory leak.
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 1ce1ccf..73b96ca 100644
--- a/parser.c
+++ b/parser.c
@@ -13894,7 +13894,8 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
xmlFreeParserCtxt(ctxt);
newDoc->intSubset = NULL;
newDoc->extSubset = NULL;
- newDoc->oldNs = NULL;
+ if(doc != NULL)
+ newDoc->oldNs = NULL;
xmlFreeDoc(newDoc);
return(ret);
--
1.7.12.4

View File

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

View File

@ -1,36 +0,0 @@
From 3776cb4745cecd8f477b45857c9033a908f25cf3 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 22 Nov 2018 15:27:28 +0100
Subject: [PATCH 35/62] Fix memory leak in xmlSwitchInputEncodingInt error path
Found by OSS-Fuzz.
---
parserInternals.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/parserInternals.c b/parserInternals.c
index 09876ab..0f015de 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -1240,8 +1240,18 @@ xmlSwitchInputEncodingInt(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
* size to be able to convert the buffer.
*/
xmlErrInternal(ctxt, "switching encoding : no input\n", NULL);
+ /*
+ * Callers assume that the input buffer takes ownership of the
+ * encoding handler. xmlCharEncCloseFunc frees unregistered
+ * handlers and avoids a memory leak.
+ */
+ xmlCharEncCloseFunc(handler);
return (-1);
}
+ /*
+ * We should actually raise an error here, see issue #34.
+ */
+ xmlCharEncCloseFunc(handler);
return (0);
}
--
1.8.3.1

View File

@ -1,37 +0,0 @@
From b48226f78c626a0fdbaed65793f1a6138de8558f Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 7 Jan 2019 17:58:32 +0100
Subject: [PATCH 61/62] Fix memory leaks in xmlParseStartTag2 error paths
Found by OSS-Fuzz.
---
parser.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/parser.c b/parser.c
index c424412..5879d3b 100644
--- a/parser.c
+++ b/parser.c
@@ -9247,7 +9247,8 @@ xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
xmlErrMemory(ctxt, "dictionary allocation failure");
if ((attvalue != NULL) && (alloc != 0))
xmlFree(attvalue);
- return(NULL);
+ localname = NULL;
+ goto done;
}
if (*URL != 0) {
uri = xmlParseURI((const char *) URL);
@@ -9497,7 +9498,8 @@ next_attr:
if ((atts == NULL) || (nbatts + 5 > maxatts)) {
if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
- return(NULL);
+ localname = NULL;
+ goto done;
}
maxatts = ctxt->maxatts;
atts = ctxt->atts;
--
1.8.3.1

View File

@ -1,44 +0,0 @@
From b697d7bb5953faa2e699aafcca4058f4caffe734 Mon Sep 17 00:00:00 2001
From: Greg Hildstrom <ghildstrom@forcepoint.com>
Date: Tue, 4 Sep 2018 16:48:15 +0200
Subject: [PATCH 22/62] Fix xmlSchemaValidCtxtPtr reuse memory leak
When reusing an xmlSchemaValidCtxtPtr to validate multiple xml documents
against the same schema, there is a memory leak in xmlschemas.c in
xmlSchemaClearValidCtxt(). The vctxt->idcKeys and associated counters
are not cleaned up in xmlSchemaClearValidCtxt() as they are in
xmlSchemaFreeValidCtxt(). As a result, vctxt->idcKeys grows with each
xmlValidateDoc() call that uses the same context and that memory is
never freed. Similarly, vctxt->nbIdcKeys and vctxt->sizeIdcKeys
increment and are never reset.
Closes: #23
---
xmlschemas.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/xmlschemas.c b/xmlschemas.c
index 405f72a..019988a 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -27653,6 +27653,17 @@ xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
vctxt->nbIdcNodes = 0;
vctxt->sizeIdcNodes = 0;
}
+
+ if (vctxt->idcKeys != NULL) {
+ int i;
+ for (i = 0; i < vctxt->nbIdcKeys; i++)
+ xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
+ xmlFree(vctxt->idcKeys);
+ vctxt->idcKeys = NULL;
+ vctxt->nbIdcKeys = 0;
+ vctxt->sizeIdcKeys = 0;
+ }
+
/*
* Note that we won't delete the XPath state pool here.
*/
--
1.8.3.1

View File

@ -1,29 +0,0 @@
From efe8c093c408311ddbb6995c92a9e077386a57bf Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 24 Nov 2018 11:39:32 +0100
Subject: [PATCH 48/62] Memory leak in xmlFreeID (xmlreader.c)
Fix a memory leak in xmlReader's private copy of xmlFreeID. Only
affects validation with NODICT.
Found by OSS-Fuzz.
---
xmlreader.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/xmlreader.c b/xmlreader.c
index db310c8..5e486c6 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -238,6 +238,8 @@ xmlFreeID(xmlIDPtr id) {
if (id->value != NULL)
DICT_FREE(id->value)
+ if (id->name != NULL)
+ DICT_FREE(id->name)
xmlFree(id);
}
--
1.8.3.1

View File

@ -1,47 +0,0 @@
From 57a3af56f4ee4418948dfbff8c02ae1d79de565e Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Sat, 24 Nov 2018 12:14:55 +0100
Subject: [PATCH 49/62] Memory leak in xmlFreeTextReader
In error cases, there might still be elements in the vstate table.
Since vstateVPop in valid.c is private, we have to pop the elements
with xmlValidatePopElement. This inspects nodes of the document, so
the reader doc must be freed after the clearing the vstate table.
Found by OSS-Fuzz.
---
xmlreader.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/xmlreader.c b/xmlreader.c
index 5e486c6..4461b36 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -2264,17 +2264,19 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
if (reader->ctxt != NULL) {
if (reader->dict == reader->ctxt->dict)
reader->dict = NULL;
- if (reader->ctxt->myDoc != NULL) {
- if (reader->preserve == 0)
- xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
- reader->ctxt->myDoc = NULL;
- }
if ((reader->ctxt->vctxt.vstateTab != NULL) &&
(reader->ctxt->vctxt.vstateMax > 0)){
+ while (reader->ctxt->vctxt.vstateNr > 0)
+ xmlValidatePopElement(&reader->ctxt->vctxt, NULL, NULL, NULL);
xmlFree(reader->ctxt->vctxt.vstateTab);
reader->ctxt->vctxt.vstateTab = NULL;
reader->ctxt->vctxt.vstateMax = 0;
}
+ if (reader->ctxt->myDoc != NULL) {
+ if (reader->preserve == 0)
+ xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
+ reader->ctxt->myDoc = NULL;
+ }
if (reader->allocs & XML_TEXTREADER_CTXT)
xmlFreeParserCtxt(reader->ctxt);
}
--
1.8.3.1

View File

@ -1,33 +0,0 @@
From d2293cdbc83b3ca79b9d7132c5a62dfd7e3751be Mon Sep 17 00:00:00 2001
From: Andrey Bienkowski <abenkovskii@gmail.com>
Date: Tue, 30 Jan 2018 15:04:11 +0300
Subject: [PATCH 11/62] Remove a misleading line from xmlCharEncOutput
Closes: https://bugzilla.gnome.org/show_bug.cgi?id=793028
It seams this line was accidentally copied over from xmlCharEncOutFunc.
In xmlCharEncOutput output is a pointer so incrementing it by ret can
point it where it wasn't supposed to be pointing. Luckily the current
implementation doesn't dereference the pointer after advancing it.
Signed-off-by: Daniel Veillard <veillard@redhat.com>
---
encoding.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/encoding.c b/encoding.c
index de7b511..a3aaf10 100644
--- a/encoding.c
+++ b/encoding.c
@@ -2460,8 +2460,6 @@ retry:
ret = -3;
}
- if (ret >= 0) output += ret;
-
/*
* Attempt to handle error cases
*/
--
1.8.3.1

View File

@ -0,0 +1,26 @@
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

View File

@ -1,39 +0,0 @@
From 60173c821eff9e01f1b8bab4f722150a4c3cf82f Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 11 Sep 2018 14:08:39 +0200
Subject: [PATCH 24/62] Reset HTML parser input pointers on encoding failure
Call xmlBufResetInput before bailing out if switching the encoding
fails. Otherwise, the input pointers could be left in an invalid state.
Similar to commit f9e7997e803457b714352c4d51a96104ae298d94 for the
XML parser.
Thanks to Yunho Kim for the report.
Closes: #27
---
HTMLparser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/HTMLparser.c b/HTMLparser.c
index 96a1bf4..9e60e27 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -3636,12 +3636,12 @@ htmlCheckEncodingDirect(htmlParserCtxtPtr ctxt, const xmlChar *encoding) {
processed = ctxt->input->cur - ctxt->input->base;
xmlBufShrink(ctxt->input->buf->buffer, processed);
nbchars = xmlCharEncInput(ctxt->input->buf, 1);
+ xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
if (nbchars < 0) {
htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
"htmlCheckEncoding: encoder error\n",
NULL, NULL);
}
- xmlBufResetInput(ctxt->input->buf->buffer, ctxt->input);
}
}
}
--
1.8.3.1

View File

@ -1,85 +0,0 @@
From 44e7a0d5f7a7e2c167a8a4196a5358830f695ab0 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 16 May 2019 21:17:28 +0200
Subject: [PATCH] Annotate functions with __attribute__((no_sanitize))
---
dict.c | 2 ++
hash.c | 2 ++
libxml.h | 7 +++++++
xpath.c | 1 +
4 files changed, 12 insertions(+)
diff --git a/dict.c b/dict.c
index 14fe398..13a7b93 100644
--- a/dict.c
+++ b/dict.c
@@ -372,6 +372,7 @@ found_pool:
* http://burtleburtle.net/bob/hash/doobs.html
*/
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
static uint32_t
xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
uint32_t hash;
@@ -404,6 +405,7 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
*
* Neither of the two strings must be NULL.
*/
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
static unsigned long
xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
const xmlChar *name, int len, int seed)
diff --git a/hash.c b/hash.c
index 1145cb9..f037af6 100644
--- a/hash.c
+++ b/hash.c
@@ -79,6 +79,7 @@ struct _xmlHashTable {
* xmlHashComputeKey:
* Calculate the hash key
*/
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
static unsigned long
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
const xmlChar *name2, const xmlChar *name3) {
@@ -109,6 +110,7 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
return (value % table->size);
}
+ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
static unsigned long
xmlHashComputeQKey(xmlHashTablePtr table,
const xmlChar *prefix, const xmlChar *name,
diff --git a/libxml.h b/libxml.h
index 64e30f7..7762331 100644
--- a/libxml.h
+++ b/libxml.h
@@ -72,6 +72,13 @@ int vfprintf(FILE *, const char *, va_list);
#define XML_POP_WARNINGS
#endif
+#if defined(__clang__) || \
+ (defined(__GNUC__) && (__GNUC__ >= 8))
+#define ATTRIBUTE_NO_SANITIZE(arg) __attribute__((no_sanitize(arg)))
+#else
+#define ATTRIBUTE_NO_SANITIZE(arg)
+#endif
+
/*
* Internal variable indicating if a callback has been registered for
* node creation/destruction. It avoids spending a lot of time in locking
diff --git a/xpath.c b/xpath.c
index 031772c..e68975e 100644
--- a/xpath.c
+++ b/xpath.c
@@ -7497,6 +7497,7 @@ xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
* The numeric operators convert their operands to numbers as if
* by calling the number function.
*/
+ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
void
xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
xmlXPathObjectPtr arg;
--
1.7.12.4

View File

@ -1,27 +0,0 @@
From 443fd9665e9471b8083e2b5770f14f200b880381 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 29 Oct 2019 16:19:37 +0100
Subject: [PATCH 3/3] Another fix for conditional sections at end of document
The previous fix introduced an uninitialized read.
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/9737ec071786c29788b9aa0971156f9e19a9c6a0
---
parser.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/parser.c b/parser.c
index f188c9d..84f1723 100644
--- a/parser.c
+++ b/parser.c
@@ -6725,6 +6725,7 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
if (RAW == 0) {
xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
+ goto error;
}
if (ctxt->input->id != id) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
--
2.18.1

View File

@ -1,62 +0,0 @@
From b88ae6d2e1c9f22931f59ff1ec490befe201fb26 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 14 Oct 2019 15:38:28 +0200
Subject: [PATCH] Avoid ignored attribute warnings under GCC
GCC doesn't support the unsigned-integer-overflow sanitizer.
---
dict.c | 4 ++++
hash.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/dict.c b/dict.c
index fb0773b..336e046 100644
--- a/dict.c
+++ b/dict.c
@@ -372,7 +372,9 @@ found_pool:
* http://burtleburtle.net/bob/hash/doobs.html
*/
+#ifdef __clang__
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+#endif
static uint32_t
xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
uint32_t hash;
@@ -405,7 +407,9 @@ xmlDictComputeBigKey(const xmlChar* data, int namelen, int seed) {
*
* Neither of the two strings must be NULL.
*/
+#ifdef __clang__
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+#endif
static unsigned long
xmlDictComputeBigQKey(const xmlChar *prefix, int plen,
const xmlChar *name, int len, int seed)
diff --git a/hash.c b/hash.c
index f037af6..a83d979 100644
--- a/hash.c
+++ b/hash.c
@@ -79,7 +79,9 @@ struct _xmlHashTable {
* xmlHashComputeKey:
* Calculate the hash key
*/
+#ifdef __clang__
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+#endif
static unsigned long
xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
const xmlChar *name2, const xmlChar *name3) {
@@ -110,7 +112,9 @@ xmlHashComputeKey(xmlHashTablePtr table, const xmlChar *name,
return (value % table->size);
}
+#ifdef __clang__
ATTRIBUTE_NO_SANITIZE("unsigned-integer-overflow")
+#endif
static unsigned long
xmlHashComputeQKey(xmlHashTablePtr table,
const xmlChar *prefix, const xmlChar *name,
--
1.7.12.4

View File

@ -1,41 +0,0 @@
From 2b9fee2b0baf675b38b5e11756e9339d14c27a3a Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Wed, 23 Oct 2019 11:40:34 +0200
Subject: [PATCH 2/3] Fix for conditional sections at end of document
Parsing conditional sections would fail if the final ']]>' was at the
end of the document. Short-lived regression caused by commit c51e38cb.
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/c1035664f989c2ac7ca31407bc6f0b48396db42c
---
parser.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/parser.c b/parser.c
index bfa6585..f188c9d 100644
--- a/parser.c
+++ b/parser.c
@@ -6723,6 +6723,9 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
ctxt->disableSAX = state;
ctxt->instate = instate;
+ if (RAW == 0) {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
+ }
if (ctxt->input->id != id) {
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
"All markup of the conditional section is"
@@ -6763,10 +6766,6 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
GROW;
}
- if (RAW == 0) {
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
- }
-
error:
xmlFree(inputIds);
}
--
2.18.1

View File

@ -1,36 +0,0 @@
From 664f881008f40356c0502c8cc154e17e3c80e353 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Thu, 26 Sep 2019 11:01:58 +0200
Subject: [PATCH] Fix use-after-free in xmlTextReaderFreeNodeList
Recent commit 1fbcf40 caused a use-after-free read because it didn't
account for the fact that xmlTextReaderFreeDoc frees entities before
freeing entity references via xmlTextReaderFreeNodeList.
Found by OSS-Fuzz.
---
xmlreader.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/xmlreader.c b/xmlreader.c
index 9229c18..b505f16 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -367,10 +367,10 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
return;
}
while (1) {
- while ((cur->children != NULL) &&
- (cur->children->parent == cur) &&
- (cur->type != XML_DTD_NODE) &&
- (cur->type != XML_ENTITY_REF_NODE)) {
+ while ((cur->type != XML_DTD_NODE) &&
+ (cur->type != XML_ENTITY_REF_NODE) &&
+ (cur->children != NULL) &&
+ (cur->children->parent == cur)) {
cur = cur->children;
depth += 1;
}
--
1.7.12.4

View File

@ -1,211 +0,0 @@
From 3be39335ced799eb1ec312b7b542c84dac4ebd57 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Fri, 4 Oct 2019 14:42:59 +0200
Subject: [PATCH] Make xmlDumpElementContent non-recursive
Avoid call stack overflow when dumping deeply nested element
declarations.
Found by OSS-Fuzz.
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/24e3973bc03c15d534b2eac6e70fc2b2bef2b6c0
---
valid.c | 157 ++++++++++++++++++++++++++++++++------------------------
1 file changed, 89 insertions(+), 68 deletions(-)
diff --git a/valid.c b/valid.c
index b1cfede..632c5e7 100644
--- a/valid.c
+++ b/valid.c
@@ -1148,83 +1148,104 @@ xmlFreeElementContent(xmlElementContentPtr cur) {
#ifdef LIBXML_OUTPUT_ENABLED
/**
- * xmlDumpElementContent:
+ * xmlDumpElementOccur:
* @buf: An XML buffer
- * @content: An element table
- * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
+ * @cur: An element table
*
- * This will dump the content of the element table as an XML DTD definition
+ * Dump the occurence operator of an element.
*/
static void
-xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) {
- if (content == NULL) return;
-
- if (glob) xmlBufferWriteChar(buf, "(");
- switch (content->type) {
- case XML_ELEMENT_CONTENT_PCDATA:
- xmlBufferWriteChar(buf, "#PCDATA");
- break;
- case XML_ELEMENT_CONTENT_ELEMENT:
- if (content->prefix != NULL) {
- xmlBufferWriteCHAR(buf, content->prefix);
- xmlBufferWriteChar(buf, ":");
- }
- xmlBufferWriteCHAR(buf, content->name);
- break;
- case XML_ELEMENT_CONTENT_SEQ:
- if ((content->c1 != NULL) &&
- ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
- (content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
- xmlDumpElementContent(buf, content->c1, 1);
- else
- xmlDumpElementContent(buf, content->c1, 0);
- xmlBufferWriteChar(buf, " , ");
- if ((content->c2 != NULL) &&
- ((content->c2->type == XML_ELEMENT_CONTENT_OR) ||
- ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) &&
- (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
- xmlDumpElementContent(buf, content->c2, 1);
- else
- xmlDumpElementContent(buf, content->c2, 0);
- break;
- case XML_ELEMENT_CONTENT_OR:
- if ((content->c1 != NULL) &&
- ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
- (content->c1->type == XML_ELEMENT_CONTENT_SEQ)))
- xmlDumpElementContent(buf, content->c1, 1);
- else
- xmlDumpElementContent(buf, content->c1, 0);
- xmlBufferWriteChar(buf, " | ");
- if ((content->c2 != NULL) &&
- ((content->c2->type == XML_ELEMENT_CONTENT_SEQ) ||
- ((content->c2->type == XML_ELEMENT_CONTENT_OR) &&
- (content->c2->ocur != XML_ELEMENT_CONTENT_ONCE))))
- xmlDumpElementContent(buf, content->c2, 1);
- else
- xmlDumpElementContent(buf, content->c2, 0);
- break;
- default:
- xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
- "Internal: ELEMENT content corrupted invalid type\n",
- NULL);
- }
- if (glob)
- xmlBufferWriteChar(buf, ")");
- switch (content->ocur) {
+xmlDumpElementOccur(xmlBufferPtr buf, xmlElementContentPtr cur) {
+ switch (cur->ocur) {
case XML_ELEMENT_CONTENT_ONCE:
- break;
+ break;
case XML_ELEMENT_CONTENT_OPT:
- xmlBufferWriteChar(buf, "?");
- break;
+ xmlBufferWriteChar(buf, "?");
+ break;
case XML_ELEMENT_CONTENT_MULT:
- xmlBufferWriteChar(buf, "*");
- break;
+ xmlBufferWriteChar(buf, "*");
+ break;
case XML_ELEMENT_CONTENT_PLUS:
- xmlBufferWriteChar(buf, "+");
- break;
+ xmlBufferWriteChar(buf, "+");
+ break;
}
}
+/**
+ * xmlDumpElementContent:
+ * @buf: An XML buffer
+ * @content: An element table
+ *
+ * This will dump the content of the element table as an XML DTD definition
+ */
+static void
+xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content) {
+ xmlElementContentPtr cur;
+
+ if (content == NULL) return;
+
+ xmlBufferWriteChar(buf, "(");
+ cur = content;
+
+ do {
+ if (cur == NULL) return;
+
+ switch (cur->type) {
+ case XML_ELEMENT_CONTENT_PCDATA:
+ xmlBufferWriteChar(buf, "#PCDATA");
+ break;
+ case XML_ELEMENT_CONTENT_ELEMENT:
+ if (cur->prefix != NULL) {
+ xmlBufferWriteCHAR(buf, cur->prefix);
+ xmlBufferWriteChar(buf, ":");
+ }
+ xmlBufferWriteCHAR(buf, cur->name);
+ break;
+ case XML_ELEMENT_CONTENT_SEQ:
+ case XML_ELEMENT_CONTENT_OR:
+ if ((cur != content) &&
+ (cur->parent != NULL) &&
+ ((cur->type != cur->parent->type) ||
+ (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
+ xmlBufferWriteChar(buf, "(");
+ cur = cur->c1;
+ continue;
+ default:
+ xmlErrValid(NULL, XML_ERR_INTERNAL_ERROR,
+ "Internal: ELEMENT cur corrupted invalid type\n",
+ NULL);
+ }
+
+ while (cur != content) {
+ xmlElementContentPtr parent = cur->parent;
+
+ if (parent == NULL) return;
+
+ if (((cur->type == XML_ELEMENT_CONTENT_OR) ||
+ (cur->type == XML_ELEMENT_CONTENT_SEQ)) &&
+ ((cur->type != parent->type) ||
+ (cur->ocur != XML_ELEMENT_CONTENT_ONCE)))
+ xmlBufferWriteChar(buf, ")");
+ xmlDumpElementOccur(buf, cur);
+
+ if (cur == parent->c1) {
+ if (parent->type == XML_ELEMENT_CONTENT_SEQ)
+ xmlBufferWriteChar(buf, " , ");
+ else if (parent->type == XML_ELEMENT_CONTENT_OR)
+ xmlBufferWriteChar(buf, " | ");
+
+ cur = parent->c2;
+ break;
+ }
+
+ cur = parent;
+ }
+ } while (cur != content);
+
+ xmlBufferWriteChar(buf, ")");
+ xmlDumpElementOccur(buf, content);
+}
+
/**
* xmlSprintfElementContent:
* @buf: an output buffer
@@ -1703,7 +1724,7 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
}
xmlBufferWriteCHAR(buf, elem->name);
xmlBufferWriteChar(buf, " ");
- xmlDumpElementContent(buf, elem->content, 1);
+ xmlDumpElementContent(buf, elem->content);
xmlBufferWriteChar(buf, ">\n");
break;
case XML_ELEMENT_TYPE_ELEMENT:
@@ -1714,7 +1735,7 @@ xmlDumpElementDecl(xmlBufferPtr buf, xmlElementPtr elem) {
}
xmlBufferWriteCHAR(buf, elem->name);
xmlBufferWriteChar(buf, " ");
- xmlDumpElementContent(buf, elem->content, 1);
+ xmlDumpElementContent(buf, elem->content);
xmlBufferWriteChar(buf, ">\n");
break;
default:
--
2.18.1

View File

@ -1,71 +0,0 @@
From 0762c9b69ba01628f72eada1c64ff3d361fb5716 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 23 Sep 2019 17:07:40 +0200
Subject: [PATCH 2/3] Make xmlFreeNodeList non-recursive
Avoid call stack overflow when freeing deeply nested documents.
---
tree.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/tree.c b/tree.c
index bba0614..4781326 100644
--- a/tree.c
+++ b/tree.c
@@ -3664,7 +3664,9 @@ xmlNextElementSibling(xmlNodePtr node) {
void
xmlFreeNodeList(xmlNodePtr cur) {
xmlNodePtr next;
+ xmlNodePtr parent;
xmlDictPtr dict = NULL;
+ size_t depth = 0;
if (cur == NULL) return;
if (cur->type == XML_NAMESPACE_DECL) {
@@ -3680,16 +3682,21 @@ xmlFreeNodeList(xmlNodePtr cur) {
return;
}
if (cur->doc != NULL) dict = cur->doc->dict;
- while (cur != NULL) {
+ while (1) {
+ while ((cur->children != NULL) &&
+ (cur->type != XML_DTD_NODE) &&
+ (cur->type != XML_ENTITY_REF_NODE)) {
+ cur = cur->children;
+ depth += 1;
+ }
+
next = cur->next;
+ parent = cur->parent;
if (cur->type != XML_DTD_NODE) {
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue(cur);
- if ((cur->children != NULL) &&
- (cur->type != XML_ENTITY_REF_NODE))
- xmlFreeNodeList(cur->children);
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_XINCLUDE_START) ||
(cur->type == XML_XINCLUDE_END)) &&
@@ -3720,7 +3727,16 @@ xmlFreeNodeList(xmlNodePtr cur) {
DICT_FREE(cur->name)
xmlFree(cur);
}
- cur = next;
+
+ if (next != NULL) {
+ cur = next;
+ } else {
+ if ((depth == 0) || (parent == NULL))
+ break;
+ depth -= 1;
+ cur = parent;
+ cur->children = NULL;
+ }
}
}
--
1.7.12.4

View File

@ -1,510 +0,0 @@
From 94aa233233dac8d6f497f6584d183e3b5cc2a0f8 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 30 Sep 2019 13:50:02 +0200
Subject: [PATCH] Make xmlParseConditionalSections non-recursive
Avoid call stack overflow in deeply nested conditional sections.
Found by OSS-Fuzz.
backport from https://gitlab.gnome.org/GNOME/libxml2/commit/c51e38cb3a808e315248e03c9e52bce08943c22b
---
parser.c | 265 ++++++++++++++--------------
result/errors/759573-2.xml.err | 10 --
result/errors/759573.xml.err | 13 --
result/valid/cond_sect1.xml | 8 +
result/valid/cond_sect1.xml.err | 0
result/valid/cond_sect1.xml.err.rdr | 0
result/valid/cond_sect2.xml | 0
result/valid/cond_sect2.xml.err | 9 +
result/valid/cond_sect2.xml.err.rdr | 10 ++
test/valid/cond_sect1.xml | 7 +
test/valid/cond_sect2.xml | 4 +
test/valid/dtds/cond_sect1.dtd | 20 +++
test/valid/dtds/cond_sect2.dtd | 16 ++
13 files changed, 203 insertions(+), 159 deletions(-)
create mode 100644 result/valid/cond_sect1.xml
create mode 100644 result/valid/cond_sect1.xml.err
create mode 100644 result/valid/cond_sect1.xml.err.rdr
create mode 100644 result/valid/cond_sect2.xml
create mode 100644 result/valid/cond_sect2.xml.err
create mode 100644 result/valid/cond_sect2.xml.err.rdr
create mode 100644 test/valid/cond_sect1.xml
create mode 100644 test/valid/cond_sect2.xml
create mode 100644 test/valid/dtds/cond_sect1.dtd
create mode 100644 test/valid/dtds/cond_sect2.dtd
diff --git a/parser.c b/parser.c
index 9fb14fe..bfa6585 100644
--- a/parser.c
+++ b/parser.c
@@ -6632,149 +6632,143 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
static void
xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
- int id = ctxt->input->id;
+ int *inputIds = NULL;
+ size_t inputIdsSize = 0;
+ size_t depth = 0;
- SKIP(3);
- SKIP_BLANKS;
- if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
- SKIP(7);
- SKIP_BLANKS;
- if (RAW != '[') {
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
- xmlHaltParser(ctxt);
- return;
- } else {
- if (ctxt->input->id != id) {
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "All markup of the conditional section is not"
- " in the same entity\n");
- }
- NEXT;
- }
- if (xmlParserDebugEntities) {
- if ((ctxt->input != NULL) && (ctxt->input->filename))
- xmlGenericError(xmlGenericErrorContext,
- "%s(%d): ", ctxt->input->filename,
- ctxt->input->line);
- xmlGenericError(xmlGenericErrorContext,
- "Entering INCLUDE Conditional Section\n");
- }
+ while (ctxt->instate != XML_PARSER_EOF) {
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ int id = ctxt->input->id;
- SKIP_BLANKS;
- GROW;
- while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
- (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
- const xmlChar *check = CUR_PTR;
- unsigned int cons = ctxt->input->consumed;
+ SKIP(3);
+ SKIP_BLANKS;
- if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
- xmlParseConditionalSections(ctxt);
- } else
- xmlParseMarkupDecl(ctxt);
+ if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
+ SKIP(7);
+ SKIP_BLANKS;
+ if (RAW != '[') {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+ xmlHaltParser(ctxt);
+ goto error;
+ }
+ if (ctxt->input->id != id) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is"
+ " not in the same entity\n");
+ }
+ NEXT;
- SKIP_BLANKS;
- GROW;
+ if (inputIdsSize <= depth) {
+ int *tmp;
- if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
- xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
- xmlHaltParser(ctxt);
- break;
- }
- }
- if (xmlParserDebugEntities) {
- if ((ctxt->input != NULL) && (ctxt->input->filename))
- xmlGenericError(xmlGenericErrorContext,
- "%s(%d): ", ctxt->input->filename,
- ctxt->input->line);
- xmlGenericError(xmlGenericErrorContext,
- "Leaving INCLUDE Conditional Section\n");
- }
+ inputIdsSize = (inputIdsSize == 0 ? 4 : inputIdsSize * 2);
+ tmp = (int *) xmlRealloc(inputIds,
+ inputIdsSize * sizeof(int));
+ if (tmp == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ goto error;
+ }
+ inputIds = tmp;
+ }
+ inputIds[depth] = id;
+ depth++;
+ } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
+ int state;
+ xmlParserInputState instate;
+ size_t ignoreDepth = 0;
+
+ SKIP(6);
+ SKIP_BLANKS;
+ if (RAW != '[') {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+ xmlHaltParser(ctxt);
+ goto error;
+ }
+ if (ctxt->input->id != id) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is"
+ " not in the same entity\n");
+ }
+ NEXT;
- } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
- int state;
- xmlParserInputState instate;
- int depth = 0;
+ /*
+ * Parse up to the end of the conditional section but disable
+ * SAX event generating DTD building in the meantime
+ */
+ state = ctxt->disableSAX;
+ instate = ctxt->instate;
+ if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+ ctxt->instate = XML_PARSER_IGNORE;
+
+ while (RAW != 0) {
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ SKIP(3);
+ ignoreDepth++;
+ /* Check for integer overflow */
+ if (ignoreDepth == 0) {
+ xmlErrMemory(ctxt, NULL);
+ goto error;
+ }
+ } else if ((RAW == ']') && (NXT(1) == ']') &&
+ (NXT(2) == '>')) {
+ if (ignoreDepth == 0)
+ break;
+ SKIP(3);
+ ignoreDepth--;
+ } else {
+ NEXT;
+ }
+ }
- SKIP(6);
- SKIP_BLANKS;
- if (RAW != '[') {
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
- xmlHaltParser(ctxt);
- return;
- } else {
- if (ctxt->input->id != id) {
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "All markup of the conditional section is not"
- " in the same entity\n");
- }
- NEXT;
- }
- if (xmlParserDebugEntities) {
- if ((ctxt->input != NULL) && (ctxt->input->filename))
- xmlGenericError(xmlGenericErrorContext,
- "%s(%d): ", ctxt->input->filename,
- ctxt->input->line);
- xmlGenericError(xmlGenericErrorContext,
- "Entering IGNORE Conditional Section\n");
- }
+ ctxt->disableSAX = state;
+ ctxt->instate = instate;
- /*
- * Parse up to the end of the conditional section
- * But disable SAX event generating DTD building in the meantime
- */
- state = ctxt->disableSAX;
- instate = ctxt->instate;
- if (ctxt->recovery == 0) ctxt->disableSAX = 1;
- ctxt->instate = XML_PARSER_IGNORE;
+ if (ctxt->input->id != id) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is"
+ " not in the same entity\n");
+ }
+ SKIP(3);
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
+ xmlHaltParser(ctxt);
+ goto error;
+ }
+ } else if ((depth > 0) &&
+ (RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
+ depth--;
+ if (ctxt->input->id != inputIds[depth]) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "All markup of the conditional section is not"
+ " in the same entity\n");
+ }
+ SKIP(3);
+ } else {
+ const xmlChar *check = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
- while (((depth >= 0) && (RAW != 0)) &&
- (ctxt->instate != XML_PARSER_EOF)) {
- if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
- depth++;
- SKIP(3);
- continue;
- }
- if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
- if (--depth >= 0) SKIP(3);
- continue;
- }
- NEXT;
- continue;
- }
+ xmlParseMarkupDecl(ctxt);
- ctxt->disableSAX = state;
- ctxt->instate = instate;
+ if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
+ xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+ xmlHaltParser(ctxt);
+ goto error;
+ }
+ }
- if (xmlParserDebugEntities) {
- if ((ctxt->input != NULL) && (ctxt->input->filename))
- xmlGenericError(xmlGenericErrorContext,
- "%s(%d): ", ctxt->input->filename,
- ctxt->input->line);
- xmlGenericError(xmlGenericErrorContext,
- "Leaving IGNORE Conditional Section\n");
- }
+ if (depth == 0)
+ break;
- } else {
- xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
- xmlHaltParser(ctxt);
- return;
+ SKIP_BLANKS;
+ GROW;
}
- if (RAW == 0)
- SHRINK;
-
if (RAW == 0) {
xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
- } else {
- if (ctxt->input->id != id) {
- xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
- "All markup of the conditional section is not in"
- " the same entity\n");
- }
- if ((ctxt-> instate != XML_PARSER_EOF) &&
- ((ctxt->input->cur + 3) <= ctxt->input->end))
- SKIP(3);
}
+
+error:
+ xmlFree(inputIds);
}
/**
@@ -6836,16 +6830,6 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
if (ctxt->instate == XML_PARSER_EOF)
return;
- /*
- * Conditional sections are allowed from entities included
- * by PE References in the internal subset.
- */
- if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
- if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
- xmlParseConditionalSections(ctxt);
- }
- }
-
ctxt->instate = XML_PARSER_DTD;
}
@@ -8306,6 +8290,15 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
xmlParseMarkupDecl(ctxt);
xmlParsePEReference(ctxt);
+ /*
+ * Conditional sections are allowed from entities included
+ * by PE References in the internal subset.
+ */
+ if ((ctxt->inputNr > 1) &&
+ (RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ xmlParseConditionalSections(ctxt);
+ }
+
if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlParseInternalSubset: error detected in Markup declaration\n");
diff --git a/result/errors/759573-2.xml.err b/result/errors/759573-2.xml.err
index 86d6420..ecaf18f 100644
--- a/result/errors/759573-2.xml.err
+++ b/result/errors/759573-2.xml.err
@@ -46,13 +46,3 @@ Entity: line 3:
Entity: line 3:
%zz;<!ELEMENTD(%MENT%MENTDŹMENTD%zNMT9KENSMYSYSTEM;MENT9%zz;
^
-./test/errors/759573-2.xml:6: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
-
-
-^
-./test/errors/759573-2.xml:6: parser error : DOCTYPE improperly terminated
-
-^
-./test/errors/759573-2.xml:6: parser error : Start tag expected, '<' not found
-
-^
diff --git a/result/errors/759573.xml.err b/result/errors/759573.xml.err
index 554039f..2617cad 100644
--- a/result/errors/759573.xml.err
+++ b/result/errors/759573.xml.err
@@ -19,16 +19,3 @@ T t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;000&#37;z;'><!ENTITYz>%xx;
Entity: line 1:
%<![INCLUDE[000%ஸ000%z;
^
-./test/errors/759573.xml:1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
-
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
-./test/errors/759573.xml:1: parser error : DOCTYPE improperly terminated
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
-./test/errors/759573.xml:1: parser error : StartTag: invalid element name
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
-./test/errors/759573.xml:1: parser error : Extra content at the end of the document
-<?h?><!DOCTYPEt[<!ELEMENT t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;00
- ^
diff --git a/result/valid/cond_sect1.xml b/result/valid/cond_sect1.xml
new file mode 100644
index 0000000..dd2e5b4
--- /dev/null
+++ b/result/valid/cond_sect1.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc SYSTEM "dtds/cond_sect1.dtd" [
+<!ENTITY % include "INCLUDE">
+<!ENTITY % ignore "IGNORE">
+]>
+<doc>
+ <child>text</child>
+</doc>
diff --git a/result/valid/cond_sect1.xml.err b/result/valid/cond_sect1.xml.err
new file mode 100644
index 0000000..e69de29
diff --git a/result/valid/cond_sect1.xml.err.rdr b/result/valid/cond_sect1.xml.err.rdr
new file mode 100644
index 0000000..e69de29
diff --git a/result/valid/cond_sect2.xml b/result/valid/cond_sect2.xml
new file mode 100644
index 0000000..e69de29
diff --git a/result/valid/cond_sect2.xml.err b/result/valid/cond_sect2.xml.err
new file mode 100644
index 0000000..9a7624b
--- /dev/null
+++ b/result/valid/cond_sect2.xml.err
@@ -0,0 +1,9 @@
+test/valid/dtds/cond_sect2.dtd:15: parser error : All markup of the conditional section is not in the same entity
+ %ent;
+ ^
+Entity: line 1:
+]]>
+^
+test/valid/dtds/cond_sect2.dtd:17: parser error : Content error in the external subset
+
+^
diff --git a/result/valid/cond_sect2.xml.err.rdr b/result/valid/cond_sect2.xml.err.rdr
new file mode 100644
index 0000000..fd3cb75
--- /dev/null
+++ b/result/valid/cond_sect2.xml.err.rdr
@@ -0,0 +1,10 @@
+test/valid/dtds/cond_sect2.dtd:15: parser error : All markup of the conditional section is not in the same entity
+ %ent;
+ ^
+Entity: line 1:
+]]>
+^
+test/valid/dtds/cond_sect2.dtd:17: parser error : Content error in the external subset
+
+^
+./test/valid/cond_sect2.xml : failed to parse
diff --git a/test/valid/cond_sect1.xml b/test/valid/cond_sect1.xml
new file mode 100644
index 0000000..796faa4
--- /dev/null
+++ b/test/valid/cond_sect1.xml
@@ -0,0 +1,7 @@
+<!DOCTYPE doc SYSTEM "dtds/cond_sect1.dtd" [
+ <!ENTITY % include "INCLUDE">
+ <!ENTITY % ignore "IGNORE">
+]>
+<doc>
+ <child>text</child>
+</doc>
diff --git a/test/valid/cond_sect2.xml b/test/valid/cond_sect2.xml
new file mode 100644
index 0000000..5153d05
--- /dev/null
+++ b/test/valid/cond_sect2.xml
@@ -0,0 +1,4 @@
+<!DOCTYPE doc SYSTEM "dtds/cond_sect2.dtd">
+<doc>
+ <child>text</child>
+</doc>
diff --git a/test/valid/dtds/cond_sect1.dtd b/test/valid/dtds/cond_sect1.dtd
new file mode 100644
index 0000000..e327022
--- /dev/null
+++ b/test/valid/dtds/cond_sect1.dtd
@@ -0,0 +1,20 @@
+<![ %include; [
+ <![%include; [
+ <![ %include;[
+ <![%include;[
+ <!ELEMENT doc (child)>
+ <!ELEMENT child (#PCDATA)>
+ ]]>
+ ]]>
+ ]]>
+]]>
+<![ %ignore; [
+ <![%include; [
+ <![ %include;[
+ <![%ignore;[
+ <!ELEMENT doc (x)>
+ <!ELEMENT child (y)>
+ ]]>
+ ]]>
+ ]]>
+]]>
diff --git a/test/valid/dtds/cond_sect2.dtd b/test/valid/dtds/cond_sect2.dtd
new file mode 100644
index 0000000..29eb4bf
--- /dev/null
+++ b/test/valid/dtds/cond_sect2.dtd
@@ -0,0 +1,16 @@
+<!ENTITY % ent "]]>">
+<![INCLUDE[
+ <![INCLUDE[
+ <![INCLUDE[
+ <![INCLUDE[
+ <![INCLUDE[
+ <![INCLUDE[
+ <![INCLUDE[
+ <![INCLUDE[
+ ]]>
+ ]]>
+ ]]>
+ ]]>
+ ]]>
+ %ent;
+]]>
--
2.18.1

View File

@ -1,286 +0,0 @@
From 62150ed2ab19a4dd76c15acc62c7d923d9f3b2cc Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 23 Sep 2019 14:46:41 +0200
Subject: [PATCH 1/3] Make xmlParseContent and xmlParseElement non-recursive
Split xmlParseElement into subfunctions. Use nameNsPush to store prefix,
URI and nsNr on the heap, similar to the push parser.
Closes #84.
---
parser.c | 121 +++++++++++++++++++++++++------------------
result/errors/754947.xml.err | 2 +-
result/errors/759398.xml.err | 4 +-
3 files changed, 74 insertions(+), 53 deletions(-)
diff --git a/parser.c b/parser.c
index 5b8df8c..cad0a9d 100644
--- a/parser.c
+++ b/parser.c
@@ -96,6 +96,12 @@ xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
static void xmlHaltParser(xmlParserCtxtPtr ctxt);
+static int
+xmlParseElementStart(xmlParserCtxtPtr ctxt);
+
+static void
+xmlParseElementEnd(xmlParserCtxtPtr ctxt);
+
/************************************************************************
* *
* Arbitrary limits set in the parser. See XML_PARSE_HUGE *
@@ -1822,7 +1828,6 @@ nodePop(xmlParserCtxtPtr ctxt)
return (ret);
}
-#ifdef LIBXML_PUSH_ENABLED
/**
* nameNsPush:
* @ctxt: an XML parser context
@@ -1858,6 +1863,11 @@ nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
goto mem_error;
}
ctxt->pushTab = tmp2;
+ } else if (ctxt->pushTab == NULL) {
+ ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
+ sizeof(ctxt->pushTab[0]));
+ if (ctxt->pushTab == NULL)
+ goto mem_error;
}
ctxt->nameTab[ctxt->nameNr] = value;
ctxt->name = value;
@@ -1869,6 +1879,7 @@ mem_error:
xmlErrMemory(ctxt, NULL);
return (-1);
}
+#ifdef LIBXML_PUSH_ENABLED
/**
* nameNsPop:
* @ctxt: an XML parser context
@@ -9812,9 +9823,10 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
void
xmlParseContent(xmlParserCtxtPtr ctxt) {
+ int nameNr = ctxt->nameNr;
+
GROW;
while ((RAW != 0) &&
- ((RAW != '<') || (NXT(1) != '/')) &&
(ctxt->instate != XML_PARSER_EOF)) {
const xmlChar *test = CUR_PTR;
unsigned int cons = ctxt->input->consumed;
@@ -9848,7 +9860,13 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
* Fourth case : a sub-element.
*/
else if (*cur == '<') {
- xmlParseElement(ctxt);
+ if (NXT(1) == '/') {
+ if (ctxt->nameNr <= nameNr)
+ break;
+ xmlParseElementEnd(ctxt);
+ } else {
+ xmlParseElementStart(ctxt);
+ }
}
/*
@@ -9883,7 +9901,7 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
* xmlParseElement:
* @ctxt: an XML parser context
*
- * parse an XML element, this is highly recursive
+ * parse an XML element
*
* [39] element ::= EmptyElemTag | STag content ETag
*
@@ -9895,6 +9913,23 @@ xmlParseContent(xmlParserCtxtPtr ctxt) {
void
xmlParseElement(xmlParserCtxtPtr ctxt) {
+ if (xmlParseElementStart(ctxt) != 0)
+ return;
+ xmlParseContent(ctxt);
+ if (ctxt->instate == XML_PARSER_EOF)
+ return;
+ xmlParseElementEnd(ctxt);
+}
+
+/**
+ * xmlParseElementStart:
+ * @ctxt: an XML parser context
+ *
+ * Parse the start of an XML element. Returns -1 in case of error, 0 if an
+ * opening tag was parsed, 1 if an empty element was parsed.
+ */
+static int
+xmlParseElementStart(xmlParserCtxtPtr ctxt) {
const xmlChar *name;
const xmlChar *prefix = NULL;
const xmlChar *URI = NULL;
@@ -9909,7 +9944,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
"Excessive depth in document: %d use XML_PARSE_HUGE option\n",
xmlParserMaxDepth);
xmlHaltParser(ctxt);
- return;
+ return(-1);
}
/* Capture start position */
@@ -9936,12 +9971,17 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
name = xmlParseStartTag(ctxt);
#endif /* LIBXML_SAX1_ENABLED */
if (ctxt->instate == XML_PARSER_EOF)
- return;
+ return(-1);
if (name == NULL) {
spacePop(ctxt);
- return;
+ return(-1);
}
- namePush(ctxt, name);
+ if (ctxt->sax2)
+ nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
+#ifdef LIBXML_SAX1_ENABLED
+ else
+ namePush(ctxt, name);
+#endif /* LIBXML_SAX1_ENABLED */
ret = ctxt->node;
#ifdef LIBXML_VALID_ENABLED
@@ -9982,7 +10022,7 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
node_info.node = ret;
xmlParserAddNodeInfo(ctxt, &node_info);
}
- return;
+ return(1);
}
if (RAW == '>') {
NEXT1;
@@ -10010,41 +10050,39 @@ xmlParseElement(xmlParserCtxtPtr ctxt) {
node_info.node = ret;
xmlParserAddNodeInfo(ctxt, &node_info);
}
- return;
+ return(-1);
}
- /*
- * Parse the content of the element:
- */
- xmlParseContent(ctxt);
- if (ctxt->instate == XML_PARSER_EOF)
- return;
- if (!IS_BYTE_CHAR(RAW)) {
- xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
- "Premature end of data in tag %s line %d\n",
- name, line, NULL);
+ return(0);
+}
- /*
- * end of parsing of this node.
- */
- nodePop(ctxt);
- namePop(ctxt);
- spacePop(ctxt);
- if (nsNr != ctxt->nsNr)
- nsPop(ctxt, ctxt->nsNr - nsNr);
- return;
- }
+/**
+ * xmlParseElementEnd:
+ * @ctxt: an XML parser context
+ *
+ * Parse the end of an XML element.
+ */
+static void
+xmlParseElementEnd(xmlParserCtxtPtr ctxt) {
+ xmlParserNodeInfo node_info;
+ xmlNodePtr ret = ctxt->node;
+
+ if (ctxt->nameNr <= 0)
+ return;
/*
* parse the end of tag: '</' should be here.
*/
if (ctxt->sax2) {
- xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
+ const xmlChar *prefix = ctxt->pushTab[ctxt->nameNr * 3 - 3];
+ const xmlChar *URI = ctxt->pushTab[ctxt->nameNr * 3 - 2];
+ int nsNr = (ptrdiff_t) ctxt->pushTab[ctxt->nameNr * 3 - 1];
+ xmlParseEndTag2(ctxt, prefix, URI, 0, nsNr, 0);
namePop(ctxt);
}
#ifdef LIBXML_SAX1_ENABLED
- else
- xmlParseEndTag1(ctxt, line);
+ else
+ xmlParseEndTag1(ctxt, 0);
#endif /* LIBXML_SAX1_ENABLED */
/*
@@ -12361,13 +12399,6 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
return(NULL);
}
ctxt->dictNames = 1;
- ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
- if (ctxt->pushTab == NULL) {
- xmlErrMemory(ctxt, NULL);
- xmlFreeParserInputBuffer(buf);
- xmlFreeParserCtxt(ctxt);
- return(NULL);
- }
if (sax != NULL) {
#ifdef LIBXML_SAX1_ENABLED
if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
@@ -14949,16 +14980,6 @@ xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
xmlCtxtReset(ctxt);
- if (ctxt->pushTab == NULL) {
- ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
- sizeof(xmlChar *));
- if (ctxt->pushTab == NULL) {
- xmlErrMemory(ctxt, NULL);
- xmlFreeParserInputBuffer(buf);
- return(1);
- }
- }
-
if (filename == NULL) {
ctxt->directory = NULL;
} else {
diff --git a/result/errors/754947.xml.err b/result/errors/754947.xml.err
index f45cb5a..51e9b4e 100644
--- a/result/errors/754947.xml.err
+++ b/result/errors/754947.xml.err
@@ -2,6 +2,6 @@
Bytes: 0xEE 0x5D 0x5D 0x3E
<d><![CDATA[0000000000000î]]>
^
-./test/errors/754947.xml:1: parser error : Premature end of data in tag d line 1
+./test/errors/754947.xml:1: parser error : EndTag: '</' not found
<d><![CDATA[0000000000000î]]>
^
diff --git a/result/errors/759398.xml.err b/result/errors/759398.xml.err
index f6036a3..bc9e5e0 100644
--- a/result/errors/759398.xml.err
+++ b/result/errors/759398.xml.err
@@ -1,10 +1,10 @@
./test/errors/759398.xml:210: parser error : StartTag: invalid element name
need to worry about parsers whi<! don't expand PErefs finding
^
-./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„m line 308 and termdef
+./test/errors/759398.xml:309: parser error : Opening and ending tag mismatch: â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„â„m line 205 and termdef
and provide access to their content and structure.</termdef> <termdef
^
-./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 50 and p
+./test/errors/759398.xml:314: parser error : Opening and ending tag mismatch: spec line 205 and p
data and the information it must provide to the application.</p>
^
./test/errors/759398.xml:316: parser error : Extra content at the end of the document
--
1.7.12.4

View File

@ -1,77 +0,0 @@
From 1fbcf4098ba2aefe241de8d7ceb229b995d8daec Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 23 Sep 2019 17:13:05 +0200
Subject: [PATCH 3/3] Make xmlTextReaderFreeNodeList non-recursive
Avoid call stack overflow when freeing deeply nested documents.
Found by OSS-Fuzz.
---
xmlreader.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/xmlreader.c b/xmlreader.c
index d715071..9229c18 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -348,7 +348,9 @@ xmlTextReaderFreePropList(xmlTextReaderPtr reader, xmlAttrPtr cur) {
static void
xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
xmlNodePtr next;
+ xmlNodePtr parent;
xmlDictPtr dict;
+ size_t depth = 0;
if ((reader != NULL) && (reader->ctxt != NULL))
dict = reader->ctxt->dict;
@@ -364,18 +366,21 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
xmlFreeDoc((xmlDocPtr) cur);
return;
}
- while (cur != NULL) {
+ while (1) {
+ while ((cur->children != NULL) &&
+ (cur->children->parent == cur) &&
+ (cur->type != XML_DTD_NODE) &&
+ (cur->type != XML_ENTITY_REF_NODE)) {
+ cur = cur->children;
+ depth += 1;
+ }
+
next = cur->next;
+ parent = cur->parent;
+
/* unroll to speed up freeing the document */
if (cur->type != XML_DTD_NODE) {
- if ((cur->children != NULL) &&
- (cur->type != XML_ENTITY_REF_NODE)) {
- if (cur->children->parent == cur)
- xmlTextReaderFreeNodeList(reader, cur->children);
- cur->children = NULL;
- }
-
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue(cur);
@@ -414,7 +419,16 @@ xmlTextReaderFreeNodeList(xmlTextReaderPtr reader, xmlNodePtr cur) {
xmlFree(cur);
}
}
- cur = next;
+
+ if (next != NULL) {
+ cur = next;
+ } else {
+ if ((depth == 0) || (parent == NULL))
+ break;
+ depth -= 1;
+ cur = parent;
+ cur->children = NULL;
+ }
}
}
--
1.7.12.4

View File

@ -1,7 +1,7 @@
Summary: Library providing XML and HTML support
Name: libxml2
Version: 2.9.10
Release: 3
Release: 4
License: MIT
Group: Development/Libraries
Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz
@ -16,7 +16,7 @@ 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
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
@ -26,6 +26,9 @@ 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
BuildRoot: %{_tmppath}/%{name}-%{version}-root
BuildRequires: python2-devel
@ -217,6 +220,9 @@ rm -fr %{buildroot}
%changelog
* Mon Aug 3 2020 Liquor <lirui130@huawei.com> - 2.9.10-4
- Fix integer overflow in xmlFAParseQuantExact
* Tue Jul 28 2020 shenyangyang <shenyangyang4@huawei.com> - 2.9.10-3
- Fix-use-after-free-with-validating-reader and
Never-expand-parameter-entities-in-text-declaration