1 #![cfg(not(miri))] // not testing unsafe code
2 
3 use wasmtime::*;
4 
async_store() -> Store<()>5 fn async_store() -> Store<()> {
6     let engine = Engine::default();
7     let mut store = Store::new(&engine, ());
8     Func::wrap_async(&mut store, |_, ()| Box::new(async {}));
9     return store;
10 }
11 
12 struct MyAsyncLimiter;
13 
14 #[async_trait::async_trait]
15 impl ResourceLimiterAsync for MyAsyncLimiter {
memory_growing( &mut self, _current: usize, _desired: usize, _maximum: Option<usize>, ) -> Result<bool>16     async fn memory_growing(
17         &mut self,
18         _current: usize,
19         _desired: usize,
20         _maximum: Option<usize>,
21     ) -> Result<bool> {
22         Ok(true)
23     }
24 
table_growing( &mut self, _current: usize, _desired: usize, _maximum: Option<usize>, ) -> Result<bool>25     async fn table_growing(
26         &mut self,
27         _current: usize,
28         _desired: usize,
29         _maximum: Option<usize>,
30     ) -> Result<bool> {
31         Ok(true)
32     }
33 }
34 
async_limiter_store() -> Store<MyAsyncLimiter>35 fn async_limiter_store() -> Store<MyAsyncLimiter> {
36     let engine = Engine::default();
37     let mut store = Store::new(&engine, MyAsyncLimiter);
38     store.limiter_async(|x| x);
39     return store;
40 }
41 
assert_requires_async<T>(store: &mut Store<T>)42 fn assert_requires_async<T>(store: &mut Store<T>) {
43     let module = Module::new(store.engine(), "(module)").unwrap();
44     assert!(Instance::new(&mut *store, &module, &[]).is_err());
45 }
46 
47 #[test]
require_async_after_func_wrap()48 fn require_async_after_func_wrap() {
49     let engine = Engine::default();
50     let mut store = Store::new(&engine, ());
51     Func::wrap_async(&mut store, |_, ()| Box::new(async {}));
52     assert_requires_async(&mut store);
53 }
54 
55 #[test]
require_async_after_func_new()56 fn require_async_after_func_new() {
57     let engine = Engine::default();
58     let mut store = Store::new(&engine, ());
59     let ty = FuncType::new(store.engine(), [], []);
60     Func::new_async(&mut store, ty, |_, _, _| Box::new(async { Ok(()) }));
61     assert_requires_async(&mut store);
62 }
63 
64 #[tokio::test]
require_async_after_linker_with_func_wrap() -> Result<()>65 async fn require_async_after_linker_with_func_wrap() -> Result<()> {
66     let engine = Engine::default();
67     let mut store = Store::new(&engine, ());
68     let mut linker = Linker::new(store.engine());
69     linker.func_wrap_async("", "", |_, ()| Box::new(async {}))?;
70     let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
71     linker.instantiate_async(&mut store, &module).await?;
72     assert_requires_async(&mut store);
73     Ok(())
74 }
75 
76 #[tokio::test]
require_async_after_linker_with_func_new() -> Result<()>77 async fn require_async_after_linker_with_func_new() -> Result<()> {
78     let engine = Engine::default();
79     let mut store = Store::new(&engine, ());
80     let mut linker = Linker::new(store.engine());
81     let ty = FuncType::new(store.engine(), [], []);
82     linker.func_new_async("", "", ty, |_, _, _| Box::new(async { Ok(()) }))?;
83     let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
84     linker.instantiate_async(&mut store, &module).await?;
85     assert_requires_async(&mut store);
86     Ok(())
87 }
88 
89 #[test]
require_async_after_epochs() -> Result<()>90 fn require_async_after_epochs() -> Result<()> {
91     let mut config = Config::new();
92     config.epoch_interruption(true);
93     let engine = Engine::new(&config)?;
94     let mut store = Store::new(&engine, ());
95     store.epoch_deadline_async_yield_and_update(1);
96     assert_requires_async(&mut store);
97     Ok(())
98 }
99 
100 #[test]
require_async_after_fuel() -> Result<()>101 fn require_async_after_fuel() -> Result<()> {
102     let mut config = Config::new();
103     config.consume_fuel(true);
104     let engine = Engine::new(&config)?;
105     let mut store = Store::new(&engine, ());
106     store.fuel_async_yield_interval(Some(1))?;
107     assert_requires_async(&mut store);
108     Ok(())
109 }
110 
111 #[test]
require_async_after_async_limiter() -> Result<()>112 fn require_async_after_async_limiter() -> Result<()> {
113     let mut store = async_limiter_store();
114     assert_requires_async(&mut store);
115     Ok(())
116 }
117 
118 #[tokio::test]
require_async_with_linker_func_wrap() -> Result<()>119 async fn require_async_with_linker_func_wrap() -> Result<()> {
120     let engine = Engine::default();
121     let mut store = Store::new(&engine, ());
122     let mut linker = Linker::new(store.engine());
123     linker.func_wrap_async("", "", |_, ()| Box::new(async {}))?;
124     let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
125     assert!(linker.instantiate(&mut store, &module).is_err());
126     linker.instantiate_async(&mut store, &module).await?;
127     Ok(())
128 }
129 
130 #[test]
require_async_with_debug_handler() -> Result<()>131 fn require_async_with_debug_handler() -> Result<()> {
132     let mut config = Config::new();
133     config.guest_debug(true);
134     let engine = Engine::new(&config)?;
135     let mut store = Store::new(&engine, ());
136     store.set_debug_handler(MyDebugHandler);
137     assert_requires_async(&mut store);
138     return Ok(());
139 
140     #[derive(Clone)]
141     struct MyDebugHandler;
142 
143     impl DebugHandler for MyDebugHandler {
144         type Data = ();
145 
146         async fn handle(&self, _: StoreContextMut<'_, ()>, _: DebugEvent<'_>) {}
147     }
148 }
149 
150 struct MyAsyncCallHook;
151 
152 #[async_trait::async_trait]
153 impl CallHookHandler<()> for MyAsyncCallHook {
handle_call_event(&self, _: StoreContextMut<'_, ()>, _: CallHook) -> Result<()>154     async fn handle_call_event(&self, _: StoreContextMut<'_, ()>, _: CallHook) -> Result<()> {
155         Ok(())
156     }
157 }
158 
159 #[test]
require_async_with_async_call_hook() -> Result<()>160 fn require_async_with_async_call_hook() -> Result<()> {
161     let engine = Engine::default();
162     let mut store = Store::new(&engine, ());
163     store.call_hook_async(MyAsyncCallHook);
164     assert_requires_async(&mut store);
165     Ok(())
166 }
167 
168 #[tokio::test]
async_disallows_instance_new() -> Result<()>169 async fn async_disallows_instance_new() -> Result<()> {
170     let mut store = async_store();
171     let module = Module::new(store.engine(), "(module)")?;
172     assert!(Instance::new(&mut store, &module, &[]).is_err());
173     Instance::new_async(&mut store, &module, &[]).await?;
174     Ok(())
175 }
176 
177 #[tokio::test]
async_disallows_linker_instantiate() -> Result<()>178 async fn async_disallows_linker_instantiate() -> Result<()> {
179     let mut store = async_store();
180     let module = Module::new(store.engine(), "(module)")?;
181     let linker = Linker::new(store.engine());
182     assert!(linker.instantiate(&mut store, &module).is_err());
183     linker.instantiate_async(&mut store, &module).await?;
184     Ok(())
185 }
186 
187 #[tokio::test]
async_disallows_func_call() -> Result<()>188 async fn async_disallows_func_call() -> Result<()> {
189     let mut store = async_store();
190     let func = Func::wrap(&mut store, || {});
191     assert!(func.call(&mut store, &[], &mut []).is_err());
192     func.call_async(&mut store, &[], &mut []).await?;
193     Ok(())
194 }
195 
196 #[tokio::test]
async_disallows_typed_func_call() -> Result<()>197 async fn async_disallows_typed_func_call() -> Result<()> {
198     let mut store = async_store();
199     let func = Func::wrap(&mut store, || {});
200     let func = func.typed::<(), ()>(&mut store)?;
201     assert!(func.call(&mut store, ()).is_err());
202     func.call_async(&mut store, ()).await?;
203     Ok(())
204 }
205 
206 #[tokio::test]
async_disallows_gc() -> Result<()>207 async fn async_disallows_gc() -> Result<()> {
208     let mut store = async_limiter_store();
209     assert!(store.gc(None).is_err());
210     store.gc_async(None).await;
211     Ok(())
212 }
213 
214 #[tokio::test]
async_disallows_array_ref_new() -> Result<()>215 async fn async_disallows_array_ref_new() -> Result<()> {
216     let mut store = async_limiter_store();
217     let ty = ArrayType::new(
218         store.engine(),
219         FieldType::new(Mutability::Var, StorageType::I8),
220     );
221     let pre = ArrayRefPre::new(&mut store, ty);
222     assert!(ArrayRef::new(&mut store, &pre, &Val::I32(0), 10).is_err());
223     ArrayRef::new_async(&mut store, &pre, &Val::I32(0), 10).await?;
224     Ok(())
225 }
226 
227 #[tokio::test]
async_disallows_array_ref_new_fixed() -> Result<()>228 async fn async_disallows_array_ref_new_fixed() -> Result<()> {
229     let mut store = async_limiter_store();
230     let ty = ArrayType::new(
231         store.engine(),
232         FieldType::new(Mutability::Var, StorageType::I8),
233     );
234     let pre = ArrayRefPre::new(&mut store, ty);
235     assert!(ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(0)]).is_err());
236     ArrayRef::new_fixed_async(&mut store, &pre, &[Val::I32(0)]).await?;
237     Ok(())
238 }
239 
240 #[tokio::test]
async_disallows_exnref_new() -> Result<()>241 async fn async_disallows_exnref_new() -> Result<()> {
242     let mut store = async_limiter_store();
243     let ty = ExnType::new(store.engine(), [])?;
244     let pre = ExnRefPre::new(&mut store, ty);
245     let fty = FuncType::new(store.engine(), [], []);
246     let tag = Tag::new(&mut store, &TagType::new(fty))?;
247     assert!(ExnRef::new(&mut store, &pre, &tag, &[]).is_err());
248     ExnRef::new_async(&mut store, &pre, &tag, &[]).await?;
249     Ok(())
250 }
251 
252 #[tokio::test]
async_disallows_externref_new() -> Result<()>253 async fn async_disallows_externref_new() -> Result<()> {
254     let mut store = async_limiter_store();
255     assert!(ExternRef::new(&mut store, 1).is_err());
256     ExternRef::new_async(&mut store, 1).await?;
257     Ok(())
258 }
259 
260 #[tokio::test]
async_disallows_structref_new() -> Result<()>261 async fn async_disallows_structref_new() -> Result<()> {
262     let mut store = async_limiter_store();
263     let ty = StructType::new(
264         store.engine(),
265         [FieldType::new(Mutability::Var, StorageType::I8)],
266     )?;
267     let pre = StructRefPre::new(&mut store, ty);
268     assert!(StructRef::new(&mut store, &pre, &[Val::I32(0)]).is_err());
269     StructRef::new_async(&mut store, &pre, &[Val::I32(0)]).await?;
270     Ok(())
271 }
272 
273 #[test]
epoch_yield_disallowed_without_async() -> Result<()>274 fn epoch_yield_disallowed_without_async() -> Result<()> {
275     let mut config = Config::new();
276     config.epoch_interruption(true);
277     let engine = Engine::new(&config)?;
278     let mut store = Store::new(&engine, ());
279 
280     let module = Module::new(&engine, r#"(module (func (export "") (loop br 0)))"#)?;
281     let instance = Instance::new(&mut store, &module, &[])?;
282     let func = instance.get_typed_func::<(), ()>(&mut store, "")?;
283 
284     store.epoch_deadline_callback(|_store| Ok(UpdateDeadline::Yield(1)));
285     assert!(func.call(&mut store, ()).is_err());
286 
287     store.epoch_deadline_callback(|_store| Ok(UpdateDeadline::YieldCustom(1, Box::pin(async {}))));
288     assert!(func.call(&mut store, ()).is_err());
289 
290     store.epoch_deadline_trap();
291     let err = func.call(&mut store, ()).unwrap_err().downcast::<Trap>()?;
292     assert_eq!(err, Trap::Interrupt);
293     Ok(())
294 }
295 
296 #[test]
start_sync_then_configure_async_then_do_async() -> Result<()>297 fn start_sync_then_configure_async_then_do_async() -> Result<()> {
298     let mut config = Config::new();
299     config.consume_fuel(true);
300     let engine = Engine::new(&config)?;
301     let mut store = Store::new(&engine, MyAsyncLimiter);
302 
303     let module = Module::new(
304         &engine,
305         r#"
306             (module
307                 (import "" "" (func $host))
308                 (memory 1)
309                 (func (export "")
310                     call $host
311                     (loop br 0)
312                 )
313             )
314         "#,
315     )?;
316 
317     let mut linker = Linker::new(&engine);
318     linker.func_wrap("", "", |mut store: Caller<'_, MyAsyncLimiter>| {
319         store.as_context_mut().fuel_async_yield_interval(Some(1))
320     })?;
321     store.set_fuel(100)?;
322     let instance = linker.instantiate(&mut store, &module)?;
323     let func = instance.get_typed_func::<(), ()>(&mut store, "")?;
324     let err = func.call(&mut store, ()).unwrap_err();
325     assert!(
326         format!("{err:?}").contains("configured to do async things"),
327         "bad error {err:?}",
328     );
329     Ok(())
330 }
331 
332 #[tokio::test]
async_limiter_disallows_table_new() -> Result<()>333 async fn async_limiter_disallows_table_new() -> Result<()> {
334     let mut store = async_limiter_store();
335     let ty = TableType::new(RefType::FUNCREF, 1, None);
336     assert!(Table::new(&mut store, ty.clone(), Ref::Func(None)).is_err());
337     Table::new_async(&mut store, ty, Ref::Func(None)).await?;
338     Ok(())
339 }
340 
341 #[tokio::test]
async_limiter_disallows_table_grow() -> Result<()>342 async fn async_limiter_disallows_table_grow() -> Result<()> {
343     let mut store = async_limiter_store();
344     let ty = TableType::new(RefType::FUNCREF, 1, None);
345     let table = Table::new_async(&mut store, ty, Ref::Func(None)).await?;
346     assert!(table.grow(&mut store, 1, Ref::Func(None)).is_err());
347     table.grow_async(&mut store, 1, Ref::Func(None)).await?;
348     Ok(())
349 }
350 
351 #[tokio::test]
async_limiter_disallows_memory_new() -> Result<()>352 async fn async_limiter_disallows_memory_new() -> Result<()> {
353     let mut store = async_limiter_store();
354     let ty = MemoryType::new(1, None);
355     assert!(Memory::new(&mut store, ty.clone()).is_err());
356     Memory::new_async(&mut store, ty).await?;
357     Ok(())
358 }
359 
360 #[tokio::test]
async_limiter_disallows_memory_grow() -> Result<()>361 async fn async_limiter_disallows_memory_grow() -> Result<()> {
362     let mut store = async_limiter_store();
363     let ty = MemoryType::new(1, None);
364     let mem = Memory::new_async(&mut store, ty).await?;
365     assert!(mem.grow(&mut store, 1).is_err());
366     mem.grow_async(&mut store, 1).await?;
367     Ok(())
368 }
369