8228502: javac crashed on a broken classfile with ConstantValue attribute on a field of type Object
Summary: Produce an error when reading a classfile with a field with ConstantValue with a wrong type.
Reviewed-by: vromero
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Aug 13 10:27:33 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Aug 13 10:27:34 2019 +0200
@@ -808,8 +808,11 @@
checkType(var, Double.class, v);
break;
case CLASS:
- Assert.check(var.type.tsym == syms.stringType.tsym);
- checkType(var, String.class, v);
+ if (var.type.tsym == syms.stringType.tsym) {
+ checkType(var, String.class, v);
+ } else {
+ throw badClassFile("bad.constant.value.type", var.type);
+ }
break;
default:
// ignore ConstantValue attribute if type is not primitive or String
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Aug 13 10:27:33 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Aug 13 10:27:34 2019 +0200
@@ -2281,6 +2281,10 @@
compiler.misc.bad.constant.value=\
bad constant value ''{0}'' for {1}, expected {2}
+# 0: type (field type)
+compiler.misc.bad.constant.value.type=\
+ variable of type ''{0}'' cannot have a constant value, but has one specified
+
# 0: string (classfile major version), 1: string (classfile minor version)
compiler.misc.invalid.default.interface=\
default method found in version {0}.{1} classfile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/BrokenConstantValue.java Tue Aug 13 10:27:34 2019 +0200
@@ -0,0 +1,9 @@
+/* @test /nodynamiccopyright/
+ * @compile HasBrokenConstantValue.jcod
+ * @compile/fail/ref=BrokenConstantValue.out -XDrawDiagnostics BrokenConstantValue.java
+ */
+public class BrokenConstantValue {
+ void t() {
+ String s = HasBrokenConstantValue.VALUE;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/BrokenConstantValue.out Tue Aug 13 10:27:34 2019 +0200
@@ -0,0 +1,2 @@
+BrokenConstantValue.java:7:21: compiler.err.cant.access: HasBrokenConstantValue, (compiler.misc.bad.class.file.header: HasBrokenConstantValue.class, (compiler.misc.bad.constant.value.type: java.lang.Object))
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/classfiles/attributes/ConstantValue/HasBrokenConstantValue.jcod Tue Aug 13 10:27:34 2019 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// ConstantValue attribute on a field that has wrong type (j.l.Object):
+
+class HasBrokenConstantValue {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ Utf8 "VALUE"; // #4
+ Utf8 "Ljava/lang/Object;"; // #5
+ Utf8 "ConstantValue"; // #6
+ String #17; // #7
+ Utf8 "<init>"; // #8
+ Utf8 "()V"; // #9
+ Utf8 "Code"; // #10
+ Utf8 "LineNumberTable"; // #11
+ Utf8 "SourceFile"; // #12
+ Utf8 "HasBrokenConstantValue.java"; // #13
+ NameAndType #8 #9; // #14
+ Utf8 "HasBrokenConstantValue"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 ""; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0019; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // ConstantValue
+ #7;
+ } // end ConstantValue
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #8; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 1;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #13;
+ } // end SourceFile
+ } // Attributes
+} // end class HasBrokenConstantValue
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/BadConstantValueType/BadConstantValueType.java Tue Aug 13 10:27:34 2019 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.misc.bad.constant.value.type
+// key: compiler.misc.bad.class.file.header
+// key: compiler.err.cant.access
+// options: -processor CreateBadClassFile
+// run: exec --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
+
+/* The annotation processor will create an invalid classfile with a static
+ * final field of type java.lang.Object having ConstantValue attribute with
+ * a String value
+ */
+class BadConstantValueType {
+ private static final String C = Test.test;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/BadConstantValueType/processors/CreateBadClassFile.java Tue Aug 13 10:27:34 2019 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info;
+import com.sun.tools.classfile.ConstantPool.CPInfo;
+
+/* Create an invalid classfile with a static final field of type object with
+ * ConstantValue of type String.
+ */
+@SupportedAnnotationTypes("*")
+public class CreateBadClassFile extends AbstractProcessor {
+ public boolean process(Set<? extends TypeElement> elems, RoundEnvironment renv) {
+ if (++round == 1) {
+ ConstantPool cp = new ConstantPool(new CPInfo[] {
+ new CONSTANT_Utf8_info(""), //0
+ new CONSTANT_Utf8_info("Test"), //1
+ new CONSTANT_Class_info(null, 1), //2
+ new CONSTANT_Utf8_info("java/lang/Object"), //3
+ new CONSTANT_Class_info(null, 3), //4
+ new CONSTANT_Utf8_info("test"), //5
+ new CONSTANT_Utf8_info("Ljava/lang/Object;"), //6
+ new CONSTANT_Utf8_info("ConstantValue"), //7
+ });
+ ClassFile cf = new ClassFile(0xCAFEBABE,
+ 0,
+ 51,
+ cp,
+ new AccessFlags(AccessFlags.ACC_ABSTRACT |
+ AccessFlags.ACC_INTERFACE |
+ AccessFlags.ACC_PUBLIC),
+ 2,
+ 4,
+ new int[0],
+ new Field[] {
+ new Field(new AccessFlags(AccessFlags.ACC_PUBLIC |
+ AccessFlags.ACC_STATIC |
+ AccessFlags.ACC_FINAL),
+ 5,
+ new Descriptor(6),
+ new Attributes(cp, new Attribute[] {
+ new ConstantValue_attribute(7, 6)
+ }))
+ },
+ new Method[0],
+ new Attributes(cp, new Attribute[0]));
+ try {
+ JavaFileObject clazz = processingEnv.getFiler().createClassFile("Test");
+ try (OutputStream out = clazz.openOutputStream()) {
+ new ClassWriter().write(cf, out);
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ int round = 0;
+}