mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 08:24:13 +00:00
Add a configurable limit for maximum nesting depth in SpEL expressions
This commit introduces support for limiting the structural nesting depth of a SpEL expression during parsing. Without such a limit, an expression with deeply nested constructs (for example, inline lists or maps, parenthesized expressions, ternary or Elvis expressions, or chained unary operators) can cause SpEL's recursive-descent parser to throw a StackOverflowError which lacks useful diagnostics for developer's attempting to assess what went wrong. With this commit, a nesting-depth counter is now tracked around the parser's primary recursive entry point (eatExpression()) as well as around chained unary operators (eatUnaryExpression()), ensuring that independent, sibling uses of assignment, Elvis, and ternary expressions do not inadvertently accumulate depth and trip the limit. If the configured (or default) nesting-depth limit is exceeded during parsing, a SpelParseException is thrown instead, with a message that reports the configured limit. The limit can be configured on a per-use-case basis via SpelParserConfiguration and defaults to 1000. Closes gh-36723
This commit is contained in:
@@ -588,6 +588,31 @@ JVM system property or Spring property named `spring.expression.maxBigPowerBits`
|
||||
maximum result size in bits (see xref:appendix.adoc#appendix-spring-properties[Supported
|
||||
Spring Properties]).
|
||||
|
||||
Likewise, the structural nesting depth of a SpEL expression -- for example, the depth of
|
||||
nested inline lists or maps, parenthesized expressions, ternary or Elvis expressions, or
|
||||
chained unary operators -- cannot exceed 1,000 by default; however, the
|
||||
`maximumNestingDepth` value is configurable. If you create a `SpelExpressionParser`
|
||||
programmatically, you can specify a custom `maximumNestingDepth` value when creating the
|
||||
`SpelParserConfiguration` that you provide to the `SpelExpressionParser`. Unlike
|
||||
`maxExpressionLength` and `maxOperations`, there is currently no JVM system property or
|
||||
Spring property available for configuring `maximumNestingDepth` globally.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Without such a limit, a sufficiently deeply nested expression can drive SpEL's
|
||||
recursive-descent parser to exhaust the current thread's call stack, resulting in a
|
||||
`StackOverflowError` instead of a descriptive exception.
|
||||
|
||||
The `maximumNestingDepth` limit improves diagnostics for that common case by converting
|
||||
it into a clear `SpelParseException`; however, it is not a guaranteed defense against
|
||||
`StackOverflowError` under every possible JVM thread stack size configuration, since the
|
||||
amount of stack space consumed per level of nesting depends on the JVM, its JIT
|
||||
compilation state, and the platform. Applications and frameworks that evaluate SpEL
|
||||
expressions from an untrusted source should not rely on `maximumNestingDepth` alone and
|
||||
should instead heed the <<expressions-evaluation-context-security,security
|
||||
considerations>> discussed previously in this chapter.
|
||||
====
|
||||
|
||||
[[expressions-spel-compilation]]
|
||||
== SpEL Compilation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user