Skip to content

Commit

Permalink
Reworked exception sandboxing to allow for multiple uncatchable types
Browse files Browse the repository at this point in the history
  • Loading branch information
danielperano committed Jun 18, 2024
1 parent 6adf27d commit e6351a1
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 173 deletions.
1 change: 0 additions & 1 deletion Lang/src/main/java/chipmunk/vm/ChipmunkScript.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ public ChipmunkScript(){

public ChipmunkScript(TrapHandler trapHandler){
this.trapHandler = trapHandler;

tags = new CopyOnWriteArrayList<>();
modules = new ConcurrentHashMap<>();

Expand Down
2 changes: 1 addition & 1 deletion Lang/src/main/java/chipmunk/vm/ChipmunkVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public ChipmunkModule load(BinaryModule module) {
}

public ChipmunkModule load(JvmCompiler jvmCompiler, BinaryModule module) {
JvmCompilation compilation = new JvmCompilation(module, new ModuleLoader(), defaultLinkPolicy, defaultJvmCompilerConfig.getTrapConfig());
JvmCompilation compilation = new JvmCompilation(module, new ModuleLoader(), defaultJvmCompilerConfig);
return jvmCompiler.compileModule(compilation);
}

Expand Down
16 changes: 9 additions & 7 deletions Lang/src/main/java/chipmunk/vm/jvm/JvmCompilation.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,15 @@ public class JvmCompilation {
protected final Set<String> bindings;
protected final Deque<NamespaceInfo> namespaceInfo;

protected final LinkingPolicy policy;
protected final TrapConfig trapConfig;
protected final JvmCompilerConfig config;

public JvmCompilation(BinaryModule module, ModuleLoader loader, LinkingPolicy policy, TrapConfig trapConfig){
public JvmCompilation(BinaryModule module, ModuleLoader loader, JvmCompilerConfig config){
this.module = module;
this.loader = loader;
namespaceInfo = new ArrayDeque<>();
bindings = new HashSet<>();

this.policy = policy;
this.trapConfig = trapConfig;
this.config = config;
}

public BinaryModule getModule() {
Expand All @@ -60,12 +58,16 @@ public ModuleLoader getLoader(){
return loader;
}

public JvmCompilerConfig getConfig(){
return config;
}

public LinkingPolicy getLinkingPolicy(){
return policy;
return config.getLinkingPolicy();
}

public TrapConfig getTrapConfig(){
return trapConfig;
return config.getTrapConfig();
}

public String getPackagePrefix() {
Expand Down
10 changes: 5 additions & 5 deletions Lang/src/main/java/chipmunk/vm/jvm/JvmCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public ChipmunkScript compile(CompilationUnit sources) throws IOException, Binar
}

public ChipmunkModule compileModule(BinaryModule module){
return compileModule(new JvmCompilation(module, new ModuleLoader(), config.getLinkingPolicy(), config.getTrapConfig()));
return compileModule(new JvmCompilation(module, new ModuleLoader(), config));
}

public ChipmunkModule compileModule(JvmCompilation compilation){
Expand Down Expand Up @@ -192,7 +192,7 @@ public ChipmunkModule compileModule(JvmCompilation compilation){
getDependencies.visitEnd();*/

// Module constructor/initializer
var sandbox = new SandboxContext(compilation.getPrefixedModuleName(), "<init>", Type.getMethodType(Type.VOID_TYPE).getDescriptor(), compilation.getLinkingPolicy(), compilation.getTrapConfig());
var sandbox = new SandboxContext(compilation.getPrefixedModuleName(), "<init>", Type.getMethodType(Type.VOID_TYPE).getDescriptor(), compilation.getConfig());
MethodVisitor moduleInit = new Sandbox(moduleWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", Type.getMethodType(Type.VOID_TYPE).getDescriptor(), null, null), sandbox);
moduleInit.visitCode();
moduleInit.visitVarInsn(Opcodes.ALOAD, 0);
Expand Down Expand Up @@ -249,7 +249,7 @@ protected Class<?> visitChipmunkClass(JvmCompilation compilation, BinaryClass cl
cClassWriter.visitAnnotation(Type.getDescriptor(AllowChipmunkLinkage.class), true).visitEnd();

// Generate class constructor
var sandbox = new SandboxContext(qualifiedCClassName, "<init>", Type.getMethodType(Type.VOID_TYPE).getDescriptor(), compilation.getLinkingPolicy(), compilation.getTrapConfig());
var sandbox = new SandboxContext(qualifiedCClassName, "<init>", Type.getMethodType(Type.VOID_TYPE).getDescriptor(), compilation.getConfig());
MethodVisitor clsConstructor = new Sandbox(cClassWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", Type.getMethodType(Type.VOID_TYPE).getDescriptor(), null, null), sandbox);
clsConstructor.visitCode();
clsConstructor.visitVarInsn(Opcodes.ALOAD, 0);
Expand Down Expand Up @@ -302,7 +302,7 @@ protected Class<?> visitChipmunkClass(JvmCompilation compilation, BinaryClass cl
// 1+: binaryConstructor params
Type[] constructorTypes = paramTypes(binaryConstructor.getArgCount() - 1);

sandbox = new SandboxContext(qualifiedInsName, "<init>", Type.getMethodType(Type.VOID_TYPE, initTypes).getDescriptor(), compilation.getLinkingPolicy(), compilation.getTrapConfig());
sandbox = new SandboxContext(qualifiedInsName, "<init>", Type.getMethodType(Type.VOID_TYPE, initTypes).getDescriptor(), compilation.getConfig());
MethodVisitor insConstructor = new Sandbox(cInsWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", Type.getMethodType(Type.VOID_TYPE, initTypes).getDescriptor(), null, null), sandbox);
insConstructor.visitCode();
insConstructor.visitVarInsn(Opcodes.ALOAD, 0);
Expand Down Expand Up @@ -530,7 +530,7 @@ protected void visitMethod(JvmCompilation compilation, ClassWriter cw, String cl

Type methodType = Type.getMethodType(objType, pTypes);

var sandbox = new SandboxContext(compilation.getPrefixedModuleName() + "." + className, name, methodType.getDescriptor(), compilation.getLinkingPolicy(), compilation.getTrapConfig());
var sandbox = new SandboxContext(compilation.getPrefixedModuleName() + "." + className, name, methodType.getDescriptor(), compilation.getConfig());
MethodVisitor mv = new Sandbox(cw.visitMethod(flags, name, methodType.getDescriptor(), null, null), sandbox);
mv.visitCode();

Expand Down
16 changes: 15 additions & 1 deletion Lang/src/main/java/chipmunk/vm/jvm/JvmCompilerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,21 @@

import chipmunk.vm.invoke.security.LinkingPolicy;

import java.util.HashSet;
import java.util.Set;

public class JvmCompilerConfig {

protected final LinkingPolicy linkingPolicy;
protected final TrapConfig trapConfig;

public JvmCompilerConfig(LinkingPolicy policy, TrapConfig trapConfig){
protected final Set<Class<? extends Throwable>> uncatchable;

public JvmCompilerConfig(LinkingPolicy policy, TrapConfig trapConfig){
linkingPolicy = policy;
this.trapConfig = trapConfig;
uncatchable = new HashSet<>();
uncatchable.add(Uncatchable.class);
}

public LinkingPolicy getLinkingPolicy(){
Expand All @@ -41,5 +47,13 @@ public TrapConfig getTrapConfig(){
return trapConfig;
}

public JvmCompilerConfig addUncatchable(Class<? extends Throwable> t){
uncatchable.add(t);
return this;
}

public Set<Class<? extends Throwable>> getUncatchable(){
return uncatchable;
}

}
140 changes: 0 additions & 140 deletions Lang/src/main/java/chipmunk/vm/jvm/JvmSandboxingVisitor.java

This file was deleted.

31 changes: 20 additions & 11 deletions Lang/src/main/java/chipmunk/vm/jvm/Sandbox.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ public void visitLabel(final Label label){
public void visitTryCatchBlock(final Label start, final Label end, Label handler, final String type){

if(!isGuardedBlock(start, end)){
var uncatchableHandler = new Label();

// Sometimes end == handler. In that case, we need to split them - a new handler label is created
// and passed to the original block's visit call below, and the new label is tracked with the guarded
Expand All @@ -101,10 +100,14 @@ public void visitTryCatchBlock(final Label start, final Label end, Label handler
handler = chainHandler;
}

super.visitTryCatchBlock(start, end, uncatchableHandler, Type.getInternalName(Uncatchable.class));
guardedBlocks.add(new TryCatch(start, end, uncatchableHandler, chainHandler));
}

for(var uncatchable : sandbox.getUncatchable()){
var uncatchableHandler = new Label();

super.visitTryCatchBlock(start, end, uncatchableHandler, Type.getInternalName(uncatchable));
guardedBlocks.add(new TryCatch(start, end, uncatchableHandler, chainHandler));
}
}
super.visitTryCatchBlock(start, end, handler, type);
}

Expand Down Expand Up @@ -168,15 +171,21 @@ protected void unmarkGuardedBlock(Label start, Label end){

protected void insertUncatchableHandler(TryCatch tc){

var uncaughtEntry = guardedBlocks.stream()
var uncaughtEntries = guardedBlocks.stream()
.filter(t -> t.sameBlock(tc.start(), tc.end()))
.findFirst()
.get();
.toList();

super.visitLabel(uncaughtEntry.handler());
visitInsn(Opcodes.ATHROW);
if(uncaughtEntry.chainHandler() != null){
super.visitLabel(uncaughtEntry.chainHandler());
// First generate the re-throwers
for(var uncaughtEntry : uncaughtEntries){
super.visitLabel(uncaughtEntry.handler());
visitInsn(Opcodes.ATHROW);
}

// After the re-throw sections, mark the chained handlers for the block
for(var uncaughtEntry : uncaughtEntries){
if(uncaughtEntry.chainHandler() != null){
super.visitLabel(uncaughtEntry.chainHandler());
}
}

unmarkGuardedBlock(tc.start(), tc.end());
Expand Down
23 changes: 16 additions & 7 deletions Lang/src/main/java/chipmunk/vm/jvm/SandboxContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,21 @@

import chipmunk.vm.invoke.security.LinkingPolicy;

import java.util.Set;

public class SandboxContext {

protected final String className;
protected final String methodName;
protected final String methodDescriptor;
protected final LinkingPolicy policy;
protected final TrapConfig trapConfig;

public SandboxContext(String className, String methodName, String methodDescriptor, LinkingPolicy policy, TrapConfig trapConfig){
protected final JvmCompilerConfig config;

public SandboxContext(String className, String methodName, String methodDescriptor, JvmCompilerConfig config){
this.className = className;
this.methodName = methodName;
this.methodDescriptor = methodDescriptor;
this.policy = policy;
this.trapConfig = trapConfig;
this.config = config;
}

public String getClassName(){
Expand All @@ -50,12 +51,20 @@ public String getMethodDescriptor(){
return methodDescriptor;
}

public JvmCompilerConfig getCompilerConfig(){
return config;
}

public LinkingPolicy getLinkingPolicy(){
return policy;
return config.getLinkingPolicy();
}

public TrapConfig getTrapConfig(){
return trapConfig;
return config.getTrapConfig();
}

public Set<Class<? extends Throwable>> getUncatchable(){
return config.getUncatchable();
}

}

0 comments on commit e6351a1

Please sign in to comment.