wasm32-unknown-unknown: wasm-ld fails to relocate drop_in_place entry in some trait object vtables
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Environment
- Rust version:
rustc 1.96.0 (ac68faa20 2026-05-25) - Binary:
wasm32-unknown-unknown,cdylib, opt-level=s, no LTO, no PIC
Summary
For some trait object vtables compiled to wasm32-unknown-unknown, wasm-ld fails to apply R_WASM_TABLE_INDEX_SLEB relocation to the drop_in_place entry. The entry retains the raw function index instead of being converted to a table index. This causes call_indirect during Box<dyn Trait>::drop to receive an index far beyond the table bounds.
Runtime error:
RuntimeError: table index is out of bounds;
This error was reported following the AI's initial modification, which was based on the hypothesis that JointorHandle was improperly crossing the WASM boundary. To address this, the AI implemented an array-based storage strategy to keep the JointorHandle within the WASM memory space, passing only the array index across the WASM–JS–WASM interface.
I believe this effectively eliminates the suspicion that the issue was caused by crossing the boundary. This conclusion is supported by two key details:
- Refutation of the Boundary-Crossing Hypothesis: The array-based implementation successfully localized the
JointorHandlewithin WASM, yet the underlying instability persisted, effectively neutralizing the theory that boundary crossing was the root cause. - Instruction Pointer Corruption: In the original error report, the trace pointed to code segments that were not even being executed. Since the issue vanished after implementing
std::mem::forget(upstream), I posit that the problem was likely the result of the instruction pointer for thedropoperation failing completely. This provides indirect evidence that the metadata or function pointers stored within the WASM memory were already corrupted or incorrect prior to execution.
The reasons for considering the AI analysis correct are:
-
As demonstrated in the code, calling other virtual functions within dyn JointorHandle is Ok
-
The AI-led modification successfully resolved the reported error.
impl Drop for JointorHandle {
fn drop(&mut self) {
if self.0.needs_manual_drop() {
unsafe {
let jointor: &dyn Jointor = &**self.0;
let layout = std::alloc::Layout::from_size_align(
std::mem::size_of_val(jointor),
std::mem::align_of_val(jointor),
)
.unwrap();
let ptr = jointor as *const dyn Jointor as *const u8 as *mut u8;
std::alloc::dealloc(ptr, layout);
}
} else {
unsafe {
std::ptr::drop_in_place(&mut *self.0);
}
}
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the wasm32-unknown-unknown case and inspecting wasm-ld handling of the R_WASM_TABLE_INDEX_SLEB relocation for the drop_in_place vtable entry. Trace the resulting call_indirect during dyn Trait drop; done means the entry contains a valid table index and the runtime no longer reports an out-of-bounds table access.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100