From 44be5edf5aa661169c665aa9386e5930a3632524 Mon Sep 17 00:00:00 2001 From: "Archie L. Cobbs" Date: Wed, 4 Jan 2023 17:50:32 +0000 Subject: [PATCH] 8219810: javac throws NullPointerException Reviewed-by: vromero --- .../com/sun/tools/javac/jvm/ClassReader.java | 11 ++- .../tools/javac/resources/compiler.properties | 3 + .../classreader/8219810/BadFieldFlags.jcod | 76 ++++++++++++++++++ .../8219810/BadFieldFlagsTest.java | 12 +++ .../classreader/8219810/BadFieldFlagsTest.out | 2 + .../classreader/8219810/BadMethodFlags.jcod | 77 +++++++++++++++++++ .../8219810/BadMethodFlagsTest.java | 12 +++ .../8219810/BadMethodFlagsTest.out | 2 + .../tools/javac/diags/examples.not-yet.txt | 1 + 9 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod create mode 100644 test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java create mode 100644 test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out create mode 100644 test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod create mode 100644 test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java create mode 100644 test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index d3f252bab0d..d47617b30ab 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -2199,18 +2199,23 @@ public class ClassReader { /** Read a field. */ VarSymbol readField() { - long flags = adjustFieldFlags(nextChar()); + char rawFlags = nextChar(); + long flags = adjustFieldFlags(rawFlags); Name name = poolReader.getName(nextChar()); Type type = poolReader.getType(nextChar()); VarSymbol v = new VarSymbol(flags, name, type, currentOwner); readMemberAttrs(v); + if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1 || + Integer.bitCount(rawFlags & (FINAL | VOLATILE)) > 1) + throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "field", v); return v; } /** Read a method. */ MethodSymbol readMethod() { - long flags = adjustMethodFlags(nextChar()); + char rawFlags = nextChar(); + long flags = adjustMethodFlags(rawFlags); Name name = poolReader.getName(nextChar()); Type type = poolReader.getType(nextChar()); if (currentOwner.isInterface() && @@ -2259,6 +2264,8 @@ public class ClassReader { validateMethodType(name, m.type); setParameters(m, type); + if (Integer.bitCount(rawFlags & (PUBLIC | PRIVATE | PROTECTED)) > 1) + throw badClassFile("illegal.flag.combo", Flags.toString((long)rawFlags), "method", m); if ((flags & VARARGS) != 0) { final Type last = type.getParameterTypes().last(); if (last == null || !last.hasTag(ARRAY)) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index f2d97c95537..582e94ca0cd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2505,6 +2505,9 @@ compiler.misc.malformed.vararg.method=\ compiler.misc.wrong.version=\ class file has wrong version {0}.{1}, should be {2}.{3} +compiler.misc.illegal.flag.combo=\ + class file contains illegal flag combination {0} for {1} {2} + ##### # 0: type, 1: type or symbol diff --git a/test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod b/test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod new file mode 100644 index 00000000000..88ac846ea54 --- /dev/null +++ b/test/langtools/tools/javac/classreader/8219810/BadFieldFlags.jcod @@ -0,0 +1,76 @@ +// +// class BadFieldFlags { +// protected int my_field; +// } +// +class BadFieldFlags { + 0xCAFEBABE; + 0; // minor version + 63; // version + [] { // Constant Pool + ; // first element is empty + Method #2 #3; // #1 + class #4; // #2 + NameAndType #5 #6; // #3 + Utf8 "java/lang/Object"; // #4 + Utf8 ""; // #5 + Utf8 "()V"; // #6 + class #8; // #7 + Utf8 "BadFieldFlags"; // #8 + Utf8 "my_field"; // #9 + Utf8 "I"; // #10 + Utf8 "Code"; // #11 + Utf8 "LineNumberTable"; // #12 + Utf8 "SourceFile"; // #13 + Utf8 "BadFieldFlags.java"; // #14 + } // Constant Pool + + 0x0020; // access + #7;// this_cpx + #2;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // Fields + { // field + 0x0006; // access *** SHOULD BE 0x0004 *** + #9; // name_index + #10; // descriptor_index + [] { // Attributes + } // Attributes + } + } // Fields + + [] { // Methods + { // method + 0x0000; // access + #5; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#11) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2AB70001B1; + } + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#12) { // LineNumberTable + [] { // line_number_table + 0 1; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } + } // Methods + + [] { // Attributes + Attr(#13) { // SourceFile + #14; + } // end SourceFile + } // Attributes +} // end class BadFieldFlags diff --git a/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java new file mode 100644 index 00000000000..947ec2f0637 --- /dev/null +++ b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8219810 + * @summary Verify ClassReader detects invalid field access flags combinations + * @build BadFieldFlags + * @compile/fail/ref=BadFieldFlagsTest.out -XDrawDiagnostics BadFieldFlagsTest.java + */ +public class BadFieldFlagsTest { + { + System.out.println(new BadFieldFlags().my_field); + } +} diff --git a/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out new file mode 100644 index 00000000000..f4c95cc9292 --- /dev/null +++ b/test/langtools/tools/javac/classreader/8219810/BadFieldFlagsTest.out @@ -0,0 +1,2 @@ +BadFieldFlagsTest.java:10:32: compiler.err.cant.access: BadFieldFlags, (compiler.misc.bad.class.file.header: BadFieldFlags.class, (compiler.misc.illegal.flag.combo: private protected, field, my_field)) +1 error diff --git a/test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod b/test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod new file mode 100644 index 00000000000..dd391479a9b --- /dev/null +++ b/test/langtools/tools/javac/classreader/8219810/BadMethodFlags.jcod @@ -0,0 +1,77 @@ +// +// class BadMethodFlags { +// protected native int my_method(); +// } +// +class BadMethodFlags { + 0xCAFEBABE; + 0; // minor version + 63; // version + [] { // Constant Pool + ; // first element is empty + Method #2 #3; // #1 + class #4; // #2 + NameAndType #5 #6; // #3 + Utf8 "java/lang/Object"; // #4 + Utf8 ""; // #5 + Utf8 "()V"; // #6 + class #8; // #7 + Utf8 "BadMethodFlags"; // #8 + Utf8 "Code"; // #9 + Utf8 "LineNumberTable"; // #10 + Utf8 "my_method"; // #11 + Utf8 "()I"; // #12 + Utf8 "SourceFile"; // #13 + Utf8 "BadMethodFlags.java"; // #14 + } // Constant Pool + + 0x0020; // access + #7;// this_cpx + #2;// super_cpx + + [] { // Interfaces + } // Interfaces + + [] { // Fields + } // Fields + + [] { // Methods + { // method + 0x0000; // access + #5; // name_index + #6; // descriptor_index + [] { // Attributes + Attr(#9) { // Code + 1; // max_stack + 1; // max_locals + Bytes[]{ + 0x2AB70001B1; + } + [] { // Traps + } // end Traps + [] { // Attributes + Attr(#10) { // LineNumberTable + [] { // line_number_table + 0 1; + } + } // end LineNumberTable + } // Attributes + } // end Code + } // Attributes + } + ; + { // method + 0x0105; // access *** SHOULD BE 0x0104 *** + #11; // name_index + #12; // descriptor_index + [] { // Attributes + } // Attributes + } + } // Methods + + [] { // Attributes + Attr(#13) { // SourceFile + #14; + } // end SourceFile + } // Attributes +} // end class BadMethodFlags diff --git a/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java new file mode 100644 index 00000000000..579b48c0a4d --- /dev/null +++ b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8219810 + * @summary Verify ClassReader detects invalid method access flags combinations + * @build BadMethodFlags + * @compile/fail/ref=BadMethodFlagsTest.out -XDrawDiagnostics BadMethodFlagsTest.java + */ +public class BadMethodFlagsTest { + { + new BadMethodFlags().my_method(); + } +} diff --git a/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out new file mode 100644 index 00000000000..85f3d43341c --- /dev/null +++ b/test/langtools/tools/javac/classreader/8219810/BadMethodFlagsTest.out @@ -0,0 +1,2 @@ +BadMethodFlagsTest.java:10:13: compiler.err.cant.access: BadMethodFlags, (compiler.misc.bad.class.file.header: BadMethodFlags.class, (compiler.misc.illegal.flag.combo: public protected native, method, my_method())) +1 error diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt index afceccad633..9d1c9a2f0af 100644 --- a/test/langtools/tools/javac/diags/examples.not-yet.txt +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt @@ -66,6 +66,7 @@ compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower compiler.misc.fatal.err.cant.close # JavaCompiler compiler.misc.feature.not.supported.in.source.plural # cannot happen (for now) compiler.misc.file.does.not.contain.package +compiler.misc.illegal.flag.combo # ClassReader compiler.misc.illegal.start.of.class.file compiler.misc.inferred.do.not.conform.to.lower.bounds # cannot happen? compiler.misc.kindname.annotation