diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index a4de5209e6..4225823ad9 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -295,14 +295,19 @@ impl Func { // Unlike our arguments we need to dynamically check that the return // values produced are correct. There could be a bug in `func` that - // produces the wrong number or wrong types of values, and we need - // to catch that here. + // produces the wrong number, wrong types, or wrong stores of + // values, and we need to catch that here. for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() { if ret.ty() != ty { return Err(Trap::new( "function attempted to return an incompatible value", )); } + if !ret.comes_from_same_store(&store) { + return Err(Trap::new( + "cross-`Store` values are not currently supported", + )); + } unsafe { ret.write_value_to(&store, values_vec.add(i)); } diff --git a/tests/all/funcref.rs b/tests/all/funcref.rs index 4abea9d791..dd1e0cb9db 100644 --- a/tests/all/funcref.rs +++ b/tests/all/funcref.rs @@ -110,3 +110,35 @@ fn wrong_store() -> anyhow::Result<()> { } } } + +#[test] +fn func_new_returns_wrong_store() -> anyhow::Result<()> { + let dropped = Rc::new(Cell::new(false)); + { + let store1 = Store::default(); + let store2 = Store::default(); + + let set = SetOnDrop(dropped.clone()); + let f1 = Func::wrap(&store1, move || drop(&set)); + let f2 = Func::new( + &store2, + FuncType::new(None, Some(ValType::FuncRef)), + move |_, _, results| { + results[0] = f1.clone().into(); + Ok(()) + }, + ); + assert!(f2.call(&[]).is_err()); + } + assert!(dropped.get()); + + return Ok(()); + + struct SetOnDrop(Rc>); + + impl Drop for SetOnDrop { + fn drop(&mut self) { + self.0.set(true); + } + } +}