Incorrect merging of frames
Consider the following Jasmin code:
.class public SimpleDecoherence
.super java/lang/Object
.method public static foo(J)V
.limit stack 1
.limit locals 2
iconst_0
ifne skip
iconst_0
istore_1
skip:
return
.end method
The following test case (using ASM 3.1) reads the compiled class, writes it
with COMPUTE_FRAMES, rereads and prints.
ClassReader cr = new ClassReader("SimpleDecoherence");
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cr.accept(cw, 0);
ClassReader cr2 = new ClassReader(cw.toByteArray());
TraceClassVisitor tcv = new TraceClassVisitor(new PrintWriter(System.out));
cr2.accept(tcv, 0);
Here is the result:
public static foo(J)V
FRAME FULL [] []
ICONST_0
IFNE L0
ICONST_0
ISTORE 1
L0
FRAME FULL [J] []
RETURN
MAXSTACK = 1
MAXLOCALS = 2
In the second FRAME, the parameter is still "J T", while it should be "T T". I
tried to fix this as follows in org.objectweb.asm.Frame (near line 930, the
third t2 compairson):
case Opcodes.ISTORE:
case Opcodes.FSTORE:
case Opcodes.ASTORE:
t1 = pop();
set(arg, t1);
if (arg > 0) {
t2 = get(arg - 1);
// if t2 is of kind STACK or LOCAL we cannot know its size!
if (t2 == LONG || t2 == DOUBLE || t2 == (LOCAL | 0)) {
set(arg - 1, TOP);
}
}
break;
and similar for LSTORE/DSTORE. The result is now:
public static foo(J)V
FRAME FULL [] []
ICONST_0
IFNE L0
ICONST_0
ISTORE 1
L0
FRAME FULL [] []
RETURN
MAXSTACK = 1
MAXLOCALS = 2
However, changing descriptor of foo to (I)V results in variable 0 turned to T
as well. I guess that's why the comment about not knowing the size is there.
Unfortunately, I am not sufficiently familiar with the implementation to
provide a real fix... (Don't really understand why t2 isn't just LONG there.)
NOTE: technically, the code (after COMPUTE_FRAMES) passes verification, but an
incorrect frame is still a problem for code that analyzes frames.