Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4210446

compiler generates unverifiable code

XMLWordPrintable

    • generic, x86
    • generic, windows_nt

      ame: gb36485 Date: 02/10/99


      Here's an example class that when
      compiled with javac, sj, and jikes fails
      to verify. As far as I can tell the
      problem is not in the compilers nor in
      the VM but in the verification algorithm
      itself (see below). At any rate it seems
      that javac shouldn't produce .class
      files that don't verify. Note too, that
      while this example is contrived this
      actually came up in real code.

      package noverify;

      public final class Test {

        public void doit(Exception e) {
          try {
            int a = 0;
            try {
              //if (a == 0) throw e;
              return;
            } catch (Exception e2) {
              a++;
            }
          } finally {
            long b = 0;
            b++;
          }
        }
        public static void main(String[] argv) {}
      }

      Here's the error from java (under Java2):

      88% java -verify noverify.Test
      Exception in thread "main"
      java.lang.VerifyError: (class:
      noverify/Test, method: doit signature:
      (Ljava/lang/Exception;)V) Accessing
      value from uninitialized register 4
      89%

      And here are the bytecodes:

      Compiled from Test.java
      public final class noverify.Test extends java.lang.Object {
          public noverify.Test();
          public void doit(java.lang.Exception);
          public static void main(java.lang.String[]);
      }

      Method noverify.Test()
         0 aload_0
         1 invokespecial #4 <Method java.lang.Object()>
         4 return

      Method void doit(java.lang.Exception)
         0 iconst_0
         1 istore 4
         3 jsr 26
         6 return
         7 pop
         8 iinc 4 1
        11 goto 14
        14 jsr 26
        17 goto 38
        20 astore_2
        21 jsr 26
        24 aload_2
        25 athrow
        26 astore_3
        27 lconst_0
        28 lstore 4
        30 lload 4
        32 lconst_1
        33 ladd
        34 lstore 4
        36 ret 3
        38 return
      Exception table:
         from to target type
           3 7 7 <Class java.lang.Exception>
           0 14 20 any

      Method void main(java.lang.String[])
         0 return


      I think the problem is with the iinc at
      8 and I think that the verifier thinks
      there's a problem because of the
      definition of "successor instructions"
      given on pages 129-30 of the VM spec:

       3. Determine the instructions that can
          follow the current instruction.
          Successor instructions can be one of
          the following:

         o The next instruction, if the
           current instruction is not an
           unconditional control transfer
           instruction (for instance goto,
           return or athrow). Verification
           fails if it is possible to "fall
           off" the last instruction of the
           method.

         o The target(s) of a conditional or
           unconditional branch or switch.

         o Any exception handlers for this
           instruction.

      The problem is that those three bullet
      items seem to be and'ed together: i.e. an
      instruction that is covered by an
      exception handler has as its successors
      both the following instruction *and* the
      first instruction of the exception
      handler. And this is true even when the
      current instruction can't throw an
      exception -- for example a return op. So
      when verifying the bytecodes above, the
      verifier analyzes the jsr at 3 and
      merges the state of the local variables
      from the ret at 36 (which includes the
      fact that register 4 has a long in it);
      then it analyzes the return which is
      fine and computes its successor
      instructions. But the successor list
      includes the pop at 7 which is then
      succeeded by the iinc at 8 which fails to
      verify because register 4 is marked as
      containing a long and we're trying to
      load an int. So it seems perhaps that
      the VM spec should be modified so the
      third bullet point above reads something
      like:

       o Any exception handlers for this
         instruction if the current
         instruction can throw an exception
         (e.g. invokevirtual, idiv)

      Cheers,
      Peter
      (Review ID: 47838)
      ======================================================================

            wmaddoxsunw William Maddox (Inactive)
            gbrachasunw Gilad Bracha (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: