File libxml2-CVE-2025-9714-8.patch of Package libxml2.41582
From 6f1470a5d6e3e369fe93f52d5760ba7c947f0cd1 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Tue, 25 Aug 2020 18:50:45 +0200
Subject: [PATCH] Hardcode maximum XPath recursion depth
Always limit nested functions calls to 5000. This avoids call stack
overflows with deeply nested expressions.
The expression parser produces about 10 nested function calls when
parsing a subexpression in parentheses, so the effective nesting limit
is about 500 which should be more than enough.
Use a lower limit when fuzzing to account for increased memory usage
when using sanitizers.
---
fuzz/xpath.c | 3 +--
xpath.c | 25 +++++++++++++++++--------
2 files changed, 18 insertions(+), 10 deletions(-)
Index: libxml2-2.9.7/xpath.c
===================================================================
--- libxml2-2.9.7.orig/xpath.c
+++ libxml2-2.9.7/xpath.c
@@ -126,6 +126,17 @@
#define XPATH_MAX_STACK_DEPTH 1000000
/*
+ * 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
+
+/*
* XPATH_DEFAULT_MAX_NODESET_LENGTH:
* when evaluating an XPath expression nodesets are created and we
* arbitrary limit the maximum length of those node set. Default value is
@@ -6215,7 +6226,6 @@ xmlXPathNewContext(xmlDocPtr doc) {
ret->contextSize = -1;
ret->proximityPosition = -1;
- ret->maxDepth = INT_MAX;
ret->maxParserDepth = INT_MAX;
#ifdef XP_DEFAULT_CACHE_ON
@@ -11100,7 +11110,7 @@ xmlXPathCompileExpr(xmlXPathParserContex
xmlXPathContextPtr xpctxt = ctxt->context;
if (xpctxt != NULL) {
- if (xpctxt->depth >= xpctxt->maxParserDepth)
+ if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
xpctxt->depth += 1;
}
@@ -11764,7 +11774,7 @@ xmlXPathCompOpEvalPredicate(xmlXPathPars
* TODO: raise an internal error.
*/
}
- 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;
contextSize = xmlXPathCompOpEvalPredicate(ctxt,
@@ -12834,7 +12844,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserCo
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;
@@ -12987,7 +12997,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserCon
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;
@@ -13432,7 +13442,7 @@ xmlXPathCompOpEval(xmlXPathParserContext
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;
@@ -14977,7 +14987,7 @@ xmlXPathOptimizeExpression(xmlXPathParse
/* Recurse */
ctxt = pctxt->context;
if (ctxt != NULL) {
- if (ctxt->depth >= ctxt->maxDepth)
+ if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
return;
ctxt->depth += 1;
}