Fix VerifyError for SpEL ternary compilation
The ternary expression node was failing to generate the necessary unboxing bytecode when the condition part of the expression returned a boxed Boolean rather than a primitive boolean. Also fixed here is an IllegalAccessError that was seen in the same expression due to generating a CHECKCAST bytecode for a private type. Issue: SPR-12271
This commit is contained in:
@@ -446,8 +446,10 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This is chopping off the 'L' to leave us with "java/lang/String"
|
||||
mv.visitTypeInsn(CHECKCAST, descriptor.substring(1));
|
||||
if (!descriptor.equals("Ljava/lang/Object")) {
|
||||
// This is chopping off the 'L' to leave us with "java/lang/String"
|
||||
mv.visitTypeInsn(CHECKCAST, descriptor.substring(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ public class Ternary extends SpelNodeImpl {
|
||||
computeExitTypeDescriptor();
|
||||
codeflow.enterCompilationScope();
|
||||
this.children[0].generateCode(mv, codeflow);
|
||||
if (!CodeFlow.isPrimitive(codeflow.lastDescriptor())) {
|
||||
CodeFlow.insertUnboxInsns(mv, 'Z', codeflow.lastDescriptor());
|
||||
}
|
||||
codeflow.exitCompilationScope();
|
||||
Label elseTarget = new Label();
|
||||
Label endOfIf = new Label();
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.expression.spel.ast;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.TypedValue;
|
||||
@@ -71,7 +73,17 @@ public class VariableReference extends SpelNodeImpl {
|
||||
return result;
|
||||
}
|
||||
TypedValue result = state.lookupVariable(this.name);
|
||||
this.exitTypeDescriptor = CodeFlow.toDescriptorFromObject(result.getValue());
|
||||
Object value = result.getValue();
|
||||
if (value == null || !Modifier.isPublic(value.getClass().getModifiers())) {
|
||||
// If the type is not public then when generateCode produces a checkcast to it
|
||||
// then an IllegalAccessError will occur.
|
||||
// If resorting to Object isn't sufficient, the hierarchy could be traversed for
|
||||
// the first public type.
|
||||
this.exitTypeDescriptor ="Ljava/lang/Object";
|
||||
}
|
||||
else {
|
||||
this.exitTypeDescriptor = CodeFlow.toDescriptorFromObject(value);
|
||||
}
|
||||
// a null value will mean either the value was null or the variable was not found
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user