Disable variable assignment in SimpleEvaluationContext

This commit introduces infrastructure to differentiate between
programmatic setting of a variable in an EvaluationContext versus the
assignment of a variable within a SpEL expression using the assignment
operator (=). In addition, this commit disables variable assignment
within expressions when using the SimpleEvaluationContext.

Closes gh-30326
This commit is contained in:
Sam Brannen
2023-04-09 18:19:33 +02:00
committed by Brian Clozel
parent b73f5fcac2
commit be17c8d85f
11 changed files with 177 additions and 40 deletions

View File

@@ -25,6 +25,8 @@ import java.util.Map;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.springframework.expression.AccessException;
import org.springframework.expression.BeanResolver;
@@ -36,6 +38,7 @@ import org.springframework.expression.MethodFilter;
import org.springframework.expression.ParseException;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.expression.spel.testresources.TestPerson;
@@ -149,8 +152,24 @@ class EvaluationTests extends AbstractExpressionTests {
// assignment
@Test
void assignmentToVariables() {
evaluate("#var1='value1'", "value1", String.class);
void assignmentToVariableWithStandardEvaluationContext() {
evaluate("#var1 = 'value1'", "value1", String.class);
}
@ParameterizedTest
@CsvSource(quoteCharacter = '"', delimiterString = "->", textBlock = """
"#var1 = 'value1'" -> #var1
"true ? #myVar = 4 : 0" -> #myVar
""")
void assignmentToVariableWithSimpleEvaluationContext(String expression, String varName) {
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
Expression expr = parser.parseExpression(expression);
assertThatExceptionOfType(SpelEvaluationException.class)
.isThrownBy(() -> expr.getValue(context))
.satisfies(ex -> {
assertThat(ex.getMessageCode()).isEqualTo(SpelMessage.VARIABLE_ASSIGNMENT_NOT_SUPPORTED);
assertThat(ex.getInserts()).as("inserts").containsExactly(varName);
});
}
@Test