8139435: Make sure CallSiteDescriptor.getLookup is subject to a security check
Reviewed-by: hannesw, sundar
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java Mon Oct 19 08:30:03 2015 +0200
@@ -101,6 +101,11 @@
*/
public interface CallSiteDescriptor {
/**
+ * A permission to invoke the {@link #getLookup()} method. It is named {@code "dynalink.getLookup"}.
+ */
+ public static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission("dynalink.getLookup");
+
+ /**
* The index of the name token that will carry the operation scheme prefix (usually, "dyn").
*/
public static final int SCHEME = 0;
@@ -160,7 +165,8 @@
* Returns the lookup passed to the bootstrap method.
* @return the lookup passed to the bootstrap method.
* @throws SecurityException if the lookup isn't the {@link MethodHandles#publicLookup()} and a security
- * manager is present, and a check for {@code RuntimePermission("dynalink.getLookup")} fails.
+ * manager is present, and a check for {@code RuntimePermission("dynalink.getLookup")} (available as
+ * {@link #GET_LOOKUP_PERMISSION}) fails.
*/
public Lookup getLookup();
@@ -194,6 +200,25 @@
}
/**
+ * Checks if the current access context is granted the {@code RuntimePermission("dynalink.getLookup")}
+ * permission, if the system contains a security manager, and the passed lookup is not the
+ * {@link MethodHandles#publicLookup()}.
+ * @param lookup the lookup being checked for access
+ * @return the passed in lookup if there's either no security manager in the system, or the passed lookup
+ * is the public lookup, or the current access context is granted the relevant permission.
+ * @throws SecurityException if the system contains a security manager, and the passed lookup is not the
+ * {@link MethodHandles#publicLookup()}, and the current access context is not granted the relevant
+ * permission.
+ */
+ public static Lookup checkLookup(final Lookup lookup) {
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null && lookup != MethodHandles.publicLookup()) {
+ sm.checkPermission(GET_LOOKUP_PERMISSION);
+ }
+ return lookup;
+ }
+
+ /**
* Tokenizes the composite name along colons, as well as {@link NameCodec#decode(String) demangles} and interns
* the tokens. The first two tokens are not demangled as they are supposed to be the naming scheme and the name of
* the operation which can be expected to consist of just alphabetical characters.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Mon Oct 19 08:30:03 2015 +0200
@@ -149,6 +149,12 @@
* </ul>
*/
public final class DynamicLinker {
+ /**
+ * A permission to invoke the {@link #getCurrentLinkRequest()} method. It is named
+ * {@code "dynalink.getCurrentLinkRequest"}.
+ */
+ public static final RuntimePermission GET_CURRENT_LINK_REQUEST_PERMISSION = new RuntimePermission("dynalink.getCurrentLinkRequest");
+
private static final String CLASS_NAME = DynamicLinker.class.getName();
private static final String RELINK_METHOD_NAME = "relink";
@@ -321,8 +327,8 @@
/**
* Returns the currently processed link request, or null if the method is invoked outside of the linking process.
* @return the currently processed link request, or null.
- * @throws SecurityException if the calling code doesn't have the {@code "dynalink.getCurrentLinkRequest"} runtime
- * permission.
+ * @throws SecurityException if the calling code doesn't have the {@code "dynalink.getCurrentLinkRequest"}
+ * runtime permission (available as {@link #GET_CURRENT_LINK_REQUEST_PERMISSION}).
*/
public static LinkRequest getCurrentLinkRequest() {
return LinkerServicesImpl.getCurrentLinkRequest();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java Mon Oct 19 08:30:03 2015 +0200
@@ -96,7 +96,6 @@
* Default implementation of the {@link LinkerServices} interface.
*/
final class LinkerServicesImpl implements LinkerServices {
- private static final RuntimePermission GET_CURRENT_LINK_REQUEST = new RuntimePermission("dynalink.getCurrentLinkRequest");
private static final ThreadLocal<LinkRequest> threadLinkRequest = new ThreadLocal<>();
private final TypeConverterFactory typeConverterFactory;
@@ -159,7 +158,7 @@
if (currentRequest != null) {
final SecurityManager sm = System.getSecurityManager();
if(sm != null) {
- sm.checkPermission(GET_CURRENT_LINK_REQUEST);
+ sm.checkPermission(DynamicLinker.GET_CURRENT_LINK_REQUEST_PERMISSION);
}
}
return currentRequest;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java Mon Oct 19 08:30:03 2015 +0200
@@ -568,7 +568,7 @@
private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments(
MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class);
private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class,
- "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class, LinkerServices.class));
+ "getTarget", MethodType.methodType(MethodHandle.class, CallSiteDescriptor.class, LinkerServices.class));
private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
@@ -591,7 +591,7 @@
final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
AnnotatedDynamicMethod.class));
final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
- GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup(), linkerServices);
+ GET_ANNOTATED_METHOD, 1, callSiteDescriptor, linkerServices);
final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
callSiteBoundMethodGetter);
// Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0)
@@ -871,8 +871,8 @@
}
@SuppressWarnings("unused")
- MethodHandle getTarget(final MethodHandles.Lookup lookup, final LinkerServices linkerServices) {
- final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(lookup));
+ MethodHandle getTarget(final CallSiteDescriptor desc, final LinkerServices linkerServices) {
+ final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(desc));
assert inv != null;
return inv;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Mon Oct 19 08:30:03 2015 +0200
@@ -91,12 +91,15 @@
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.Lookup;
/**
* A dynamic method bound to exactly one Java method or constructor that is caller sensitive. Since the target method is
* caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in
- * {@link #getTarget(java.lang.invoke.MethodHandles.Lookup)} to unreflect a method handle from the reflective member on
+ * {@link #getTarget(CallSiteDescriptor)} to unreflect a method handle from the reflective member on
* every request.
*/
class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
@@ -143,7 +146,11 @@
}
@Override
- MethodHandle getTarget(final MethodHandles.Lookup lookup) {
+ MethodHandle getTarget(final CallSiteDescriptor desc) {
+ final MethodHandles.Lookup lookup = AccessController.doPrivileged(
+ (PrivilegedAction<MethodHandles.Lookup>)()->desc.getLookup(), null,
+ CallSiteDescriptor.GET_LOOKUP_PERMISSION);
+
if(target instanceof Method) {
final MethodHandle mh = Lookup.unreflect(lookup, (Method)target);
if(Modifier.isStatic(((Member)target).getModifiers())) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Mon Oct 19 08:30:03 2015 +0200
@@ -84,7 +84,6 @@
package jdk.internal.dynalink.beans;
import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.text.Collator;
import java.util.ArrayList;
@@ -216,9 +215,8 @@
// methods here to their handles, as the OverloadedMethod instance is specific to a call site, so it
// has an already determined Lookup.
final List<MethodHandle> methodHandles = new ArrayList<>(invokables.size());
- final MethodHandles.Lookup lookup = callSiteDescriptor.getLookup();
for(final SingleDynamicMethod method: invokables) {
- methodHandles.add(method.getTarget(lookup));
+ methodHandles.add(method.getTarget(callSiteDescriptor));
}
return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker();
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Mon Oct 19 08:30:03 2015 +0200
@@ -84,13 +84,13 @@
package jdk.internal.dynalink.beans;
import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
+import jdk.internal.dynalink.CallSiteDescriptor;
/**
* A dynamic method bound to exactly one Java method or constructor that is not caller sensitive. Since its target is
* not caller sensitive, this class pre-caches its method handle and always returns it from the call to
- * {@link #getTarget(Lookup)}. Can be used in general to represents dynamic methods bound to a single method handle,
+ * {@link #getTarget(CallSiteDescriptor)}. Can be used in general to represents dynamic methods bound to a single method handle,
* even if that handle is not mapped to a Java method, i.e. as a wrapper around field getters/setters, array element
* getters/setters, etc.
*/
@@ -140,7 +140,7 @@
}
@Override
- MethodHandle getTarget(final Lookup lookup) {
+ MethodHandle getTarget(final CallSiteDescriptor desc) {
return target;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Mon Oct 19 08:30:03 2015 +0200
@@ -119,15 +119,17 @@
abstract MethodType getMethodType();
/**
- * Given a specified lookup, returns a method handle to this method's target.
- * @param lookup the lookup to use.
+ * Given a specified call site descriptor, returns a method handle to this method's target. The target
+ * should only depend on the descriptor's lookup, and it should only retrieve it (as a privileged
+ * operation) when it is absolutely needed.
+ * @param desc the call site descriptor to use.
* @return the handle to this method's target method.
*/
- abstract MethodHandle getTarget(MethodHandles.Lookup lookup);
+ abstract MethodHandle getTarget(CallSiteDescriptor desc);
@Override
MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
- return getInvocation(getTarget(callSiteDescriptor.getLookup()), callSiteDescriptor.getMethodType(),
+ return getInvocation(getTarget(callSiteDescriptor), callSiteDescriptor.getMethodType(),
linkerServices);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java Mon Oct 19 08:30:03 2015 +0200
@@ -89,30 +89,32 @@
import jdk.internal.dynalink.CallSiteDescriptor;
/**
- * A base class for call site descriptor implementations. Provides reconstruction of the name from the tokens, as well
- * as a generally useful {@code equals} and {@code hashCode} methods.
+ * A base class for call site descriptor implementations. Provides reconstruction of the name from the tokens,
+ * as well as generally useful {@code equals}, {@code hashCode}, and {@code toString} methods. For security
+ * and performance reasons, subclasses must implement {@link #lookupEquals(AbstractCallSiteDescriptor)},
+ * {@link #lookupHashCode()} and {@link #lookupToString()} methods.
+ * @param <T> The call site descriptor subclass
*/
-public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
+public abstract class AbstractCallSiteDescriptor<T extends AbstractCallSiteDescriptor<T>> implements CallSiteDescriptor {
@Override
public String getName() {
return appendName(new StringBuilder(getNameLength())).toString();
}
+ @SuppressWarnings("unchecked")
@Override
public boolean equals(final Object obj) {
- return obj instanceof CallSiteDescriptor && equals((CallSiteDescriptor)obj);
+ return obj != null && obj.getClass() == getClass() && equalsInKind((T)obj);
}
/**
- * Returns true if this call site descriptor is equal to the passed call site descriptor.
+ * Returns true if this call site descriptor is equal to the passed, non-null call site descriptor of the
+ * same class.
* @param csd the other call site descriptor.
* @return true if they are equal.
*/
- public boolean equals(final CallSiteDescriptor csd) {
- if(csd == null) {
- return false;
- }
+ protected boolean equalsInKind(final T csd) {
if(csd == this) {
return true;
}
@@ -128,13 +130,32 @@
if(!getMethodType().equals(csd.getMethodType())) {
return false;
}
- return lookupsEqual(getLookup(), csd.getLookup());
+ return lookupEquals(csd);
+ }
+
+ /**
+ * Returns true if this call site descriptor's lookup is equal to the other call site descriptor's lookup.
+ * Typical implementation should try to obtain the other lookup directly without going through
+ * {@link #getLookup()} (e.g. directly using the implementation) and then delegate to
+ * {@link #lookupsEqual(MethodHandles.Lookup, MethodHandles.Lookup)}.
+ * @param other the other lookup
+ * @return true if the lookups are equal
+ */
+ protected abstract boolean lookupEquals(T other);
+
+ protected static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
+ if(l1 == l2) {
+ return true;
+ }
+ if(l1.lookupClass() != l2.lookupClass()) {
+ return false;
+ }
+ return l1.lookupModes() == l2.lookupModes();
}
@Override
public int hashCode() {
- final MethodHandles.Lookup lookup = getLookup();
- int h = lookup.lookupClass().hashCode() + 31 * lookup.lookupModes();
+ int h = lookupHashCode();
final int c = getNameTokenCount();
for(int i = 0; i < c; ++i) {
h = h * 31 + getNameToken(i).hashCode();
@@ -142,14 +163,32 @@
return h * 31 + getMethodType().hashCode();
}
+ /**
+ * Return the hash code of this call site descriptor's {@link Lookup} object. Typical
+ * implementation should delegate to {@link #lookupHashCode(MethodHandles.Lookup)}.
+ * @return the hash code of this call site descriptor's {@link Lookup} object.
+ */
+ protected abstract int lookupHashCode();
+
+ protected static int lookupHashCode(final Lookup lookup) {
+ return lookup.lookupClass().hashCode() + 31 * lookup.lookupModes();
+ }
+
@Override
public String toString() {
final String mt = getMethodType().toString();
- final String l = getLookup().toString();
+ final String l = lookupToString();
final StringBuilder b = new StringBuilder(l.length() + 1 + mt.length() + getNameLength());
return appendName(b).append(mt).append("@").append(l).toString();
}
+ /**
+ * Return a string representation of this call site descriptor's {@link Lookup} object. Typically will
+ * return {@link Lookup#toString()}.
+ * @return a string representation of this call site descriptor's {@link Lookup} object.
+ */
+ protected abstract String lookupToString();
+
private int getNameLength() {
final int c = getNameTokenCount();
int l = 0;
@@ -167,14 +206,4 @@
}
return b;
}
-
- private static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
- if(l1 == l2) {
- return true;
- }
- if(l1.lookupClass() != l2.lookupClass()) {
- return false;
- }
- return l1.lookupModes() == l2.lookupModes();
- }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleCallSiteDescriptor.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleCallSiteDescriptor.java Mon Oct 19 08:30:03 2015 +0200
@@ -83,18 +83,19 @@
package jdk.internal.dynalink.support;
+import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
-import java.security.Permission;
import java.util.Objects;
import jdk.internal.dynalink.CallSiteDescriptor;
/**
* A simple implementation of the call site descriptor. It stores the lookup, the name, and the method type.
+ * Even if you roll your own implementation of {@link CallSiteDescriptor}, you might want to use
+ * {@link CallSiteDescriptor#checkLookup(MethodHandles.Lookup)} as a ready-made utility method to ensure you're handing
+ * out lookup objects securely.
*/
-public class SimpleCallSiteDescriptor extends AbstractCallSiteDescriptor {
- private static final Permission GET_LOOKUP_PERMISSION = new RuntimePermission("dynalink.getLookup");
-
+public class SimpleCallSiteDescriptor extends AbstractCallSiteDescriptor<SimpleCallSiteDescriptor> {
private final Lookup lookup;
private final String[] tokenizedName;
private final MethodType methodType;
@@ -138,11 +139,26 @@
@Override
public final Lookup getLookup() {
- return lookup;
+ return CallSiteDescriptor.checkLookup(lookup);
}
@Override
public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
return new SimpleCallSiteDescriptor(lookup, tokenizedName, newMethodType);
}
+
+ @Override
+ protected boolean lookupEquals(final SimpleCallSiteDescriptor other) {
+ return AbstractCallSiteDescriptor.lookupsEqual(lookup, other.lookup);
+ }
+
+ @Override
+ protected int lookupHashCode() {
+ return AbstractCallSiteDescriptor.lookupHashCode(lookup);
+ }
+
+ @Override
+ protected String lookupToString() {
+ return lookup.toString();
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Mon Oct 19 08:30:03 2015 +0200
@@ -29,10 +29,14 @@
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.invoke.SwitchPoint;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -914,7 +918,7 @@
} else if (data.isBuiltin() && "extend".equals(data.getName())) {
// NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
// current lookup as its "this" so it can do security-sensitive creation of adapter classes.
- boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, type.parameterType(0), type.parameterType(1));
+ boundHandle = MH.dropArguments(MH.bindTo(callHandle, getLookupPrivileged(desc)), 0, type.parameterType(0), type.parameterType(1));
} else if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
// (this, args...) => ([this], args...)
@@ -955,6 +959,12 @@
exceptionGuard);
}
+ private static Lookup getLookupPrivileged(final CallSiteDescriptor desc) {
+ // NOTE: we'd rather not make NashornCallSiteDescriptor.getLookupPrivileged public.
+ return AccessController.doPrivileged((PrivilegedAction<Lookup>)()->desc.getLookup(), null,
+ CallSiteDescriptor.GET_LOOKUP_PERMISSION);
+ }
+
private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) {
final MethodType descType = desc.getMethodType();
final int paramCount = descType.parameterCount();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Mon Oct 19 08:30:03 2015 +0200
@@ -95,7 +95,8 @@
final String opName = hasFixedName ? (DYN_GET_METHOD_FIXED + descriptor.getNameToken(
CallSiteDescriptor.NAME_OPERAND)) : DYN_GET_METHOD;
- final CallSiteDescriptor newDescriptor = NashornCallSiteDescriptor.get(descriptor.getLookup(), opName,
+ final CallSiteDescriptor newDescriptor = NashornCallSiteDescriptor.get(
+ NashornCallSiteDescriptor.getLookupPrivileged(descriptor), opName,
type.changeParameterType(0, adapterClass), 0);
// Delegate to BeansLinker
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Mon Oct 19 08:30:03 2015 +0200
@@ -108,8 +108,9 @@
if (name != null) {
final MethodType callType = desc.getMethodType();
// drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod:<name>
- final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(),
- "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2),
+ final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(
+ NashornCallSiteDescriptor.getLookupPrivileged(desc), "dyn:callMethod:" + name,
+ desc.getMethodType().dropParameterTypes(1, 2),
NashornCallSiteDescriptor.getFlags(desc));
final GuardedInvocation gi = getGuardedInvocation(beansLinker,
linkRequest.replaceArguments(newDesc, linkRequest.getArguments()),
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Mon Oct 19 08:30:03 2015 +0200
@@ -28,6 +28,8 @@
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.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import jdk.internal.dynalink.CallSiteDescriptor;
@@ -40,7 +42,7 @@
* we can have a more compact representation, as we know that we're always only using {@code "dyn:*"} operations; also
* we're storing flags in an additional primitive field.
*/
-public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor {
+public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor<NashornCallSiteDescriptor> {
/** Flags that the call site references a scope variable (it's an identifier reference or a var declaration, not a
* property access expression. */
public static final int CALLSITE_SCOPE = 1 << 0;
@@ -199,12 +201,20 @@
@Override
public Lookup getLookup() {
- return lookup;
+ return CallSiteDescriptor.checkLookup(lookup);
+ }
+
+ static Lookup getLookupPrivileged(final CallSiteDescriptor csd) {
+ if (csd instanceof NashornCallSiteDescriptor) {
+ return ((NashornCallSiteDescriptor)csd).lookup;
+ }
+ return AccessController.doPrivileged((PrivilegedAction<Lookup>)()->csd.getLookup(), null,
+ CallSiteDescriptor.GET_LOOKUP_PERMISSION);
}
@Override
- public boolean equals(final CallSiteDescriptor csd) {
- return super.equals(csd) && flags == getFlags(csd);
+ protected boolean equalsInKind(final NashornCallSiteDescriptor csd) {
+ return super.equalsInKind(csd) && flags == csd.flags;
}
@Override
@@ -444,7 +454,22 @@
@Override
public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
- return get(getLookup(), operator, operand, newMethodType, flags);
+ return get(lookup, operator, operand, newMethodType, flags);
+ }
+
+
+ @Override
+ protected boolean lookupEquals(final NashornCallSiteDescriptor other) {
+ return AbstractCallSiteDescriptor.lookupsEqual(lookup, other.lookup);
}
+ @Override
+ protected int lookupHashCode() {
+ return AbstractCallSiteDescriptor.lookupHashCode(lookup);
+ }
+
+ @Override
+ protected String lookupToString() {
+ return lookup.toString();
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Mon Oct 19 08:30:03 2015 +0200
@@ -171,14 +171,14 @@
return null;
}
- private static java.lang.invoke.MethodHandles.Lookup getCurrentLookup() {
- final LinkRequest currentRequest = AccessController.doPrivileged(new PrivilegedAction<LinkRequest>() {
+ private static MethodHandles.Lookup getCurrentLookup() {
+ return AccessController.doPrivileged(new PrivilegedAction<MethodHandles.Lookup>() {
@Override
- public LinkRequest run() {
- return DynamicLinker.getCurrentLinkRequest();
+ public MethodHandles.Lookup run() {
+ final LinkRequest currentRequest = DynamicLinker.getCurrentLinkRequest();
+ return currentRequest == null ? MethodHandles.publicLookup() : currentRequest.getCallSiteDescriptor().getLookup();
}
- });
- return currentRequest == null ? MethodHandles.publicLookup() : currentRequest.getCallSiteDescriptor().getLookup();
+ }, null, CallSiteDescriptor.GET_LOOKUP_PERMISSION, DynamicLinker.GET_CURRENT_LINK_REQUEST_PERMISSION);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Mon Oct 19 08:23:03 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Mon Oct 19 08:30:03 2015 +0200
@@ -83,7 +83,7 @@
// Change this link request into a link request on the adapter class.
final Object[] args = request.getArguments();
args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null,
- linkRequest.getCallSiteDescriptor().getLookup());
+ NashornCallSiteDescriptor.getLookupPrivileged(linkRequest.getCallSiteDescriptor()));
final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args);
final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass);
// Finally, modify the guard to test for the original abstract class.