-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Early versions of this project had such an option, but I had to drop as part of the refactoring required to support native extensions. The implementation is a bit tricky, since we need to import WASI during pre-initialization, but then stub out the imports in the final component. Normally, that would require significant surgery on the pre-initialized component, but I've "cheated" by applying the state snapshot to a stubbed component instead of the original one. Signed-off-by: Joel Dice <joel.dice@fermyon.com>
- Loading branch information
Showing
17 changed files
with
603 additions
and
204 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Example: `sandbox` | ||
|
||
This is an example of how to use | ||
[`wasmtime-py`](https://github.com/bytecodealliance/wasmtime-py) and | ||
[`componentize-py`](https://github.com/dicej/componentize-py) to execute | ||
sandboxed Python code snippets from within a Python app. | ||
|
||
## Prerequisites | ||
|
||
* `wasmtime-py` 18.0.0 or later | ||
* `componentize-py` 0.13.0 | ||
|
||
``` | ||
pip install componentize-py==0.13.0 wasmtime==18.0.2 | ||
``` | ||
|
||
## Running the demo | ||
|
||
``` | ||
componentize-py -d wit -w sandbox componentize guest -o sandbox.wasm | ||
python3 -m wasmtime.bindgen sandbox.wasm --out-dir sandbox | ||
python3 host.py "2 + 2" | ||
``` | ||
|
||
## Examples | ||
|
||
`host.py` accepts zero or more `exec` strings (e.g. newline-delimited | ||
statements) followed by a final `eval` string (i.e. an expression). Note that | ||
any symbols you declare in an `exec` string must be explicitly added to the | ||
global scope using `global`. This ensures they are visible to subsequent `exec` | ||
and `eval` strings. | ||
|
||
```shell-session | ||
$ python3 host.py "2 + 2" | ||
result: 4 | ||
$ python3 host.py 'global foo | ||
def foo(): return 42' 'foo()' | ||
result: 42 | ||
``` | ||
|
||
### Time limit | ||
|
||
`host.py` enforces a twenty second timeout on guest execution. If and when the | ||
timeout is reached, `wasmtime` will raise a `Trap` error. | ||
|
||
```shell-session | ||
$ python3 host.py 'while True: pass' '1' | ||
timeout! | ||
Traceback (most recent call last): | ||
File "/Users/dicej/p/component-sandbox-demo/host.py", line 31, in <module> | ||
result = sandbox.exec(store, arg) | ||
^^^^^^^^^^^^^^^^^^^^^^^^ | ||
... | ||
``` | ||
|
||
### Memory limit | ||
|
||
`host.py` limits guest memory usage to 20MB. Any attempt to allocate beyond | ||
that limit will fail. | ||
|
||
```shell-session | ||
$ python3 host.py 'global foo | ||
foo = bytes(100 * 1024 * 1024)' 'foo[42]' | ||
exec error: MemoryError | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import sandbox | ||
from sandbox.types import Err | ||
import json | ||
|
||
def handle(e: Exception): | ||
message = str(e) | ||
if message == '': | ||
raise Err(f"{type(e).__name__}") | ||
else: | ||
raise Err(f"{type(e).__name__}: {message}") | ||
|
||
class Sandbox(sandbox.Sandbox): | ||
def eval(self, expression: str) -> str: | ||
try: | ||
return json.dumps(eval(expression)) | ||
except Exception as e: | ||
handle(e) | ||
|
||
def exec(self, statements: str): | ||
try: | ||
exec(statements) | ||
except Exception as e: | ||
handle(e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from sandbox import Root | ||
from sandbox.types import Ok, Err | ||
from wasmtime import Config, Engine, Store | ||
import json | ||
import sys | ||
from threading import Timer | ||
from typing import List, Tuple | ||
|
||
TIMEOUT_SECONDS = 20 | ||
MEMORY_LIMIT_BYTES = 20 * 1024 * 1024 | ||
|
||
args = sys.argv[1:] | ||
if len(args) == 0: | ||
print("usage: python3 host.py [<statement>...] <expression>", file=sys.stderr) | ||
exit(-1) | ||
|
||
config = Config() | ||
config.epoch_interruption = True | ||
|
||
def on_timeout(engine): | ||
print("timeout!") | ||
engine.increment_epoch() | ||
|
||
engine = Engine(config) | ||
timer = Timer(TIMEOUT_SECONDS, on_timeout, args=(engine,)) | ||
timer.start() | ||
|
||
try: | ||
store = Store(engine) | ||
store.set_epoch_deadline(1) | ||
store.set_limits(memory_size=MEMORY_LIMIT_BYTES) | ||
|
||
sandbox = Root(store) | ||
for arg in args[:-1]: | ||
result = sandbox.exec(store, arg) | ||
if isinstance(result, Err): | ||
print(f"exec error: {result.value}") | ||
exit(-1) | ||
|
||
result = sandbox.eval(store, args[-1]) | ||
if isinstance(result, Ok): | ||
result = json.loads(result.value) | ||
print(f"result: {result}") | ||
else: | ||
print(f"eval error: {result.value}") | ||
|
||
finally: | ||
timer.cancel() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package local:sandbox; | ||
|
||
world sandbox { | ||
export eval: func(expression: string) -> result<string, string>; | ||
export exec: func(statements: string) -> result<_, string>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.