Skip to content

Commit 0f04052

Browse files
committed
Support compilation of array and list indexing with Integer in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to compile an expression that indexed into an array or list using an Integer. This commit adds support for compilation of such expressions by ensuring that an Integer is unboxed into an int in the compiled bytecode. See gh-32694 Closes gh-32908 (cherry picked from commit 079d53c)
1 parent 98aa03c commit 0f04052

File tree

2 files changed

+456
-11
lines changed

2 files changed

+456
-11
lines changed

Diff for: spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 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.
@@ -226,6 +226,8 @@ public void generateCode(MethodVisitor mv, CodeFlow cf) {
226226
cf.loadTarget(mv);
227227
}
228228

229+
SpelNodeImpl index = this.children[0];
230+
229231
if (this.indexedType == IndexedType.ARRAY) {
230232
int insn;
231233
if ("D".equals(this.exitTypeDescriptor)) {
@@ -262,33 +264,29 @@ else if ("C".equals(this.exitTypeDescriptor)) {
262264
//depthPlusOne(exitTypeDescriptor)+"Ljava/lang/Object;");
263265
insn = AALOAD;
264266
}
265-
SpelNodeImpl index = this.children[0];
266-
cf.enterCompilationScope();
267-
index.generateCode(mv, cf);
268-
cf.exitCompilationScope();
267+
268+
generateIndexCode(mv, cf, index, int.class);
269269
mv.visitInsn(insn);
270270
}
271271

272272
else if (this.indexedType == IndexedType.LIST) {
273273
mv.visitTypeInsn(CHECKCAST, "java/util/List");
274-
cf.enterCompilationScope();
275-
this.children[0].generateCode(mv, cf);
276-
cf.exitCompilationScope();
274+
generateIndexCode(mv, cf, index, int.class);
277275
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true);
278276
}
279277

280278
else if (this.indexedType == IndexedType.MAP) {
281279
mv.visitTypeInsn(CHECKCAST, "java/util/Map");
282280
// Special case when the key is an unquoted string literal that will be parsed as
283281
// a property/field reference
284-
if ((this.children[0] instanceof PropertyOrFieldReference)) {
282+
if (index instanceof PropertyOrFieldReference) {
285283
PropertyOrFieldReference reference = (PropertyOrFieldReference) this.children[0];
286284
String mapKeyName = reference.getName();
287285
mv.visitLdcInsn(mapKeyName);
288286
}
289287
else {
290288
cf.enterCompilationScope();
291-
this.children[0].generateCode(mv, cf);
289+
index.generateCode(mv, cf);
292290
cf.exitCompilationScope();
293291
}
294292
mv.visitMethodInsn(
@@ -325,6 +323,11 @@ else if (this.indexedType == IndexedType.OBJECT) {
325323
cf.pushDescriptor(this.exitTypeDescriptor);
326324
}
327325

326+
private void generateIndexCode(MethodVisitor mv, CodeFlow cf, SpelNodeImpl indexNode, Class<?> indexType) {
327+
String indexDesc = CodeFlow.toDescriptor(indexType);
328+
generateCodeForArgument(mv, cf, indexNode, indexDesc);
329+
}
330+
328331
@Override
329332
public String toStringAST() {
330333
StringJoiner sj = new StringJoiner(",", "[", "]");

0 commit comments

Comments
 (0)