提交 d3f9f38e 编写于 作者: J jrose

6839839: access checking logic is wrong at three points in MethodHandles

Summary: point fixes to access checking logic
Reviewed-by: mr
上级 2f4b4ba5
......@@ -145,27 +145,30 @@ public class MethodHandles {
this.lookupClass = lookupClass;
}
private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
/** Version of lookup which is trusted minimally.
* It can only be used to create method handles to
* publicly accessible members.
*/
public static final Lookup PUBLIC_LOOKUP = new Lookup(null);
public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
/** Package-private version of lookup which is trusted. */
static final Lookup IMPL_LOOKUP = new Lookup(Access.class);
static final Lookup IMPL_LOOKUP = new Lookup(null);
static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
if (lookupClass == null ||
lookupClass == Access.class ||
lookupClass.getName().startsWith("java.dyn."))
String name = lookupClass.getName();
if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
}
@Override
public String toString() {
if (lookupClass == null)
if (lookupClass == PUBLIC_ONLY)
return "public";
if (lookupClass == null)
return "privileged";
return lookupClass.getName();
}
......@@ -205,6 +208,13 @@ public class MethodHandles {
* with the receiver type ({@code defc}) prepended.
* The method and all its argument types must be accessible to the lookup class.
* <p>
* (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
* of the receiver type, if the receiver type is not on the boot class path.
* This is due to a temporary JVM limitation, in which MethodHandle
* claims to be unable to access such classes. To work around this
* bug, use {@code convertArguments} to normalize the type of the leading
* argument to a type on the boot class path, such as {@code Object}.)
* <p>
* When called, the handle will treat the first argument as a receiver
* and dispatch on the receiver's type to determine which method
* implementation to enter.
......@@ -253,8 +263,7 @@ public class MethodHandles {
MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
checkStatic(false, method, lookupClass);
if (name.equals("<init>")) {
if (defc != specialCaller)
throw newNoAccessException("constructor must be local to lookup class", method, lookupClass);
throw newNoAccessException("cannot directly invoke a constructor", method, null);
} else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
}
......
......@@ -45,8 +45,6 @@ class DirectMethodHandle extends MethodHandle {
if (!m.isResolved())
throw new InternalError();
// Null check and replace privilege token (as passed to JVM) with null.
if (lookupClass.equals(Access.class)) lookupClass = null;
MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
}
......
......@@ -450,7 +450,7 @@ public final class MemberName implements Member, Cloneable {
for (;;) {
int bufCount = MethodHandleNatives.getMembers(defc,
matchName, matchSig, matchFlags,
MethodHandleNatives.asNativeCaller(lookupClass),
lookupClass,
totalCount, buf);
if (bufCount <= buf.length) {
if (bufCount >= 0)
......@@ -487,14 +487,13 @@ public final class MemberName implements Member, Cloneable {
return result;
}
boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
Class<?> caller = MethodHandleNatives.asNativeCaller(lookupClass);
MethodHandleNatives.resolve(m, caller);
MethodHandleNatives.resolve(m, lookupClass);
if (m.isResolved()) return true;
int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
String matchSig = m.getSignature();
MemberName[] buf = { m };
int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
m.getName(), matchSig, matchFlags, caller, 0, buf);
m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
if (n != 1) return false;
return m.isResolved();
}
......
......@@ -95,7 +95,7 @@ public abstract class MethodHandleImpl {
public static void initLookup(Access token, Lookup lookup) {
Access.check(token);
if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != Access.class)
if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != null)
throw new InternalError();
IMPL_LOOKUP_INIT = lookup;
}
......@@ -144,19 +144,28 @@ public abstract class MethodHandleImpl {
boolean doDispatch, Class<?> lookupClass) {
Access.check(token); // only trusted calls
MethodType mtype = method.getMethodType();
MethodType rtype = mtype;
if (method.isStatic()) {
doDispatch = false;
} else {
// adjust the advertised receiver type to be exactly the one requested
// (in the case of invokespecial, this will be the calling class)
mtype = mtype.insertParameterType(0, method.getDeclaringClass());
Class<?> recvType = method.getDeclaringClass();
mtype = mtype.insertParameterType(0, recvType);
if (method.isConstructor())
doDispatch = true;
// FIXME: JVM has trouble building MH.invoke sites for
// classes off the boot class path
rtype = mtype;
if (recvType.getClassLoader() != null)
rtype = rtype.changeParameterType(0, Object.class);
}
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
if (!mh.isValid())
throw newNoAccessException(method, lookupClass);
return mh;
MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh);
if (rmh == null) throw new InternalError();
return rmh;
}
public static
......@@ -189,6 +198,15 @@ public abstract class MethodHandleImpl {
MethodHandle bindReceiver(Access token,
MethodHandle target, Object receiver) {
Access.check(token);
if (target instanceof AdapterMethodHandle) {
Object info = MethodHandleNatives.getTargetInfo(target);
if (info instanceof DirectMethodHandle) {
DirectMethodHandle dmh = (DirectMethodHandle) info;
if (receiver == null ||
dmh.type().parameterType(0).isAssignableFrom(receiver.getClass()))
target = dmh;
}
}
if (target instanceof DirectMethodHandle)
return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
return null; // let caller try something else
......
......@@ -47,14 +47,6 @@ class MethodHandleNatives {
static native int getMembers(Class<?> defc, String matchName, String matchSig,
int matchFlags, Class<?> caller, int skip, MemberName[] results);
static Class<?> asNativeCaller(Class<?> lookupClass) {
if (lookupClass == null) // means "public only, non-privileged"
return sun.dyn.empty.Empty.class;
if (lookupClass == Access.class) // means "internal, privileged"
return null; // to the JVM, null means completely privileged
return lookupClass;
}
/// MethodHandle support
/** Initialize the method handle to adapt the call. */
......
......@@ -95,7 +95,7 @@ public class VerifyAccess {
public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
if (class1 == class2)
return true;
if (loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
return false;
String name1 = class1.getName(), name2 = class2.getName();
int dot = name1.lastIndexOf('.');
......@@ -159,7 +159,7 @@ public class VerifyAccess {
*/
public static void checkBootstrapPrivilege(Class requestingClass, Class subjectClass,
String permissionName) {
if (requestingClass == Access.class) return;
if (requestingClass == null) return;
if (requestingClass == subjectClass) return;
SecurityManager security = System.getSecurityManager();
if (security == null) return; // open season
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册