Skip to content

Commit 411099e

Browse files
committed
[GR-67458][GR-66543] Smoke-test SandboxPolicy.UNTRUSTED.
PullRequest: graalpython/3904
2 parents 535b5ff + b9a2a3b commit 411099e

File tree

8 files changed

+124
-19
lines changed

8 files changed

+124
-19
lines changed

graalpython/com.oracle.graal.python.test.integration/pom.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,6 @@ Additionally, one can change the polyglot artifacts version with
152152
</profile>
153153
<profile>
154154
<id>isolate</id>
155-
<activation>
156-
<property>
157-
<name>polyglot.engine.SpawnIsolate</name>
158-
</property>
159-
</activation>
160155
<dependencies>
161156
<dependency>
162157
<groupId>org.graalvm.polyglot</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.test.integration.advanced;
42+
43+
import static org.junit.Assert.assertEquals;
44+
45+
import java.io.ByteArrayOutputStream;
46+
47+
import org.graalvm.polyglot.Context;
48+
import org.graalvm.polyglot.SandboxPolicy;
49+
import org.graalvm.polyglot.Value;
50+
import org.junit.Assume;
51+
import org.junit.BeforeClass;
52+
import org.junit.Test;
53+
54+
public class SandboxPolicyUntrustedTest {
55+
@BeforeClass
56+
public static void setupClass() {
57+
String requestedTest = System.getProperty("test");
58+
Assume.assumeTrue(requestedTest != null && requestedTest.equals(SandboxPolicyUntrustedTest.class.getSimpleName()));
59+
}
60+
61+
private static Value run(String source) {
62+
ByteArrayOutputStream output = new ByteArrayOutputStream();
63+
ByteArrayOutputStream errorOutput = new ByteArrayOutputStream();
64+
try (Context context = Context.newBuilder("python") //
65+
.sandbox(SandboxPolicy.UNTRUSTED) //
66+
.out(output) //
67+
.err(errorOutput) //
68+
.option("engine.MaxIsolateMemory", "1GB") //
69+
.option("sandbox.MaxHeapMemory", "800MB") //
70+
.option("sandbox.MaxCPUTime", "10s") //
71+
.option("sandbox.MaxASTDepth", "100") //
72+
.option("sandbox.MaxStackFrames", "10") //
73+
.option("sandbox.MaxThreads", "1") //
74+
.option("sandbox.MaxOutputStreamSize", "1MB") //
75+
.option("sandbox.MaxErrorStreamSize", "1MB") //
76+
.build()) {
77+
return context.eval("python", source);
78+
}
79+
}
80+
81+
@Test
82+
public void helloworld() {
83+
assertEquals("hello world", run("'hello world'").asString());
84+
}
85+
86+
@Test
87+
public void canImportBuiltinModules() {
88+
assertEquals("graalpy", run("import sys; sys.implementation.name").asString());
89+
}
90+
91+
@Test
92+
public void canImportNonBuiltinModules() {
93+
assertEquals("email", run("import email; email.__name__").asString());
94+
}
95+
96+
@Test
97+
public void doesNotLeakEnvironmentVariables() {
98+
assertEquals("<empty>", run("import os; os.environ.get('JAVA_HOME', '<empty>')").asString());
99+
}
100+
}

graalpython/com.oracle.graal.python.test.integration/src/com/oracle/graal/python/test/integration/engine/SharedEngineMultithreadingTestBase.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@
5555

5656
import org.graalvm.polyglot.Context;
5757
import org.graalvm.polyglot.Engine;
58-
import org.junit.Assume;
59-
import org.junit.BeforeClass;
6058
import org.junit.Rule;
6159

