[libxml2] Optional recursion limit when evaluating XPath expressions
- From: Nick Wellnhofer <nwellnhof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml2] Optional recursion limit when evaluating XPath expressions
- Date: Mon, 15 Apr 2019 12:24:18 +0000 (UTC)
commit 64115ed62dd01dab81a9157a54738523fe117333
Author: Nick Wellnhofer <wellnhofer aevum de>
Date: Mon Mar 18 11:34:26 2019 +0100
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(-)
---
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index d782ab0b..3d9b1cee 100644
--- a/include/libxml/xpath.h
+++ b/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;
};
/*
diff --git a/xpath.c b/xpath.c
index ce2b437d..993e016f 100644
--- a/xpath.c
+++ b/xpath.c
@@ -611,6 +611,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) / \
@@ -6180,6 +6181,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);
@@ -12724,6 +12727,9 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
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:
@@ -12835,6 +12841,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
break;
}
+ ctxt->context->depth -= 1;
return(total);
}
@@ -12860,6 +12867,9 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
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:
@@ -12965,6 +12975,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
break;
}
+ ctxt->context->depth -= 1;
return (total);
}
@@ -13257,6 +13268,9 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
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:
@@ -14028,6 +14042,7 @@ rangeto_error:
break;
}
+ ctxt->context->depth -= 1;
return (total);
}
@@ -14381,6 +14396,8 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
if ((ctxt == NULL) || (ctxt->comp == NULL))
return(-1);
+ ctxt->context->depth = 0;
+
if (ctxt->valueTab == NULL) {
/* Allocate the value stack */
ctxt->valueTab = (xmlXPathObjectPtr *)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]