This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

problem in gij bytecode verifier


Hi,

I've found a problem in gij's bytecode verifier. Consider the following
(legal) code:

public class Main {
    // I is an interface
    public static void a (I i) {}

    public static void main (String[] argv) {
        // A implements I ...
        I i = new A ();
        if (foo()) {
            // ... and so does B.
            i = new B ();
        }
        a (i);
    }

    public static boolean foo () {
        return true;
    }
}

resulting in the following bytecode:

Method name:"main" public static Signature: 9=(java.lang.String[])void
Attribute "Code", length:63, max_stack:2, max_locals:2, code_length:27
  0: new #11=<Class A>
  3: dup
  4: invokespecial #15=<Method A.<init> ()void>
  7: astore_1
  8: invokestatic #19=<Method Main.foo ()boolean>
 11: ifeq 22
 14: new #21=<Class B>
 17: dup
 18: invokespecial #22=<Method B.<init> ()void>
 21: astore_1
 22: aload_1
 23: invokestatic #24=<Method Main.a (I)void>
 26: return

This fails during verification with:

Exception in thread "main" java.lang.VerifyError: verification failed at PC 23 
in Main:main(([Ljava.lang.String;)V): incompatible type on stack
(...)

The error does not occur when A extends B or vice versa.

I suspect that during the state merge at PC 22, the information about the
interface implemented by A and B is lost, leading to an plain Object passed to a().
The following snippet from type->merge() in libjava/verify.cc led to this suspicion:

(...)
  // Ordinarily this terminates when we hit Object...
  while (k != NULL)
    {
      if (is_assignable_from_slow (k, oldk))
        break;
      k = k->getSuperclass ();
      changed = true;
    }
  // ... but K could have been an interface, in which
  // case we'll end up here.  We just convert this
  // into Object.
  if (k == NULL)
    k = &java::lang::Object::class$;
(...)

but I'm neither sure that my analysis is correct, nor what an appropriate fix
would be.

Any hints would be very welcome. Complete testcase attached.

regards,

Sonja

-- 
Sonja Krause-Harder (skh@suse.de)                       SuSE Linux AG

Attachment: interface_verify_error.tar.gz
Description: application/gunzip


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]