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 { repositories {
mavenLocal() mavenLocal()
maven { url 'https://repo.nea.moe/releases/' }
} }
base { 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. // 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. // 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}" 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 // Example optional mod dependency with JEI
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime // 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}" // 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 private static final MapCodec<ComputerTerminal> screenCodec = ComputerTerminal.CODEC
.fieldOf("screen") .fieldOf("screen")
.setPartial(() -> ComputerTerminal.ofSize(20, 30)); .setPartial(() -> ComputerTerminal.ofSize(20, 30));
JsVm jsVm = new JsVm(); JsVm jsVm = new JsVm(this);
private List<String> lines = new ArrayList<>(); private List<String> lines = new ArrayList<>();
@Override @Override
@ -77,20 +77,17 @@ public class ComputerBlockEntity extends BlockEntity {
public void executeCommand(String line) { public void executeCommand(String line) {
lines.add("$ " + line); lines.add("$ " + line);
lines.add(jsVm.evalJs(line)); if (line.equals("small")) {
// if (line.equals("small")) { screen = ComputerTerminal.ofSize(10, 20);
// screen = ComputerTerminal.ofSize(10, 20); lines.add("Made small!");
// lines.add("Made small!"); } else if (line.equals("big")) {
// } else if (line.equals("big")) { screen = ComputerTerminal.ofSize(20, 30);
// screen = ComputerTerminal.ofSize(20, 30); lines.add("Made big!");
// lines.add("Made big!"); } else if (line.startsWith("add")) {
// } else if (line.startsWith("add")) { lines.add(jsVm.add(69, 42) + "");
// var newline = line.replaceFirst("add ", "").split(" "); } else {
// lines.add(JsVm.EvalJs("mathj.add("+newline[0]+","+newline[1]+")")); lines.add("Made unknown!");
// } }
// else {
// lines.add("Made unknown!");
// }
} }
public ComputerScreenUpdate getSyncPacket(int windowId) { public ComputerScreenUpdate getSyncPacket(int windowId) {

View file

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

View file

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