Skip to content

Commit 8e83f93

Browse files
committed
Improve diagnostics for repeated text size overflow in SpEL
If the resulting size of repeated text in a SpEL expression (using the repeat operator '*') would exceed MAX_REPEATED_TEXT_SIZE, we currently throw a SpelEvaluationException with the MAX_REPEATED_TEXT_SIZE_EXCEEDED message. However, if the calculation of the repeated text size results in integer overflow, our max size check fails to detect that, and String#repeat(int) throws a preemptive OutOfMemoryError from which the application immediately recovers. To improve diagnostics for users, this commit ensures that we consistently throw a SpelEvaluationException with the MAX_REPEATED_TEXT_SIZE_EXCEEDED message when integer overflow occurs. Closes gh-31341
1 parent 4071139 commit 8e83f93

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ else if (CodeFlow.isIntegerForNumericOp(leftNumber) || CodeFlow.isIntegerForNume
123123
}
124124

125125
private void checkRepeatedTextSize(String text, int count) {
126-
if (text.length() * count > MAX_REPEATED_TEXT_SIZE) {
126+
int result = text.length() * count;
127+
if (result < 0 || result > MAX_REPEATED_TEXT_SIZE) {
127128
throw new SpelEvaluationException(getStartPosition(),
128129
SpelMessage.MAX_REPEATED_TEXT_SIZE_EXCEEDED, MAX_REPEATED_TEXT_SIZE);
129130
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,12 @@ void stringRepeat() {
579579

580580
// 4 is the position of the '*' (repeat operator)
581581
evaluateAndCheckError("'a' * 257", String.class, MAX_REPEATED_TEXT_SIZE_EXCEEDED, 4);
582+
583+
// Integer overflow: 2 * ((Integer.MAX_VALUE / 2) + 1) --> integer overflow
584+
int repeatCount = (Integer.MAX_VALUE / 2) + 1;
585+
assertThat(2 * repeatCount).isNegative();
586+
// 5 is the position of the '*' (repeat operator)
587+
evaluateAndCheckError("'ab' * " + repeatCount, String.class, MAX_REPEATED_TEXT_SIZE_EXCEEDED, 5);
582588
}
583589

584590
@Test

0 commit comments

Comments
 (0)