8038023: Compiler crash ClassCastException
Summary: Add additional checks on results of ClassReader.readPool
Reviewed-by: vromero
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Apr 22 16:51:10 2014 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Apr 22 19:52:15 2014 +0100
@@ -475,14 +475,14 @@
break;
case CONSTANT_Fieldref: {
ClassSymbol owner = readClassSymbol(getChar(index + 1));
- NameAndType nt = (NameAndType)readPool(getChar(index + 3));
+ NameAndType nt = readNameAndType(getChar(index + 3));
poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
break;
}
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref: {
ClassSymbol owner = readClassSymbol(getChar(index + 1));
- NameAndType nt = (NameAndType)readPool(getChar(index + 3));
+ NameAndType nt = readNameAndType(getChar(index + 3));
poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
break;
}
@@ -551,13 +551,34 @@
/** Read class entry.
*/
ClassSymbol readClassSymbol(int i) {
- return (ClassSymbol) (readPool(i));
+ Object obj = readPool(i);
+ if (obj != null && !(obj instanceof ClassSymbol))
+ throw badClassFile("bad.const.pool.entry",
+ currentClassFile.toString(),
+ "CONSTANT_Class_info", i);
+ return (ClassSymbol)obj;
}
/** Read name.
*/
Name readName(int i) {
- return (Name) (readPool(i));
+ Object obj = readPool(i);
+ if (obj != null && !(obj instanceof Name))
+ throw badClassFile("bad.const.pool.entry",
+ currentClassFile.toString(),
+ "CONSTANT_Utf8_info or CONSTANT_String_info", i);
+ return (Name)obj;
+ }
+
+ /** Read name and type.
+ */
+ NameAndType readNameAndType(int i) {
+ Object obj = readPool(i);
+ if (obj != null && !(obj instanceof NameAndType))
+ throw badClassFile("bad.const.pool.entry",
+ currentClassFile.toString(),
+ "CONSTANT_NameAndType_info", i);
+ return (NameAndType)obj;
}
/************************************************************************
@@ -1209,7 +1230,7 @@
sym.owner.members().remove(sym);
ClassSymbol self = (ClassSymbol)sym;
ClassSymbol c = readClassSymbol(nextChar());
- NameAndType nt = (NameAndType)readPool(nextChar());
+ NameAndType nt = readNameAndType(nextChar());
if (c.members_field == null)
throw badClassFile("bad.enclosing.class", self, c);
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Apr 22 16:51:10 2014 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Apr 22 19:52:15 2014 +0100
@@ -1719,6 +1719,11 @@
compiler.misc.bad.class.file=\
class file is invalid for class {0}
+# 0: file name, 1: expected CP entry type, 2: constant pool index
+compiler.misc.bad.const.pool.entry=\
+ bad constant pool entry in {0}\n\
+ expected {1} at index {2}
+
# 0: file name, 1: message segment
compiler.misc.bad.class.file.header=\
bad class file: {0}\n\
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Tue Apr 22 16:51:10 2014 +0200
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Tue Apr 22 19:52:15 2014 +0100
@@ -113,3 +113,4 @@
compiler.warn.file.from.future # warning for future modification times on files
compiler.err.cant.inherit.from.anon # error for subclass of anonymous class
compiler.misc.bad.class.file # class file is malformed
+compiler.misc.bad.const.pool.entry # constant pool entry has wrong type