Stream: git-wasmtime

Topic: wasmtime / issue #13584 Stack switching: host-ward unwind...


view this post on Zulip Wasmtime GitHub notifications bot (Jun 06 2026 at 21:06):

Nymphium opened issue #13584:

Summary

With the stack-switching proposal enabled, once a resume has executed, any subsequent host-ward unwindproc_exit, a wasm trap, or an uncaught exception reaching the host — corrupts the fiber/stack allocator and aborts the process with free(): invalid pointer / munmap_chunk(): invalid pointer (SIGABRT). The resume is the trigger; no exceptions are involved in the minimal repro below. A resume that returns normally (process exits 0) is fine.

Steps to Reproduce

Minimal .wat (no exceptions, just cont.new + resume + proc_exit):

(module
  (import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
  (memory (export "memory") 1)
  (type $ft (func))
  (type $ct (cont $ft))
  (func $body)
  (elem declare func $body)
  (func $start (local $k (ref null $ct))
    ref.func $body
    cont.new $ct
    local.set $k
    block $done
      (resume $ct (local.get $k))
      br $done
    end
    i32.const 0
    call $proc_exit)
  (start $start))
$ wasm-tools parse ss.wat -o ss.wasm
$ wasmtime run -W exceptions=y,function-references=y,stack-switching=y,tail-call=y ss.wasm

Expected Results

The continuation runs to completion, resume returns to $start, and proc_exit(0) exits the process cleanly with code 0.

Actual Results

Process aborts (SIGABRT, exit 134) with a heap-allocator error:

The same crash occurs if, instead of proc_exit, the post-resume code traps (e.g. unreachable / integer divide-by-zero) or lets an uncaught exception reach the host. cont.new without resume followed by proc_exit does not crash, so resume is the trigger. Guest-side attempts to clear state (nulling the cont local, clearing the table slot, nesting the workload in a child continuation, calling proc_exit from within a fiber) all still crash — the corruption appears to live in the per-store stack allocator.

Versions and Environment

Context

This is hit in practice by a language that compiles effect handlers to stack switching: any program that combines a with @k-style handler (a resume) with a later trap or uncaught-exception/proc_exit termination aborts instead of exiting cleanly. Programs that only ever exit 0 after a resume are unaffected.

Filing as a distinct case under the stack-switching tracking issue (#10248). It seems related to the existing "Stack-switching crash with traps and missing bounds checks" item and to the note there that hostcalls from continuation stacks "should not be allowed", but I didn't find a dedicated issue for the proc_exit/host-unwind-after-resume double-free, so opening one with a self-contained repro.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 06 2026 at 23:18):

alexcrichton added the wasm-proposal:stack-switching label to Issue #13584.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 06 2026 at 23:18):

alexcrichton commented on issue #13584:

Thanks for the report, and stack-switching is known to be incomplete and is not recommended for users to enable at this point.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 27 2026 at 16:04):

dhil commented on issue #13584:

This issue will be fixed by #11717. I can add the POC as a regression test.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 28 2026 at 17:45):

dhil commented on issue #13584:

This issue can be closed now, as it was fixed by #11717. I have added the POC as a regression test in #13996.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 28 2026 at 17:52):

alexcrichton closed issue #13584:

Summary

With the stack-switching proposal enabled, once a resume has executed, any subsequent host-ward unwindproc_exit, a wasm trap, or an uncaught exception reaching the host — corrupts the fiber/stack allocator and aborts the process with free(): invalid pointer / munmap_chunk(): invalid pointer (SIGABRT). The resume is the trigger; no exceptions are involved in the minimal repro below. A resume that returns normally (process exits 0) is fine.

Steps to Reproduce

Minimal .wat (no exceptions, just cont.new + resume + proc_exit):

(module
  (import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32)))
  (memory (export "memory") 1)
  (type $ft (func))
  (type $ct (cont $ft))
  (func $body)
  (elem declare func $body)
  (func $start (local $k (ref null $ct))
    ref.func $body
    cont.new $ct
    local.set $k
    block $done
      (resume $ct (local.get $k))
      br $done
    end
    i32.const 0
    call $proc_exit)
  (start $start))
$ wasm-tools parse ss.wat -o ss.wasm
$ wasmtime run -W exceptions=y,function-references=y,stack-switching=y,tail-call=y ss.wasm

Expected Results

The continuation runs to completion, resume returns to $start, and proc_exit(0) exits the process cleanly with code 0.

Actual Results

Process aborts (SIGABRT, exit 134) with a heap-allocator error:

The same crash occurs if, instead of proc_exit, the post-resume code traps (e.g. unreachable / integer divide-by-zero) or lets an uncaught exception reach the host. cont.new without resume followed by proc_exit does not crash, so resume is the trigger. Guest-side attempts to clear state (nulling the cont local, clearing the table slot, nesting the workload in a child continuation, calling proc_exit from within a fiber) all still crash — the corruption appears to live in the per-store stack allocator.

Versions and Environment

Context

This is hit in practice by a language that compiles effect handlers to stack switching: any program that combines a with @k-style handler (a resume) with a later trap or uncaught-exception/proc_exit termination aborts instead of exiting cleanly. Programs that only ever exit 0 after a resume are unaffected.

Filing as a distinct case under the stack-switching tracking issue (#10248). It seems related to the existing "Stack-switching crash with traps and missing bounds checks" item and to the note there that hostcalls from continuation stacks "should not be allowed", but I didn't find a dedicated issue for the proc_exit/host-unwind-after-resume double-free, so opening one with a self-contained repro.


Last updated: Jul 29 2026 at 05:03 UTC