Fix assertion with cross-store values in Func::new

If a host-defined `Func::new` closure returns values from the wrong
store, this currently trips a debug assertion and causes other issues
elsewhere in release mode. This commit adds the same dynamic checks
found in `Func::wrap` in the `Func::new` case today.
This commit is contained in:
Alex Crichton
2020-11-16 11:54:57 -08:00
parent 8675fa5aa7
commit ffca0fc908
2 changed files with 39 additions and 2 deletions

View File

@@ -295,14 +295,19 @@ impl Func {
// Unlike our arguments we need to dynamically check that the return // Unlike our arguments we need to dynamically check that the return
// values produced are correct. There could be a bug in `func` that // values produced are correct. There could be a bug in `func` that
// produces the wrong number or wrong types of values, and we need // produces the wrong number, wrong types, or wrong stores of
// to catch that here. // values, and we need to catch that here.
for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() { for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() {
if ret.ty() != ty { if ret.ty() != ty {
return Err(Trap::new( return Err(Trap::new(
"function attempted to return an incompatible value", "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 { unsafe {
ret.write_value_to(&store, values_vec.add(i)); ret.write_value_to(&store, values_vec.add(i));
} }

View File

@@ -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<Cell<bool>>);
impl Drop for SetOnDrop {
fn drop(&mut self) {
self.0.set(true);
}
}
}