Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit d88d7a4

Browse files
committed
avoid undefined behavior in poll_with_state
Previously, we were storing a `*mut dyn VMStore` in the thread-local `STATE` variable, then using the `&mut dyn VMStore` from which it was derived, which invalidates the raw pointer according to stacked borrow rules, triggering undefined behavior. This fixes that. Also, it turns out `poll_with_state` needs neither a `T` type parameter nor a `StoreToken`, so I've removed those. Note that Alex has plans to consolidate our thread-local state, which should eliminate the redundant `*mut dyn VMStore` pointers stored in `STATE` and `INSTANCE_STATE`, which should allow us to simplify `poll_with_state` even more. Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent f041787 commit d88d7a4

1 file changed

Lines changed: 18 additions & 14 deletions

File tree

crates/wasmtime/src/runtime/component/concurrent.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -608,27 +608,32 @@ fn get_store() -> *mut dyn VMStore {
608608
/// Note that this uses `with_local_instance` to access the thread-local store
609609
/// and instance stored in `INSTANCE_STATE`. See that function's documentation
610610
/// for details.
611-
fn poll_with_state<T: 'static, F: Future + Send + ?Sized>(
612-
token: StoreToken<T>,
611+
fn poll_with_state<F: Future + Send + ?Sized>(
613612
cx: &mut Context,
614613
mut future: Pin<&mut F>,
615614
) -> Poll<F::Output> {
616615
with_local_instance(|store, instance| {
617-
let store_ptr = store.traitobj();
618-
let store_cx = token.as_context_mut(store);
619-
620616
let result = {
621617
let old_state = STATE.with(|v| {
622618
v.replace(Some(State {
623-
store: store_ptr.as_ptr(),
619+
store: store.traitobj().as_ptr(),
624620
}))
625621
});
626622
let _reset_state = ResetState(old_state);
627-
poll_with_local_instance(store_cx.0.traitobj_mut(), instance, &mut future, cx)
623+
// SAFETY: `get_store` will retrieve the store we just stored in
624+
// `STATE` above. Note that we avoid using the `store` parameter
625+
// here since that would invalidate the pointer stored in `STATE`
626+
// according to stacked borrow rules.
627+
poll_with_local_instance(unsafe { &mut *get_store() }, instance, &mut future, cx)
628628
};
629629

630-
let spawned_tasks = mem::take(&mut store_cx.0.concurrent_async_state().spawned_tasks);
631-
let instance = instance.instance(store_cx.0);
630+
let spawned_tasks = mem::take(
631+
&mut store
632+
.store_opaque_mut()
633+
.concurrent_async_state()
634+
.spawned_tasks,
635+
);
636+
let instance = instance.instance(store.store_opaque_mut());
632637
for spawned in spawned_tasks {
633638
instance.push_future(spawned);
634639
}
@@ -1497,7 +1502,7 @@ impl Instance {
14971502
let mut accessor = Accessor::new(token, self);
14981503
let mut future = Box::pin(async move { fun(&mut accessor).await });
14991504
Box::pin(future::poll_fn(move |cx| {
1500-
poll_with_state(token, cx, future.as_mut())
1505+
poll_with_state(cx, future.as_mut())
15011506
}))
15021507
}
15031508

@@ -1532,7 +1537,7 @@ impl Instance {
15321537
T: 'static,
15331538
D: HasData,
15341539
{
1535-
let mut store = store.as_context_mut();
1540+
let store = store.as_context_mut();
15361541

15371542
// Here a `future` is created with a connection to the `handle` being
15381543
// returned such that if the `handle` is dropped then the future will be
@@ -1546,7 +1551,6 @@ impl Instance {
15461551
task.run(&mut accessor).await
15471552
}))));
15481553
let handle = AbortHandle::new(future.clone());
1549-
let token = StoreToken::new(store.as_context_mut());
15501554
let spawned = future.clone();
15511555
let future = Box::pin(future::poll_fn({
15521556
move |cx| {
@@ -1557,7 +1561,7 @@ impl Instance {
15571561
if let AbortWrapper::Unpolled(mut future)
15581562
| AbortWrapper::Polled { mut future, .. } = inner
15591563
{
1560-
let result = poll_with_state(token, cx, future.as_mut());
1564+
let result = poll_with_state(cx, future.as_mut());
15611565
*spawned = AbortWrapper::Polled {
15621566
future,
15631567
waker: cx.waker().clone(),
@@ -2683,7 +2687,7 @@ impl Instance {
26832687
let mut accessor = Accessor::new(token, self);
26842688
let mut future = Box::pin(async move { closure(&mut accessor, params).await });
26852689
Box::pin(future::poll_fn(move |cx| {
2686-
poll_with_state(token, cx, future.as_mut())
2690+
poll_with_state(cx, future.as_mut())
26872691
}))
26882692
}
26892693

0 commit comments

Comments
 (0)