diff --git a/src/main/java/org/truffleruby/core/string/CoreStrings.java b/src/main/java/org/truffleruby/core/string/CoreStrings.java index 755c3e546cfa..57bb4dfb8e86 100644 --- a/src/main/java/org/truffleruby/core/string/CoreStrings.java +++ b/src/main/java/org/truffleruby/core/string/CoreStrings.java @@ -29,7 +29,6 @@ public class CoreStrings { public final CoreString STACK_LEVEL_TOO_DEEP; public final CoreString TIME_INTERVAL_MUST_BE_POS; public final CoreString TOO_FEW_ARGUMENTS; - public final CoreString TZ; public final CoreString UNKNOWN; public final CoreString UTC; public final CoreString WRONG_ARGS_ZERO_PLUS_ONE; @@ -52,7 +51,6 @@ public CoreStrings(RubyLanguage language) { STACK_LEVEL_TOO_DEEP = new CoreString(language, "stack level too deep"); TIME_INTERVAL_MUST_BE_POS = new CoreString(language, "time interval must be positive"); TOO_FEW_ARGUMENTS = new CoreString(language, "too few arguments"); - TZ = new CoreString(language, "TZ"); UNKNOWN = new CoreString(language, "(unknown)"); UTC = new CoreString(language, "UTC"); WRONG_ARGS_ZERO_PLUS_ONE = new CoreString(language, "wrong number of arguments (0 for 1+)"); diff --git a/src/main/java/org/truffleruby/core/string/FrozenStrings.java b/src/main/java/org/truffleruby/core/string/FrozenStrings.java index 9a2f962dfb73..9de3ec1071d6 100644 --- a/src/main/java/org/truffleruby/core/string/FrozenStrings.java +++ b/src/main/java/org/truffleruby/core/string/FrozenStrings.java @@ -39,6 +39,7 @@ public class FrozenStrings { public static final ImmutableRubyString SELF = createFrozenStaticBinaryString("self"); public static final ImmutableRubyString SUPER = createFrozenStaticBinaryString("super"); public static final ImmutableRubyString TRUE = createFrozenStaticBinaryString("true"); + public static final ImmutableRubyString TZ = createFrozenStaticBinaryString("TZ"); private static ImmutableRubyString createFrozenStaticBinaryString(String string) { // defined?(...) returns frozen strings with a binary encoding diff --git a/src/main/java/org/truffleruby/core/time/GetTimeZoneNode.java b/src/main/java/org/truffleruby/core/time/GetTimeZoneNode.java index 6bafd302bb2c..095e16f5e673 100644 --- a/src/main/java/org/truffleruby/core/time/GetTimeZoneNode.java +++ b/src/main/java/org/truffleruby/core/time/GetTimeZoneNode.java @@ -34,7 +34,7 @@ import java.util.regex.Pattern; import com.oracle.truffle.api.CompilerDirectives; -import org.truffleruby.RubyLanguage; +import org.truffleruby.core.string.FrozenStrings; import org.truffleruby.language.RubyBaseNode; import org.truffleruby.language.RubyGuards; import org.truffleruby.language.control.RaiseException; @@ -63,13 +63,17 @@ public static void invalidateTZ() { @Specialization(assumptions = "TZ_UNCHANGED.getAssumption()") protected TimeZoneAndName getTimeZone( - @Cached("getTZ(getLanguage())") Object tzValue, + @Cached("getTZ()") Object tzValue, @Cached("getTimeZone(tzValue)") TimeZoneAndName zone) { return zone; } - protected Object getTZ(RubyLanguage language) { - return lookupEnvNode.call(coreLibrary().getENV(), "[]", language.coreStrings.TZ.createInstance(getContext())); + protected Object getTZ() { + if (getContext().getEnv().isNativeAccessAllowed()) { + return lookupEnvNode.call(coreLibrary().getENV(), "[]", FrozenStrings.TZ); + } else { + return nil; + } } @TruffleBoundary @@ -82,7 +86,7 @@ protected TimeZoneAndName getTimeZone(Object tz) { if (tz == nil) { // $TZ is not set, use the system timezone - return new TimeZoneAndName(getSystemTimeZone()); + return new TimeZoneAndName(getContext().getEnv().getTimeZone()); } else if (libString.isRubyString(tz)) { return parse(tzString); } else { @@ -90,10 +94,6 @@ protected TimeZoneAndName getTimeZone(Object tz) { } } - private static ZoneId getSystemTimeZone() { - return ZoneId.systemDefault(); - } - private static final Map LONG_TZNAME = Helpers.map( "MET", "CET", // JRUBY-2759 diff --git a/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngine.java b/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngine.java index 98ccaa60cdd1..9b5125659c72 100644 --- a/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngine.java +++ b/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngine.java @@ -38,9 +38,9 @@ public class TruffleRubyScriptEngine extends AbstractScriptEngine private final Context polyglot; - TruffleRubyScriptEngine(TruffleRubyScriptEngineFactory factory) { + TruffleRubyScriptEngine(TruffleRubyScriptEngineFactory factory, boolean allowAllAccess) { this.factory = factory; - polyglot = Context.newBuilder().allowAllAccess(true).build(); + this.polyglot = Context.newBuilder("ruby").allowAllAccess(allowAllAccess).build(); } @Override diff --git a/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngineFactory.java b/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngineFactory.java index 98251b6347f7..b9fbeedb0fac 100644 --- a/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngineFactory.java +++ b/src/services/java/org/truffleruby/services/scriptengine/TruffleRubyScriptEngineFactory.java @@ -106,7 +106,11 @@ public String getProgram(String... statements) { @Override public ScriptEngine getScriptEngine() { - return new TruffleRubyScriptEngine(this); + return getScriptEngine(false); + } + + public ScriptEngine getScriptEngine(boolean allowAllAccess) { + return new TruffleRubyScriptEngine(this, allowAllAccess); } private String query(String expression) { diff --git a/src/test/java/org/truffleruby/JSR223InteropTest.java b/src/test/java/org/truffleruby/JSR223InteropTest.java index 8b2d82d9d62f..fd58d0a29f9c 100644 --- a/src/test/java/org/truffleruby/JSR223InteropTest.java +++ b/src/test/java/org/truffleruby/JSR223InteropTest.java @@ -10,6 +10,8 @@ package org.truffleruby; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.List; @@ -17,17 +19,36 @@ import javax.script.Compilable; import javax.script.CompiledScript; import javax.script.Invocable; +import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import org.junit.After; import org.junit.Test; import org.truffleruby.fixtures.FluidForce; -import org.truffleruby.services.scriptengine.TruffleRubyScriptEngine; import org.truffleruby.services.scriptengine.TruffleRubyScriptEngineFactory; import org.truffleruby.shared.TruffleRuby; public class JSR223InteropTest { + private ScriptEngine scriptEngine = null; + + @After + public void after() { + if (scriptEngine != null) { + close(scriptEngine); + scriptEngine = null; + } + } + + private static void close(ScriptEngine scriptEngine) { + try { + ((AutoCloseable) scriptEngine).close(); + } catch (Exception e) { + throw new Error(e); + } + } + @Test public void testVersion() { assertEquals(TruffleRuby.getEngineVersion(), new TruffleRubyScriptEngineFactory().getEngineVersion()); @@ -36,91 +57,93 @@ public void testVersion() { @Test public void testCreateEngine() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - assertEquals(14, scriptEngine.eval("14")); + scriptEngine = m.getEngineByName("ruby"); + assertEquals(42, scriptEngine.eval("6 * 7")); + } + + @Test + public void testNoPermissionsByDefault() { + final ScriptEngineManager m = new ScriptEngineManager(); + scriptEngine = m.getEngineByName("ruby"); + try { + scriptEngine.eval("Process.pid"); + fail("should have thrown"); + } catch (ScriptException scriptException) { + assertEquals("org.graalvm.polyglot.PolyglotException: native access is not allowed (SecurityError)", + scriptException.getMessage()); } } + @Test + public void testAllAccess() throws ScriptException { + scriptEngine = new TruffleRubyScriptEngineFactory().getScriptEngine(true); + assertTrue(scriptEngine.eval("Process.pid") instanceof Integer); + } + @Test public void testParameters() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - final Bindings bindings = scriptEngine.createBindings(); - bindings.put("a", 14); - bindings.put("b", 2); - assertEquals(16, scriptEngine.eval("a + b", bindings)); - } + scriptEngine = m.getEngineByName("ruby"); + final Bindings bindings = scriptEngine.createBindings(); + bindings.put("a", 14); + bindings.put("b", 2); + assertEquals(16, scriptEngine.eval("a + b", bindings)); } @Test public void testCallingMethods() throws ScriptException, NoSuchMethodException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - assertEquals( - 0.909, - (double) ((Invocable) scriptEngine).invokeMethod(scriptEngine.eval("Math"), "sin", 2), - 0.01); - } + scriptEngine = m.getEngineByName("ruby"); + assertEquals( + 0.909, + (double) ((Invocable) scriptEngine).invokeMethod(scriptEngine.eval("Math"), "sin", 2), + 0.01); } @Test public void testCreatingObjects() throws ScriptException, NoSuchMethodException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - final Object time = ((Invocable) scriptEngine).invokeMethod(scriptEngine.eval("Time"), "new", 2021, 3, 18); - final Object year = ((Invocable) scriptEngine).invokeMethod(time, "year"); - assertEquals(2021, year); - } + scriptEngine = m.getEngineByName("ruby"); + final Object time = ((Invocable) scriptEngine).invokeMethod(scriptEngine.eval("Time"), "new", 2021, 3, 18); + final Object year = ((Invocable) scriptEngine).invokeMethod(time, "year"); + assertEquals(2021, year); } @SuppressWarnings("unchecked") @Test public void testAccessingArrays() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - assertEquals(4, ((List) scriptEngine.eval("[3, 4, 5]")).get(1)); - } + scriptEngine = m.getEngineByName("ruby"); + assertEquals(4, ((List) scriptEngine.eval("[3, 4, 5]")).get(1)); } - @SuppressWarnings("unchecked") @Test public void testAccessingHashes() throws ScriptException, NoSuchMethodException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - assertEquals( - 4, - (int) ((Invocable) scriptEngine).invokeMethod( - scriptEngine.eval("{'a' => 3, 'b' => 4, 'c' => 5}"), - "fetch", - 'b')); - } + scriptEngine = m.getEngineByName("ruby"); + assertEquals( + 4, + (int) ((Invocable) scriptEngine).invokeMethod( + scriptEngine.eval("{'a' => 3, 'b' => 4, 'c' => 5}"), + "fetch", + 'b')); } @Test public void testImplementInterface() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - final FluidForce fluidForce = ((Invocable) scriptEngine) - .getInterface(scriptEngine.eval(FluidForce.RUBY_SOURCE), FluidForce.class); - assertEquals(5587.008375144088, fluidForce.getFluidForce(2.0, 3.0, 6.0), 0.01); - } + scriptEngine = m.getEngineByName("ruby"); + final FluidForce fluidForce = ((Invocable) scriptEngine) + .getInterface(scriptEngine.eval(FluidForce.RUBY_SOURCE), FluidForce.class); + assertEquals(5587.008375144088, fluidForce.getFluidForce(2.0, 3.0, 6.0), 0.01); } @Test public void testParseOnceRunMany() throws ScriptException { final ScriptEngineManager m = new ScriptEngineManager(); - try (TruffleRubyScriptEngine scriptEngine = (TruffleRubyScriptEngine) m - .getEngineByName(TruffleRuby.LANGUAGE_ID)) { - final CompiledScript compiled = ((Compilable) scriptEngine).compile("14"); - assertEquals(14, compiled.eval()); - } + scriptEngine = m.getEngineByName("ruby"); + final CompiledScript compiled = ((Compilable) scriptEngine).compile("14"); + assertEquals(14, compiled.eval()); } } diff --git a/src/test/java/org/truffleruby/PolyglotInteropTest.java b/src/test/java/org/truffleruby/PolyglotInteropTest.java index 4d18513eb33a..147fb2bf81e2 100644 --- a/src/test/java/org/truffleruby/PolyglotInteropTest.java +++ b/src/test/java/org/truffleruby/PolyglotInteropTest.java @@ -62,8 +62,7 @@ public void testPassingBlocks() { @Test public void testCreatingObjects() { - // Native access needed for ENV['TZ'] - try (Context polyglot = Context.newBuilder().allowNativeAccess(true).build()) { + try (Context polyglot = Context.create()) { assertEquals( 2021, polyglot.eval("ruby", "Time").newInstance(2021, 3, 18).getMember("year").execute().asInt());