diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java b/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java index 9c08841158ed..fe8dd70468d5 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java @@ -260,7 +260,11 @@ public enum SpelMessage { /** @since 5.3.17 */ EXCEPTION_COMPILING_EXPRESSION(Kind.ERROR, 1074, - "An exception occurred while compiling an expression"); + "An exception occurred while compiling an expression"), + + /** @since 5.3.17 */ + MAX_ARRAY_ELEMENTS_THRESHOLD_EXCEEDED(Kind.ERROR, 1075, + "Array declares too many elements, exceeding the threshold of ''{0}''"); private final Kind kind; diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java index d42a375410f6..6f4f3c8c69cc 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,10 +53,18 @@ * * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ public class ConstructorReference extends SpelNodeImpl { + /** + * Maximum number of elements permitted in an array declaration, applying + * to one-dimensional as well as multi-dimensional arrays. + * @since 5.3.17 + */ + private static final int MAX_ARRAY_ELEMENTS = 256 * 1024; // 256K + private final boolean isArrayConstructor; @Nullable @@ -259,14 +267,19 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException // Shortcut for 1-dimensional TypedValue o = this.dimensions[0].getTypedValue(state); int arraySize = ExpressionUtils.toInt(typeConverter, o); + checkNumElements(arraySize); newArray = Array.newInstance(componentType, arraySize); } else { // Multi-dimensional - hold onto your hat! int[] dims = new int[this.dimensions.length]; + long numElements = 1; for (int d = 0; d < this.dimensions.length; d++) { TypedValue o = this.dimensions[d].getTypedValue(state); - dims[d] = ExpressionUtils.toInt(typeConverter, o); + int arraySize = ExpressionUtils.toInt(typeConverter, o); + dims[d] = arraySize; + numElements *= arraySize; + checkNumElements(numElements); } newArray = Array.newInstance(componentType, dims); } @@ -327,6 +340,13 @@ else if (arrayTypeCode == TypeCode.SHORT) { return new TypedValue(newArray); } + private void checkNumElements(long numElements) { + if (numElements >= MAX_ARRAY_ELEMENTS) { + throw new SpelEvaluationException(getStartPosition(), + SpelMessage.MAX_ARRAY_ELEMENTS_THRESHOLD_EXCEEDED, MAX_ARRAY_ELEMENTS); + } + } + private void populateReferenceTypeArray(ExpressionState state, Object newArray, TypeConverter typeConverter, InlineList initializer, Class componentType) {