Mercurial > hg > release > icedtea7-forest-2.3 > jdk
changeset 6353:951c38772db3
8017196: Ensure Proxies are handled appropriately
Reviewed-by: dfuchs, jrose, jdn, ahgross, chegar
author | mchung |
---|---|
date | Thu, 18 Jul 2013 17:22:11 -0700 |
parents | dd1551343d65 |
children | accde587b25a |
files | src/share/classes/java/lang/invoke/MethodHandleNatives.java src/share/classes/java/lang/invoke/MethodHandles.java src/share/classes/java/lang/reflect/Proxy.java src/share/classes/sun/reflect/misc/ReflectUtil.java |
diffstat | 4 files changed, 75 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java Tue Jul 23 10:01:25 2013 +0400 +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Jul 18 17:22:11 2013 -0700 @@ -511,6 +511,7 @@ return defc == java.lang.ClassLoader.class; case "registerAsParallelCapable": return defc == java.lang.ClassLoader.class; + case "getInvocationHandler": case "getProxyClass": case "newProxyInstance": return defc == java.lang.reflect.Proxy.class;
--- a/src/share/classes/java/lang/invoke/MethodHandles.java Tue Jul 23 10:01:25 2013 +0400 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Thu Jul 18 17:22:11 2013 -0700 @@ -412,7 +412,7 @@ */ Lookup(Class<?> lookupClass) { this(lookupClass, ALL_MODES); - checkUnprivilegedlookupClass(lookupClass); + checkUnprivilegedlookupClass(lookupClass, ALL_MODES); } private Lookup(Class<?> lookupClass, int allowedModes) { @@ -466,7 +466,7 @@ // No permissions. newModes = 0; } - checkUnprivilegedlookupClass(requestedLookupClass); + checkUnprivilegedlookupClass(requestedLookupClass, newModes); return new Lookup(requestedLookupClass, newModes); } @@ -482,10 +482,19 @@ /** Package-private version of lookup which is trusted. */ static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); - private static void checkUnprivilegedlookupClass(Class<?> lookupClass) { + private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) { String name = lookupClass.getName(); if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); + + // For caller-sensitive MethodHandles.lookup() + // disallow lookup more restricted packages + if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { + if (name.startsWith("java.") || + (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { + throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); + } + } } /**
--- a/src/share/classes/java/lang/reflect/Proxy.java Tue Jul 23 10:01:25 2013 +0400 +++ b/src/share/classes/java/lang/reflect/Proxy.java Thu Jul 18 17:22:11 2013 -0700 @@ -788,6 +788,7 @@ * @throws IllegalArgumentException if the argument is not a * proxy instance */ + @CallerSensitive public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { @@ -798,8 +799,19 @@ throw new IllegalArgumentException("not a proxy instance"); } - Proxy p = (Proxy) proxy; - return p.h; + final Proxy p = (Proxy) proxy; + final InvocationHandler ih = p.h; + if (System.getSecurityManager() != null) { + Class<?> ihClass = ih.getClass(); + Class<?> caller = Reflection.getCallerClass(); + if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), + ihClass.getClassLoader())) + { + ReflectUtil.checkPackageAccess(ihClass); + } + } + + return ih; } private static native Class defineClass0(ClassLoader loader, String name,
--- a/src/share/classes/sun/reflect/misc/ReflectUtil.java Tue Jul 23 10:01:25 2013 +0400 +++ b/src/share/classes/sun/reflect/misc/ReflectUtil.java Thu Jul 18 17:22:11 2013 -0700 @@ -26,8 +26,10 @@ package sun.reflect.misc; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; +import java.util.Arrays; import sun.reflect.Reflection; public final class ReflectUtil { @@ -249,4 +251,50 @@ String pkg = (i != -1) ? name.substring(0, i) : ""; return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); } + + /** + * Check if the given method is a method declared in the proxy interface + * implemented by the given proxy instance. + * + * @param proxy a proxy instance + * @param method an interface method dispatched to a InvocationHandler + * + * @throws IllegalArgumentException if the given proxy or method is invalid. + */ + public static void checkProxyMethod(Object proxy, Method method) { + // check if it is a valid proxy instance + if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { + throw new IllegalArgumentException("Not a Proxy instance"); } + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalArgumentException("Can't handle static method"); + } + + Class<?> c = method.getDeclaringClass(); + if (c == Object.class) { + String name = method.getName(); + if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) { + return; + } + } + + if (isSuperInterface(proxy.getClass(), c)) { + return; + } + + // disallow any method not declared in one of the proxy intefaces + throw new IllegalArgumentException("Can't handle: " + method); + } + + private static boolean isSuperInterface(Class<?> c, Class<?> intf) { + for (Class<?> i : c.getInterfaces()) { + if (i == intf) { + return true; + } + if (isSuperInterface(i, intf)) { + return true; + } + } + return false; + } +}