8034967: Reduce access to Nashorn internals

Reviewed-by: ahgross, jlaskey, sundar
This commit is contained in:
Attila Szegedi 2014-04-25 14:20:07 +02:00
parent e5a91499f0
commit 8fb1f303f7
4 changed files with 32 additions and 19 deletions

View File

@ -64,7 +64,6 @@ import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter; import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptObject;
@ -132,23 +131,18 @@ import sun.reflect.CallerSensitive;
* implemented securely. * implemented securely.
*/ */
final class JavaAdapterBytecodeGenerator { final class JavaAdapterBytecodeGenerator {
static final Type CONTEXT_TYPE = Type.getType(Context.class);
static final Type OBJECT_TYPE = Type.getType(Object.class); static final Type OBJECT_TYPE = Type.getType(Object.class);
static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
static final Type GLOBAL_TYPE = Type.getType(Global.class);
static final String CONTEXT_TYPE_NAME = CONTEXT_TYPE.getInternalName();
static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName(); static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName();
static final String INIT = "<init>"; static final String INIT = "<init>";
static final String GLOBAL_FIELD_NAME = "global"; static final String GLOBAL_FIELD_NAME = "global";
static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor(); // "global" is declared as Object instead of Global - avoid static references to internal Nashorn classes when possible.
static final String GLOBAL_TYPE_DESCRIPTOR = GLOBAL_TYPE.getDescriptor(); static final String GLOBAL_TYPE_DESCRIPTOR = OBJECT_TYPE.getDescriptor();
static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, GLOBAL_TYPE);
static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE); static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class); private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
@ -159,7 +153,7 @@ final class JavaAdapterBytecodeGenerator {
OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE); OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE);
private static final String GET_HANDLE_FUNCTION_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE, private static final String GET_HANDLE_FUNCTION_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE,
SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE); SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE);
private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(SCRIPT_OBJECT_TYPE); private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE);
private static final Type RUNTIME_EXCEPTION_TYPE = Type.getType(RuntimeException.class); private static final Type RUNTIME_EXCEPTION_TYPE = Type.getType(RuntimeException.class);
private static final Type THROWABLE_TYPE = Type.getType(Throwable.class); private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
private static final Type UNSUPPORTED_OPERATION_TYPE = Type.getType(UnsupportedOperationException.class); private static final Type UNSUPPORTED_OPERATION_TYPE = Type.getType(UnsupportedOperationException.class);
@ -171,7 +165,7 @@ final class JavaAdapterBytecodeGenerator {
private static final String UNSUPPORTED_OPERATION_TYPE_NAME = UNSUPPORTED_OPERATION_TYPE.getInternalName(); private static final String UNSUPPORTED_OPERATION_TYPE_NAME = UNSUPPORTED_OPERATION_TYPE.getInternalName();
private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor(); private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor();
private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(GLOBAL_TYPE); private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE);
private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class)); private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class));
// Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because // Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because
@ -528,11 +522,11 @@ final class JavaAdapterBytecodeGenerator {
} }
private static void invokeGetGlobal(final InstructionAdapter mv) { private static void invokeGetGlobal(final InstructionAdapter mv) {
mv.invokestatic(CONTEXT_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false); mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false);
} }
private static void invokeSetGlobal(final InstructionAdapter mv) { private static void invokeSetGlobal(final InstructionAdapter mv) {
mv.invokestatic(CONTEXT_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false); mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false);
} }
/** /**

View File

@ -31,6 +31,8 @@ import java.security.PrivilegedAction;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.security.SecureClassLoader; import java.security.SecureClassLoader;
import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.beans.StaticClass;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
/** /**
* This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class. * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class.
@ -85,13 +87,14 @@ final class JavaAdapterClassLoader {
@Override @Override
public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
try { try {
Context.checkPackageAccess(name);
return super.loadClass(name, resolve); return super.loadClass(name, resolve);
} catch (final SecurityException se) { } catch (final SecurityException se) {
// we may be implementing an interface or extending a class that was // we may be implementing an interface or extending a class that was
// loaded by a loader that prevents package.access. If so, it'd throw // loaded by a loader that prevents package.access. If so, it'd throw
// SecurityException for nashorn's classes!. For adapter's to work, we // SecurityException for nashorn's classes!. For adapter's to work, we
// should be able to refer to nashorn classes. // should be able to refer to the few classes it needs in its implementation.
if (name.startsWith("jdk.nashorn.internal.")) { if(ScriptFunction.class.getName().equals(name) || JavaAdapterServices.class.getName().equals(name)) {
return myLoader.loadClass(name); return myLoader.loadClass(name);
} }
throw se; throw se;

View File

@ -247,7 +247,7 @@ public final class JavaAdapterFactory {
} }
private static class AdapterInfo { private static class AdapterInfo {
private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptObject.class, true); private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptFunction.class, true);
private final ClassLoader commonLoader; private final ClassLoader commonLoader;
// TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed. // TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed.

View File

@ -116,8 +116,8 @@ public final class JavaAdapterServices {
* static initializers. * static initializers.
* @return the thread-local JS object used to define methods for the class being initialized. * @return the thread-local JS object used to define methods for the class being initialized.
*/ */
public static ScriptObject getClassOverrides() { public static Object getClassOverrides() {
final ScriptObject overrides = classOverrides.get(); final Object overrides = classOverrides.get();
assert overrides != null; assert overrides != null;
return overrides; return overrides;
} }
@ -134,6 +134,22 @@ public final class JavaAdapterServices {
NO_PERMISSIONS_INVOKER.invokeExact(method, arg); NO_PERMISSIONS_INVOKER.invokeExact(method, arg);
} }
/**
* Set the current global scope
* @param global the global scope
*/
public static void setGlobal(final Object global) {
Context.setGlobal((ScriptObject)global);
}
/**
* Get the current global scope
* @return the current global scope
*/
public static Object getGlobal() {
return Context.getGlobal();
}
static void setClassOverrides(ScriptObject overrides) { static void setClassOverrides(ScriptObject overrides) {
classOverrides.set(overrides); classOverrides.set(overrides);
} }