Skip to content

Commit b39f087

Browse files
authored
Merge pull request from GHSA-q879-9g95-56mx
Add an assertion that a `HostFunc`'s `store` agrees on engines
2 parents 398a73f + eb4089e commit b39f087

File tree

4 files changed

+69
-9
lines changed

4 files changed

+69
-9
lines changed

crates/wasmtime/src/func.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1982,6 +1982,14 @@ impl HostFunc {
19821982
}
19831983

19841984
unsafe fn register_trampoline(&self, store: &mut StoreOpaque) {
1985+
// This assert is required to ensure that we can indeed safely insert
1986+
// `self` into the `store` provided, otherwise the type information we
1987+
// have listed won't be correct. This is possible to hit with the public
1988+
// API of Wasmtime, and should be documented in relevant functions.
1989+
assert!(
1990+
Engine::same(&self.engine, store.engine()),
1991+
"cannot use a store with a different engine than a linker was created with",
1992+
);
19851993
let idx = self.export.anyfunc.as_ref().type_index;
19861994
store.register_host_trampoline(idx, self.trampoline);
19871995
}

crates/wasmtime/src/instance.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,9 @@ impl<T> InstancePre<T> {
953953
/// # Panics
954954
///
955955
/// Panics if any import closed over by this [`InstancePre`] isn't owned by
956-
/// `store`, or if `store` has async support enabled.
956+
/// `store`, or if `store` has async support enabled. Additionally this
957+
/// function will panic if the `store` provided comes from a different
958+
/// [`Engine`] than the [`InstancePre`] originally came from.
957959
pub fn instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> {
958960
// For the unsafety here the typecheck happened at creation time of this
959961
// structure and then othrewise the `T` of `InstancePre<T>` connects any

crates/wasmtime/src/linker.rs

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ use std::sync::Arc;
7070
/// point only the [`Store`] that owns the [`Global`] can be used to instantiate
7171
/// modules.
7272
///
73+
/// ## Multiple `Engine`s
74+
///
75+
/// The [`Linker`] type is not compatible with usage between multiple [`Engine`]
76+
/// values. An [`Engine`] is provided when a [`Linker`] is created and only
77+
/// stores and items which originate from that [`Engine`] can be used with this
78+
/// [`Linker`]. If more than one [`Engine`] is used with a [`Linker`] then that
79+
/// may cause a panic at runtime, similar to how if a [`Func`] is used with the
80+
/// wrong [`Store`] that can also panic at runtime.
81+
///
7382
/// [`Store`]: crate::Store
7483
/// [`Global`]: crate::Global
7584
pub struct Linker<T> {
@@ -150,6 +159,11 @@ macro_rules! generate_wrap_async_func {
150159

151160
impl<T> Linker<T> {
152161
/// Creates a new [`Linker`].
162+
///
163+
/// The linker will define functions within the context of the `engine`
164+
/// provided and can only instantiate modules for a [`Store`] that is also
165+
/// defined within the same [`Engine`]. Usage of stores with different
166+
/// [`Engine`]s may cause a panic when used with this [`Linker`].
153167
pub fn new(engine: &Engine) -> Linker<T> {
154168
Linker {
155169
engine: engine.clone(),
@@ -236,9 +250,6 @@ impl<T> Linker<T> {
236250
/// of the same type as the `item` provided and if shadowing is disallowed.
237251
/// For more information see the documentation on [`Linker`].
238252
///
239-
/// Also returns an error if `item` comes from a different store than this
240-
/// [`Linker`] was created with.
241-
///
242253
/// # Examples
243254
///
244255
/// ```
@@ -417,6 +428,11 @@ impl<T> Linker<T> {
417428
/// for each export is `module_name`, and the name for each export is the
418429
/// name in the instance itself.
419430
///
431+
/// Note that when this API is used the [`Linker`] is no longer compatible
432+
/// with multi-[`Store` ] instantiation because the items defined within
433+
/// this store will belong to the `store` provided, and only the `store`
434+
/// provided.
435+
///
420436
/// # Errors
421437
///
422438
/// Returns an error if the any item is redefined twice in this linker (for
@@ -505,7 +521,8 @@ impl<T> Linker<T> {
505521
/// # Panics
506522
///
507523
/// Panics if any item used to instantiate the provided [`Module`] is not
508-
/// owned by `store`.
524+
/// owned by `store`, or if the `store` provided comes from a different
525+
/// [`Engine`] than this [`Linker`].
509526
///
510527
/// # Examples
511528
///
@@ -602,6 +619,15 @@ impl<T> Linker<T> {
602619
{
603620
// NB: this is intended to function the same as `Linker::module_async`,
604621
// they should be kept in sync.
622+
623+
// This assert isn't strictly necessary since it'll bottom out in the
624+
// `HostFunc::to_func` method anyway. This is placed earlier for this
625+
// function though to prevent the functions created here from delaying
626+
// the panic until they're called.
627+
assert!(
628+
Engine::same(&self.engine, store.as_context().engine()),
629+
"different engines for this linker and the store provided"
630+
);
605631
match ModuleKind::categorize(module)? {
606632
ModuleKind::Command => {
607633
self.command(
@@ -672,6 +698,10 @@ impl<T> Linker<T> {
672698
{
673699
// NB: this is intended to function the same as `Linker::module`, they
674700
// should be kept in sync.
701+
assert!(
702+
Engine::same(&self.engine, store.as_context().engine()),
703+
"different engines for this linker and the store provided"
704+
);
675705
match ModuleKind::categorize(module)? {
676706
ModuleKind::Command => self.command(
677707
store,
@@ -899,7 +929,8 @@ impl<T> Linker<T> {
899929
/// # Panics
900930
///
901931
/// Panics if any item used to instantiate `module` is not owned by
902-
/// `store`.
932+
/// `store`. Additionally this will panic if the [`Engine`] that the `store`
933+
/// belongs to is different than this [`Linker`].
903934
///
904935
/// # Examples
905936
///
@@ -958,7 +989,9 @@ impl<T> Linker<T> {
958989
/// # Panics
959990
///
960991
/// This method will panic if any item defined in this linker used by
961-
/// `module` is not owned by `store`.
992+
/// `module` is not owned by `store`. Additionally this will panic if the
993+
/// [`Engine`] that the `store` belongs to is different than this
994+
/// [`Linker`].
962995
///
963996
/// # Examples
964997
///
@@ -1027,6 +1060,11 @@ impl<T> Linker<T> {
10271060
///
10281061
/// Note that multiple `Extern` items may be defined for the same
10291062
/// module/name pair.
1063+
///
1064+
/// # Panics
1065+
///
1066+
/// This function will panic if the `store` provided does not come from the
1067+
/// same [`Engine`] that this linker was created with.
10301068
pub fn iter<'a: 'p, 'p>(
10311069
&'a self,
10321070
mut store: impl AsContextMut<Data = T> + 'p,
@@ -1047,6 +1085,11 @@ impl<T> Linker<T> {
10471085
///
10481086
/// Returns `None` if this name was not previously defined in this
10491087
/// [`Linker`].
1088+
///
1089+
/// # Panics
1090+
///
1091+
/// This function will panic if the `store` provided does not come from the
1092+
/// same [`Engine`] that this linker was created with.
10501093
pub fn get(
10511094
&self,
10521095
mut store: impl AsContextMut<Data = T>,
@@ -1073,6 +1116,11 @@ impl<T> Linker<T> {
10731116
/// provided.
10741117
///
10751118
/// Returns `None` if no match was found.
1119+
///
1120+
/// # Panics
1121+
///
1122+
/// This function will panic if the `store` provided does not come from the
1123+
/// same [`Engine`] that this linker was created with.
10761124
pub fn get_by_import(
10771125
&self,
10781126
mut store: impl AsContextMut<Data = T>,
@@ -1126,7 +1174,9 @@ impl<T> Linker<T> {
11261174
///
11271175
/// # Panics
11281176
///
1129-
/// Panics if the default function found is not owned by `store`.
1177+
/// Panics if the default function found is not owned by `store`. This
1178+
/// function will also panic if the `store` provided does not come from the
1179+
/// same [`Engine`] that this linker was created with.
11301180
pub fn get_default(
11311181
&self,
11321182
mut store: impl AsContextMut<Data = T>,

tests/all/linker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ fn get_host_function() -> Result<()> {
256256

257257
let mut linker = Linker::new(&engine);
258258
linker.func_wrap("mod", "f1", || {})?;
259-
let mut store = Store::<()>::default();
259+
let mut store = Store::new(&engine, ());
260260
assert!(linker
261261
.get_by_import(&mut store, &module.imports().nth(0).unwrap())
262262
.is_some());

0 commit comments

Comments
 (0)