Skip to content

Commit 15f255a

Browse files
committed
Relaxed position assertion (for overflows in large inline maps)
Issue: SPR-17605 (cherry picked from commit b2756f5)
1 parent 8685f9f commit 15f255a

File tree

2 files changed

+24
-27
lines changed

2 files changed

+24
-27
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,8 +21,8 @@
2121
import org.springframework.expression.spel.ExpressionState;
2222

2323
/**
24-
* Represents assignment. An alternative to calling setValue() for an expression is to use
25-
* an assign.
24+
* Represents assignment. An alternative to calling {@code setValue}
25+
* for an expression which indicates an assign statement.
2626
*
2727
* <p>Example: 'someNumberProperty=42'
2828
*
@@ -31,8 +31,8 @@
3131
*/
3232
public class Assign extends SpelNodeImpl {
3333

34-
public Assign(int pos,SpelNodeImpl... operands) {
35-
super(pos,operands);
34+
public Assign(int pos, SpelNodeImpl... operands) {
35+
super(pos, operands);
3636
}
3737

3838

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

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
4747
private static final SpelNodeImpl[] NO_CHILDREN = new SpelNodeImpl[0];
4848

4949

50-
protected int pos; // start = top 16bits, end = bottom 16bits
50+
protected final int pos; // start = top 16bits, end = bottom 16bits
5151

5252
protected SpelNodeImpl[] children = SpelNodeImpl.NO_CHILDREN;
5353

@@ -69,8 +69,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
6969

7070
public SpelNodeImpl(int pos, SpelNodeImpl... operands) {
7171
this.pos = pos;
72-
// pos combines start and end so can never be zero because tokens cannot be zero length
73-
Assert.isTrue(pos != 0, "Pos must not be 0");
7472
if (!ObjectUtils.isEmpty(operands)) {
7573
this.children = operands;
7674
for (SpelNodeImpl operand : operands) {
@@ -84,17 +82,17 @@ public SpelNodeImpl(int pos, SpelNodeImpl... operands) {
8482
/**
8583
* Return {@code true} if the next child is one of the specified classes.
8684
*/
87-
protected boolean nextChildIs(Class<?>... clazzes) {
85+
protected boolean nextChildIs(Class<?>... classes) {
8886
if (this.parent != null) {
8987
SpelNodeImpl[] peers = this.parent.children;
9088
for (int i = 0, max = peers.length; i < max; i++) {
9189
if (this == peers[i]) {
9290
if (i + 1 >= max) {
9391
return false;
9492
}
95-
Class<?> clazz = peers[i + 1].getClass();
96-
for (Class<?> desiredClazz : clazzes) {
97-
if (clazz.equals(desiredClazz)) {
93+
Class<?> peerClass = peers[i + 1].getClass();
94+
for (Class<?> desiredClass : classes) {
95+
if (peerClass == desiredClass) {
9896
return true;
9997
}
10098
}
@@ -146,11 +144,6 @@ public Class<?> getObjectClass(@Nullable Object obj) {
146144
return (obj instanceof Class ? ((Class<?>) obj) : obj.getClass());
147145
}
148146

149-
@Nullable
150-
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException {
151-
return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), getValueInternal(state), desiredReturnType);
152-
}
153-
154147
@Override
155148
public int getStartPosition() {
156149
return (this.pos >> 16);
@@ -161,10 +154,6 @@ public int getEndPosition() {
161154
return (this.pos & 0xffff);
162155
}
163156

164-
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
165-
throw new SpelEvaluationException(this.pos, SpelMessage.NOT_ASSIGNABLE, toStringAST());
166-
}
167-
168157
/**
169158
* Check whether a node can be compiled to bytecode. The reasoning in each node may
170159
* be different but will typically involve checking whether the exit type descriptor
@@ -177,9 +166,8 @@ public boolean isCompilable() {
177166

178167
/**
179168
* Generate the bytecode for this node into the supplied visitor. Context info about
180-
* the current expression being compiled is available in the codeflow object. For
181-
* example it will include information about the type of the object currently
182-
* on the stack.
169+
* the current expression being compiled is available in the codeflow object, e.g.
170+
* including information about the type of the object currently on the stack.
183171
* @param mv the ASM MethodVisitor into which code should be generated
184172
* @param cf a context object with info about what is on the stack
185173
*/
@@ -192,9 +180,18 @@ public String getExitDescriptor() {
192180
return this.exitTypeDescriptor;
193181
}
194182

183+
@Nullable
184+
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException {
185+
return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), getValueInternal(state), desiredReturnType);
186+
}
187+
188+
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
189+
throw new SpelEvaluationException(getStartPosition(), SpelMessage.NOT_ASSIGNABLE, toStringAST());
190+
}
191+
195192
public abstract TypedValue getValueInternal(ExpressionState expressionState) throws EvaluationException;
196193

197-
194+
198195
/**
199196
* Generate code that handles building the argument values for the specified method.
200197
* This method will take account of whether the invoked method is a varargs method
@@ -222,12 +219,12 @@ protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Me
222219
// have been passed to satisfy the varargs and so something needs to be built.
223220
int p = 0; // Current supplied argument being processed
224221
int childCount = arguments.length;
225-
222+
226223
// Fulfill all the parameter requirements except the last one
227224
for (p = 0; p < paramDescriptors.length - 1; p++) {
228225
generateCodeForArgument(mv, cf, arguments[p], paramDescriptors[p]);
229226
}
230-
227+
231228
SpelNodeImpl lastChild = (childCount == 0 ? null : arguments[childCount - 1]);
232229
String arrayType = paramDescriptors[paramDescriptors.length - 1];
233230
// Determine if the final passed argument is already suitably packaged in array

0 commit comments

Comments
 (0)