8161985: Spurious override of Object.getClass leads to NPE

Attr.adjustMethodReturnType() tweaks return types w/o checking what method is being patched

Reviewed-by: vromero
This commit is contained in:
Maurizio Cimadamore 2016-07-22 12:38:06 +01:00
parent fa9af401fe
commit f89b798523
5 changed files with 66 additions and 12 deletions

View File

@ -1900,7 +1900,8 @@ public class Attr extends JCTree.Visitor {
Type qualifier = (tree.meth.hasTag(SELECT))
? ((JCFieldAccess) tree.meth).selected.type
: env.enclClass.sym.type;
restype = adjustMethodReturnType(qualifier, methName, argtypes, restype);
Symbol msym = TreeInfo.symbol(tree.meth);
restype = adjustMethodReturnType(msym, qualifier, methName, argtypes, restype);
chk.checkRefTypes(tree.typeargs, typeargtypes);
@ -1912,19 +1913,25 @@ public class Attr extends JCTree.Visitor {
chk.validate(tree.typeargs, localEnv);
}
//where
Type adjustMethodReturnType(Type qualifierType, Name methodName, List<Type> argtypes, Type restype) {
if (methodName == names.clone && types.isArray(qualifierType)) {
Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, List<Type> argtypes, Type restype) {
if (msym != null &&
msym.owner == syms.objectType.tsym &&
methodName == names.getClass &&
argtypes.isEmpty()) {
// as a special case, x.getClass() has type Class<? extends |X|>
return new ClassType(restype.getEnclosingType(),
List.<Type>of(new WildcardType(types.erasure(qualifierType),
BoundKind.EXTENDS,
syms.boundClass)),
restype.tsym,
restype.getMetadata());
} else if (msym != null &&
msym.owner == syms.arrayClass &&
methodName == names.clone &&
types.isArray(qualifierType)) {
// as a special case, array.clone() has a result that is
// the same as static type of the array being cloned
return qualifierType;
} else if (methodName == names.getClass && argtypes.isEmpty()) {
// as a special case, x.getClass() has type Class<? extends |X|>
return new ClassType(restype.getEnclosingType(),
List.<Type>of(new WildcardType(types.erasure(qualifierType),
BoundKind.EXTENDS,
syms.boundClass)),
restype.tsym,
restype.getMetadata());
} else {
return restype;
}
@ -2989,7 +2996,7 @@ public class Attr extends JCTree.Visitor {
if (!refType.isErroneous()) {
refType = types.createMethodTypeWithReturn(refType,
adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
adjustMethodReturnType(refSym, lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
}
//go ahead with standard method reference compatibility check - note that param check

View File

@ -0,0 +1,28 @@
/*
* @test /nodynamiccopyright/
* @bug 8161985
* @summary Spurious override of Object.getClass leads to NPE
* @compile/fail/ref=T8161985a.out -XDrawDiagnostics T8161985a.java
*/
class T8161985 {
public static void main(String [] arg) {
T8161985 t = new T8161985();
t.getClass();
}
public void getClass() {
Fred1 f = new Fred1();
System.out.println( "fred classname: " + f.getClassName());
}
abstract class Fred {
public String getClassName() {
return this.getClass().getSimpleName();
}
}
class Fred1 extends Fred {
}
}

View File

@ -0,0 +1,2 @@
T8161985a.java:14:17: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), T8161985, getClass(), java.lang.Object), final
1 error

View File

@ -0,0 +1,14 @@
/*
* @test /nodynamiccopyright/
* @bug 8161985
* @summary Spurious override of Object.getClass leads to NPE
* @compile/fail/ref=T8161985b.out -XDrawDiagnostics T8161985b.java
*/
class T8161985b {
public String getClass() { return ""; }
void test() {
this.getClass().getSimpleName();
}
}

View File

@ -0,0 +1,3 @@
T8161985b.java:9:18: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), T8161985b, getClass(), java.lang.Object), final
T8161985b.java:12:22: compiler.err.cant.resolve.location.args: kindname.method, getSimpleName, , , (compiler.misc.location: kindname.class, java.lang.String, null)
2 errors