From e59aafaf995290ac44c9bc9ebb3a88ed546d5253 Mon Sep 17 00:00:00 2001 From: panxiaohe Date: Sat, 23 Oct 2021 16:26:08 +0800 Subject: [PATCH] fix fuzz issues --- Fix-XPath-recursion-limit.patch | 31 +++++ ...ks-in-XPointer-string-range-function.patch | 102 +++++++++++++++++ ...-deref-in-xmlXPtrRangeInsideFunction.patch | 41 +++++++ Hardcode-maximum-XPath-recursion-depth.patch | 108 ++++++++++++++++++ Stop-using-maxParserDepth-in-xpath.c.patch | 43 +++++++ libxml2.spec | 18 ++- 6 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 Fix-XPath-recursion-limit.patch create mode 100644 Fix-memory-leaks-in-XPointer-string-range-function.patch create mode 100644 Fix-null-pointer-deref-in-xmlXPtrRangeInsideFunction.patch create mode 100644 Hardcode-maximum-XPath-recursion-depth.patch create mode 100644 Stop-using-maxParserDepth-in-xpath.c.patch diff --git a/Fix-XPath-recursion-limit.patch b/Fix-XPath-recursion-limit.patch new file mode 100644 index 0000000..0f47ad5 --- /dev/null +++ b/Fix-XPath-recursion-limit.patch @@ -0,0 +1,31 @@ +From 3e1aad4fe584747fd7d17cc7b2863a78e2d21a77 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Wed, 2 Jun 2021 17:31:49 +0200 +Subject: [PATCH] Fix XPath recursion limit + +Fix accounting of recursion depth when parsing XPath expressions. + +This silly bug introduced in commit 804c5297 could lead to spurious +errors when parsing larger expressions or XSLT documents. + +Should fix #264. +--- + xpath.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xpath.c b/xpath.c +index 7497ba0..1aa2f1a 100644 +--- a/xpath.c ++++ b/xpath.c +@@ -10983,7 +10983,7 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) { + } + + if (xpctxt != NULL) +- xpctxt->depth -= 1; ++ xpctxt->depth -= 10; + } + + /** +-- +1.8.3.1 + diff --git a/Fix-memory-leaks-in-XPointer-string-range-function.patch b/Fix-memory-leaks-in-XPointer-string-range-function.patch new file mode 100644 index 0000000..81a1f6f --- /dev/null +++ b/Fix-memory-leaks-in-XPointer-string-range-function.patch @@ -0,0 +1,102 @@ +From 46837d47d59c7b8c9bd1d08a6a717a90a7f1ceb6 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Sat, 3 Oct 2020 01:13:35 +0200 +Subject: [PATCH] Fix memory leaks in XPointer string-range function + +Found by OSS-Fuzz. +--- + xpointer.c | 41 +++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 14 deletions(-) + +diff --git a/xpointer.c b/xpointer.c +index 53def72..ad2c288 100644 +--- a/xpointer.c ++++ b/xpointer.c +@@ -2706,10 +2706,10 @@ static void + xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + int i, startindex, endindex = 0, fendindex; + xmlNodePtr start, end = 0, fend; +- xmlXPathObjectPtr set; ++ xmlXPathObjectPtr set = NULL; + xmlLocationSetPtr oldset; +- xmlLocationSetPtr newset; +- xmlXPathObjectPtr string; ++ xmlLocationSetPtr newset = NULL; ++ xmlXPathObjectPtr string = NULL; + xmlXPathObjectPtr position = NULL; + xmlXPathObjectPtr number = NULL; + int found, pos = 0, num = 0; +@@ -2721,29 +2721,39 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + XP_ERROR(XPATH_INVALID_ARITY); + + if (nargs >= 4) { +- CHECK_TYPE(XPATH_NUMBER); ++ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) { ++ xmlXPathErr(ctxt, XPATH_INVALID_TYPE); ++ goto error; ++ } + number = valuePop(ctxt); + if (number != NULL) + num = (int) number->floatval; + } + if (nargs >= 3) { +- CHECK_TYPE(XPATH_NUMBER); ++ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) { ++ xmlXPathErr(ctxt, XPATH_INVALID_TYPE); ++ goto error; ++ } + position = valuePop(ctxt); + if (position != NULL) + pos = (int) position->floatval; + } +- CHECK_TYPE(XPATH_STRING); ++ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { ++ xmlXPathErr(ctxt, XPATH_INVALID_TYPE); ++ goto error; ++ } + string = valuePop(ctxt); + if ((ctxt->value == NULL) || + ((ctxt->value->type != XPATH_LOCATIONSET) && +- (ctxt->value->type != XPATH_NODESET))) +- XP_ERROR(XPATH_INVALID_TYPE) +- ++ (ctxt->value->type != XPATH_NODESET))) { ++ xmlXPathErr(ctxt, XPATH_INVALID_TYPE); ++ goto error; ++ } + set = valuePop(ctxt); + newset = xmlXPtrLocationSetCreate(NULL); + if (newset == NULL) { +- xmlXPathFreeObject(set); +- XP_ERROR(XPATH_MEMORY_ERROR); ++ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR); ++ goto error; + } + if (set->nodesetval == NULL) { + goto error; +@@ -2756,8 +2766,10 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + */ + tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval); + xmlXPathFreeObject(set); +- if (tmp == NULL) +- XP_ERROR(XPATH_MEMORY_ERROR) ++ if (tmp == NULL) { ++ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR); ++ goto error; ++ } + set = tmp; + } + oldset = (xmlLocationSetPtr) set->user; +@@ -2830,7 +2842,8 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) { + * Save the new value and cleanup + */ + error: +- valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); ++ if (newset != NULL) ++ valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); + xmlXPathFreeObject(set); + xmlXPathFreeObject(string); + if (position) xmlXPathFreeObject(position); +-- +1.8.3.1 + diff --git a/Fix-null-pointer-deref-in-xmlXPtrRangeInsideFunction.patch b/Fix-null-pointer-deref-in-xmlXPtrRangeInsideFunction.patch new file mode 100644 index 0000000..fd671b3 --- /dev/null +++ b/Fix-null-pointer-deref-in-xmlXPtrRangeInsideFunction.patch @@ -0,0 +1,41 @@ +From a218ff0ec0ca6da74236b1419e841848a249f011 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Sun, 6 Dec 2020 17:26:36 +0100 +Subject: [PATCH] Fix null pointer deref in xmlXPtrRangeInsideFunction + +Found by OSS-Fuzz. +--- + xpointer.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/xpointer.c b/xpointer.c +index ad2c288..3e3c8b8 100644 +--- a/xpointer.c ++++ b/xpointer.c +@@ -2200,7 +2200,6 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) { + XP_ERROR(XPATH_MEMORY_ERROR) + set = tmp; + } +- oldset = (xmlLocationSetPtr) set->user; + + /* + * The loop is to compute the covering range for each item and add it +@@ -2210,9 +2209,12 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathFreeObject(set); + XP_ERROR(XPATH_MEMORY_ERROR); + } +- for (i = 0;i < oldset->locNr;i++) { +- xmlXPtrLocationSetAdd(newset, +- xmlXPtrInsideRange(ctxt, oldset->locTab[i])); ++ oldset = (xmlLocationSetPtr) set->user; ++ if (oldset != NULL) { ++ for (i = 0;i < oldset->locNr;i++) { ++ xmlXPtrLocationSetAdd(newset, ++ xmlXPtrInsideRange(ctxt, oldset->locTab[i])); ++ } + } + + /* +-- +1.8.3.1 + diff --git a/Hardcode-maximum-XPath-recursion-depth.patch b/Hardcode-maximum-XPath-recursion-depth.patch new file mode 100644 index 0000000..1832caf --- /dev/null +++ b/Hardcode-maximum-XPath-recursion-depth.patch @@ -0,0 +1,108 @@ +From 6f1470a5d6e3e369fe93f52d5760ba7c947f0cd1 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Tue, 25 Aug 2020 18:50:45 +0200 +Subject: [PATCH] Hardcode maximum XPath recursion depth + +Always limit nested functions calls to 5000. This avoids call stack +overflows with deeply nested expressions. + +The expression parser produces about 10 nested function calls when +parsing a subexpression in parentheses, so the effective nesting limit +is about 500 which should be more than enough. + +Use a lower limit when fuzzing to account for increased memory usage +when using sanitizers. + +Conflict:delete contents of fuzz/xpath.c +--- + xpath.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/xpath.c b/xpath.c +index c018d03..2850a1a 100644 +--- a/xpath.c ++++ b/xpath.c +@@ -136,6 +136,17 @@ + #define XPATH_MAX_NODESET_LENGTH 10000000 + + /* ++ * XPATH_MAX_RECRUSION_DEPTH: ++ * Maximum amount of nested functions calls when parsing or evaluating ++ * expressions ++ */ ++#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++#define XPATH_MAX_RECURSION_DEPTH 500 ++#else ++#define XPATH_MAX_RECURSION_DEPTH 5000 ++#endif ++ ++/* + * TODO: + * There are a few spots where some tests are done which depend upon ascii + * data. These should be enhanced for full UTF8 support (see particularly +@@ -6118,8 +6129,6 @@ xmlXPathNewContext(xmlDocPtr doc) { + ret->contextSize = -1; + ret->proximityPosition = -1; + +- ret->maxDepth = INT_MAX; +- + #ifdef XP_DEFAULT_CACHE_ON + if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) { + xmlXPathFreeContext(ret); +@@ -10947,7 +10956,7 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) { + xmlXPathContextPtr xpctxt = ctxt->context; + + if (xpctxt != NULL) { +- if (xpctxt->depth >= xpctxt->maxDepth) ++ if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH) + XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED); + /* + * Parsing a single '(' pushes about 10 functions on the call stack +@@ -11883,7 +11892,7 @@ xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt, + "xmlXPathCompOpEvalPredicate: Expected a predicate\n"); + XP_ERROR(XPATH_INVALID_OPERAND); + } +- if (ctxt->context->depth >= ctxt->context->maxDepth) ++ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH) + XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED); + ctxt->context->depth += 1; + xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set, +@@ -12599,7 +12608,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, + CHECK_ERROR0; + if (OP_LIMIT_EXCEEDED(ctxt, 1)) + return(0); +- if (ctxt->context->depth >= ctxt->context->maxDepth) ++ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH) + XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED); + ctxt->context->depth += 1; + comp = ctxt->comp; +@@ -12740,7 +12749,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, + CHECK_ERROR0; + if (OP_LIMIT_EXCEEDED(ctxt, 1)) + return(0); +- if (ctxt->context->depth >= ctxt->context->maxDepth) ++ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH) + XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED); + ctxt->context->depth += 1; + comp = ctxt->comp; +@@ -12958,7 +12967,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) + CHECK_ERROR0; + if (OP_LIMIT_EXCEEDED(ctxt, 1)) + return(0); +- if (ctxt->context->depth >= ctxt->context->maxDepth) ++ if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH) + XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED); + ctxt->context->depth += 1; + comp = ctxt->comp; +@@ -14192,7 +14201,7 @@ xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt, + /* Recurse */ + ctxt = pctxt->context; + if (ctxt != NULL) { +- if (ctxt->depth >= ctxt->maxDepth) ++ if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH) + return; + ctxt->depth += 1; + } +-- +1.8.3.1 + diff --git a/Stop-using-maxParserDepth-in-xpath.c.patch b/Stop-using-maxParserDepth-in-xpath.c.patch new file mode 100644 index 0000000..fa5137a --- /dev/null +++ b/Stop-using-maxParserDepth-in-xpath.c.patch @@ -0,0 +1,43 @@ +From 804c52978fef3f18b8a634280bc5cc79a390c141 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer +Date: Mon, 17 Aug 2020 03:37:18 +0200 +Subject: [PATCH] Stop using maxParserDepth in xpath.c + +Only use a single maxDepth value. + +Conflict:delete contents of fuzz/xpath.c +--- + xpath.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/xpath.c b/xpath.c +index 673482a..c018d03 100644 +--- a/xpath.c ++++ b/xpath.c +@@ -6119,7 +6119,6 @@ xmlXPathNewContext(xmlDocPtr doc) { + ret->proximityPosition = -1; + + ret->maxDepth = INT_MAX; +- ret->maxParserDepth = INT_MAX; + + #ifdef XP_DEFAULT_CACHE_ON + if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) { +@@ -10948,9 +10947,13 @@ xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) { + xmlXPathContextPtr xpctxt = ctxt->context; + + if (xpctxt != NULL) { +- if (xpctxt->depth >= xpctxt->maxParserDepth) ++ if (xpctxt->depth >= xpctxt->maxDepth) + XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED); +- xpctxt->depth += 1; ++ /* ++ * Parsing a single '(' pushes about 10 functions on the call stack ++ * before recursing! ++ */ ++ xpctxt->depth += 10; + } + + xmlXPathCompAndExpr(ctxt); +-- +1.8.3.1 + diff --git a/libxml2.spec b/libxml2.spec index 2708996..7307f46 100644 --- a/libxml2.spec +++ b/libxml2.spec @@ -1,7 +1,7 @@ Summary: Library providing XML and HTML support Name: libxml2 Version: 2.9.10 -Release: 17 +Release: 18 License: MIT Group: Development/Libraries Source: ftp://xmlsoft.org/libxml2/libxml2-%{version}.tar.gz @@ -95,6 +95,11 @@ Patch82: Fix-regression-introduced-with-commit-d88df4b.patch Patch83: Make-xmlNodeDumpOutputInternal-non-recursive.patch Patch84: Don-t-add-formatting-newlines-to-XInclude-nodes.patch Patch85: Make-htmlNodeDumpFormatOutput-non-recursive.patch +Patch86: Fix-memory-leaks-in-XPointer-string-range-function.patch +Patch87: Fix-null-pointer-deref-in-xmlXPtrRangeInsideFunction.patch +Patch88: Stop-using-maxParserDepth-in-xpath.c.patch +Patch89: Hardcode-maximum-XPath-recursion-depth.patch +Patch90: Fix-XPath-recursion-limit.patch BuildRoot: %{_tmppath}/%{name}-%{version}-root BuildRequires: python2-devel @@ -287,6 +292,17 @@ rm -fr %{buildroot} %changelog +* Sat Oct 23 2021 panxiaohe - 2.9.10-18 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix fuzz issues + fix memory leaks in XPointer string-range function + fix null pointer deref in xmlXPtrRangeInsideFunction + stop using maxParserDepth in xpath.c + hardcode maximum XPath recursion depth + fix XPath recursion limit + * Thu Oct 21 2021 panxiaohe - 2.9.10-17 - Type:bugfix - ID:NA -- Gitee