Skip to content

Commit ee0a3be

Browse files
committed
AnyRef::from_raw needs to clone its GC ref
Like `ExternRef::from_raw` does. This is because while `to_raw` clones the GC ref, it also exposes it to Wasm, inserting it into the DRC collector's table, which effectively gives ownership of that clone to Wasm. Then, if we don't clone in `from_raw`, when a GC is triggered, the DRC collector will see that Wasm isn't holding the ref alive anymore and will decref (and perhaps even deallocate) it, which leaves the `AnyRef` we constructed via `from_raw` dangling. Fixes bytecodealliance#10182
1 parent 8357599 commit ee0a3be

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

crates/wasmtime/src/runtime/gc/enabled/anyref.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ impl AnyRef {
278278
// (Not actually memory unsafe since we have indexed GC heaps.)
279279
pub(crate) fn _from_raw(store: &mut AutoAssertNoGc, raw: u32) -> Option<Rooted<Self>> {
280280
let gc_ref = VMGcRef::from_raw_u32(raw)?;
281+
let gc_ref = store.unwrap_gc_store_mut().clone_gc_ref(&gc_ref);
281282
Some(Self::from_cloned_gc_ref(store, gc_ref))
282283
}
283284

crates/wasmtime/src/runtime/vm/const_expr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ impl ConstExprEvaluator {
167167
let mut store = AutoAssertNoGc::new(&mut store);
168168

169169
for op in expr.ops() {
170+
log::trace!("const-evaluating op: {op:?}");
170171
match op {
171172
ConstOp::I32Const(i) => self.stack.push(ValRaw::i32(*i)),
172173
ConstOp::I64Const(i) => self.stack.push(ValRaw::i64(*i)),
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
;;! gc = true
2+
3+
(module
4+
(type (array (mut anyref)))
5+
6+
(global (ref 0) (array.new_fixed 0 1 (array.new_fixed 0 0)))
7+
8+
(func (export "")
9+
(local $l (ref 0))
10+
11+
global.get 0
12+
local.set $l
13+
14+
local.get 0
15+
i32.const 0
16+
local.get 0
17+
i32.const 0
18+
i32.const 1
19+
array.copy 0 0
20+
)
21+
)
22+
23+
(assert_return (invoke ""))

0 commit comments

Comments
 (0)