changeset 39810:d290bef927c4

8161985: Spurious override of Object.getClass leads to NPE Summary: Attr.adjustMethodReturnType() tweaks return types w/o checking what method is being patched Reviewed-by: vromero
author mcimadamore
date Fri, 22 Jul 2016 12:38:06 +0100
parents 74b7aea686d8
children b8d3d2487379
files langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java langtools/test/tools/javac/8161985/T8161985a.java langtools/test/tools/javac/8161985/T8161985a.out langtools/test/tools/javac/8161985/T8161985b.java langtools/test/tools/javac/8161985/T8161985b.out
diffstat 5 files changed, 66 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jul 21 07:43:17 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Jul 22 12:38:06 2016 +0100
@@ -1900,7 +1900,8 @@
             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 @@
         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 @@
 
             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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985a.java	Fri Jul 22 12:38:06 2016 +0100
@@ -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 {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985a.out	Fri Jul 22 12:38:06 2016 +0100
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985b.java	Fri Jul 22 12:38:06 2016 +0100
@@ -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();
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8161985/T8161985b.out	Fri Jul 22 12:38:06 2016 +0100
@@ -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