bytecodealliance / bytecodealliance/wit-bindgen
Bug report: Generated C++ glue code bug.
- Dominant language
- Rust
- Stars
- 1.5k
- Forks
- 286
- Avg merge
- 6h 32m
- Merged PRs (30d)
- 19
Description
[cplusplus.zip](https://github.com/user-attachments/files/26672400/cplusplus.zip)
[generated_wit_00000.wit.zip](https://github.com/user-attachments/files/26672406/generated_wit_00000.wit.zip)
[generated_wit_00000b.wit.zip](https://github.com/user-attachments/files/26672402/generated_wit_00000b.wit.zip)
[python.zip](https://github.com/user-attachments/files/26672403/python.zip)
[world0-pvwxtgtmlk_fromPython.wasm.zip](https://github.com/user-attachments/files/26672401/world0-pvwxtgtmlk_fromPython.wasm.zip)
[world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm.zip](https://github.com/user-attachments/files/26672405/world1-consumer_fromC%2B%2B_importworld0-pvwxtgtmlk_fromPython.wasm.zip)
[world1-consumer_fromC++.wasm.zip](https://github.com/user-attachments/files/26672404/world1-consumer_fromC%2B%2B.wasm.zip)
## Summary
Generate C++ glue code via wit-bindgen, then generate a Wasm component.
When executed, both wasmtime and jco crash.
It may be caused by the glue code generated by wit-bindgen causing resource dropped multiple times.
## Environment
jco 1.16.1
wasmtime 41.0.0
wit-bindgen 0.51.0
OS: macOS Sequoia 15.7
CPU: Intel Core i7
## Reproduce steps
The specific reproduction steps are as follows:
1. Use the following command to generate Python binding files from generated_wit_00000.wit.
`componentize-py -d xxx/witfiles/package3hl16smu1p -w world0-pvwxtgtmlk bindings xxx/python/world0-pvwxtgtmlk`
2. Implement the Python program as shown in python.zip.
3. Use the following command to generate Wasm component file from Python.
`cd xxx/python/world0-pvwxtgtmlk`
`componentize-py --wit-path xxx/witfiles/package3hl16smu1p --world world0-pvwxtgtmlk componentize world0-pvwxtgtmlk_generated -o xxx/componentfiles/world0-pvwxtgtmlk_fromPython.wasm`
4. Use the following command to generate C++ binding files from generated_wit_00000b.wit.
`wit-bindgen cpp xxx/witfiles/package3hl16smu1p --world world1-consumer --out-dir xxx/cplusplus/world1-consumer`
5. Implement the C++ program as shown in cplusplus.zip.
6. Use the following command to generate Wasm component file from C++.
`xxx/WASI/wasi-sdk-27.0/wasi-sdk-27.0-x86_64-macos/bin/wasm32-wasip2-clang++ -std=c++23 -o xxx/componentfiles/world1-consumer_fromC++.wasm -mexec-model=reactor xxx/cplusplus/world1-consumer/world1-consumer_generated.cpp xxx/cplusplus/world1-consumer/world1_consumer.cpp xxx/cplusplus/world1-consumer/world1_consumer_component_type.o`
7. Use wac to combine the two Wasm component files:
`wac plug xxx/componentfiles/world1-consumer_fromC++.wasm --plug xxx/componentfiles/world0-pvwxtgtmlk_fromPython.wasm -o xxx/componentfiles/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
8. Use wasmtime to run the final Wasm component file:
`wasmtime run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
Wasmtime prints:
```
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
Error: failed to run main module `world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
Caused by:
0: failed to invoke `run` function
1: error while executing at wasm backtrace:
0: 0x22813ea - world1-consumer_fromC++.wasm!mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File()
1: 0x227fdba - world1-consumer_fromC++.wasm!wit::vector::~vector()
2: 0x227f7dd - world1-consumer_fromC++.wasm!exports::wasi::cli::run::Run()
3: 0x2281dae - world1-consumer_fromC++.wasm!__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
2: unknown handle index 5
```
9. Use jco to run the same final Wasm component file:
`jco run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
jco prints:
```
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
TypeError: Invalid handle
at rscTableRemove (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:1597:13)
at trampoline165 (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:37995:23)
at world1-consumer_fromC++.wasm.mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[84]:0x2e9d)
at world1-consumer_fromC++.wasm.wit::vector::~vector() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[36]:0x186d)
at world1-consumer_fromC++.wasm.exports::wasi::cli::run::Run() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[23]:0x1290)
at world1-consumer_fromC++.wasm.__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[103]:0x3861)
at fn (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38984:15)
at _withGlobalCurrentTaskMeta (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:487:12)
at Object.run (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38981:15)
at file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/_run.js:14:15
```
## Simplified reproduction steps
1. Use wasmtime to run the final Wasm component file:
`wasmtime run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
Wasmtime prints:
```
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
Error: failed to run main module `world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
Caused by:
0: failed to invoke `run` function
1: error while executing at wasm backtrace:
0: 0x22813ea - world1-consumer_fromC++.wasm!mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File()
1: 0x227fdba - world1-consumer_fromC++.wasm!wit::vector::~vector()
2: 0x227f7dd - world1-consumer_fromC++.wasm!exports::wasi::cli::run::Run()
3: 0x2281dae - world1-consumer_fromC++.wasm!__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
2: unknown handle index 5
```
2. Use jco to run the same final Wasm component file:
`jco run world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.wasm`
jco prints:
```
[min-list-own] run begin
[py-provider] make_seq n=2 begin
[py-provider] file.__init__ path=mem://file-1 id=1
[py-provider] file.__init__ path=mem://file-2 id=2
[py-provider] make_seq end ids=[1, 2]
[min-list-own] after make_seq size=2
[py-provider] drain_ids begin len=2
[py-provider] drain_ids consumed ids=[1, 2]
[py-provider] drain_ids end len=2
[min-list-own] drain_ids len=2 ids=[1,2]
[min-list-own] PASS
TypeError: Invalid handle
at rscTableRemove (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:1597:13)
at trampoline165 (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:37995:23)
at world1-consumer_fromC++.wasm.mydefined::package3hl16smu1p::itf0_tmmdqdfhit::File::~File() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[84]:0x2e9d)
at world1-consumer_fromC++.wasm.wit::vector::~vector() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[36]:0x186d)
at world1-consumer_fromC++.wasm.exports::wasi::cli::run::Run() (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[23]:0x1290)
at world1-consumer_fromC++.wasm.__wasm_export_wasiX3AcliX2FrunX400X2E2X2E0X23run (wasm://wasm/world1-consumer_fromC++.wasm-00abfbfa:wasm-function[103]:0x3861)
at fn (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38984:15)
at _withGlobalCurrentTaskMeta (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:487:12)
at Object.run (file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/world1-consumer_fromC++_importworld0-pvwxtgtmlk_fromPython.js:38981:15)
at file:///private/var/folders/ng/263gml_52h33wsbthhfjjr980000gn/T/6vhFlu/_run.js:14:15
```
## Result Analysis
It may due to:
wit-bindgen C++: list> imported argument is not invalidated after call, causing invalid-handle/double-drop in destructor.
When importing a function with signature drain-ids: func(xs: list>) -> list, generated C++ bindings map it to DrainIds(std::span xs).
After the call returns, caller-side xs elements are still destructed as if they own live handles, leading to a second drop and runtime error (unknown handle index / Invalid handle).
And when we replace C++ with Rust to implement the same logic, this bug disappers in both wasmtime and jco. So, it is not due to the Wasm runtime.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.