File libxml2-CVE-2025-9714-2.patch of Package libxml2.41582
From 64115ed62dd01dab81a9157a54738523fe117333 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer <wellnhofer@aevum.de>
Date: Mon, 18 Mar 2019 11:34:26 +0100
Subject: [PATCH] Optional recursion limit when evaluating XPath expressions
Useful to avoid call stack overflows when fuzzing.
---
include/libxml/xpath.h | 5 ++++-
xpath.c | 17 +++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
Index: libxml2-2.9.7/include/libxml/xpath.h
===================================================================
--- libxml2-2.9.7.orig/include/libxml/xpath.h
+++ libxml2-2.9.7/include/libxml/xpath.h
@@ -71,7 +71,8 @@ typedef enum {
XPATH_INVALID_CTXT,
XPATH_STACK_ERROR,
XPATH_FORBID_VARIABLE_ERROR,
- XPATH_OP_LIMIT_EXCEEDED
+ XPATH_OP_LIMIT_EXCEEDED,
+ XPATH_RECURSION_LIMIT_EXCEEDED
} xmlXPathError;
/*
@@ -357,6 +358,8 @@ struct _xmlXPathContext {
/* Resource limits */
unsigned long opLimit;
unsigned long opCount;
+ int depth;
+ int maxDepth;
};
/*
Index: libxml2-2.9.7/xpath.c
===================================================================
--- libxml2-2.9.7.orig/xpath.c
+++ libxml2-2.9.7/xpath.c
@@ -646,6 +646,7 @@ static const char *xmlXPathErrorMessages
"Stack usage error\n",
"Forbidden variable\n",
"Operation limit exceeded\n",
+ "Recursion limit exceeded\n",
"?? Unknown error ??\n" /* Must be last in the list! */
};
#define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
@@ -6205,6 +6206,8 @@ 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);
@@ -12806,6 +12809,9 @@ xmlXPathCompOpEvalFirst(xmlXPathParserCo
CHECK_ERROR0;
if (OP_LIMIT_EXCEEDED(ctxt, 1))
return(0);
+ if (ctxt->context->depth >= ctxt->context->maxDepth)
+ XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
+ ctxt->context->depth += 1;
comp = ctxt->comp;
switch (op->op) {
case XPATH_OP_END:
@@ -12926,6 +12932,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserCo
break;
}
+ ctxt->context->depth -= 1;
return(total);
}
@@ -12955,6 +12962,9 @@ xmlXPathCompOpEvalLast(xmlXPathParserCon
CHECK_ERROR0;
if (OP_LIMIT_EXCEEDED(ctxt, 1))
return(0);
+ if (ctxt->context->depth >= ctxt->context->maxDepth)
+ XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
+ ctxt->context->depth += 1;
comp = ctxt->comp;
switch (op->op) {
case XPATH_OP_END:
@@ -13077,6 +13087,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserCon
break;
}
+ ctxt->context->depth -= 1;
return (total);
}
@@ -13396,6 +13407,9 @@ xmlXPathCompOpEval(xmlXPathParserContext
CHECK_ERROR0;
if (OP_LIMIT_EXCEEDED(ctxt, 1))
return(0);
+ if (ctxt->context->depth >= ctxt->context->maxDepth)
+ XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
+ ctxt->context->depth += 1;
comp = ctxt->comp;
switch (op->op) {
case XPATH_OP_END:
@@ -14279,6 +14293,7 @@ xmlXPathCompOpEval(xmlXPathParserContext
break;
}
+ ctxt->context->depth -= 1;
return (total);
}
@@ -14632,6 +14647,8 @@ xmlXPathRunEval(xmlXPathParserContextPtr
if ((ctxt == NULL) || (ctxt->comp == NULL))
return(-1);
+ ctxt->context->depth = 0;
+
if (ctxt->valueTab == NULL) {
/* Allocate the value stack */
ctxt->valueTab = (xmlXPathObjectPtr *)