changeset 6439:6bf5fa233df0

8014925: Disable sun.reflect.Reflection.getCallerClass(int) with a temporary switch to re-enable it Reviewed-by: jrose, alanb, chegar, twisti
author mchung
date Tue, 02 Jul 2013 13:23:35 -0700
parents 298aa6322743
children e42c2964343c
files src/share/classes/sun/misc/VM.java src/share/classes/sun/reflect/Reflection.java test/sun/reflect/GetCallerClass.java
diffstat 3 files changed, 91 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/misc/VM.java	Tue Jul 02 12:33:03 2013 +0400
+++ b/src/share/classes/sun/misc/VM.java	Tue Jul 02 13:23:35 2013 -0700
@@ -216,6 +216,16 @@
         return allowArraySyntax;
     }
 
+    private static boolean allowGetCallerClass = false;
+
+    // Reflection.getCallerClass(int) is disabled by default.
+    // It can be enabled by setting the system property
+    // "jdk.reflect.allowGetCallerClass" and also used by
+    // logging stack walk of a resource bundle if it is turned on.
+    public static boolean allowGetCallerClass() {
+        return allowGetCallerClass;
+    }
+
     /**
      * Returns the system property of the specified key saved at
      * system initialization time.  This method should only be used
@@ -280,6 +290,16 @@
                                ? defaultAllowArraySyntax
                                : Boolean.parseBoolean(s));
 
+        // Reflection.getCallerClass(int) is disabled by default.
+        // It can be enabled by setting the system property
+        // "jdk.reflect.allowGetCallerClass" and also used by
+        // logging stack walk of a resource bundle if it is turned on.
+        s = props.getProperty("jdk.reflect.allowGetCallerClass");
+        allowGetCallerClass = (s != null
+                                   ? (s.isEmpty() || Boolean.parseBoolean(s))
+                                   : false) ||
+             Boolean.valueOf(props.getProperty("jdk.logging.allowStackWalkSearch"));
+
         // Remove other private system properties
         // used by java.lang.Integer.IntegerCache
         props.remove("java.lang.Integer.IntegerCache.high");
--- a/src/share/classes/sun/reflect/Reflection.java	Tue Jul 02 12:33:03 2013 +0400
+++ b/src/share/classes/sun/reflect/Reflection.java	Tue Jul 02 13:23:35 2013 -0700
@@ -65,7 +65,15 @@
     @Deprecated
     @CallerSensitive
     public static Class getCallerClass(int depth) {
-        return getCallerClass0(depth+1);
+        if (sun.misc.VM.allowGetCallerClass()) {
+            return getCallerClass0(depth+1);
+        }
+        throw new UnsupportedOperationException("This method is in the sun.* " +
+             "namespace so it is not a supported, public interface. " +
+             "The 7u40 release notes describe a temporary mechanism " +
+             "to reenable the historical functionality of this method. " +
+             "Update code to function properly and this method will be " +
+             "removed without further warning in a subsequent 7 update release.");
     }
 
     // If the VM enforces getting caller class with @CallerSensitive,
--- a/test/sun/reflect/GetCallerClass.java	Tue Jul 02 12:33:03 2013 +0400
+++ b/test/sun/reflect/GetCallerClass.java	Tue Jul 02 13:23:35 2013 -0700
@@ -23,29 +23,83 @@
 
 /*
  * @test
- * @bug 8016814
- * @summary Test sun.reflect.Reflection.getCallerClass(int)
+ * @bug 8016814 8014925
+ * @summary Test sun.reflect.Reflection.getCallerClass(int) disabled by default
  * @compile -XDignore.symbol.file GetCallerClass.java
- * @run main GetCallerClass
+ * @run main/othervm GetCallerClass
+ * @run main/othervm -Djdk.reflect.allowGetCallerClass GetCallerClass
+ * @run main/othervm -Djdk.reflect.allowGetCallerClass=true GetCallerClass
+ * @run main/othervm -Djdk.reflect.allowGetCallerClass=false GetCallerClass
  */
 
 public class GetCallerClass {
     public static void main(String[] args) throws Exception {
-        Class<?> c = Temp.test();
-        if (c != GetCallerClass.class) {
-            throw new RuntimeException("Incorrect caller: " + c);
+        String s = System.getProperty("jdk.reflect.allowGetCallerClass");
+        boolean allowed;
+        if (s == null || s.equals("false")) {
+            allowed = false;
+        } else if (s.equals("") || s.equals("true")) {
+            allowed = true;
+        } else {
+            throw new RuntimeException("Unsupported test setting");
+        }
+
+        try {
+            Class<?> c = Test.test();
+            if (!allowed) {
+                throw new RuntimeException("Reflection.getCallerClass should not be allowed");
+            }
+            Class<?> caller = Test.caller();
+            if (c != GetCallerClass.class || caller != c) {
+                throw new RuntimeException("Incorrect caller: " + c);
+            }
+            Test.selfTest();
+        } catch (UnsupportedOperationException e) {
+            if (allowed) throw e;
         }
     }
 
     @sun.reflect.CallerSensitive
     public Class<?> getCallerClass() {
-        // 0: Reflection 1: getCallerClass 2: Temp.test 3: main
+        // 0: Reflection 1: getCallerClass 2: Test.test 3: main
         return sun.reflect.Reflection.getCallerClass(3);
     }
 
-    static class Temp {
+    static class Test {
+        // Returns the caller of this method
         public static Class<?> test() {
             return new GetCallerClass().getCallerClass();
         }
+        @sun.reflect.CallerSensitive
+        public static Class<?> caller() {
+            return sun.reflect.Reflection.getCallerClass();
+        }
+        @sun.reflect.CallerSensitive
+        public static void selfTest() {
+            // 0: Reflection 1: Test.selfTest
+            Class<?> c = sun.reflect.Reflection.getCallerClass(1);
+            if (c != Test.class || caller() != c) {
+                throw new RuntimeException("Incorrect caller: " + c);
+            }
+            Inner1.deep();
+        }
+
+        static class Inner1 {
+            static void deep() {
+                 deeper();
+            }
+            static void deeper() {
+                 Inner2.deepest();
+            }
+            static class Inner2 {
+                static void deepest() {
+                    // 0: Reflection 1: deepest 2: deeper 3: deep 4: Test.selfTest
+                    Class<?> c = sun.reflect.Reflection.getCallerClass(4);
+                    if (c != Test.class) {
+                        throw new RuntimeException("Incorrect caller: " + c);
+                    }
+                }
+            }
+        }
     }
 }