Skip to content

catch_unwind doesn't catch non-C++ exceptions on wasm #148273

@bjorn3

Description

@bjorn3

I tried this code:

#[unsafe(no_mangle)]
pub fn square(num: i32) -> std::thread::Result<i32> {
    std::panic::catch_unwind(|| bar())
}

unsafe extern "C-unwind" {
    safe fn bar() -> i32;
}

compiled with -Cpanic=unwind --crate-type cdylib --target wasm32-wasip1 + -Zbuild-std.

I expected to see this happen: An exception originating from bar which doesn't conform with the wasm C++ exception ABI will cause an abort, just like foreign exceptions would on native platforms when unwinding through catch_unwind.

Instead, this happened: catch_unwind only generates a wasm catch instruction matching the C++ exception tag. For unwinding out of functions that are not allowed to unwind at all we do correctly generate a catch_all instruction to call panic_cannot_unwind.

(func $square (;2;) (type 0) (param i32 i32)
    (local i32 i32 i32)
    global.get $__stack_pointer
    i32.const 16
    i32.sub
    local.tee 2
    global.set $__stack_pointer
    block ;; label = @1
      try ;; label = @2
        call $bar
        local.set 3
      catch 0
        local.set 3
        local.get 2
        global.set $__stack_pointer
        try ;; label = @3
          local.get 2
          i32.const 8
          i32.add
          local.get 3
          call $_ZN3std9panicking12catch_unwind7cleanup17h1c165d98d6186f41E
        catch_all
          local.get 2
          global.set $__stack_pointer
          call $_ZN4core9panicking19panic_cannot_unwind17h45f1d8e8d54a6393E
          unreachable
        end
        local.get 2
        i32.load offset=12
        local.set 3
        local.get 2
        i32.load offset=8
        local.set 4
        local.get 0
        local.get 4
        i32.store
        local.get 0
        local.get 3
        i32.store offset=4
        br 1 (;@1;)
      end
      local.get 0
      i32.const 0
      i32.store
      local.get 0
      local.get 3
      i32.store offset=4
    end
    local.get 2
    i32.const 16
    i32.add
    global.set $__stack_pointer
  )

Meta

rustc --version --verbose:

rustc 1.92.0-nightly (695857bc3 2025-10-21)
binary: rustc
commit-hash: 695857bc3f72ec4f59c79f323460fe488c38a53f
commit-date: 2025-10-21
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-prioritizeIssue: Indicates that prioritization has been requested for this issue.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-wasmTarget: WASM (WebAssembly), http://webassembly.org/WG-ffi-unwindWorking group: FFI unwindneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions