BZ #49: VerifyError with obfuscated classes

Status fields:

creation_ts:2008-03-04 23:29
component:jit
version:default branch
rep_platform:i386
op_sys:Linux
bug_status:RESOLVED
resolution:FIXED
reporter:glegris-bugzilla@thenesis.org
While trying to start Opera Mini 4 with MIDPath (SVN revision 216) a VerifyError
occurred at some point in the obfuscated code.

This problem doesn't occur with JamVM or the Sun VM.

Steps to reproduce the problem
------------------------------

1) Load the debug package :
> wget http://midpath.thenesis.org/downloads/midpath-verifyerror-debug-040308.tar.gz
> tar -zxvf midpath-verifyerror-debug-040308.tar.gz

2) Load Opera Mini 4.0.10406:
> wget http://mini.opera.com/global/opera-mini-4.0.10406-advanced-int.jar

3) Start the script:

> ./MIDPath-cacao-debug.sh

4) Add the breakpoint:

(gdb) handle SIGILL SIGSEGV SIGPWR SIGXCPU nostop noprint
(gdb) break exceptions_throw_verifyerror
(gdb) run

Result
------

Breakpoint 2, exceptions_throw_verifyerror (m=0x8b132a4,
    message=0xb7d97120 "Local variable type mismatch") at exceptions.c:1208
1208            if (m != NULL)
(gdb) bt
#0  exceptions_throw_verifyerror (m=0x8b132a4,
    message=0xb7d97120 "Local variable type mismatch") at exceptions.c:1208
#1  0xb7d73117 in typecheck (jd=0x862b698) at src/vm/jit/verify/icmds.c:566
#2  0xb7d6091a in jit_compile_intern (jd=0x862b698) at jit.c:699
#3  0xb7d6104b in jit_compile (m=0x8b132a4) at jit.c:414
#4  0xb7d611f2 in jit_compile_handle (m=0x8b132a4, pv=0xb67a2018,
    ra=0xb67a334b, mptr=0xb680dfd0) at jit.c:1061
#5  0xb7d3f6af in signal_handle (type=9, val=-1233068080, pv=0xb680dfd0,
    sp=0xb72ded40, ra=0xb67a334b, xpc=0xb67a3349, context=0xb72dea4c)
    at signal.c:342
#6  0xb7d6068b in md_signal_handler_sigsegv (sig=11, siginfo=0xb72de9cc,
    _p=0xb72dea4c) at md-os.c:137
