swiftwasm / swiftwasm/WasmKit

Guest execution limits: fuel/epoch interruption + public ResourceLimiter

Open
#421 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
504
Forks
37
Avg merge
1d 1h
Merged PRs (30d)
44

Description

Motivation

We are embedding WasmKit in a game engine as the execution tier for downloaded gameplay modules — the interpreter path exists specifically for platforms where JIT is unavailable (iOS), so WasmKit is a natural fit and has been working well for us (the em_host-style import surface runs a ~50-function host table at 60 Hz ticks).

The gap we hit is guest resource containment. Module code is not fully trusted (eventually user-generated), and today an embedder has no in-process way to bound either of:

  1. Execution time — a guest that never returns from a call (an accidental while true {} is enough) cannot be stopped. We currently contain this at process level (the instance lives in a child process with a heartbeat watchdog that kills and quarantines it), which works but forces a process boundary on every embedder and loses the instance-per-actor isolation story for in-process hosts.

  2. Memory growth — a guest can memory.grow until OS pressure. The machinery for this already exists: ResourceLimiter is a plain public protocol, but the installation point is SPI-gated:

    // Sources/WasmKit/Execution/Store.swift
    @_spi(Fuzzing)  // Consider making this public
    public var resourceLimiter: ResourceLimiter = DefaultResourceLimiter()
    

Requests

1. A preemption/budget mechanism for runaway guests

Either shape would serve embedders:

  • Fuel metering: a configurable budget decremented on back-edges/calls, trapping with a distinct Trap reason when exhausted (wasmi's model), or
  • Epoch/deadline interruption: a cheap flag checked at loop back-edges and function entries that an external thread can set to interrupt the running guest (Wasmtime's epoch model — typically cited as the lower-overhead option for interpreters too).

EngineInterceptor (onEnterFunction/onExitFunction) can't substitute here — it is function-granular, so a loop that never calls out is invisible to it. And #364's fuzzing fix (@_spi(Fuzzing) Module.dropStartFunction()) sidesteps the same class of problem for instantiation rather than solving it generally, which suggests the primitive is missing rather than merely unexposed.

A trap-on-exhaustion/interrupt would compose naturally with the existing Trap error surface — the embedder catches it at the export call site, exactly like an OOB today.

2. Make Store.resourceLimiter public

The protocol (ResourceLimiter) is already public (and AnyObject-constrained since #393, so this stays Embedded-Swift-friendly); only the @_spi(Fuzzing) on the Store property stands between embedders and memory/table growth limits. Promoting it — with whatever rename/shape you prefer — would let hosts cap a guest instance without patching.

Offer

Happy to help: we can test either mechanism against our embedding (a 52-import host table driven at fixed 60 Hz on macOS/arm64, both full-Swift and Embedded-flavor wasm32-unknown-wasip1 guests), contribute benchmarks of the check overhead on the register-machine interpreter, or take a swing at the resourceLimiter promotion as a PR if the direction is agreeable.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Sources/WasmKit/Execution/Store.swift and the existing ResourceLimiter property, then trace EngineInterceptor and the Trap error surface. Compare the proposed fuel or epoch interruption shapes against the interpreter entry and loop paths named in the issue. Done means embedders can configure resource limits publicly and runaway guests stop through a Trap-compatible mechanism, validated with the offered host scenarios and overhead benchmarks.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift, wasm
Domain
backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.