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

The CodeBuilder.trying(BlockCodeBuilder,CatchBuilder) method generates corrupted bytecode in certain cases

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • None
    • 24, 25, 26
    • core-libs
    • None

      A valid method *) was converted into an equivalent piece of ClassFile API code **) for testing purposes.
      *)
      public static int run(int i) {
          try {
              if (i < 0) {
                  throw new IllegalArgumentException();
              }
              throw new IndexOutOfBoundsException();
          } catch (IllegalArgumentException e) {
              return 0;
          } catch (Exception e) {
              return 1000;
          }
      }
      **)
      mb.withCode(cb -> {
          cb.trying(
                  tb -> {
                      tb.block(bb -> {
                          bb.iload(0);
                          bb.branch(Opcode.IFGE, bb.endLabel()); // ifge L12
                          bb.new_(CD_IAE);
                          bb.dup();
                          bb.invokespecial(CD_IAE, "<init>", MTD_void);
                          bb.athrow();
                      });
                      tb.block(bb -> {
                          bb.new_(CD_IOBE);
                          bb.dup();
                          bb.invokespecial(CD_IOBE, "<init>", MTD_void);
                          bb.athrow();
                      });
                      // 20: {opcode: GOTO, target: 31} added by the ClassFile API
                      // "31" exceeds the end of the Code attribute.
                      // can be fixed by adding tb.return_();
                  },
                  catchBuilder -> {
                      catchBuilder.catching(CD_IAE, bb -> {
                          bb.aload(1); // astore_1
                          bb.iconst_0(); // iconst_0
                          bb.ireturn(); // ireturn
                      });
                      catchBuilder.catching(CD_E, bb -> {
                          bb.aload(1); // astore_1
                          bb.sipush(1000); // sipush 1000
                          bb.ireturn(); // ireturn
                      });
                  }
          );
      });
      Then, building the classfile bytes throws the following exception:
      java.lang.IllegalArgumentException: Detected branch target out of bytecode range at bytecode offset 20 of method run(int)
      — max stack: 65535
      — max locals: 65535
      — attributes: []
      // stack map frame @0: {locals: [int], stack: []}
      0: {opcode: ILOAD_0, slot: 0}
      1: {opcode: IFGE, target: 12}
      4: {opcode: NEW, type: java/lang/IllegalArgumentException}
      7: {opcode: DUP}
      8: {opcode: INVOKESPECIAL, owner: java/lang/IllegalArgumentException, method name: <init>, method type: ()V}
      11: {opcode: ATHROW}
      12: {opcode: NEW, type: java/lang/IndexOutOfBoundsException}
      15: {opcode: DUP}
      16: {opcode: INVOKESPECIAL, owner: java/lang/IndexOutOfBoundsException, method name: <init>, method type: ()V}
      19: {opcode: ATHROW}
      20: {opcode: GOTO, target: 31}
      23: {opcode: ALOAD_1, slot: 1}
      24: {opcode: ICONST_0, constant value: 0}
      25: {opcode: IRETURN}
      26: {opcode: ALOAD_1, slot: 1}
      27: {opcode: SIPUSH, constant value: 1000}
      30: {opcode: IRETURN}

      As can be seen, the instruction at offset 20: {opcode: GOTO, target: 31} was added to the output. This instruction jumps beyond the valid code range.

      An example of the code is attached.

            liach Chen Liang
            lkuskov Leonid Kuskov
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: