зеркало из https://github.com/mozilla/pjs.git
Fixing design flaw in SecurityController:
The new SecurityController in its current form does not allow to define more then one generated class class in the same class loader effectively preventing to use optimizer which needs to define classes that refer each other and should be defined in the same loader. To fix this I replaced the defineClass method in SecurityController by public GeneratedClassLoader createClassLoader(Object securityDomain); which returns instance of the new GeneratedClassLoader interface which can be used to define several classes. I also made DefiningClassLoader to implement this interface to simplify code in JavaAdapter.java and optimizer/Codegen.java.
This commit is contained in:
Родитель
c202f30c42
Коммит
bbb8216d37
|
@ -40,12 +40,16 @@ package org.mozilla.classfile;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.GeneratedClassLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load generated classes.
|
* Load generated classes.
|
||||||
*
|
*
|
||||||
* @author Norris Boyd
|
* @author Norris Boyd
|
||||||
*/
|
*/
|
||||||
public class DefiningClassLoader extends ClassLoader {
|
public class DefiningClassLoader extends ClassLoader
|
||||||
|
implements GeneratedClassLoader
|
||||||
|
{
|
||||||
|
|
||||||
public static ClassLoader getContextClassLoader() {
|
public static ClassLoader getContextClassLoader() {
|
||||||
try {
|
try {
|
||||||
|
@ -62,10 +66,14 @@ public class DefiningClassLoader extends ClassLoader {
|
||||||
return DefiningClassLoader.class.getClassLoader();
|
return DefiningClassLoader.class.getClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class defineClass(String name, byte data[]) {
|
public Class defineClass(String name, byte[] data) {
|
||||||
return super.defineClass(name, data, 0, data.length);
|
return super.defineClass(name, data, 0, data.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void linkClass(Class cl) {
|
||||||
|
resolveClass(cl);
|
||||||
|
}
|
||||||
|
|
||||||
public Class loadClass(String name, boolean resolve)
|
public Class loadClass(String name, boolean resolve)
|
||||||
throws ClassNotFoundException
|
throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Rhino code, released
|
||||||
|
* May 6, 1999.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Igor Bukanov
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* terms of the GNU Public License (the "GPL"), in which case the
|
||||||
|
* provisions of the GPL are applicable instead of those above.
|
||||||
|
* If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of the GPL and not to allow others to use your
|
||||||
|
* version of this file under the NPL, indicate your decision by
|
||||||
|
* deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this
|
||||||
|
* file under either the NPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// API class
|
||||||
|
|
||||||
|
package org.mozilla.javascript;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to define classes from generated byte code.
|
||||||
|
*/
|
||||||
|
public interface GeneratedClassLoader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a new Java class.
|
||||||
|
* Classes created via this method should have the same class loader.
|
||||||
|
*
|
||||||
|
* @param name fully qualified class name
|
||||||
|
* @param data class byte code
|
||||||
|
* @return new class object
|
||||||
|
*/
|
||||||
|
public Class defineClass(String name, byte[] data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link the given class.
|
||||||
|
*
|
||||||
|
* @param cl Class instance returned from the previous call to
|
||||||
|
* {@link #defineClass(String, byte[])}
|
||||||
|
* @see java.lang.ClassLoader#resolveClass(Class)
|
||||||
|
*/
|
||||||
|
public void linkClass(Class cl);
|
||||||
|
}
|
|
@ -334,16 +334,17 @@ public class JavaAdapter extends ScriptableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeneratedClassLoader loader;
|
||||||
SecurityController sc = cx.getSecurityController();
|
SecurityController sc = cx.getSecurityController();
|
||||||
if (sc != null) {
|
if (sc == null) {
|
||||||
|
loader = new DefiningClassLoader();
|
||||||
|
} else {
|
||||||
Object securityDomain = sc.getDynamicSecurityDomain(null);
|
Object securityDomain = sc.getDynamicSecurityDomain(null);
|
||||||
Class result = sc.defineClass(adapterName, bytes, securityDomain);
|
loader = sc.createClassLoader(securityDomain);
|
||||||
if (result != null)
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
DefiningClassLoader classLoader = new DefiningClassLoader();
|
Class result = loader.defineClass(adapterName, bytes);
|
||||||
classLoader.defineClass(adapterName, bytes);
|
loader.linkClass(result);
|
||||||
return classLoader.loadClass(adapterName, true);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -65,23 +65,13 @@ package org.mozilla.javascript;
|
||||||
public abstract class SecurityController {
|
public abstract class SecurityController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define and load a Java class.
|
* Get class loader-like object that can be used
|
||||||
* <p>
|
* to define classes with the given security context.
|
||||||
* In embeddings that care about security, the securityDomain
|
|
||||||
* must be associated with the defined class such that a call to
|
|
||||||
* <code>getSecurityDomain</code> with that class will return this security
|
|
||||||
* context.
|
|
||||||
* <p>
|
|
||||||
* @param name the name of the class
|
|
||||||
* @param data the bytecode of the class
|
|
||||||
* @param securityDomain some object specifying the security
|
* @param securityDomain some object specifying the security
|
||||||
* context of the code that is defining this class.
|
* context of the code that is defined by the returned class loader.
|
||||||
* Embeddings that don't care about security may allow
|
|
||||||
* null here. This value propagated from the values passed
|
|
||||||
* into methods of Context that evaluate scripts.
|
|
||||||
*/
|
*/
|
||||||
public abstract Class defineClass(String name, byte[] data,
|
public abstract GeneratedClassLoader
|
||||||
Object securityDomain);
|
createClassLoader(Object securityDomain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get dynamic security domain that allows an action only if it is allowed
|
* Get dynamic security domain that allows an action only if it is allowed
|
||||||
|
|
|
@ -80,9 +80,11 @@ public class Codegen extends Interpreter {
|
||||||
|
|
||||||
Exception e = null;
|
Exception e = null;
|
||||||
Class result = null;
|
Class result = null;
|
||||||
DefiningClassLoader classLoader = null;
|
GeneratedClassLoader loader;
|
||||||
if (securityController == null) {
|
if (securityController == null) {
|
||||||
classLoader = new DefiningClassLoader();
|
loader = new DefiningClassLoader();
|
||||||
|
} else {
|
||||||
|
loader = securityController.createClassLoader(securityDomain);
|
||||||
}
|
}
|
||||||
nameHelper.reset();
|
nameHelper.reset();
|
||||||
|
|
||||||
|
@ -98,39 +100,25 @@ public class Codegen extends Interpreter {
|
||||||
String name = (String) names.get(i);
|
String name = (String) names.get(i);
|
||||||
byte[] classFile = (byte[]) classFiles.get(i);
|
byte[] classFile = (byte[]) classFiles.get(i);
|
||||||
boolean isTopLevel = name.equals(generatedName);
|
boolean isTopLevel = name.equals(generatedName);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (repository.storeClass(name, classFile, isTopLevel)) {
|
if (repository.storeClass(name, classFile, isTopLevel)) {
|
||||||
Class clazz = null;
|
Class cl = loader.defineClass(name, classFile);
|
||||||
if (securityController != null) {
|
if (isTopLevel) {
|
||||||
clazz = securityController.
|
result = cl;
|
||||||
defineClass(name, classFile, securityDomain);
|
|
||||||
if (clazz == null) {
|
|
||||||
throw new NullPointerException
|
|
||||||
("SecurityController.defineClass"
|
|
||||||
+" may not return null");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clazz = classLoader.defineClass(name, classFile);
|
|
||||||
ClassLoader loader = clazz.getClassLoader();
|
|
||||||
clazz = loader.loadClass(name);
|
|
||||||
}
|
}
|
||||||
if (isTopLevel)
|
|
||||||
result = clazz;
|
|
||||||
}
|
}
|
||||||
} catch (ClassFormatError ex) {
|
} catch (ClassFormatError ex) {
|
||||||
throw new RuntimeException(ex.toString());
|
throw new RuntimeException(ex.toString());
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
throw new RuntimeException(ex.toString());
|
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
throw WrappedException.wrapException(iox);
|
throw WrappedException.wrapException(iox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (result != null) {
|
||||||
catch (SecurityException x) {
|
loader.linkClass(result);
|
||||||
|
}
|
||||||
|
} catch (SecurityException x) {
|
||||||
e = x;
|
e = x;
|
||||||
}
|
} catch (IllegalArgumentException x) {
|
||||||
catch (IllegalArgumentException x) {
|
|
||||||
e = x;
|
e = x;
|
||||||
}
|
}
|
||||||
if (e != null)
|
if (e != null)
|
||||||
|
|
|
@ -48,10 +48,22 @@ public class JavaPolicySecurity extends SecurityProxy
|
||||||
{
|
{
|
||||||
|
|
||||||
private static class Loader extends ClassLoader
|
private static class Loader extends ClassLoader
|
||||||
|
implements GeneratedClassLoader
|
||||||
{
|
{
|
||||||
Class defineClass(String name, byte[] data, ProtectionDomain domain) {
|
private ProtectionDomain domain;
|
||||||
|
|
||||||
|
Loader(ClassLoader parent, ProtectionDomain domain) {
|
||||||
|
super(parent != null ? parent : getSystemClassLoader());
|
||||||
|
this.domain = domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class defineClass(String name, byte[] data) {
|
||||||
return super.defineClass(name, data, 0, data.length, domain);
|
return super.defineClass(name, data, 0, data.length, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void linkClass(Class cl) {
|
||||||
|
resolveClass(cl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ContextPermissions extends PermissionCollection
|
private static class ContextPermissions extends PermissionCollection
|
||||||
|
@ -134,7 +146,7 @@ public class JavaPolicySecurity extends SecurityProxy
|
||||||
URL urlObj;
|
URL urlObj;
|
||||||
try {
|
try {
|
||||||
urlObj = new URL(url);
|
urlObj = new URL(url);
|
||||||
}catch (MalformedURLException ex) {
|
} catch (MalformedURLException ex) {
|
||||||
// Assume as Main.processFileSecure it is file, need to build its
|
// Assume as Main.processFileSecure it is file, need to build its
|
||||||
// URL
|
// URL
|
||||||
String curDir = System.getProperty("user.dir");
|
String curDir = System.getProperty("user.dir");
|
||||||
|
@ -145,7 +157,7 @@ public class JavaPolicySecurity extends SecurityProxy
|
||||||
try {
|
try {
|
||||||
URL curDirURL = new URL("file:"+curDir);
|
URL curDirURL = new URL("file:"+curDir);
|
||||||
urlObj = new URL(curDirURL, url);
|
urlObj = new URL(curDirURL, url);
|
||||||
}catch (MalformedURLException ex2) {
|
} catch (MalformedURLException ex2) {
|
||||||
throw new RuntimeException
|
throw new RuntimeException
|
||||||
("Can not construct file URL for '"+url+"':"
|
("Can not construct file URL for '"+url+"':"
|
||||||
+ex2.getMessage());
|
+ex2.getMessage());
|
||||||
|
@ -160,15 +172,9 @@ public class JavaPolicySecurity extends SecurityProxy
|
||||||
return new ProtectionDomain(cs, pc);
|
return new ProtectionDomain(cs, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void doPrivileged(final Runnable code) {
|
public GeneratedClassLoader createClassLoader(Object securityDomain) {
|
||||||
}
|
|
||||||
|
|
||||||
public Class defineClass(String name, byte[] data,
|
|
||||||
Object securityDomain)
|
|
||||||
{
|
|
||||||
ProtectionDomain domain = (ProtectionDomain)securityDomain;
|
ProtectionDomain domain = (ProtectionDomain)securityDomain;
|
||||||
Loader loader = new Loader();
|
return new Loader(getClass().getClassLoader(), domain);
|
||||||
return loader.defineClass(name, data, domain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getDynamicSecurityDomain(Object securityDomain)
|
public Object getDynamicSecurityDomain(Object securityDomain)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче