bytecodealliance / bytecodealliance/wit-bindgen

wit-bindgen cpp drops a handle twice

Open
#1,682 0 comments 0 reactions 0 assignees View on GitHub
gen-cpp
Dominant language
Rust
Stars
1.5k
Forks
286
Avg merge
6h 32m
Merged PRs (30d)
19

Description

Summary: wit-bindgen-cpp: generated C++ resource destructor calls resource.drop on an already-freed handle, trapping with "invalid handle" in wasmtime

Reproduction of a wit-bindgen-cpp bug where the generated C++ resource-export destructor chain (ResourceExportBase::Deregister → ResourceDrop) performs an invalid/duplicate resource.drop, aborting the component with an invalid-handle trap under wasmtime.

The wit-bindgen C++ backend is at fault—its glue layer performs an extra drop in the lift/destructor chain, translating a semantically valid program into a component that contains illegal operations.

## Environment

| component | version |
|---|---|
| OS | macOS 15.7 (Darwin 24.6.0), x86_64 |
| wasmtime | wasmtime 41.0.0 (3dda91692 2026-01-20) |
| wac | wac-cli 0.8.1 |
| wasi-sdk | 27.0 (wasm32-wasip2-clang/clang++) |

## Steps to reproduce

The full chain is: compile the guest sources into a provider component and a consumer component, compose them with `wac`, then run the composed component. Prebuilt copies of every artifact are included (`components/provider.wasm`, `components/consumer.wasm`, `composed.wasm`), so you can also skip straight to step 5.

**Github repo:https://github.com/xiaozzzZZzzz240/G006-wit-bindgen-cpp-resource-drop-invalid-handle-trap-in-generated**

1. Clone this repository:

```console
git clone
cd
```

2. Compile the provider component from the **C++** sources in `src/provider-Cpp/` (toolchain versions in the table above; the WIT package is in `wit/`):

```console
wasm32-wasip2-clang++ -std=c++23 -fno-exceptions -o components/provider.wasm -mexec-model=reactor src/provider-Cpp/world9-wi7n9u47_generated.cpp src/provider-Cpp/world9_wi7n9u47.cpp src/provider-Cpp/world9_wi7n9u47_component_type.o
```

3. Compile the consumer component from the **C** sources in `src/consumer-C/`:

```console
wasm32-wasip2-clang -o components/consumer.wasm -mexec-model=reactor src/consumer-C/world9b-mul38v8w_generated.c src/consumer-C/world9b_mul38v8w.c src/consumer-C/world9b_mul38v8w_component_type.o
```

4. Compose the two components into one runnable component with wac 0.8.1:

```console
wac plug components/consumer.wasm --plug components/provider.wasm -o composed.wasm
```

5. Run the composed component with wasmtime 41.0.0:

```console
wasmtime run composed.wasm
```

## Expected result

This test case intentionally performs an invalid resource-handle operation at the very end, so the **expected** behavior is: print the prefix below, then trap cleanly with `invalid handle`.

```text
"resinst0"
"resinst1"
"resinst2"
"resinst0"
resource("temres32")
"c1"
true
"c0"
resource("temres35")
(resource("temres36"), "foo")
"c1"
true
true
resource("temres225")
"bar"
"c2"
true
true
"temres35"
"temres40"
"beta"
"c0"
true
true
5
true
trap(invalid handle)
```

## Actual result

Under **wasmtime** the same `composed.wasm` exits with rc=1. stdout:

```text
"resinst0"
"resinst1"
"resinst2"
"resinst0"
resource("temres32")
"c1"
true
"c0"
resource("temres35")
(resource("temres36"), "foo")
"c1"
true
true
resource("temres225")
"bar"
"c2"
true
true
```

stderr:

```text
Error: failed to run main module `/Users/myuser/WASM/myProject/Wasm_component_testing/mycode/execute/reportrepo/G006-wit-bindgen-cpp-resource-drop-invalid-handle-trap-in-generated/composed.wasm`

Caused by:
0: failed to invoke `run` function
1: error while executing at wasm backtrace:
0: 0x1b078 - provider.wasm!exports::mydefined::package3hl16smu1p::itf_ou0j0n064d::Res2::ResourceDrop(int)
1: 0x12e58 - provider.wasm!wit::ResourceExportBase::Deregister::operator()(exports::mydefined::package3hl16smu1p::itf_ou0j0n064d::Res2*) const
2: 0x69f9 - provider.wasm!std::__2::unique_ptr::Deregister>::reset[abi:nn200100](exports::mydefined::package3hl16smu1p::itf_ou0j0n064d::Res2*)
3: 0x5b98 - provider.wasm!std::__2::unique_ptr::Deregister>::~unique_ptr[abi:nn200100]()
4: 0x1e008 - provider.wasm!std::__2::__tuple_leaf<0ul, std::__2::unique_ptr::Deregister>, false>::~__tuple_leaf()
5: 0x1af60 - provider.wasm!std::__2::__tuple_impl, std::__2::unique_ptr::Deregister>, wit::string>::~__tuple_impl()
6: 0x1ad37 - provider.wasm!std::__2::tuple::Deregister>, wit::string>::~tuple()
7: 0x1b45b - provider.wasm!__wasm_export_mydefinedX3Apackage3hl16smu1pX2Fitf_ou0j0n064dX23f_m2yyf8i
8: 0xab2 - !
9: 0xe5f60 - wit-component:shim!indirect-mydefined:package3hl16smu1p/itf-ou0j0n064d-f-m2yyf8i
10: 0xa9057 - consumer.wasm!mydefined_package3hl16smu1p_itf_ou0j0n064d_f_m2yyf8i
11: 0xa7845 - consumer.wasm!exports_wasi_cli_run_run
12: 0xa9209 - consumer.wasm!__wasm_export_exports_wasi_cli_run_run
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
2: handle index 1 used with the wrong type, expected guest-defined resource but found a different guest-defined resource
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.