You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

22 lines
620 B

Revamp memory management of `InstanceHandle` (#1624) * Revamp memory management of `InstanceHandle` This commit fixes a known but in Wasmtime where an instance could still be used after it was freed. Unfortunately the fix here is a bit of a hammer, but it's the best that we can do for now. The changes made in this commit are: * A `Store` now stores all `InstanceHandle` objects it ever creates. This keeps all instances alive unconditionally (along with all host functions and such) until the `Store` is itself dropped. Note that a `Store` is reference counted so basically everything has to be dropped to drop anything, there's no longer any partial deallocation of instances. * The `InstanceHandle` type's own reference counting has been removed. This is largely redundant with what's already happening in `Store`, so there's no need to manage two reference counts. * Each `InstanceHandle` no longer tracks its dependencies in terms of instance handles. This set was actually inaccurate due to dynamic updates to tables and such, so we needed to revamp it anyway. * Initialization of an `InstanceHandle` is now deferred until after `InstanceHandle::new`. This allows storing the `InstanceHandle` before side-effectful initialization, such as copying element segments or running the start function, to ensure that regardless of the result of instantiation the underlying `InstanceHandle` is still available to persist in storage. Overall this should fix a known possible way to safely segfault Wasmtime today (yay!) and it should also fix some flaikness I've seen on CI. Turns out one of the spec tests (bulk-memory-operations/partial-init-table-segment.wast) exercises this functionality and we were hitting sporating use-after-free, but only on Windows. * Shuffle some APIs around * Comment weak cycle
5 years ago
use anyhow::Result;
use wasmtime::*;
#[test]
fn use_func_after_drop() -> Result<()> {
let table;
{
let store = Store::default();
let closed_over_data = String::from("abcd");
let func = Func::wrap(&store, move || {
assert_eq!(closed_over_data, "abcd");
});
let ty = TableType::new(ValType::FuncRef, Limits::new(1, None));
table = Table::new(&store, ty, Val::FuncRef(None))?;
Revamp memory management of `InstanceHandle` (#1624) * Revamp memory management of `InstanceHandle` This commit fixes a known but in Wasmtime where an instance could still be used after it was freed. Unfortunately the fix here is a bit of a hammer, but it&#39;s the best that we can do for now. The changes made in this commit are: * A `Store` now stores all `InstanceHandle` objects it ever creates. This keeps all instances alive unconditionally (along with all host functions and such) until the `Store` is itself dropped. Note that a `Store` is reference counted so basically everything has to be dropped to drop anything, there&#39;s no longer any partial deallocation of instances. * The `InstanceHandle` type&#39;s own reference counting has been removed. This is largely redundant with what&#39;s already happening in `Store`, so there&#39;s no need to manage two reference counts. * Each `InstanceHandle` no longer tracks its dependencies in terms of instance handles. This set was actually inaccurate due to dynamic updates to tables and such, so we needed to revamp it anyway. * Initialization of an `InstanceHandle` is now deferred until after `InstanceHandle::new`. This allows storing the `InstanceHandle` before side-effectful initialization, such as copying element segments or running the start function, to ensure that regardless of the result of instantiation the underlying `InstanceHandle` is still available to persist in storage. Overall this should fix a known possible way to safely segfault Wasmtime today (yay!) and it should also fix some flaikness I&#39;ve seen on CI. Turns out one of the spec tests (bulk-memory-operations/partial-init-table-segment.wast) exercises this functionality and we were hitting sporating use-after-free, but only on Windows. * Shuffle some APIs around * Comment weak cycle
5 years ago
table.set(0, func.into())?;
}
let func = table.get(0).unwrap().funcref().unwrap().unwrap().clone();
Revamp memory management of `InstanceHandle` (#1624) * Revamp memory management of `InstanceHandle` This commit fixes a known but in Wasmtime where an instance could still be used after it was freed. Unfortunately the fix here is a bit of a hammer, but it&#39;s the best that we can do for now. The changes made in this commit are: * A `Store` now stores all `InstanceHandle` objects it ever creates. This keeps all instances alive unconditionally (along with all host functions and such) until the `Store` is itself dropped. Note that a `Store` is reference counted so basically everything has to be dropped to drop anything, there&#39;s no longer any partial deallocation of instances. * The `InstanceHandle` type&#39;s own reference counting has been removed. This is largely redundant with what&#39;s already happening in `Store`, so there&#39;s no need to manage two reference counts. * Each `InstanceHandle` no longer tracks its dependencies in terms of instance handles. This set was actually inaccurate due to dynamic updates to tables and such, so we needed to revamp it anyway. * Initialization of an `InstanceHandle` is now deferred until after `InstanceHandle::new`. This allows storing the `InstanceHandle` before side-effectful initialization, such as copying element segments or running the start function, to ensure that regardless of the result of instantiation the underlying `InstanceHandle` is still available to persist in storage. Overall this should fix a known possible way to safely segfault Wasmtime today (yay!) and it should also fix some flaikness I&#39;ve seen on CI. Turns out one of the spec tests (bulk-memory-operations/partial-init-table-segment.wast) exercises this functionality and we were hitting sporating use-after-free, but only on Windows. * Shuffle some APIs around * Comment weak cycle
5 years ago
let func = func.get0::<()>()?;
func()?;
Ok(())
}