Skip to content

Commit 7c8fed7

Browse files
committed
Make maximum SpEL expression length configurable
Closes gh-30452
1 parent 89a3d64 commit 7c8fed7

File tree

4 files changed

+82
-11
lines changed

4 files changed

+82
-11
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/SpelParserConfiguration.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,11 +25,19 @@
2525
* @author Juergen Hoeller
2626
* @author Phillip Webb
2727
* @author Andy Clement
28+
* @author Sam Brannen
2829
* @since 3.0
2930
* @see org.springframework.expression.spel.standard.SpelExpressionParser#SpelExpressionParser(SpelParserConfiguration)
3031
*/
3132
public class SpelParserConfiguration {
3233

34+
/**
35+
* Default maximum length permitted for a SpEL expression.
36+
* @since 5.2.24
37+
*/
38+
private static final int DEFAULT_MAX_EXPRESSION_LENGTH = 10_000;
39+
40+
3341
private static final SpelCompilerMode defaultCompilerMode;
3442

3543
static {
@@ -50,6 +58,8 @@ public class SpelParserConfiguration {
5058

5159
private final int maximumAutoGrowSize;
5260

61+
private final int maximumExpressionLength;
62+
5363

5464
/**
5565
* Create a new {@code SpelParserConfiguration} instance with default settings.
@@ -98,11 +108,30 @@ public SpelParserConfiguration(boolean autoGrowNullReferences, boolean autoGrowC
98108
public SpelParserConfiguration(@Nullable SpelCompilerMode compilerMode, @Nullable ClassLoader compilerClassLoader,
99109
boolean autoGrowNullReferences, boolean autoGrowCollections, int maximumAutoGrowSize) {
100110

111+
this(compilerMode, compilerClassLoader, autoGrowNullReferences, autoGrowCollections,
112+
maximumAutoGrowSize, DEFAULT_MAX_EXPRESSION_LENGTH);
113+
}
114+
115+
/**
116+
* Create a new {@code SpelParserConfiguration} instance.
117+
* @param compilerMode the compiler mode that parsers using this configuration object should use
118+
* @param compilerClassLoader the ClassLoader to use as the basis for expression compilation
119+
* @param autoGrowNullReferences if null references should automatically grow
120+
* @param autoGrowCollections if collections should automatically grow
121+
* @param maximumAutoGrowSize the maximum size that a collection can auto grow
122+
* @param maximumExpressionLength the maximum length of a SpEL expression;
123+
* must be a positive number
124+
* @since 5.2.25
125+
*/
126+
public SpelParserConfiguration(@Nullable SpelCompilerMode compilerMode, @Nullable ClassLoader compilerClassLoader,
127+
boolean autoGrowNullReferences, boolean autoGrowCollections, int maximumAutoGrowSize, int maximumExpressionLength) {
128+
101129
this.compilerMode = (compilerMode != null ? compilerMode : defaultCompilerMode);
102130
this.compilerClassLoader = compilerClassLoader;
103131
this.autoGrowNullReferences = autoGrowNullReferences;
104132
this.autoGrowCollections = autoGrowCollections;
105133
this.maximumAutoGrowSize = maximumAutoGrowSize;
134+
this.maximumExpressionLength = maximumExpressionLength;
106135
}
107136

108137

@@ -142,4 +171,12 @@ public int getMaximumAutoGrowSize() {
142171
return this.maximumAutoGrowSize;
143172
}
144173

174+
/**
175+
* Return the maximum number of characters that a SpEL expression can contain.
176+
* @since 5.2.25
177+
*/
178+
public int getMaximumExpressionLength() {
179+
return this.maximumExpressionLength;
180+
}
181+
145182
}

spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
9393

9494
private static final Pattern VALID_QUALIFIED_ID_PATTERN = Pattern.compile("[\\p{L}\\p{N}_$]+");
9595

96-
/**
97-
* Maximum length permitted for a SpEL expression.
98-
* @since 5.2.24
99-
*/
100-
private static final int MAX_EXPRESSION_LENGTH = 10_000;
101-
102-
10396
private final SpelParserConfiguration configuration;
10497

10598
// For rules that build nodes, they are stacked here for return
@@ -158,8 +151,11 @@ protected SpelExpression doParseExpression(String expressionString, @Nullable Pa
158151
}
159152

160153
private void checkExpressionLength(String string) {
161-
if (string != null && string.length() > MAX_EXPRESSION_LENGTH) {
162-
throw new SpelEvaluationException(SpelMessage.MAX_EXPRESSION_LENGTH_EXCEEDED, MAX_EXPRESSION_LENGTH);
154+
if (string != null) {
155+
int maxLength = this.configuration.getMaximumExpressionLength();
156+
if (string.length() > maxLength) {
157+
throw new SpelEvaluationException(SpelMessage.MAX_EXPRESSION_LENGTH_EXCEEDED, maxLength);
158+
}
163159
}
164160
}
165161

spring-expression/src/test/java/org/springframework/expression/spel/AbstractExpressionTests.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -164,6 +164,24 @@ protected void evaluateAndCheckError(String expression, SpelMessage expectedMess
164164
*/
165165
protected void evaluateAndCheckError(String expression, Class<?> expectedReturnType, SpelMessage expectedMessage,
166166
Object... otherProperties) {
167+
168+
evaluateAndCheckError(this.parser, expression, expectedReturnType, expectedMessage, otherProperties);
169+
}
170+
171+
/**
172+
* Evaluate the specified expression and ensure the expected message comes out.
173+
* The message may have inserts and they will be checked if otherProperties is specified.
174+
* The first entry in otherProperties should always be the position.
175+
* @param parser the expression parser to use
176+
* @param expression the expression to evaluate
177+
* @param expectedReturnType ask the expression return value to be of this type if possible
178+
* ({@code null} indicates don't ask for conversion)
179+
* @param expectedMessage the expected message
180+
* @param otherProperties the expected inserts within the message
181+
*/
182+
protected void evaluateAndCheckError(ExpressionParser parser, String expression, Class<?> expectedReturnType, SpelMessage expectedMessage,
183+
Object... otherProperties) {
184+
167185
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() -> {
168186
Expression expr = parser.parseExpression(expression);
169187
assertThat(expr).as("expression").isNotNull();

spring-expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,26 @@ void expressionLength() {
7676
evaluateAndCheckError(expression, String.class, SpelMessage.MAX_EXPRESSION_LENGTH_EXCEEDED);
7777
}
7878

79+
@Test
80+
void maxExpressionLengthIsConfigurable() {
81+
int maximumExpressionLength = 20_000;
82+
83+
String expression = String.format("'%s'", repeat("Y", 19_998));
84+
assertThat(expression).hasSize(maximumExpressionLength);
85+
86+
SpelParserConfiguration configuration =
87+
new SpelParserConfiguration(null, null, false, false, 0, maximumExpressionLength);
88+
ExpressionParser parser = new SpelExpressionParser(configuration);
89+
90+
Expression expr = parser.parseExpression(expression);
91+
String result = expr.getValue(String.class);
92+
assertThat(result).hasSize(19_998);
93+
94+
expression = String.format("'%s'", repeat("Y", 25_000));
95+
assertThat(expression).hasSize(25_002);
96+
evaluateAndCheckError(parser, expression, String.class, SpelMessage.MAX_EXPRESSION_LENGTH_EXCEEDED);
97+
}
98+
7999
@Test
80100
public void testCreateListsOnAttemptToIndexNull01() throws EvaluationException, ParseException {
81101
ExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));

0 commit comments

Comments
 (0)