mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-03-19 14:50:07 +03:00
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.
This commit is contained in:
parent
8c3ef083ca
commit
6f1470a5d6
@ -33,8 +33,7 @@ LLVMFuzzerTestOneInput(const char *data, size_t size) {
|
||||
if (doc != NULL) {
|
||||
xmlXPathContextPtr xpctxt = xmlXPathNewContext(doc);
|
||||
|
||||
/* Resource limits to avoid timeouts and call stack overflows */
|
||||
xpctxt->maxDepth = 500;
|
||||
/* Operation limit to avoid timeout */
|
||||
xpctxt->opLimit = 500000;
|
||||
|
||||
xmlXPathFreeObject(xmlXPtrEval(BAD_CAST expr, xpctxt));
|
||||
|
25
xpath.c
25
xpath.c
@ -135,6 +135,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
|
||||
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user