提交 056924fd 编写于 作者: J jrose

7050328: (jsr-292) findConstructor throws ExceptionInInitializerError if run under SecurityManager

Summary: Wrap system property and reflection accesses under doPrivileged.  Ensure constant pool linkage bypasses the SM as specified.
Reviewed-by: kvn, never
上级 10f42a32
......@@ -26,6 +26,8 @@
package java.lang.invoke;
import sun.invoke.util.VerifyType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
......@@ -336,18 +338,20 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
// cast (V) is OK here, since we wrap convertArguments around the MH.
static Object staticBase(MemberName field) {
static Object staticBase(final MemberName field) {
if (!field.isStatic()) return null;
Class c = field.getDeclaringClass();
java.lang.reflect.Field f;
try {
// FIXME: Should not have to create 'f' to get this value.
f = c.getDeclaredField(field.getName());
// Note: Previous line might invalidly throw SecurityException (7042829)
return unsafe.staticFieldBase(f);
} catch (NoSuchFieldException ee) {
throw uncaughtException(ee);
}
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
try {
Class c = field.getDeclaringClass();
// FIXME: Should not have to create 'f' to get this value.
java.lang.reflect.Field f = c.getDeclaredField(field.getName());
return unsafe.staticFieldBase(f);
} catch (NoSuchFieldException ee) {
throw uncaughtException(ee);
}
}
});
}
int getStaticI() { return unsafe.getInt(base, offset); }
......
......@@ -395,18 +395,7 @@ class MethodHandleNatives {
Class<?> defc, String name, Object type) {
try {
Lookup lookup = IMPL_LOOKUP.in(callerClass);
switch (refKind) {
case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type );
case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type );
case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type );
case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type );
case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type );
case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type );
case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass );
case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type );
case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type );
}
throw new InternalError("bad MethodHandle constant "+name+" : "+type);
return lookup.linkMethodHandleConstant(refKind, defc, name, type);
} catch (ReflectiveOperationException ex) {
Error err = new IncompatibleClassChangeError();
err.initCause(ex);
......
......@@ -25,6 +25,9 @@
package java.lang.invoke;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* This class consists exclusively of static names internal to the
* method handle implementation.
......@@ -35,7 +38,17 @@ package java.lang.invoke;
private MethodHandleStatics() { } // do not instantiate
static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
static final boolean DEBUG_METHOD_HANDLE_NAMES;
static {
final Object[] values = { false };
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
return null;
}
});
DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
}
/*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
if (type == null)
......
......@@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import sun.reflect.Reflection;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
/**
* This class consists exclusively of static methods that operate on or return
......@@ -579,9 +580,18 @@ public class MethodHandles {
MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(refc, name, type, true);
checkSecurityManager(refc, method); // stack walk magic: do not refactor
return accessStatic(refc, method);
}
private
MethodHandle accessStatic(Class<?> refc, MemberName method) throws IllegalAccessException {
checkMethod(refc, method, true);
return MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
}
private
MethodHandle resolveStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(refc, name, type, true);
return accessStatic(refc, method);
}
/**
* Produces a method handle for a virtual method.
......@@ -624,6 +634,13 @@ public class MethodHandles {
public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(refc, name, type, false);
checkSecurityManager(refc, method); // stack walk magic: do not refactor
return accessVirtual(refc, method);
}
private MethodHandle resolveVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
MemberName method = resolveOrFail(refc, name, type, false);
return accessVirtual(refc, method);
}
private MethodHandle accessVirtual(Class<?> refc, MemberName method) throws IllegalAccessException {
checkMethod(refc, method, false);
MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
return restrictProtectedReceiver(method, mh);
......@@ -658,13 +675,21 @@ public class MethodHandles {
public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
String name = "<init>";
MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
assert(ctor.isConstructor());
checkSecurityManager(refc, ctor); // stack walk magic: do not refactor
return accessConstructor(refc, ctor);
}
private MethodHandle accessConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
assert(ctor.isConstructor());
checkAccess(refc, ctor);
MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH);
return fixVarargs(allocMH, rawMH);
}
private MethodHandle resolveConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
String name = "<init>";
MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
return accessConstructor(refc, ctor);
}
/** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */
private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) {
......@@ -720,10 +745,20 @@ public class MethodHandles {
checkSpecialCaller(specialCaller);
MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
checkSecurityManager(refc, method); // stack walk magic: do not refactor
return accessSpecial(refc, method, specialCaller);
}
private MethodHandle accessSpecial(Class<?> refc, MemberName method,
Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
checkMethod(refc, method, false);
MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller);
return restrictReceiver(method, mh, specialCaller);
}
private MethodHandle resolveSpecial(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
Class<?> specialCaller = lookupClass();
checkSpecialCaller(specialCaller);
MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
return accessSpecial(refc, method, specialCaller);
}
/**
* Produces a method handle giving read access to a non-static field.
......@@ -747,6 +782,10 @@ public class MethodHandles {
checkSecurityManager(refc, field); // stack walk magic: do not refactor
return makeAccessor(refc, field, false, false, 0);
}
private MethodHandle resolveGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(refc, name, type, false);
return makeAccessor(refc, field, false, false, 0);
}
/**
* Produces a method handle giving write access to a non-static field.
......@@ -770,6 +809,10 @@ public class MethodHandles {
checkSecurityManager(refc, field); // stack walk magic: do not refactor
return makeAccessor(refc, field, false, true, 0);
}
private MethodHandle resolveSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(refc, name, type, false);
return makeAccessor(refc, field, false, true, 0);
}
/**
* Produces a method handle giving read access to a static field.
......@@ -792,6 +835,10 @@ public class MethodHandles {
checkSecurityManager(refc, field); // stack walk magic: do not refactor
return makeAccessor(refc, field, false, false, 1);
}
private MethodHandle resolveStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(refc, name, type, true);
return makeAccessor(refc, field, false, false, 1);
}
/**
* Produces a method handle giving write access to a static field.
......@@ -814,6 +861,10 @@ public class MethodHandles {
checkSecurityManager(refc, field); // stack walk magic: do not refactor
return makeAccessor(refc, field, false, true, 1);
}
private MethodHandle resolveStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(refc, name, type, true);
return makeAccessor(refc, field, false, true, 1);
}
/**
* Produces an early-bound method handle for a non-static method.
......@@ -1179,6 +1230,25 @@ return mh1;
MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
return restrictProtectedReceiver(field, mh);
}
/** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
*/
/*non-public*/
MethodHandle linkMethodHandleConstant(int refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException {
switch (refKind) {
case REF_getField: return resolveGetter( defc, name, (Class<?>) type );
case REF_getStatic: return resolveStaticGetter( defc, name, (Class<?>) type );
case REF_putField: return resolveSetter( defc, name, (Class<?>) type );
case REF_putStatic: return resolveStaticSetter( defc, name, (Class<?>) type );
case REF_invokeVirtual: return resolveVirtual( defc, name, (MethodType) type );
case REF_invokeStatic: return resolveStatic( defc, name, (MethodType) type );
case REF_invokeSpecial: return resolveSpecial( defc, name, (MethodType) type );
case REF_newInvokeSpecial: return resolveConstructor( defc, (MethodType) type );
case REF_invokeInterface: return resolveVirtual( defc, name, (MethodType) type );
}
// oops
throw new ReflectiveOperationException("bad MethodHandle constant #"+refKind+" "+name+" : "+type);
}
}
/**
......
......@@ -29,6 +29,8 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
......@@ -38,7 +40,17 @@ import java.util.List;
public class ValueConversions {
private static final Class<?> THIS_CLASS = ValueConversions.class;
// Do not adjust this except for special platforms:
private static final int MAX_ARITY = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
private static final int MAX_ARITY;
static {
final Object[] values = { 255 };
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
return null;
}
});
MAX_ARITY = (Integer) values[0];
}
private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
......
......@@ -30,6 +30,10 @@
* --verify-specifier-count=3
* --expand-properties --classpath ${test.classes}
* --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output
* @run main/othervm
* indify.Indify
* --expand-properties --classpath ${test.classes}
* --java test.java.lang.invoke.InvokeDynamicPrintArgs --security-manager
*/
package test.java.lang.invoke;
......@@ -45,7 +49,8 @@ import static java.lang.invoke.MethodType.*;
public class InvokeDynamicPrintArgs {
public static void main(String... av) throws Throwable {
if (av.length > 0) openBuf(); // --check-output mode
if (av.length > 0 && av[0].equals("--check-output")) openBuf();
if (av.length > 0 && av[0].equals("--security-manager")) setSM();
System.out.println("Printing some argument lists, starting with a empty one:");
INDY_nothing().invokeExact(); // BSM specifier #0 = {bsm}
INDY_bar().invokeExact("bar arg", 1); // BSM specifier #1 = {bsm2, Void.class, "void type"}
......@@ -55,6 +60,43 @@ public class InvokeDynamicPrintArgs {
// Hence, BSM specifier count should be 3. See "--verify-specifier-count=3" above.
System.out.println("Done printing argument lists.");
closeBuf();
checkConstantRefs();
}
private static void checkConstantRefs() throws Throwable {
// check some constant references:
assertEquals(MT_bsm(), MH_bsm().type());
assertEquals(MT_bsm2(), MH_bsm2().type());
try {
assertEquals(MT_bsm(), non_MH_bsm().type());
// if SM is installed, must throw before this point
assertEquals(false, System.getSecurityManager() != null);
} catch (SecurityException ex) {
// if SM is installed, must throw to this point
assertEquals(true, System.getSecurityManager() != null);
}
}
private static void assertEquals(Object exp, Object act) {
if (exp == act || (exp != null && exp.equals(act))) return;
throw new AssertionError("not equal: "+exp+", "+act);
}
private static void setSM() {
// Test for severe security manager interactions (7050328).
class SM extends SecurityManager {
public void checkPackageAccess(String pkg) {
if (pkg.startsWith("test."))
throw new SecurityException("checkPackageAccess "+pkg);
}
public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz == InvokeDynamicPrintArgs.class)
throw new SecurityException("checkMemberAccess "+clazz.getName()+" #"+which);
}
// allow these others:
public void checkPermission(java.security.Permission perm) {
}
}
System.setSecurityManager(new SM());
}
@Test
......@@ -130,6 +172,9 @@ public class InvokeDynamicPrintArgs {
shouldNotCallThis();
return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
}
private static MethodHandle non_MH_bsm() throws ReflectiveOperationException {
return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
}
/* Example of a constant call site with user-data.
* In this case, the user data is exactly the BSM data.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册