From 5545dc1ab8a1ca9c40bcf4e45d5ae60ed96af190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linnea=20Gr=C3=A4f?= Date: Mon, 22 Jul 2024 02:54:29 +0200 Subject: [PATCH] Add nashorn sandbox --- build.gradle | 6 +- .../ajarc/computer/ComputerBlockEntity.java | 27 ++++--- src/main/java/dev/exhq/ajarc/vm/JsVm.java | 71 +++++++++++-------- src/main/resources/assets/ajarc/script.js | 3 + 4 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 src/main/resources/assets/ajarc/script.js diff --git a/build.gradle b/build.gradle index 2064e23..3b1e951 100644 --- a/build.gradle +++ b/build.gradle @@ -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}" diff --git a/src/main/java/dev/exhq/ajarc/computer/ComputerBlockEntity.java b/src/main/java/dev/exhq/ajarc/computer/ComputerBlockEntity.java index 49156f0..3a756c5 100644 --- a/src/main/java/dev/exhq/ajarc/computer/ComputerBlockEntity.java +++ b/src/main/java/dev/exhq/ajarc/computer/ComputerBlockEntity.java @@ -35,7 +35,7 @@ public class ComputerBlockEntity extends BlockEntity { private static final MapCodec screenCodec = ComputerTerminal.CODEC .fieldOf("screen") .setPartial(() -> ComputerTerminal.ofSize(20, 30)); - JsVm jsVm = new JsVm(); + JsVm jsVm = new JsVm(this); private List 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) { diff --git a/src/main/java/dev/exhq/ajarc/vm/JsVm.java b/src/main/java/dev/exhq/ajarc/vm/JsVm.java index 6e293b4..749a63b 100644 --- a/src/main/java/dev/exhq/ajarc/vm/JsVm.java +++ b/src/main/java/dev/exhq/ajarc/vm/JsVm.java @@ -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(); - try { - scope = cx.initStandardObjects(); - MathJ mathJ = new MathJ(); - Object wrappedJsVm = Context.javaToJS(mathJ, scope); - ScriptableObject.putProperty(scope, "mathj", wrappedJsVm); - } finally { - Context.exit(); + 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 String evalJs(String command) { - Context.enter(); + public int add(int left, int right) { + String text; try { - Object result = cx.evaluateString(scope, command, "", 1, null); - return Context.toString(result); - } catch (JavaScriptException e) { - return e.getMessage(); - } catch (Exception e) { - return e.getMessage(); - } 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); + } + 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() { - if (cx != null) { - cx.exit(); - cx = null; - } + return (int) (double) bindings.get("result"); } } diff --git a/src/main/resources/assets/ajarc/script.js b/src/main/resources/assets/ajarc/script.js new file mode 100644 index 0000000..4e7ac84 --- /dev/null +++ b/src/main/resources/assets/ajarc/script.js @@ -0,0 +1,3 @@ + +screen.setScreenSize(5, 30) +result = left + right \ No newline at end of file