8228502: javac crashed on a broken classfile with ConstantValue attribute on a field of type Object

Produce an error when reading a classfile with a field with ConstantValue with a wrong type.

Reviewed-by: vromero
This commit is contained in:
Jan Lahoda 2019-08-13 10:27:34 +02:00
parent 36ae680f2a
commit f033152eae
7 changed files with 250 additions and 2 deletions

View file

@ -808,8 +808,11 @@ public class ClassReader {
checkType(var, Double.class, v); checkType(var, Double.class, v);
break; break;
case CLASS: case CLASS:
Assert.check(var.type.tsym == syms.stringType.tsym); if (var.type.tsym == syms.stringType.tsym) {
checkType(var, String.class, v); checkType(var, String.class, v);
} else {
throw badClassFile("bad.constant.value.type", var.type);
}
break; break;
default: default:
// ignore ConstantValue attribute if type is not primitive or String // ignore ConstantValue attribute if type is not primitive or String

View file

@ -2281,6 +2281,10 @@ compiler.misc.bad.constant.range=\
compiler.misc.bad.constant.value=\ compiler.misc.bad.constant.value=\
bad constant value ''{0}'' for {1}, expected {2} 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) # 0: string (classfile major version), 1: string (classfile minor version)
compiler.misc.invalid.default.interface=\ compiler.misc.invalid.default.interface=\
default method found in version {0}.{1} classfile default method found in version {0}.{1} classfile

View file

@ -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;
}
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}