8023301: Enhance generic classes
authorjfranck
Fri, 11 Oct 2013 13:14:15 +0200
changeset 22323 5eaa4f56582e
parent 22322 40151ab78d1a
child 22324 54a74fc6e85c
8023301: Enhance generic classes Reviewed-by: mchung, hawtin
jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java
--- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Wed Oct 09 18:58:16 2013 +0800
+++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java	Fri Oct 11 13:14:15 2013 +0200
@@ -28,7 +28,10 @@
 import java.lang.annotation.*;
 import java.lang.reflect.AnnotatedType;
 import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 import java.util.LinkedHashMap;
@@ -40,6 +43,7 @@
 import sun.reflect.generics.factory.GenericsFactory;
 import sun.reflect.generics.tree.FieldTypeSignature;
 import sun.reflect.generics.visitor.Reifier;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * Implementation of <tt>java.lang.reflect.TypeVariable</tt> interface
@@ -95,6 +99,13 @@
                              TypeVariableImpl<T> make(T decl, String name,
                                                       FieldTypeSignature[] bs,
                                                       GenericsFactory f) {
+
+        if (!((decl instanceof Class) ||
+                (decl instanceof Method) ||
+                (decl instanceof Constructor))) {
+            throw new AssertionError("Unexpected kind of GenericDeclaration" +
+                    decl.getClass().toString());
+        }
         return new TypeVariableImpl<T>(decl, name, bs, f);
     }
 
@@ -149,6 +160,13 @@
      * @since 1.5
      */
     public D getGenericDeclaration(){
+        if (genericDeclaration instanceof Class)
+            ReflectUtil.checkPackageAccess((Class)genericDeclaration);
+        else if ((genericDeclaration instanceof Method) ||
+                (genericDeclaration instanceof Constructor))
+            ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
+        else
+            throw new AssertionError("Unexpected kind of GenericDeclaration");
         return genericDeclaration;
     }
 
@@ -164,7 +182,8 @@
 
     @Override
     public boolean equals(Object o) {
-        if (o instanceof TypeVariable) {
+        if (o instanceof TypeVariable &&
+                o.getClass() == TypeVariableImpl.class) {
             TypeVariable<?> that = (TypeVariable<?>) o;
 
             GenericDeclaration thatDecl = that.getGenericDeclaration();
--- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java	Wed Oct 09 18:58:16 2013 +0800
+++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java	Fri Oct 11 13:14:15 2013 +0200
@@ -26,11 +26,13 @@
 
 package sun.reflect.misc;
 
+import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import java.util.Arrays;
 import sun.reflect.Reflection;
+import sun.security.util.SecurityConstants;
 
 public final class ReflectUtil {
 
@@ -118,6 +120,40 @@
     }
 
     /**
+     * Does a conservative approximation of member access check. Use this if
+     * you don't have an actual 'userland' caller Class/ClassLoader available.
+     * This might be more restrictive than a precise member access check where
+     * you have a caller, but should never allow a member access that is
+     * forbidden.
+     *
+     * @param m the {@code Member} about to be accessed
+     */
+    public static void conservativeCheckMemberAccess(Member m) throws SecurityException{
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm == null)
+            return;
+
+        // Check for package access on the declaring class.
+        //
+        // In addition, unless the member and the declaring class are both
+        // public check for access declared member permissions.
+        //
+        // This is done regardless of ClassLoader relations between the {@code
+        // Member m} and any potential caller.
+
+        final Class<?> declaringClass = m.getDeclaringClass();
+
+        checkPackageAccess(declaringClass);
+
+        if (Modifier.isPublic(m.getModifiers()) &&
+                Modifier.isPublic(declaringClass.getModifiers()))
+            return;
+
+        // Check for declared member access.
+        sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
+    }
+
+    /**
      * Checks package access on the given class.
      *
      * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements