From 8e83f93bcb775536ae66edf45abdbe9bfb60c22b Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Fri, 29 Sep 2023 16:50:13 +0200 Subject: [PATCH] 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 --- .../org/springframework/expression/spel/ast/OpMultiply.java | 3 ++- .../org/springframework/expression/spel/OperatorTests.java | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java index a10c3e98b2c..559a55817f9 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/OpMultiply.java @@ -123,7 +123,8 @@ public class OpMultiply extends Operator { } private void checkRepeatedTextSize(String text, int count) { - if (text.length() * count > MAX_REPEATED_TEXT_SIZE) { + int result = text.length() * count; + if (result < 0 || result > MAX_REPEATED_TEXT_SIZE) { throw new SpelEvaluationException(getStartPosition(), SpelMessage.MAX_REPEATED_TEXT_SIZE_EXCEEDED, MAX_REPEATED_TEXT_SIZE); } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java index bb4c6c1ba59..cbbb153c9b0 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/OperatorTests.java @@ -579,6 +579,12 @@ class OperatorTests extends AbstractExpressionTests { // 4 is the position of the '*' (repeat operator) evaluateAndCheckError("'a' * 257", String.class, MAX_REPEATED_TEXT_SIZE_EXCEEDED, 4); + + // Integer overflow: 2 * ((Integer.MAX_VALUE / 2) + 1) --> integer overflow + int repeatCount = (Integer.MAX_VALUE / 2) + 1; + assertThat(2 * repeatCount).isNegative(); + // 5 is the position of the '*' (repeat operator) + evaluateAndCheckError("'ab' * " + repeatCount, String.class, MAX_REPEATED_TEXT_SIZE_EXCEEDED, 5); } @Test