RFR(XS): JDK-8040018 Remove bad assert in ClassFileParser.cpp
Lois Foltan
lois.foltan at oracle.com
Wed Apr 16 23:46:31 UTC 2014
Hi Harold,
Overall I think the change to classFileParser.cpp looks good. My only
comments are about the test case, ClassFileParserBug.java. I personally
find the readability of the .jcod file cumbersome. I have attached a
ASM file, TestBadBootstrapMethodsAttr.java, in case you would prefer a
straight java file. It needs to be cleaned up before it can be checked
into the test system, but it does demonstrate the issue. Also, is it
possible to have the test case live in test/runtime/verifier instead of
a new directory?
If you feel that the .jcod file and test.jar file better exercise this
class format issue, then by all means you have my review to go forward.
Thanks,
Lois
On 4/16/2014 1:49 PM, harold seigel wrote:
> Hi,
>
> Please review this small change to fix bug JDK-8040018 for JDK-9. The
> fix removes the assert because it can be triggered by a class file
> containing an incorrect attribute_length value for the BoostrapMethods
> attribute, not just by a JVM inconsistency. Removing the assert lets
> the following guarantee_property() call catch the problem and throw a
> java.lang.ClassFormatError exception.
>
> The fix was tested with JPRT, JCK lang, JCK vm, hotspot jtreg, and nsk
> quick tests. The new test was tested on Linux and Windows.
>
> Open webrev at: http://cr.openjdk.java.net/~hseigel/bug_8040018/
> <http://cr.openjdk.java.net/%7Ehseigel/bug_8040018/>
> Bug: https://bugs.openjdk.java.net/browse/JDK-8040018
>
> Thanks! Harold
-------------- next part --------------
import java.util.*;
import jdk.internal.org.objectweb.asm.*;
public class TestBadBootstrapMethodsAttr implements Opcodes {
static final String classLambdaMathName = "LambdaMath";
public static void main(String[] args) throws Exception {
ClassLoader cl = new ClassLoader() {
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (findLoadedClass(name) != null) {
return findLoadedClass(name);
}
if (classLambdaMathName.equals(name)) {
try {
byte[] classFile = dump();
return defineClass(classLambdaMathName, classFile, 0, classFile.length);
} catch (Exception e) {
}
}
return super.loadClass(name);
}
};
cl.loadClass(classLambdaMathName).getDeclaredMethod("main_test").invoke(null);
}
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(52, ACC_PUBLIC + ACC_SUPER, "LambdaMath", null, "java/lang/Object", null);
cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main_test", "()V", null, null);
mv.visitCode();
mv.visitIntInsn(BIPUSH, 7);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Integer");
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitInsn(ICONST_1);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_1);
mv.visitInsn(ICONST_2);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_2);
mv.visitInsn(ICONST_3);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitInsn(ICONST_4);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_4);
mv.visitInsn(ICONST_5);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_5);
mv.visitIntInsn(BIPUSH, 6);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitInsn(DUP);
mv.visitIntInsn(BIPUSH, 6);
mv.visitIntInsn(BIPUSH, 7);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
mv.visitInsn(AASTORE);
mv.visitMethodInsn(INVOKESTATIC, "java/util/Arrays", "asList", "([Ljava/lang/Object;)Ljava/util/List;", false);
mv.visitVarInsn(ASTORE, 1);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Print all numbers:");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitVarInsn(ALOAD, 1);
mv.visitInvokeDynamicInsn("test", "()Ljava/util/function/Predicate;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("(Ljava/lang/Object;)Z"), new Handle(Opcodes.H_INVOKESTATIC, "LambdaMath", "lambda$main$0", "(Ljava/lang/Integer;)Z"), Type.getType("(Ljava/lang/Integer;)Z")});
mv.visitMethodInsn(INVOKESTATIC, "LambdaMath", "evaluate", "(Ljava/util/List;Ljava/util/function/Predicate;)V", false);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Print no numbers:");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitVarInsn(ALOAD, 1);
mv.visitInvokeDynamicInsn("test", "()Ljava/util/function/Predicate;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("(Ljava/lang/Object;)Z"), new Handle(Opcodes.H_INVOKESTATIC, "LambdaMath", "lambda$main$1", "(Ljava/lang/Integer;)Z"), Type.getType("(Ljava/lang/Integer;)Z")});
mv.visitMethodInsn(INVOKESTATIC, "LambdaMath", "evaluate", "(Ljava/util/List;Ljava/util/function/Predicate;)V", false);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Print even numbers:");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitVarInsn(ALOAD, 1);
mv.visitInvokeDynamicInsn("test", "()Ljava/util/function/Predicate;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("(Ljava/lang/Object;)Z"), new Handle(Opcodes.H_INVOKESTATIC, "LambdaMath", "lambda$main$2", "(Ljava/lang/Integer;)Z"), Type.getType("(Ljava/lang/Integer;)Z")});
mv.visitMethodInsn(INVOKESTATIC, "LambdaMath", "evaluate", "(Ljava/util/List;Ljava/util/function/Predicate;)V", false);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Print odd numbers:");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitVarInsn(ALOAD, 1);
mv.visitInvokeDynamicInsn("test", "()Ljava/util/function/Predicate;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("(Ljava/lang/Object;)Z"), new Handle(Opcodes.H_INVOKESTATIC, "LambdaMath", "lambda$main$3", "(Ljava/lang/Integer;)Z"), Type.getType("(Ljava/lang/Integer;)Z")});
mv.visitMethodInsn(INVOKESTATIC, "LambdaMath", "evaluate", "(Ljava/util/List;Ljava/util/function/Predicate;)V", false);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Print numbers greater than 5:");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitVarInsn(ALOAD, 1);
mv.visitInvokeDynamicInsn("test", "()Ljava/util/function/Predicate;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("(Ljava/lang/Object;)Z")});
mv.visitMethodInsn(INVOKESTATIC, "LambdaMath", "evaluate", "(Ljava/util/List;Ljava/util/function/Predicate;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(4, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "evaluate", "(Ljava/util/List;Ljava/util/function/Predicate;)V", "(Ljava/util/List<Ljava/lang/Integer;>;Ljava/util/function/Predicate<Ljava/lang/Integer;>;)V", null);
mv.visitCode();
Label l0 = new Label();
Label l1 = new Label();
Label l2 = new Label();
mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;", true);
mv.visitVarInsn(ASTORE, 2);
Label l3 = new Label();
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {"java/util/Iterator"}, 0, null);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);
mv.visitJumpInsn(IFEQ, l1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);
mv.visitInsn(MONITORENTER);
mv.visitInsn(NOP);
mv.visitInsn(ICONST_M1);
mv.visitVarInsn(ISTORE, 3);
mv.visitVarInsn(ALOAD, 1);
//mv.visitVarInsn(ILOAD, 3);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/function/Predicate", "test", "(Ljava/lang/Object;)Z", true);
Label l4 = new Label();
mv.visitJumpInsn(IFEQ, l4);
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitTypeInsn(NEW, "java/lang/StringFuilder");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringFuilder", "<init>", "()V", false);
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringFuilder", "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;", false);
mv.visitLdcInsn(" ");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringFuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringFuilder", "toString", "()Ljava/lang/String;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitLabel(l4);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitJumpInsn(GOTO, l3);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_CHOP,1, null, 0, null);
Label l5 = new Label();
mv.visitJumpInsn(GOTO, l5);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Throwable"});
mv.visitVarInsn(ASTORE, 2);
mv.visitLabel(l5);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 4);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$main$4", "(Ljava/lang/Integer;)Z", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
mv.visitInsn(ICONST_5);
Label l0 = new Label();
mv.visitJumpInsn(IF_ICMPLE, l0);
mv.visitInsn(ICONST_1);
Label l1 = new Label();
mv.visitJumpInsn(GOTO, l1);
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(ICONST_0);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
mv.visitInsn(IRETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$main$3", "(Ljava/lang/Integer;)Z", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
mv.visitInsn(ICONST_2);
mv.visitInsn(IREM);
mv.visitInsn(ICONST_1);
Label l0 = new Label();
mv.visitJumpInsn(IF_ICMPNE, l0);
mv.visitInsn(ICONST_1);
Label l1 = new Label();
mv.visitJumpInsn(GOTO, l1);
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(ICONST_0);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
mv.visitInsn(IRETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$main$2", "(Ljava/lang/Integer;)Z", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
mv.visitInsn(ICONST_2);
mv.visitInsn(IREM);
Label l0 = new Label();
mv.visitJumpInsn(IFNE, l0);
mv.visitInsn(ICONST_1);
Label l1 = new Label();
mv.visitJumpInsn(GOTO, l1);
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(ICONST_0);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
mv.visitInsn(IRETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$main$1", "(Ljava/lang/Integer;)Z", null, null);
mv.visitCode();
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$main$0", "(Ljava/lang/Integer;)Z", null, null);
mv.visitCode();
mv.visitInsn(ICONST_1);
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
}
More information about the hotspot-runtime-dev
mailing list