outl_exec/wasm/engine.rs
1//! `wasmtime::Engine` factory + sandbox knobs.
2//!
3//! We build the engine once per runtime instance (engines are cheap to
4//! share — modules are the heavy thing) and clone it into every store.
5//! The configuration is the **single source of truth** for what
6//! "sandboxed" means in outl:
7//!
8//! - Fuel on (consume_fuel = true) → caller decides how many
9//! instructions a run gets.
10//! - Epoch interruption on → caller bumps the engine's epoch from a
11//! timer thread for wall-clock cancellation. Today
12//! [`crate::sandbox::with_timeout`] still does the thread-based
13//! timeout; the epoch path is wired up so an upcoming refactor can
14//! move to it without a config churn.
15
16use wasmtime::{Config, Engine, OptLevel};
17
18/// Sandbox limits a single `execute` call may use.
19///
20/// The defaults are conservative: 1 million instructions, 64 MiB heap,
21/// no growth beyond that. Callers tighten as needed (a tiny snippet
22/// running in a TUI loop deserves much less than a long batch job).
23#[derive(Debug, Clone, Copy)]
24pub struct SandboxLimits {
25 /// Maximum wasm instructions the run may execute. wasmtime calls
26 /// this "fuel"; one unit ≈ one instruction.
27 pub fuel: u64,
28 /// Hard cap on heap, in bytes. Past this, wasmtime traps.
29 pub max_memory_bytes: usize,
30}
31
32impl Default for SandboxLimits {
33 fn default() -> Self {
34 Self {
35 fuel: 5_000_000,
36 max_memory_bytes: 64 * 1024 * 1024,
37 }
38 }
39}
40
41/// Build a `wasmtime::Engine` with the outl sandbox configuration.
42/// Cheap to call; reuse the result across `WasmModule` instances when
43/// possible.
44pub fn make_engine() -> Engine {
45 let mut cfg = Config::new();
46 cfg.consume_fuel(true);
47 cfg.epoch_interruption(true);
48 cfg.cranelift_opt_level(OptLevel::Speed);
49 // WASI requires multi-memory and bulk-memory; both enabled by
50 // default on recent wasmtime, but be explicit.
51 cfg.wasm_multi_memory(true);
52 cfg.wasm_bulk_memory(true);
53 Engine::new(&cfg).expect("wasmtime Config we control is always valid")
54}