#7  <signal handler called>
#8  0xb680dfd0 in ?? ()
#9  0xb67a334b in ?? ()
#10 0x08143e10 in ?? ()
#11 0x081f81c0 in ?? ()
#12 0x0811ff80 in ?? ()
#13 0xb7f198c5 in pthread_getspecific () from /lib/i686/cmov/libpthread.so.0
Previous frame inner to this frame (corrupt stack?)
(gdb) f 2
#2  0xb7d6091a in jit_compile_intern (jd=0x862b698) at jit.c:699
699                             if (!typecheck(jd)) {
(gdb) call show_method(jd, 2)

d.Code(Ljavax/microedition/lcdui/Graphics;)Z PRIVATE (mono) (impl)

(see the attached file for the full trace)

Comment #1 by glegris-bugzilla@thenesis.org on 2008-03-04 23:33:14

Created an attachment (id=33)
Full trace

Comment #2 by twisti@complang.tuwien.ac.at on 2008-03-12 09:20:20

SVN revision 216?  Are you sure?

Edwin, could you take a look at this one?

Comment #3 by edwin.steiner@gmx.net on 2008-03-15 09:48:36

I tried to download the "debug package", but it did not work:

wget http://midpath.thenesis.org/downloads/midpath-verifyerror-debug-040308.tar.gz
--21:27:54--  http://midpath.thenesis.org/downloads/midpath-verifyerror-
debug-040308.tar.gz
           => `midpath-verifyerror-debug-040308.tar.gz'
Resolving midpath.thenesis.org... 82.121.44.250
Connecting to midpath.thenesis.org|82.121.44.250|:80... failed: Connection refused.

-Edwin

Comment #4 by glegris-bugzilla@thenesis.org on 2008-03-15 10:28:00

(In reply to comment #3)
> I tried to download the "debug package", but it did not work:
>
> wget
> http://midpath.thenesis.org/downloads/midpath-verifyerror-debug-040308.tar.gz
> --21:27:54--
> http://midpath.thenesis.org/downloads/midpath-verifyerror-debug-040308.tar.gz
>            => `midpath-verifyerror-debug-040308.tar.gz'
> Resolving midpath.thenesis.org... 82.121.44.250
> Connecting to midpath.thenesis.org|82.121.44.250|:80... failed: Connection
> refused.
>
> -Edwin
>

Sorry for that. The web server was down a few hours yesterday... It should work now.

Guillaume

Comment #5 by edwin.steiner@gmx.net on 2008-03-16 14:24:42

I found the bug and it is a rather nasty one:

The problem is bytecode like this sequence:

aload_0
aload_0
arraylength
istore_0
astore_1

The bytecode is legal and the local variables
should have the types (0=INT,1=ADR) afterwards.

CACAO, however, infers (0=INT,1=void). The problem is in the handling
of the istore_0. As javalocal 0 is used for both INT and ADR types,
it is split into two CACAO variables. The javalocal to CACAO mapping
looks like this:

javalocal 0 as INT -> CACAO local Li0
javalocal 0 as ADR -> CACAO local La1
javalocal 1 as ADR -> CACAO local La2

When istore_0 writes Li0, the variable La1 must be marked as invalidated
(type void), because it is the same javalocal (index 0). This is done by
typecheck_invalidate_locals. The problem is that at that time a copy
of La1 is still on the "stack". As the stack has already been eliminated,
there is no separate variable for the stack slot, so the "stack slot"
is invalidated, too. The following astore copies the invalidated La1 to
La2, making it "void". When one of the following blocks then loads La2, a
verifier error is signalled.

The actual bug seems to be in stack_analyse. It should create a temporary
variable for the destination of the first aload_0, I think, to avoid the
conflict with the istore_0. I have to think about that some more, as it has
been a long time since I worked on stack_analyse.

-Edwin

Comment #6 by edwin.steiner@gmx.net on 2008-03-16 17:36:21

BTW, Guillaume, thanks for this excellent bug report. :)
Such a good recipe for reproduction is very rare indeed.

I think this bug was introduced with the variable renaming
in stack_analyse. In particular, the following conflict check
which had been correct up to this point, became insufficient
because of variable renaming:

stack.c:3267:
    if ((copy->varkind == LOCALVAR) &&
        (copy->varnum == varindex))

The check can miss conflicts because the same javalocal
is mapped to different "varnum"s if it is used for multiple
types.

One could say that the check is correct, as there is no
conflict of _CACAO_ variables, BUT: Register allocation assumes
that variables corresponding to the same javalocal can be
coalesced without doing its own conflict checks! (At least it
was this way when I worked on these parts of CACAO.)
So the verifier is correct in reporting the error as otherwise
an invalid allocation could be made. - Thus we must fix
the conflict check.

I'll try to prepare a patch.

-Edwin

Comment #7 by edwin.steiner@gmx.net on 2008-03-16 18:11:43

Created an attachment (id=34)
trial patch for checking conflicts using the javaindex

Guillaume, could you please try the attached patch?

@twisti: Please do not commit as is. If we want to check
conflicts this way, I will put the reverselocalmap into jd,
so the verifier can reuse it instead of building its own.

-Edwin

Comment #8 by twisti@complang.tuwien.ac.at on 2008-03-16 20:11:24

OK, I'll stay tuned.  Do you still have problems with commit access?

Comment #9 by glegris-bugzilla@thenesis.org on 2008-03-17 14:31:07

(In reply to comment #7)
> Created an attachment (id=34) [details]
> trial patch for checking conflicts using the javaindex
>
> Guillaume, could you please try the attached patch?
>
> @twisti: Please do not commit as is. If we want to check
> conflicts this way, I will put the reverselocalmap into jd,
> so the verifier can reuse it instead of building its own.
>
> -Edwin
>

It works fine with the patch now !

Guillaume

Comment #10 by edwin.steiner@gmx.net on 2008-04-01 12:01:11

Fixed with http://mips.complang.tuwien.ac.at/hg/cacao/rev/08444c22b833

Attachment id=33

date:2008-03-04 23:33
desc:Full trace
type:text/plain
download:bug-obfscated_classes-verifyerror.txt

Attachment id=34

date:2008-03-16 18:11
desc:trial patch for checking conflicts using the javaindex
type:text/plain
download:check_javaindex_conflicts.patch