Skip to content

Latest commit

 

History

History
60 lines (51 loc) · 2.86 KB

README.md

File metadata and controls

60 lines (51 loc) · 2.86 KB

The aim of this code is to reproduce a bug in javac, the Java compiler included in the Java Development Kit. This bug does not appear to lead to incorrect bytecode execution, but it causes the ASM bytecode engineering library to fail. A number of tools, such as Findbugs and JaCoCo, rely on ASM for bytecode analysis and thus also fail on affected bytecode.

This was investigated by Oracle as OpenJDK bug 8144185, and is fixed in JDK 8u172.

Stack traces of ASM exceptions caused by the bug include the following (ASM v5.0.2):

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 42
	at org.objectweb.asm.ClassReader.readLabel(ClassReader.java:2174)
	at org.objectweb.asm.ClassReader.readTypeAnnotations(ClassReader.java:1598)
	at org.objectweb.asm.ClassReader.readCode(ClassReader.java:1184)
	at org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1017)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:693)
	at org.objectweb.asm.ClassReader.accept(ClassReader.java:506)

The bug results in an incorrect value of the length field in the localvar_target item (page 147 of the Java Virtual Machine Specification, Java SE 8 edition). The value of the length field ends up exceeding the length of the method bytecode, which trips up ASM because the labels array is pre-initialized based on that bytecode length. It appears that a combination of a type annotation and lambda code might be required to trigger the javac bug.

The Eclipse Java Compiler is unaffected.

To reproduce the bug, run ./check_bug from the repository root.

Relevant excerpt of javap -v bin.ReproduceJavacBug, after compilation with javac 1.8.0_65:

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class java/util/ArrayList
         3: dup
         4: invokespecial #3                  // Method java/util/ArrayList."":()V
         7: astore_1
         8: aload_1
         9: invokeinterface #4,  1            // InterfaceMethod java/util/Collection.stream:()Ljava/util/stream/Stream;
        14: aload_1
        15: invokedynamic #5,  0              // InvokeDynamic #0:accept:(Ljava/util/Collection;)Ljava/util/function/Consumer;
        20: invokeinterface #6,  2            // InterfaceMethod java/util/stream/Stream.forEach:(Ljava/util/function/Consumer;)V
        25: return
      LineNumberTable:
        line 29: 0
        line 30: 8
        line 36: 25
      RuntimeInvisibleTypeAnnotations:
        0: #30(): LOCAL_VARIABLE, {start_pc=0, length=42, index=0}, location=[TYPE_ARGUMENT(0)]

length=42 extends beyond the return statement at offset 25.