Vallid bytecode for jvm, but failed to pass the CheckClassAdapter
// access flags 0x9
public static get(Ljava/lang/String;)Ljava/lang/String;
ALOAD 0
ASTORE 1
ICONST_0
ISTORE 0 <--- the slot of the argument overwritten.
ALOAD 1
ARETURN
MAXSTACK = 1
MAXLOCALS = 2
Expected Behavior
Succeed to pass over the CheckClassAdapter
Current Behavior
java.lang.IllegalArgumentException: Error at instruction 0: Expected an object reference, but found I get(Ljava/lang/String;)Ljava/lang/String;
00000 I R : : ALOAD 0
00001 R . : R : ASTORE 1
00002 R R : : ICONST_0
00003 R R : I : ISTORE 0
00004 I R : : ALOAD 1
00005 I R : R : ARETURN
at org.objectweb.asm.util.CheckMethodAdapter$1.throwError(CheckMethodAdapter.java:489)
at org.objectweb.asm.util.CheckMethodAdapter$1.visitEnd(CheckMethodAdapter.java:475)
at org.objectweb.asm.MethodVisitor.visitEnd(MethodVisitor.java:796)
at org.objectweb.asm.util.CheckMethodAdapter.visitEnd(CheckMethodAdapter.java:1044)
at TestAsm.test(TestAsm.java:35)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 0: Expected an object reference, but found I
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:284)
at org.objectweb.asm.util.CheckMethodAdapter$1.visitEnd(CheckMethodAdapter.java:470)
... 6 more
Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Expected an object reference, but found I
at org.objectweb.asm.tree.analysis.BasicVerifier.copyOperation(BasicVerifier.java:90)
at org.objectweb.asm.tree.analysis.BasicVerifier.copyOperation(BasicVerifier.java:44)
at org.objectweb.asm.tree.analysis.Frame.execute(Frame.java:326)
at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:171)
... 7 more
Steps to Reproduce
@Test
public void test() throws Exception {
ClassWriter writer = new ClassWriter(0);
ClassVisitor cv = new CheckClassAdapter(writer);
// ClassVisitor cv = writer;
cv.visit(V1_7, ACC_PUBLIC | ACC_SUPER, "SampleBytecode", null, "java/lang/Object", null);
{
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, "get", "(Ljava/lang/String;)Ljava/lang/String;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ASTORE, 1);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 2);
mv.visitEnd();
}
cv.visitEnd();
byte[] content = writer.toByteArray();
new ClassLoader() {
{
Method method = defineClass(null, content, 0, content.length).getMethod("get", String.class);
assertEquals("abc", method.invoke(null, "abc"));
}
};
}
Suggestion to fix
diff --git a/asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java b/asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java
--- a/asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java
+++ b/asm-util/src/main/java/org/objectweb/asm/util/CheckFrameAnalyzer.java
@@ -123,7 +123,7 @@ class CheckFrameAnalyzer<V extends Value> extends Analyzer<V> {
}
Frame<V>[] frames = getFrames();
- Frame<V> currentFrame = frames[0];
+ Frame<V> currentFrame = newFrame(frames[0]);
expandFrames(owner, method, currentFrame);
for (int insnIndex = 0; insnIndex < insnList.size(); ++insnIndex) {
Frame<V> oldFrame = frames[insnIndex];