6260
import com.oracle.graal.python.test.integration.CleanupRule;
@@ -75,12 +73,6 @@ public class SharedEngineMultithreadingTestBase extends PythonTests {
7573

7674
@Rule public CleanupRule cleanup = new CleanupRule();
7775

78-
@BeforeClass
79-
public static void setupClass() {
80-
Assume.assumeFalse("Polyglot isolates may run out of socket descriptors, this is to be investigated",
81-
Boolean.getBoolean("polyglot.engine.SpawnIsolate"));
82-
}
83-
8476
protected static void log(String fmt, Object... args) {
8577
if (LOG) {
8678
System.out.printf(fmt + "\n", args);

graalpython/com.oracle.graal.python.test.integration/src/org/graalvm/python/embedding/test/integration/VirtualFileSystemIntegrationTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,6 @@ public void fsOperations(Context ctx, String pathPrefix) {
270270
eval(ctx, "import os; assert os.path.exists('{pathPrefix}emptydir')", pathPrefix);
271271
eval(ctx, "import os; assert os.path.exists('{pathPrefix}emptydir/')", pathPrefix);
272272
eval(ctx, "import os; assert os.path.exists('{pathPrefix}dir1/file2')", pathPrefix);
273-
Assume.assumeFalse("[GR-66484] FileNotFoundException is not translated properly to isolate and then the Python code gets a generic I/O error",
274-
Boolean.getBoolean("polyglot.engine.SpawnIsolate"));
275273
eval(ctx, "import os; assert not os.path.exists('{pathPrefix}doesnotexist')", pathPrefix);
276274
eval(ctx, "import os; assert not os.path.exists('{pathPrefix}doesnotexist/')", pathPrefix);
277275

graalpython/com.oracle.graal.python/.checkstyle_checks.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@
4747
<property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
4848
</module>
4949
<module name="NoWhitespaceBefore">
50-
<property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
50+
<property name="tokens" value="SEMI,POST_DEC,POST_INC"/>
51+
</module>
52+
<module name="NoWhitespaceBefore">
53+
<property name="tokens" value="DOT"/>
54+
<property name="allowLineBreaks" value="true"/>
5155
</module>
5256
<module name="ParenPad"/>
5357
<module name="TypecastParenPad">

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.graalvm.options.OptionDescriptors;
5656
import org.graalvm.options.OptionKey;
5757
import org.graalvm.options.OptionValues;
58+
import org.graalvm.polyglot.SandboxPolicy;
5859

5960
import com.oracle.graal.python.builtins.Python3Core;
6061
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -147,6 +148,7 @@
147148

148149
@TruffleLanguage.Registration(id = PythonLanguage.ID, //
149150
name = PythonLanguage.NAME, //
151+
sandbox = SandboxPolicy.UNTRUSTED, //
150152
implementationName = PythonLanguage.IMPLEMENTATION_NAME, //
151153
version = PythonLanguage.VERSION, //
152154
characterMimeTypes = {PythonLanguage.MIME_TYPE,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
import java.util.concurrent.ScheduledExecutorService;
5656
import java.util.concurrent.TimeUnit;
5757

58+
import org.graalvm.polyglot.SandboxPolicy;
59+
5860
import com.oracle.graal.python.PythonLanguage;
5961
import com.oracle.graal.python.builtins.objects.function.PArguments;
6062
import com.oracle.graal.python.builtins.objects.function.Signature;
@@ -139,7 +141,7 @@ public final void execute(PythonContext context) {
139141
// Avoid pointless stack walks in random places
140142
PArguments.setException(args, PException.NO_EXCEPTION);
141143

142-
if (debugger == null) {
144+
if (debugger == null && !context.getEnv().getSandboxPolicy().isStricterThan(SandboxPolicy.TRUSTED)) {
143145
debugger = Debugger.find(context.getEnv());
144146
}
145147
if (threadState == null) {
@@ -153,13 +155,17 @@ public final void execute(PythonContext context) {
153155
if (!alreadyProfiling) {
154156
threadState.profilingStart();
155157
}
156-
debugger.disableStepping();
158+
if (debugger != null) {
159+
debugger.disableStepping();
160+
}
157161
try {
158162
CallDispatchers.SimpleIndirectInvokeNode.executeUncached(context.getAsyncHandler().callTarget, args);
159163
} catch (PException e) {
160164
handleException(e);
161165
} finally {
162-
debugger.restoreStepping();
166+
if (debugger != null) {
167+
debugger.restoreStepping();
168+
}
163169
if (!alreadyTracing) {
164170
threadState.tracingStop();
165171
}

mx.graalpython/mx_graalpython.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,13 +1247,21 @@ def graalpython_gate_runner(args, tasks):
12471247
env['JAVA_HOME'] = graalvm_jdk(enterprise=True)
12481248
mx.run_maven(mvn_cmd_base + [
12491249
'-U',
1250+
'-Pisolate',
12501251
'-Dpolyglot.engine.AllowExperimentalOptions=true',
12511252
'-Dpolyglot.engine.SpawnIsolate=true',
12521253
'-Dpolyglot.engine.IsolateMode=external',
12531254
'clean',
12541255
'test',
12551256
], env=env)
12561257

1258+
mx.log("Running integration JUnit tests on GraalVM SDK with untrusted sandbox policy")
1259+
mx.run_maven(mvn_cmd_base + [
1260+
'-Pisolate',
1261+
'-Dtest=SandboxPolicyUntrustedTest',
1262+
'test',
1263+
], env=env)
1264+
12571265
# Unittests on JVM
12581266
with Task('GraalPython JVM build', tasks, tags=[GraalPythonTags.jvmbuild]) as task:
12591267
if task:

0 commit comments

Comments
 (0)