changeset 4903:0a66867d6baa

8007812: (reflect) Class.getEnclosingMethod problematic for some classes Summary: Better checking in getEnclosing(Method|Constructor|Class) Reviewed-by: darcy, ahgross, mchung
author jfranck
date Mon, 25 Mar 2013 20:18:21 +0100
parents d22aa05d0e4c
children 38c68381e29f
files src/share/classes/java/lang/Class.java src/share/classes/java/lang/invoke/MethodHandleNatives.java
diffstat 2 files changed, 35 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/Class.java	Thu Mar 21 22:32:42 2013 +0400
+++ b/src/share/classes/java/lang/Class.java	Mon Mar 25 20:18:21 2013 +0100
@@ -915,13 +915,22 @@
             for(int i = 0; i < parameterClasses.length; i++)
                 parameterClasses[i] = toClass(parameterTypes[i]);
 
+            // Perform access check
+            Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
+            // be very careful not to change the stack depth of this
+            // checkMemberAccess call for security reasons
+            // see java.lang.SecurityManager.checkMemberAccess
+            //
+            // Note that we need to do this on the enclosing class
+            enclosingCandidate.checkMemberAccess(Member.DECLARED,
+                        ClassLoader.getCallerClassLoader(), true);
             /*
              * Loop over all declared methods; match method name,
              * number of and type of parameters, *and* return
              * type.  Matching return type is also necessary
              * because of covariant returns, etc.
              */
-            for(Method m: enclosingInfo.getEnclosingClass().getDeclaredMethods()) {
+            for(Method m: enclosingCandidate.getDeclaredMethods()) {
                 if (m.getName().equals(enclosingInfo.getName()) ) {
                     Class<?>[] candidateParamClasses = m.getParameterTypes();
                     if (candidateParamClasses.length == parameterClasses.length) {
@@ -1042,11 +1051,20 @@
             for(int i = 0; i < parameterClasses.length; i++)
                 parameterClasses[i] = toClass(parameterTypes[i]);
 
+            // Perform access check
+            Class<?> enclosingCandidate = enclosingInfo.getEnclosingClass();
+            // be very careful not to change the stack depth of this
+            // checkMemberAccess call for security reasons
+            // see java.lang.SecurityManager.checkMemberAccess
+            //
+            // Note that we need to do this on the enclosing class
+            enclosingCandidate.checkMemberAccess(Member.DECLARED,
+                        ClassLoader.getCallerClassLoader(), true);
             /*
              * Loop over all declared constructors; match number
              * of and type of parameters.
              */
-            for(Constructor<?> c: enclosingInfo.getEnclosingClass().getDeclaredConstructors()) {
+            for(Constructor<?> c: enclosingCandidate.getDeclaredConstructors()) {
                 Class<?>[] candidateParamClasses = c.getParameterTypes();
                 if (candidateParamClasses.length == parameterClasses.length) {
                     boolean matches = true;
@@ -1101,18 +1119,28 @@
         // attribute if and only if it is a local class or an
         // anonymous class.
         EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo();
+        Class<?> enclosingCandidate;
 
         if (enclosingInfo == null) {
             // This is a top level or a nested class or an inner class (a, b, or c)
-            return getDeclaringClass();
+            enclosingCandidate = getDeclaringClass();
         } else {
             Class<?> enclosingClass = enclosingInfo.getEnclosingClass();
             // This is a local class or an anonymous class (d or e)
             if (enclosingClass == this || enclosingClass == null)
                 throw new InternalError("Malformed enclosing method information");
             else
-                return enclosingClass;
+                enclosingCandidate = enclosingClass;
         }
+
+        // be very careful not to change the stack depth of this
+        // checkMemberAccess call for security reasons
+        // see java.lang.SecurityManager.checkMemberAccess
+        if (enclosingCandidate != null) {
+            enclosingCandidate.checkMemberAccess(Member.DECLARED,
+                    ClassLoader.getCallerClassLoader(), true);
+        }
+        return enclosingCandidate;
     }
 
     /**
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Mar 21 22:32:42 2013 +0400
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Mar 25 20:18:21 2013 +0100
@@ -480,6 +480,9 @@
         case "getDeclaredField":
         case "getDeclaredMethod":
         case "getDeclaredConstructor":
+        case "getEnclosingClass":
+        case "getEnclosingMethod":
+        case "getEnclosingConstructor":
             return defc == java.lang.Class.class;
         case "getConnection":
         case "getDriver":