Add nashorn sandbox

This commit is contained in:
Linnea Gräf 2024-07-22 02:54:29 +02:00
parent 4039d11513
commit 5545dc1ab8
No known key found for this signature in database
GPG key ID: AA563E93EB628D91
4 changed files with 60 additions and 47 deletions

View file

@ -20,6 +20,7 @@ group = mod_group_id
repositories {
mavenLocal()
maven { url 'https://repo.nea.moe/releases/' }
}
base {
@ -52,7 +53,10 @@ dependencies {
// And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version.
// For all intends and purposes: You can treat this dependency as if it is a normal library you would use.
implementation "net.neoforged:neoforge:${neo_version}"
libraries 'org.mozilla:rhino-engine:1.7.15'
libraries('org.javadelight:delight-nashorn-sandbox:0.4.2-jpms') {
exclude(group: "org.ow2.asm")
exclude(group: "org.slf4j")
}
// Example optional mod dependency with JEI
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"

View file

@ -35,7 +35,7 @@ public class ComputerBlockEntity extends BlockEntity {
private static final MapCodec<ComputerTerminal> screenCodec = ComputerTerminal.CODEC
.fieldOf("screen")
.setPartial(() -> ComputerTerminal.ofSize(20, 30));
JsVm jsVm = new JsVm();
JsVm jsVm = new JsVm(this);
private List<String> lines = new ArrayList<>();
@Override
@ -77,20 +77,17 @@ public class ComputerBlockEntity extends BlockEntity {
public void executeCommand(String line) {
lines.add("$ " + line);
lines.add(jsVm.evalJs(line));
// if (line.equals("small")) {
// screen = ComputerTerminal.ofSize(10, 20);
// lines.add("Made small!");
// } else if (line.equals("big")) {
// screen = ComputerTerminal.ofSize(20, 30);
// lines.add("Made big!");
// } else if (line.startsWith("add")) {
// var newline = line.replaceFirst("add ", "").split(" ");
// lines.add(JsVm.EvalJs("mathj.add("+newline[0]+","+newline[1]+")"));
// }
// else {
// lines.add("Made unknown!");
// }
if (line.equals("small")) {
screen = ComputerTerminal.ofSize(10, 20);
lines.add("Made small!");
} else if (line.equals("big")) {
screen = ComputerTerminal.ofSize(20, 30);
lines.add("Made big!");
} else if (line.startsWith("add")) {
lines.add(jsVm.add(69, 42) + "");
} else {
lines.add("Made unknown!");
}
}
public ComputerScreenUpdate getSyncPacket(int windowId) {

View file

@ -1,44 +1,53 @@
package dev.exhq.ajarc.vm;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.JavaScriptException;
import delight.nashornsandbox.NashornSandbox;
import delight.nashornsandbox.NashornSandboxes;
import delight.nashornsandbox.internal.JsSanitizer;
import dev.exhq.ajarc.Ajar;
import dev.exhq.ajarc.computer.ComputerBlockEntity;
import dev.exhq.ajarc.computer.ComputerTerminal;
import net.minecraft.client.Minecraft;
import org.apache.commons.io.IOUtils;
import javax.script.ScriptException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public class JsVm {
private Context cx;
private Scriptable scope;
private final NashornSandbox sandbox;
public JsVm() {
cx = Context.enter();
public JsVm(ComputerBlockEntity entity) {
sandbox = NashornSandboxes.create();
sandbox.inject("screen", new ScreenHelper(entity));
}
public record ScreenHelper(ComputerBlockEntity entity) {
public void setScreenSize(int rows, int cols) {
entity.setTerminal(ComputerTerminal.ofSize(rows, cols));
}
}
public int add(int left, int right) {
String text;
try {
scope = cx.initStandardObjects();
MathJ mathJ = new MathJ();
Object wrappedJsVm = Context.javaToJS(mathJ, scope);
ScriptableObject.putProperty(scope, "mathj", wrappedJsVm);
} finally {
Context.exit();
var stream = Minecraft.getInstance()
.getResourceManager()
.getResourceOrThrow(Ajar.identifier("script.js"))
.open();
text = IOUtils.toString(stream, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String evalJs(String command) {
Context.enter();
var bindings = sandbox.createBindings();
bindings.put("left", left);
bindings.put("right", right);
try {
Object result = cx.evaluateString(scope, command, "<cmd>", 1, null);
return Context.toString(result);
} catch (JavaScriptException e) {
return e.getMessage();
} catch (Exception e) {
return e.getMessage();
} finally {
Context.exit();
}
sandbox.eval(text, bindings);
} catch (ScriptException e) {
throw new RuntimeException(e);
}
public void cleanup() {
if (cx != null) {
cx.exit();
cx = null;
}
return (int) (double) bindings.get("result");
}
}

View file

@ -0,0 +1,3 @@
screen.setScreenSize(5, 30)
result = left + right