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 7aa5efe5becf..d25be4be047c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 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. @@ -34,6 +34,8 @@ * if it is known. * * @author Andy Clement + * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ public enum SpelMessage { @@ -108,7 +110,19 @@ public enum SpelMessage { NOT_ASSIGNABLE(Kind.ERROR,1068,"the expression component ''{0}'' is not assignable"), MISSING_CHARACTER(Kind.ERROR,1069,"missing expected character ''{0}''"), LEFT_OPERAND_PROBLEM(Kind.ERROR,1070, "Problem parsing left operand"), - MISSING_SELECTION_EXPRESSION(Kind.ERROR, 1071, "A required selection expression has not been specified"); + MISSING_SELECTION_EXPRESSION(Kind.ERROR, 1071, "A required selection expression has not been specified"), + + /** @since 4.1 */ + EXCEPTION_RUNNING_COMPILED_EXPRESSION(Kind.ERROR, 1072, + "An exception occurred whilst evaluating a compiled expression"), + + /** @since 4.3.17 */ + FLAWED_PATTERN(Kind.ERROR, 1073, + "Failed to efficiently evaluate pattern ''{0}'': consider redesigning it"), + + /** @since 5.2.20 */ + 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 63294e62b5fe..dcad8df621b4 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-2012 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. @@ -47,11 +47,19 @@ * * @author Andy Clement * @author Juergen Hoeller + * @author Sam Brannen * @since 3.0 */ public class ConstructorReference extends SpelNodeImpl { - private boolean isArrayConstructor = false; + /** + * Maximum number of elements permitted in an array declaration, applying + * to one-dimensional as well as multi-dimensional arrays. + * @since 5.2.20 + */ + private static final int MAX_ARRAY_ELEMENTS = 256 * 1024; // 256K + + private final boolean isArrayConstructor; private SpelNodeImpl[] dimensions; @@ -247,14 +255,19 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException if (this.dimensions.length == 1) { 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); } @@ -314,6 +327,13 @@ else if (arrayTypeCode == TypeCode.BYTE) { 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) { TypeDescriptor toTypeDescriptor = TypeDescriptor.valueOf(componentType);