1 #![cfg(not(miri))]
2 
3 use super::{REALLOC_AND_FREE, TypedFuncExt};
4 use anyhow::Result;
5 use std::sync::Arc;
6 use wasmtime::component::*;
7 use wasmtime::{Config, Engine, Store, StoreContextMut, Trap};
8 
9 const CANON_32BIT_NAN: u32 = 0b01111111110000000000000000000000;
10 const CANON_64BIT_NAN: u64 = 0b0111111111111000000000000000000000000000000000000000000000000000;
11 
12 #[test]
13 fn thunks() -> Result<()> {
14     let component = r#"
15         (component
16             (core module $m
17                 (func (export "thunk"))
18                 (func (export "thunk-trap") unreachable)
19             )
20             (core instance $i (instantiate $m))
21             (func (export "thunk")
22                 (canon lift (core func $i "thunk"))
23             )
24             (func (export "thunk-trap")
25                 (canon lift (core func $i "thunk-trap"))
26             )
27         )
28     "#;
29 
30     let engine = super::engine();
31     let component = Component::new(&engine, component)?;
32     let mut store = Store::new(&engine, ());
33     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
34     instance
35         .get_typed_func::<(), ()>(&mut store, "thunk")?
36         .call_and_post_return(&mut store, ())?;
37     let err = instance
38         .get_typed_func::<(), ()>(&mut store, "thunk-trap")?
39         .call(&mut store, ())
40         .unwrap_err();
41     assert_eq!(err.downcast::<Trap>()?, Trap::UnreachableCodeReached);
42 
43     Ok(())
44 }
45 
46 #[test]
47 fn typecheck() -> Result<()> {
48     let component = r#"
49         (component
50             (core module $m
51                 (func (export "thunk"))
52                 (func (export "take-string") (param i32 i32))
53                 (func (export "two-args") (param i32 i32 i32))
54                 (func (export "ret-one") (result i32) unreachable)
55 
56                 (memory (export "memory") 1)
57                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
58                     unreachable)
59             )
60             (core instance $i (instantiate (module $m)))
61             (func (export "thunk")
62                 (canon lift (core func $i "thunk"))
63             )
64             (func (export "take-string") (param "a" string)
65                 (canon lift (core func $i "take-string") (memory $i "memory") (realloc (func $i "realloc")))
66             )
67             (func (export "take-two-args") (param "a" s32) (param "b" (list u8))
68                 (canon lift (core func $i "two-args") (memory $i "memory") (realloc (func $i "realloc")))
69             )
70             (func (export "ret-tuple") (result (tuple u8 s8))
71                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
72             )
73             (func (export "ret-tuple1") (result (tuple u32))
74                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
75             )
76             (func (export "ret-string") (result string)
77                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
78             )
79             (func (export "ret-list-u8") (result (list u8))
80                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
81             )
82         )
83     "#;
84 
85     let engine = Engine::default();
86     let component = Component::new(&engine, component)?;
87     let mut store = Store::new(&engine, ());
88     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
89     let thunk = instance.get_func(&mut store, "thunk").unwrap();
90     let take_string = instance.get_func(&mut store, "take-string").unwrap();
91     let take_two_args = instance.get_func(&mut store, "take-two-args").unwrap();
92     let ret_tuple = instance.get_func(&mut store, "ret-tuple").unwrap();
93     let ret_tuple1 = instance.get_func(&mut store, "ret-tuple1").unwrap();
94     let ret_string = instance.get_func(&mut store, "ret-string").unwrap();
95     let ret_list_u8 = instance.get_func(&mut store, "ret-list-u8").unwrap();
96     assert!(thunk.typed::<(), (u32,)>(&store).is_err());
97     assert!(thunk.typed::<(u32,), ()>(&store).is_err());
98     assert!(thunk.typed::<(), ()>(&store).is_ok());
99     assert!(take_string.typed::<(), ()>(&store).is_err());
100     assert!(take_string.typed::<(String,), ()>(&store).is_ok());
101     assert!(take_string.typed::<(&str,), ()>(&store).is_ok());
102     assert!(take_string.typed::<(&[u8],), ()>(&store).is_err());
103     assert!(take_two_args.typed::<(), ()>(&store).is_err());
104     assert!(take_two_args.typed::<(i32, &[u8]), (u32,)>(&store).is_err());
105     assert!(take_two_args.typed::<(u32, &[u8]), ()>(&store).is_err());
106     assert!(take_two_args.typed::<(i32, &[u8]), ()>(&store).is_ok());
107     assert!(ret_tuple.typed::<(), ()>(&store).is_err());
108     assert!(ret_tuple.typed::<(), (u8,)>(&store).is_err());
109     assert!(ret_tuple.typed::<(), ((u8, i8),)>(&store).is_ok());
110     assert!(ret_tuple1.typed::<(), ((u32,),)>(&store).is_ok());
111     assert!(ret_tuple1.typed::<(), (u32,)>(&store).is_err());
112     assert!(ret_string.typed::<(), ()>(&store).is_err());
113     assert!(ret_string.typed::<(), (WasmStr,)>(&store).is_ok());
114     assert!(ret_list_u8.typed::<(), (WasmList<u16>,)>(&store).is_err());
115     assert!(ret_list_u8.typed::<(), (WasmList<i8>,)>(&store).is_err());
116     assert!(ret_list_u8.typed::<(), (WasmList<u8>,)>(&store).is_ok());
117 
118     Ok(())
119 }
120 
121 #[test]
122 fn integers() -> Result<()> {
123     let component = r#"
124         (component
125             (core module $m
126                 (func (export "take-i32-100") (param i32)
127                     local.get 0
128                     i32.const 100
129                     i32.eq
130                     br_if 0
131                     unreachable
132                 )
133                 (func (export "take-i64-100") (param i64)
134                     local.get 0
135                     i64.const 100
136                     i64.eq
137                     br_if 0
138                     unreachable
139                 )
140                 (func (export "ret-i32-0") (result i32) i32.const 0)
141                 (func (export "ret-i64-0") (result i64) i64.const 0)
142                 (func (export "ret-i32-minus-1") (result i32) i32.const -1)
143                 (func (export "ret-i64-minus-1") (result i64) i64.const -1)
144                 (func (export "ret-i32-100000") (result i32) i32.const 100000)
145             )
146             (core instance $i (instantiate (module $m)))
147             (func (export "take-u8") (param "a" u8) (canon lift (core func $i "take-i32-100")))
148             (func (export "take-s8") (param "a" s8) (canon lift (core func $i "take-i32-100")))
149             (func (export "take-u16") (param "a" u16) (canon lift (core func $i "take-i32-100")))
150             (func (export "take-s16") (param "a" s16) (canon lift (core func $i "take-i32-100")))
151             (func (export "take-u32") (param "a" u32) (canon lift (core func $i "take-i32-100")))
152             (func (export "take-s32") (param "a" s32) (canon lift (core func $i "take-i32-100")))
153             (func (export "take-u64") (param "a" u64) (canon lift (core func $i "take-i64-100")))
154             (func (export "take-s64") (param "a" s64) (canon lift (core func $i "take-i64-100")))
155 
156             (func (export "ret-u8") (result u8) (canon lift (core func $i "ret-i32-0")))
157             (func (export "ret-s8") (result s8) (canon lift (core func $i "ret-i32-0")))
158             (func (export "ret-u16") (result u16) (canon lift (core func $i "ret-i32-0")))
159             (func (export "ret-s16") (result s16) (canon lift (core func $i "ret-i32-0")))
160             (func (export "ret-u32") (result u32) (canon lift (core func $i "ret-i32-0")))
161             (func (export "ret-s32") (result s32) (canon lift (core func $i "ret-i32-0")))
162             (func (export "ret-u64") (result u64) (canon lift (core func $i "ret-i64-0")))
163             (func (export "ret-s64") (result s64) (canon lift (core func $i "ret-i64-0")))
164 
165             (func (export "retm1-u8") (result u8) (canon lift (core func $i "ret-i32-minus-1")))
166             (func (export "retm1-s8") (result s8) (canon lift (core func $i "ret-i32-minus-1")))
167             (func (export "retm1-u16") (result u16) (canon lift (core func $i "ret-i32-minus-1")))
168             (func (export "retm1-s16") (result s16) (canon lift (core func $i "ret-i32-minus-1")))
169             (func (export "retm1-u32") (result u32) (canon lift (core func $i "ret-i32-minus-1")))
170             (func (export "retm1-s32") (result s32) (canon lift (core func $i "ret-i32-minus-1")))
171             (func (export "retm1-u64") (result u64) (canon lift (core func $i "ret-i64-minus-1")))
172             (func (export "retm1-s64") (result s64) (canon lift (core func $i "ret-i64-minus-1")))
173 
174             (func (export "retbig-u8") (result u8) (canon lift (core func $i "ret-i32-100000")))
175             (func (export "retbig-s8") (result s8) (canon lift (core func $i "ret-i32-100000")))
176             (func (export "retbig-u16") (result u16) (canon lift (core func $i "ret-i32-100000")))
177             (func (export "retbig-s16") (result s16) (canon lift (core func $i "ret-i32-100000")))
178             (func (export "retbig-u32") (result u32) (canon lift (core func $i "ret-i32-100000")))
179             (func (export "retbig-s32") (result s32) (canon lift (core func $i "ret-i32-100000")))
180         )
181     "#;
182 
183     let engine = super::engine();
184     let component = Component::new(&engine, component)?;
185     let mut store = Store::new(&engine, ());
186     let new_instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
187     let instance = new_instance(&mut store)?;
188 
189     // Passing in 100 is valid for all primitives
190     instance
191         .get_typed_func::<(u8,), ()>(&mut store, "take-u8")?
192         .call_and_post_return(&mut store, (100,))?;
193     instance
194         .get_typed_func::<(i8,), ()>(&mut store, "take-s8")?
195         .call_and_post_return(&mut store, (100,))?;
196     instance
197         .get_typed_func::<(u16,), ()>(&mut store, "take-u16")?
198         .call_and_post_return(&mut store, (100,))?;
199     instance
200         .get_typed_func::<(i16,), ()>(&mut store, "take-s16")?
201         .call_and_post_return(&mut store, (100,))?;
202     instance
203         .get_typed_func::<(u32,), ()>(&mut store, "take-u32")?
204         .call_and_post_return(&mut store, (100,))?;
205     instance
206         .get_typed_func::<(i32,), ()>(&mut store, "take-s32")?
207         .call_and_post_return(&mut store, (100,))?;
208     instance
209         .get_typed_func::<(u64,), ()>(&mut store, "take-u64")?
210         .call_and_post_return(&mut store, (100,))?;
211     instance
212         .get_typed_func::<(i64,), ()>(&mut store, "take-s64")?
213         .call_and_post_return(&mut store, (100,))?;
214 
215     // This specific wasm instance traps if any value other than 100 is passed
216     new_instance(&mut store)?
217         .get_typed_func::<(u8,), ()>(&mut store, "take-u8")?
218         .call(&mut store, (101,))
219         .unwrap_err()
220         .downcast::<Trap>()?;
221     new_instance(&mut store)?
222         .get_typed_func::<(i8,), ()>(&mut store, "take-s8")?
223         .call(&mut store, (101,))
224         .unwrap_err()
225         .downcast::<Trap>()?;
226     new_instance(&mut store)?
227         .get_typed_func::<(u16,), ()>(&mut store, "take-u16")?
228         .call(&mut store, (101,))
229         .unwrap_err()
230         .downcast::<Trap>()?;
231     new_instance(&mut store)?
232         .get_typed_func::<(i16,), ()>(&mut store, "take-s16")?
233         .call(&mut store, (101,))
234         .unwrap_err()
235         .downcast::<Trap>()?;
236     new_instance(&mut store)?
237         .get_typed_func::<(u32,), ()>(&mut store, "take-u32")?
238         .call(&mut store, (101,))
239         .unwrap_err()
240         .downcast::<Trap>()?;
241     new_instance(&mut store)?
242         .get_typed_func::<(i32,), ()>(&mut store, "take-s32")?
243         .call(&mut store, (101,))
244         .unwrap_err()
245         .downcast::<Trap>()?;
246     new_instance(&mut store)?
247         .get_typed_func::<(u64,), ()>(&mut store, "take-u64")?
248         .call(&mut store, (101,))
249         .unwrap_err()
250         .downcast::<Trap>()?;
251     new_instance(&mut store)?
252         .get_typed_func::<(i64,), ()>(&mut store, "take-s64")?
253         .call(&mut store, (101,))
254         .unwrap_err()
255         .downcast::<Trap>()?;
256 
257     // Zero can be returned as any integer
258     assert_eq!(
259         instance
260             .get_typed_func::<(), (u8,)>(&mut store, "ret-u8")?
261             .call_and_post_return(&mut store, ())?,
262         (0,)
263     );
264     assert_eq!(
265         instance
266             .get_typed_func::<(), (i8,)>(&mut store, "ret-s8")?
267             .call_and_post_return(&mut store, ())?,
268         (0,)
269     );
270     assert_eq!(
271         instance
272             .get_typed_func::<(), (u16,)>(&mut store, "ret-u16")?
273             .call_and_post_return(&mut store, ())?,
274         (0,)
275     );
276     assert_eq!(
277         instance
278             .get_typed_func::<(), (i16,)>(&mut store, "ret-s16")?
279             .call_and_post_return(&mut store, ())?,
280         (0,)
281     );
282     assert_eq!(
283         instance
284             .get_typed_func::<(), (u32,)>(&mut store, "ret-u32")?
285             .call_and_post_return(&mut store, ())?,
286         (0,)
287     );
288     assert_eq!(
289         instance
290             .get_typed_func::<(), (i32,)>(&mut store, "ret-s32")?
291             .call_and_post_return(&mut store, ())?,
292         (0,)
293     );
294     assert_eq!(
295         instance
296             .get_typed_func::<(), (u64,)>(&mut store, "ret-u64")?
297             .call_and_post_return(&mut store, ())?,
298         (0,)
299     );
300     assert_eq!(
301         instance
302             .get_typed_func::<(), (i64,)>(&mut store, "ret-s64")?
303             .call_and_post_return(&mut store, ())?,
304         (0,)
305     );
306 
307     // Returning -1 should reinterpret the bytes as defined by each type.
308     assert_eq!(
309         instance
310             .get_typed_func::<(), (u8,)>(&mut store, "retm1-u8")?
311             .call_and_post_return(&mut store, ())?,
312         (0xff,)
313     );
314     assert_eq!(
315         instance
316             .get_typed_func::<(), (i8,)>(&mut store, "retm1-s8")?
317             .call_and_post_return(&mut store, ())?,
318         (-1,)
319     );
320     assert_eq!(
321         instance
322             .get_typed_func::<(), (u16,)>(&mut store, "retm1-u16")?
323             .call_and_post_return(&mut store, ())?,
324         (0xffff,)
325     );
326     assert_eq!(
327         instance
328             .get_typed_func::<(), (i16,)>(&mut store, "retm1-s16")?
329             .call_and_post_return(&mut store, ())?,
330         (-1,)
331     );
332     assert_eq!(
333         instance
334             .get_typed_func::<(), (u32,)>(&mut store, "retm1-u32")?
335             .call_and_post_return(&mut store, ())?,
336         (0xffffffff,)
337     );
338     assert_eq!(
339         instance
340             .get_typed_func::<(), (i32,)>(&mut store, "retm1-s32")?
341             .call_and_post_return(&mut store, ())?,
342         (-1,)
343     );
344     assert_eq!(
345         instance
346             .get_typed_func::<(), (u64,)>(&mut store, "retm1-u64")?
347             .call_and_post_return(&mut store, ())?,
348         (0xffffffff_ffffffff,)
349     );
350     assert_eq!(
351         instance
352             .get_typed_func::<(), (i64,)>(&mut store, "retm1-s64")?
353             .call_and_post_return(&mut store, ())?,
354         (-1,)
355     );
356 
357     // Returning 100000 should chop off bytes as necessary
358     let ret: u32 = 100000;
359     assert_eq!(
360         instance
361             .get_typed_func::<(), (u8,)>(&mut store, "retbig-u8")?
362             .call_and_post_return(&mut store, ())?,
363         (ret as u8,),
364     );
365     assert_eq!(
366         instance
367             .get_typed_func::<(), (i8,)>(&mut store, "retbig-s8")?
368             .call_and_post_return(&mut store, ())?,
369         (ret as i8,),
370     );
371     assert_eq!(
372         instance
373             .get_typed_func::<(), (u16,)>(&mut store, "retbig-u16")?
374             .call_and_post_return(&mut store, ())?,
375         (ret as u16,),
376     );
377     assert_eq!(
378         instance
379             .get_typed_func::<(), (i16,)>(&mut store, "retbig-s16")?
380             .call_and_post_return(&mut store, ())?,
381         (ret as i16,),
382     );
383     assert_eq!(
384         instance
385             .get_typed_func::<(), (u32,)>(&mut store, "retbig-u32")?
386             .call_and_post_return(&mut store, ())?,
387         (ret,),
388     );
389     assert_eq!(
390         instance
391             .get_typed_func::<(), (i32,)>(&mut store, "retbig-s32")?
392             .call_and_post_return(&mut store, ())?,
393         (ret as i32,),
394     );
395 
396     Ok(())
397 }
398 
399 #[test]
400 fn type_layers() -> Result<()> {
401     let component = r#"
402         (component
403             (core module $m
404                 (func (export "take-i32-100") (param i32)
405                     local.get 0
406                     i32.const 2
407                     i32.eq
408                     br_if 0
409                     unreachable
410                 )
411             )
412             (core instance $i (instantiate $m))
413             (func (export "take-u32") (param "a" u32) (canon lift (core func $i "take-i32-100")))
414         )
415     "#;
416 
417     let engine = super::engine();
418     let component = Component::new(&engine, component)?;
419     let mut store = Store::new(&engine, ());
420     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
421 
422     instance
423         .get_typed_func::<(Box<u32>,), ()>(&mut store, "take-u32")?
424         .call_and_post_return(&mut store, (Box::new(2),))?;
425     instance
426         .get_typed_func::<(&u32,), ()>(&mut store, "take-u32")?
427         .call_and_post_return(&mut store, (&2,))?;
428     instance
429         .get_typed_func::<(Arc<u32>,), ()>(&mut store, "take-u32")?
430         .call_and_post_return(&mut store, (Arc::new(2),))?;
431     instance
432         .get_typed_func::<(&Box<Arc<Box<u32>>>,), ()>(&mut store, "take-u32")?
433         .call_and_post_return(&mut store, (&Box::new(Arc::new(Box::new(2))),))?;
434 
435     Ok(())
436 }
437 
438 #[test]
439 fn floats() -> Result<()> {
440     let component = r#"
441         (component
442             (core module $m
443                 (func (export "i32.reinterpret_f32") (param f32) (result i32)
444                     local.get 0
445                     i32.reinterpret_f32
446                 )
447                 (func (export "i64.reinterpret_f64") (param f64) (result i64)
448                     local.get 0
449                     i64.reinterpret_f64
450                 )
451                 (func (export "f32.reinterpret_i32") (param i32) (result f32)
452                     local.get 0
453                     f32.reinterpret_i32
454                 )
455                 (func (export "f64.reinterpret_i64") (param i64) (result f64)
456                     local.get 0
457                     f64.reinterpret_i64
458                 )
459             )
460             (core instance $i (instantiate $m))
461 
462             (func (export "f32-to-u32") (param "a" float32) (result u32)
463                 (canon lift (core func $i "i32.reinterpret_f32"))
464             )
465             (func (export "f64-to-u64") (param "a" float64) (result u64)
466                 (canon lift (core func $i "i64.reinterpret_f64"))
467             )
468             (func (export "u32-to-f32") (param "a" u32) (result float32)
469                 (canon lift (core func $i "f32.reinterpret_i32"))
470             )
471             (func (export "u64-to-f64") (param "a" u64) (result float64)
472                 (canon lift (core func $i "f64.reinterpret_i64"))
473             )
474         )
475     "#;
476 
477     let engine = super::engine();
478     let component = Component::new(&engine, component)?;
479     let mut store = Store::new(&engine, ());
480     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
481     let f32_to_u32 = instance.get_typed_func::<(f32,), (u32,)>(&mut store, "f32-to-u32")?;
482     let f64_to_u64 = instance.get_typed_func::<(f64,), (u64,)>(&mut store, "f64-to-u64")?;
483     let u32_to_f32 = instance.get_typed_func::<(u32,), (f32,)>(&mut store, "u32-to-f32")?;
484     let u64_to_f64 = instance.get_typed_func::<(u64,), (f64,)>(&mut store, "u64-to-f64")?;
485 
486     assert_eq!(f32_to_u32.call(&mut store, (1.0,))?, (1.0f32.to_bits(),));
487     f32_to_u32.post_return(&mut store)?;
488     assert_eq!(f64_to_u64.call(&mut store, (2.0,))?, (2.0f64.to_bits(),));
489     f64_to_u64.post_return(&mut store)?;
490     assert_eq!(u32_to_f32.call(&mut store, (3.0f32.to_bits(),))?, (3.0,));
491     u32_to_f32.post_return(&mut store)?;
492     assert_eq!(u64_to_f64.call(&mut store, (4.0f64.to_bits(),))?, (4.0,));
493     u64_to_f64.post_return(&mut store)?;
494 
495     assert_eq!(
496         u32_to_f32
497             .call(&mut store, (CANON_32BIT_NAN | 1,))?
498             .0
499             .to_bits(),
500         CANON_32BIT_NAN | 1
501     );
502     u32_to_f32.post_return(&mut store)?;
503     assert_eq!(
504         u64_to_f64
505             .call(&mut store, (CANON_64BIT_NAN | 1,))?
506             .0
507             .to_bits(),
508         CANON_64BIT_NAN | 1,
509     );
510     u64_to_f64.post_return(&mut store)?;
511 
512     assert_eq!(
513         f32_to_u32.call(&mut store, (f32::from_bits(CANON_32BIT_NAN | 1),))?,
514         (CANON_32BIT_NAN | 1,)
515     );
516     f32_to_u32.post_return(&mut store)?;
517     assert_eq!(
518         f64_to_u64.call(&mut store, (f64::from_bits(CANON_64BIT_NAN | 1),))?,
519         (CANON_64BIT_NAN | 1,)
520     );
521     f64_to_u64.post_return(&mut store)?;
522 
523     Ok(())
524 }
525 
526 #[test]
527 fn bools() -> Result<()> {
528     let component = r#"
529         (component
530             (core module $m
531                 (func (export "pass") (param i32) (result i32) local.get 0)
532             )
533             (core instance $i (instantiate $m))
534 
535             (func (export "u32-to-bool") (param "a" u32) (result bool)
536                 (canon lift (core func $i "pass"))
537             )
538             (func (export "bool-to-u32") (param "a" bool) (result u32)
539                 (canon lift (core func $i "pass"))
540             )
541         )
542     "#;
543 
544     let engine = super::engine();
545     let component = Component::new(&engine, component)?;
546     let mut store = Store::new(&engine, ());
547     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
548     let u32_to_bool = instance.get_typed_func::<(u32,), (bool,)>(&mut store, "u32-to-bool")?;
549     let bool_to_u32 = instance.get_typed_func::<(bool,), (u32,)>(&mut store, "bool-to-u32")?;
550 
551     assert_eq!(bool_to_u32.call(&mut store, (false,))?, (0,));
552     bool_to_u32.post_return(&mut store)?;
553     assert_eq!(bool_to_u32.call(&mut store, (true,))?, (1,));
554     bool_to_u32.post_return(&mut store)?;
555     assert_eq!(u32_to_bool.call(&mut store, (0,))?, (false,));
556     u32_to_bool.post_return(&mut store)?;
557     assert_eq!(u32_to_bool.call(&mut store, (1,))?, (true,));
558     u32_to_bool.post_return(&mut store)?;
559     assert_eq!(u32_to_bool.call(&mut store, (2,))?, (true,));
560     u32_to_bool.post_return(&mut store)?;
561 
562     Ok(())
563 }
564 
565 #[test]
566 fn chars() -> Result<()> {
567     let component = r#"
568         (component
569             (core module $m
570                 (func (export "pass") (param i32) (result i32) local.get 0)
571             )
572             (core instance $i (instantiate $m))
573 
574             (func (export "u32-to-char") (param "a" u32) (result char)
575                 (canon lift (core func $i "pass"))
576             )
577             (func (export "char-to-u32") (param "a" char) (result u32)
578                 (canon lift (core func $i "pass"))
579             )
580         )
581     "#;
582 
583     let engine = super::engine();
584     let component = Component::new(&engine, component)?;
585     let mut store = Store::new(&engine, ());
586     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
587     let u32_to_char = instance.get_typed_func::<(u32,), (char,)>(&mut store, "u32-to-char")?;
588     let char_to_u32 = instance.get_typed_func::<(char,), (u32,)>(&mut store, "char-to-u32")?;
589 
590     let mut roundtrip = |x: char| -> Result<()> {
591         assert_eq!(char_to_u32.call(&mut store, (x,))?, (x as u32,));
592         char_to_u32.post_return(&mut store)?;
593         assert_eq!(u32_to_char.call(&mut store, (x as u32,))?, (x,));
594         u32_to_char.post_return(&mut store)?;
595         Ok(())
596     };
597 
598     roundtrip('x')?;
599     roundtrip('a')?;
600     roundtrip('\0')?;
601     roundtrip('\n')?;
602     roundtrip('��')?;
603 
604     let u32_to_char = |store: &mut Store<()>| {
605         Linker::new(&engine)
606             .instantiate(&mut *store, &component)?
607             .get_typed_func::<(u32,), (char,)>(&mut *store, "u32-to-char")
608     };
609     let err = u32_to_char(&mut store)?
610         .call(&mut store, (0xd800,))
611         .unwrap_err();
612     assert!(err.to_string().contains("integer out of range"), "{}", err);
613     let err = u32_to_char(&mut store)?
614         .call(&mut store, (0xdfff,))
615         .unwrap_err();
616     assert!(err.to_string().contains("integer out of range"), "{}", err);
617     let err = u32_to_char(&mut store)?
618         .call(&mut store, (0x110000,))
619         .unwrap_err();
620     assert!(err.to_string().contains("integer out of range"), "{}", err);
621     let err = u32_to_char(&mut store)?
622         .call(&mut store, (u32::MAX,))
623         .unwrap_err();
624     assert!(err.to_string().contains("integer out of range"), "{}", err);
625 
626     Ok(())
627 }
628 
629 #[test]
630 fn tuple_result() -> Result<()> {
631     let component = r#"
632         (component
633             (core module $m
634                 (memory (export "memory") 1)
635                 (func (export "foo") (param i32 i32 f32 f64) (result i32)
636                     (local $base i32)
637                     (local.set $base (i32.const 8))
638                     (i32.store8 offset=0 (local.get $base) (local.get 0))
639                     (i32.store16 offset=2 (local.get $base) (local.get 1))
640                     (f32.store offset=4 (local.get $base) (local.get 2))
641                     (f64.store offset=8 (local.get $base) (local.get 3))
642                     local.get $base
643                 )
644 
645                 (func (export "invalid") (result i32)
646                     i32.const -8
647                 )
648             )
649             (core instance $i (instantiate $m))
650 
651             (type $result (tuple s8 u16 float32 float64))
652             (func (export "tuple")
653                 (param "a" s8) (param "b" u16) (param "c" float32) (param "d" float64) (result $result)
654                 (canon lift (core func $i "foo") (memory $i "memory"))
655             )
656             (func (export "invalid") (result $result)
657                 (canon lift (core func $i "invalid") (memory $i "memory"))
658             )
659         )
660     "#;
661 
662     let engine = super::engine();
663     let component = Component::new(&engine, component)?;
664     let mut store = Store::new(&engine, ());
665     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
666 
667     let input = (-1, 100, 3.0, 100.0);
668     let output = instance
669         .get_typed_func::<(i8, u16, f32, f64), ((i8, u16, f32, f64),)>(&mut store, "tuple")?
670         .call_and_post_return(&mut store, input)?;
671     assert_eq!((input,), output);
672 
673     let invalid_func =
674         instance.get_typed_func::<(), ((i8, u16, f32, f64),)>(&mut store, "invalid")?;
675     let err = invalid_func.call(&mut store, ()).err().unwrap();
676     assert!(
677         err.to_string().contains("pointer out of bounds of memory"),
678         "{}",
679         err
680     );
681 
682     Ok(())
683 }
684 
685 #[test]
686 fn strings() -> Result<()> {
687     let component = format!(
688         r#"(component
689             (core module $m
690                 (memory (export "memory") 1)
691                 (func (export "roundtrip") (param i32 i32) (result i32)
692                     (local $base i32)
693                     (local.set $base
694                         (call $realloc
695                             (i32.const 0)
696                             (i32.const 0)
697                             (i32.const 4)
698                             (i32.const 8)))
699                     (i32.store offset=0
700                         (local.get $base)
701                         (local.get 0))
702                     (i32.store offset=4
703                         (local.get $base)
704                         (local.get 1))
705                     (local.get $base)
706                 )
707 
708                 {REALLOC_AND_FREE}
709             )
710             (core instance $i (instantiate $m))
711 
712             (func (export "list8-to-str") (param "a" (list u8)) (result string)
713                 (canon lift
714                     (core func $i "roundtrip")
715                     (memory $i "memory")
716                     (realloc (func $i "realloc"))
717                 )
718             )
719             (func (export "str-to-list8") (param "a" string) (result (list u8))
720                 (canon lift
721                     (core func $i "roundtrip")
722                     (memory $i "memory")
723                     (realloc (func $i "realloc"))
724                 )
725             )
726             (func (export "list16-to-str") (param "a" (list u16)) (result string)
727                 (canon lift
728                     (core func $i "roundtrip")
729                     string-encoding=utf16
730                     (memory $i "memory")
731                     (realloc (func $i "realloc"))
732                 )
733             )
734             (func (export "str-to-list16") (param "a" string) (result (list u16))
735                 (canon lift
736                     (core func $i "roundtrip")
737                     string-encoding=utf16
738                     (memory $i "memory")
739                     (realloc (func $i "realloc"))
740                 )
741             )
742         )"#
743     );
744 
745     let engine = super::engine();
746     let component = Component::new(&engine, component)?;
747     let mut store = Store::new(&engine, ());
748     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
749     let list8_to_str =
750         instance.get_typed_func::<(&[u8],), (WasmStr,)>(&mut store, "list8-to-str")?;
751     let str_to_list8 =
752         instance.get_typed_func::<(&str,), (WasmList<u8>,)>(&mut store, "str-to-list8")?;
753     let list16_to_str =
754         instance.get_typed_func::<(&[u16],), (WasmStr,)>(&mut store, "list16-to-str")?;
755     let str_to_list16 =
756         instance.get_typed_func::<(&str,), (WasmList<u16>,)>(&mut store, "str-to-list16")?;
757 
758     let mut roundtrip = |x: &str| -> Result<()> {
759         let ret = list8_to_str.call(&mut store, (x.as_bytes(),))?.0;
760         assert_eq!(ret.to_str(&store)?, x);
761         list8_to_str.post_return(&mut store)?;
762 
763         let utf16 = x.encode_utf16().collect::<Vec<_>>();
764         let ret = list16_to_str.call(&mut store, (&utf16[..],))?.0;
765         assert_eq!(ret.to_str(&store)?, x);
766         list16_to_str.post_return(&mut store)?;
767 
768         let ret = str_to_list8.call(&mut store, (x,))?.0;
769         assert_eq!(
770             ret.iter(&mut store).collect::<Result<Vec<_>>>()?,
771             x.as_bytes()
772         );
773         str_to_list8.post_return(&mut store)?;
774 
775         let ret = str_to_list16.call(&mut store, (x,))?.0;
776         assert_eq!(ret.iter(&mut store).collect::<Result<Vec<_>>>()?, utf16,);
777         str_to_list16.post_return(&mut store)?;
778 
779         Ok(())
780     };
781 
782     roundtrip("")?;
783     roundtrip("foo")?;
784     roundtrip("hello there")?;
785     roundtrip("��")?;
786     roundtrip("Löwe 老虎 Léopard")?;
787 
788     let ret = list8_to_str.call(&mut store, (b"\xff",))?.0;
789     let err = ret.to_str(&store).unwrap_err();
790     assert!(err.to_string().contains("invalid utf-8"), "{}", err);
791     list8_to_str.post_return(&mut store)?;
792 
793     let ret = list8_to_str
794         .call(&mut store, (b"hello there \xff invalid",))?
795         .0;
796     let err = ret.to_str(&store).unwrap_err();
797     assert!(err.to_string().contains("invalid utf-8"), "{}", err);
798     list8_to_str.post_return(&mut store)?;
799 
800     let ret = list16_to_str.call(&mut store, (&[0xd800],))?.0;
801     let err = ret.to_str(&store).unwrap_err();
802     assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
803     list16_to_str.post_return(&mut store)?;
804 
805     let ret = list16_to_str.call(&mut store, (&[0xdfff],))?.0;
806     let err = ret.to_str(&store).unwrap_err();
807     assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
808     list16_to_str.post_return(&mut store)?;
809 
810     let ret = list16_to_str.call(&mut store, (&[0xd800, 0xff00],))?.0;
811     let err = ret.to_str(&store).unwrap_err();
812     assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
813     list16_to_str.post_return(&mut store)?;
814 
815     Ok(())
816 }
817 
818 #[tokio::test]
819 async fn async_reentrance() -> Result<()> {
820     _ = env_logger::try_init();
821 
822     let component = r#"
823         (component
824             (core module $shim
825                 (import "" "task.return" (func $task-return (param i32)))
826                 (table (export "funcs") 1 1 funcref)
827                 (func (export "export") (param i32) (result i32)
828                     (call_indirect (i32.const 0) (local.get 0))
829                 )
830                 (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
831             )
832             (core func $task-return (canon task.return (result u32)))
833             (core instance $shim (instantiate $shim
834                 (with "" (instance (export "task.return" (func $task-return))))
835             ))
836             (func $shim-export (param "p1" u32) (result u32)
837                 (canon lift (core func $shim "export") async (callback (func $shim "callback")))
838             )
839 
840             (component $inner
841                 (import "import" (func $import (param "p1" u32) (result u32)))
842                 (core module $libc (memory (export "memory") 1))
843                 (core instance $libc (instantiate $libc))
844                 (core func $import (canon lower (func $import) async (memory $libc "memory")))
845 
846                 (core module $m
847                     (import "libc" "memory" (memory 1))
848                     (import "" "import" (func $import (param i32 i32) (result i32)))
849                     (import "" "task.return" (func $task-return (param i32)))
850                     (func (export "export") (param i32) (result i32)
851                         (i32.store offset=0 (i32.const 1200) (local.get 0))
852                         (call $import (i32.const 1200) (i32.const 1204))
853                         drop
854                         (call $task-return (i32.load offset=0 (i32.const 1204)))
855                         i32.const 0
856                     )
857                     (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
858                 )
859                 (core type $task-return-type (func (param i32)))
860                 (core func $task-return (canon task.return (result u32)))
861                 (core instance $i (instantiate $m
862                     (with "" (instance
863                         (export "task.return" (func $task-return))
864                         (export "import" (func $import))
865                     ))
866                     (with "libc" (instance $libc))
867                 ))
868                 (func (export "export") (param "p1" u32) (result u32)
869                     (canon lift (core func $i "export") async (callback (func $i "callback")))
870                 )
871             )
872             (instance $inner (instantiate $inner (with "import" (func $shim-export))))
873 
874             (core module $libc (memory (export "memory") 1))
875             (core instance $libc (instantiate $libc))
876             (core func $inner-export (canon lower (func $inner "export") async (memory $libc "memory")))
877 
878             (core module $donut
879                 (import "" "funcs" (table 1 1 funcref))
880                 (import "libc" "memory" (memory 1))
881                 (import "" "import" (func $import (param i32 i32) (result i32)))
882                 (import "" "task.return" (func $task-return (param i32)))
883                 (func $host-export (export "export") (param i32) (result i32)
884                     (i32.store offset=0 (i32.const 1200) (local.get 0))
885                     (call $import (i32.const 1200) (i32.const 1204))
886                     drop
887                     (call $task-return (i32.load offset=0 (i32.const 1204)))
888                     i32.const 0
889                 )
890                 (func $guest-export (export "guest-export") (param i32) (result i32) unreachable)
891                 (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
892                 (func $start
893                     (table.set (i32.const 0) (ref.func $guest-export))
894                 )
895                 (start $start)
896             )
897 
898             (core instance $donut (instantiate $donut
899                 (with "" (instance
900                     (export "task.return" (func $task-return))
901                     (export "import" (func $inner-export))
902                     (export "funcs" (table $shim "funcs"))
903                 ))
904                 (with "libc" (instance $libc))
905             ))
906             (func (export "export") (param "p1" u32) (result u32)
907                 (canon lift (core func $donut "export") async (callback (func $donut "callback")))
908             )
909         )"#;
910 
911     let mut config = Config::new();
912     config.wasm_component_model_async(true);
913     config.async_support(true);
914     let engine = &Engine::new(&config)?;
915     let component = Component::new(&engine, component)?;
916     let mut store = Store::new(&engine, ());
917 
918     let instance = Linker::new(&engine)
919         .instantiate_async(&mut store, &component)
920         .await?;
921     let func = instance.get_typed_func::<(u32,), (u32,)>(&mut store, "export")?;
922     let message = "cannot enter component instance";
923     match instance
924         .run_concurrent(&mut store, async move |accessor| {
925             func.call_concurrent(accessor, (42,)).await
926         })
927         .await
928     {
929         Ok(_) => panic!(),
930         Err(e) => assert!(
931             format!("{e:?}").contains(message),
932             "expected `{message}`; got `{e:?}`"
933         ),
934     }
935 
936     Ok(())
937 }
938 
939 #[tokio::test]
940 async fn missing_task_return_call_stackless() -> Result<()> {
941     task_return_trap(
942         r#"(component
943             (core module $m
944                 (import "" "task.return" (func $task-return))
945                 (func (export "foo") (result i32)
946                     i32.const 0
947                 )
948                 (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
949             )
950             (core func $task-return (canon task.return))
951             (core instance $i (instantiate $m
952                 (with "" (instance (export "task.return" (func $task-return))))
953             ))
954             (func (export "foo") (canon lift (core func $i "foo") async (callback (func $i "callback"))))
955         )"#,
956         "wasm trap: async-lifted export failed to produce a result",
957     )
958     .await
959 }
960 
961 #[tokio::test]
962 async fn missing_task_return_call_stackful() -> Result<()> {
963     task_return_trap(
964         r#"(component
965             (core module $m
966                 (import "" "task.return" (func $task-return))
967                 (func (export "foo"))
968             )
969             (core func $task-return (canon task.return))
970             (core instance $i (instantiate $m
971                 (with "" (instance (export "task.return" (func $task-return))))
972             ))
973             (func (export "foo") (canon lift (core func $i "foo") async))
974         )"#,
975         "wasm trap: async-lifted export failed to produce a result",
976     )
977     .await
978 }
979 
980 #[tokio::test]
981 async fn task_return_type_mismatch() -> Result<()> {
982     task_return_trap(
983         r#"(component
984             (core module $m
985                 (import "" "task.return" (func $task-return (param i32)))
986                 (func (export "foo") (call $task-return (i32.const 42)))
987             )
988             (core func $task-return (canon task.return (result u32)))
989             (core instance $i (instantiate $m
990                 (with "" (instance (export "task.return" (func $task-return))))
991             ))
992             (func (export "foo") (canon lift (core func $i "foo") async))
993         )"#,
994         "invalid `task.return` signature and/or options for current task",
995     )
996     .await
997 }
998 
999 #[tokio::test]
1000 async fn task_return_memory_mismatch() -> Result<()> {
1001     task_return_trap(
1002         r#"(component
1003             (core module $libc (memory (export "memory") 1))
1004             (core instance $libc (instantiate $libc))
1005             (core module $m
1006                 (import "" "task.return" (func $task-return))
1007                 (func (export "foo") (call $task-return))
1008             )
1009             (core func $task-return (canon task.return (memory $libc "memory")))
1010             (core instance $i (instantiate $m
1011                 (with "" (instance (export "task.return" (func $task-return))))
1012             ))
1013             (func (export "foo") (canon lift (core func $i "foo") async))
1014         )"#,
1015         "invalid `task.return` signature and/or options for current task",
1016     )
1017     .await
1018 }
1019 
1020 #[tokio::test]
1021 async fn task_return_string_encoding_mismatch() -> Result<()> {
1022     task_return_trap(
1023         r#"(component
1024             (core module $m
1025                 (import "" "task.return" (func $task-return))
1026                 (func (export "foo") (call $task-return))
1027             )
1028             (core func $task-return (canon task.return string-encoding=utf16))
1029             (core instance $i (instantiate $m
1030                 (with "" (instance (export "task.return" (func $task-return))))
1031             ))
1032             (func (export "foo") (canon lift (core func $i "foo") async))
1033         )"#,
1034         "invalid `task.return` signature and/or options for current task",
1035     )
1036     .await
1037 }
1038 
1039 async fn task_return_trap(component: &str, substring: &str) -> Result<()> {
1040     let mut config = Config::new();
1041     config.wasm_component_model_async(true);
1042     config.wasm_component_model_async_stackful(true);
1043     config.async_support(true);
1044     let engine = &Engine::new(&config)?;
1045     let component = Component::new(&engine, component)?;
1046     let mut store = Store::new(&engine, ());
1047 
1048     let instance = Linker::new(&engine)
1049         .instantiate_async(&mut store, &component)
1050         .await?;
1051 
1052     let func = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
1053     match instance
1054         .run_concurrent(&mut store, async move |accessor| {
1055             func.call_concurrent(accessor, ()).await
1056         })
1057         .await
1058     {
1059         Ok(_) => panic!(),
1060         Err(e) => {
1061             assert!(
1062                 format!("{e:?}").contains(substring),
1063                 "could not find `{substring}` in `{e:?}`"
1064             )
1065         }
1066     }
1067 
1068     Ok(())
1069 }
1070 
1071 #[tokio::test]
1072 async fn many_parameters() -> Result<()> {
1073     test_many_parameters(false, false).await
1074 }
1075 
1076 #[tokio::test]
1077 async fn many_parameters_concurrent() -> Result<()> {
1078     test_many_parameters(false, true).await
1079 }
1080 
1081 #[tokio::test]
1082 async fn many_parameters_dynamic() -> Result<()> {
1083     test_many_parameters(true, false).await
1084 }
1085 
1086 #[tokio::test]
1087 async fn many_parameters_dynamic_concurrent() -> Result<()> {
1088     test_many_parameters(true, true).await
1089 }
1090 
1091 async fn test_many_parameters(dynamic: bool, concurrent: bool) -> Result<()> {
1092     let (body, async_opts) = if concurrent {
1093         (
1094             r#"
1095                     (call $task-return
1096                         (i32.const 0)
1097                         (i32.mul
1098                             (memory.size)
1099                             (i32.const 65536)
1100                         )
1101                         (local.get 0)
1102                     )
1103 
1104                     (i32.const 0)
1105             "#,
1106             r#"async (callback (func $i "callback"))"#,
1107         )
1108     } else {
1109         (
1110             r#"
1111                     (local $base i32)
1112 
1113                     ;; Allocate space for the return
1114                     (local.set $base
1115                         (call $realloc
1116                             (i32.const 0)
1117                             (i32.const 0)
1118                             (i32.const 4)
1119                             (i32.const 12)))
1120 
1121                     ;; Store the pointer/length of the entire linear memory
1122                     ;; so we have access to everything.
1123                     (i32.store offset=0
1124                         (local.get $base)
1125                         (i32.const 0))
1126                     (i32.store offset=4
1127                         (local.get $base)
1128                         (i32.mul
1129                             (memory.size)
1130                             (i32.const 65536)))
1131 
1132                     ;; And also store our pointer parameter
1133                     (i32.store offset=8
1134                         (local.get $base)
1135                         (local.get 0))
1136 
1137                     (local.get $base)
1138             "#,
1139             "",
1140         )
1141     };
1142 
1143     let component = format!(
1144         r#"(component
1145             (core module $libc
1146                 (memory (export "memory") 1)
1147 
1148                 {REALLOC_AND_FREE}
1149             )
1150             (core instance $libc (instantiate $libc))
1151             (core module $m
1152                 (import "libc" "memory" (memory 1))
1153                 (import "libc" "realloc" (func $realloc (param i32 i32 i32 i32) (result i32)))
1154                 (import "" "task.return" (func $task-return (param i32 i32 i32)))
1155                 (func (export "foo") (param i32) (result i32)
1156                     {body}
1157                 )
1158                 (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
1159             )
1160             (type $tuple (tuple (list u8) u32))
1161             (core func $task-return (canon task.return
1162                 (result $tuple)
1163                 (memory $libc "memory")
1164             ))
1165             (core instance $i (instantiate $m
1166                 (with "" (instance (export "task.return" (func $task-return))))
1167                 (with "libc" (instance $libc))
1168             ))
1169 
1170             (type $t (func
1171                 (param "p1" s8)              ;; offset  0, size 1
1172                 (param "p2" u64)             ;; offset  8, size 8
1173                 (param "p3" float32)         ;; offset 16, size 4
1174                 (param "p4" u8)              ;; offset 20, size 1
1175                 (param "p5" s16)             ;; offset 22, size 2
1176                 (param "p6" string)          ;; offset 24, size 8
1177                 (param "p7" (list u32))      ;; offset 32, size 8
1178                 (param "p8" bool)            ;; offset 40, size 1
1179                 (param "p9" bool)            ;; offset 41, size 1
1180                 (param "p0" char)            ;; offset 44, size 4
1181                 (param "pa" (list bool))     ;; offset 48, size 8
1182                 (param "pb" (list char))     ;; offset 56, size 8
1183                 (param "pc" (list string))   ;; offset 64, size 8
1184 
1185                 (result $tuple)
1186             ))
1187             (func (export "many-param") (type $t)
1188                 (canon lift
1189                     (core func $i "foo")
1190                     (memory $libc "memory")
1191                     (realloc (func $libc "realloc"))
1192                     {async_opts}
1193                 )
1194             )
1195         )"#
1196     );
1197 
1198     let mut config = Config::new();
1199     config.wasm_component_model_async(true);
1200     config.async_support(true);
1201     let engine = &Engine::new(&config)?;
1202     let component = Component::new(&engine, component)?;
1203     let mut store = Store::new(&engine, ());
1204 
1205     let instance = Linker::new(&engine)
1206         .instantiate_async(&mut store, &component)
1207         .await?;
1208 
1209     let input = (
1210         -100,
1211         u64::MAX / 2,
1212         f32::from_bits(CANON_32BIT_NAN | 1),
1213         38,
1214         18831,
1215         "this is the first string",
1216         [1, 2, 3, 4, 5, 6, 7, 8].as_slice(),
1217         true,
1218         false,
1219         '��',
1220         [false, true, false, true, true].as_slice(),
1221         ['��', '��', '��', '��', '��'].as_slice(),
1222         [
1223             "the quick",
1224             "brown fox",
1225             "was too lazy",
1226             "to jump over the dog",
1227             "what a demanding dog",
1228         ]
1229         .as_slice(),
1230     );
1231 
1232     let (memory, pointer) = if dynamic {
1233         let input = vec![
1234             Val::S8(input.0),
1235             Val::U64(input.1),
1236             Val::Float32(input.2),
1237             Val::U8(input.3),
1238             Val::S16(input.4),
1239             Val::String(input.5.into()),
1240             Val::List(input.6.iter().copied().map(Val::U32).collect()),
1241             Val::Bool(input.7),
1242             Val::Bool(input.8),
1243             Val::Char(input.9),
1244             Val::List(input.10.iter().copied().map(Val::Bool).collect()),
1245             Val::List(input.11.iter().copied().map(Val::Char).collect()),
1246             Val::List(input.12.iter().map(|&s| Val::String(s.into())).collect()),
1247         ];
1248         let func = instance.get_func(&mut store, "many-param").unwrap();
1249 
1250         let mut results = vec![Val::Bool(false)];
1251         if concurrent {
1252             instance
1253                 .run_concurrent(&mut store, async |store| {
1254                     func.call_concurrent(store, &input, &mut results).await
1255                 })
1256                 .await??;
1257         } else {
1258             func.call_async(&mut store, &input, &mut results).await?;
1259         };
1260         let mut results = results.into_iter();
1261         let Some(Val::Tuple(results)) = results.next() else {
1262             panic!()
1263         };
1264         let mut results = results.into_iter();
1265         let Some(Val::List(memory)) = results.next() else {
1266             panic!()
1267         };
1268         let Some(Val::U32(pointer)) = results.next() else {
1269             panic!()
1270         };
1271         (
1272             memory
1273                 .into_iter()
1274                 .map(|v| if let Val::U8(v) = v { v } else { panic!() })
1275                 .collect(),
1276             pointer,
1277         )
1278     } else {
1279         let func = instance.get_typed_func::<(
1280             i8,
1281             u64,
1282             f32,
1283             u8,
1284             i16,
1285             &str,
1286             &[u32],
1287             bool,
1288             bool,
1289             char,
1290             &[bool],
1291             &[char],
1292             &[&str],
1293         ), ((Vec<u8>, u32),)>(&mut store, "many-param")?;
1294 
1295         if concurrent {
1296             instance
1297                 .run_concurrent(&mut store, async move |accessor| {
1298                     func.call_concurrent(accessor, input).await
1299                 })
1300                 .await??
1301                 .0
1302         } else {
1303             func.call_async(&mut store, input).await?.0
1304         }
1305     };
1306     let memory = &memory[..];
1307 
1308     let mut actual = &memory[pointer as usize..][..72];
1309     assert_eq!(i8::from_le_bytes(*actual.take_n::<1>()), input.0);
1310     actual.skip::<7>();
1311     assert_eq!(u64::from_le_bytes(*actual.take_n::<8>()), input.1);
1312     assert_eq!(
1313         u32::from_le_bytes(*actual.take_n::<4>()),
1314         CANON_32BIT_NAN | 1
1315     );
1316     assert_eq!(u8::from_le_bytes(*actual.take_n::<1>()), input.3);
1317     actual.skip::<1>();
1318     assert_eq!(i16::from_le_bytes(*actual.take_n::<2>()), input.4);
1319     assert_eq!(actual.ptr_len(memory, 1), input.5.as_bytes());
1320     let mut mem = actual.ptr_len(memory, 4);
1321     for expected in input.6.iter() {
1322         assert_eq!(u32::from_le_bytes(*mem.take_n::<4>()), *expected);
1323     }
1324     assert!(mem.is_empty());
1325     assert_eq!(actual.take_n::<1>(), &[input.7 as u8]);
1326     assert_eq!(actual.take_n::<1>(), &[input.8 as u8]);
1327     actual.skip::<2>();
1328     assert_eq!(u32::from_le_bytes(*actual.take_n::<4>()), input.9 as u32);
1329 
1330     // (list bool)
1331     mem = actual.ptr_len(memory, 1);
1332     for expected in input.10.iter() {
1333         assert_eq!(mem.take_n::<1>(), &[*expected as u8]);
1334     }
1335     assert!(mem.is_empty());
1336 
1337     // (list char)
1338     mem = actual.ptr_len(memory, 4);
1339     for expected in input.11.iter() {
1340         assert_eq!(u32::from_le_bytes(*mem.take_n::<4>()), *expected as u32);
1341     }
1342     assert!(mem.is_empty());
1343 
1344     // (list string)
1345     mem = actual.ptr_len(memory, 8);
1346     for expected in input.12.iter() {
1347         let actual = mem.ptr_len(memory, 1);
1348         assert_eq!(actual, expected.as_bytes());
1349     }
1350     assert!(mem.is_empty());
1351     assert!(actual.is_empty());
1352 
1353     Ok(())
1354 }
1355 
1356 #[tokio::test]
1357 async fn many_results() -> Result<()> {
1358     test_many_results(false, false).await
1359 }
1360 
1361 #[tokio::test]
1362 async fn many_results_concurrent() -> Result<()> {
1363     test_many_results(false, true).await
1364 }
1365 
1366 #[tokio::test]
1367 async fn many_results_dynamic() -> Result<()> {
1368     test_many_results(true, false).await
1369 }
1370 
1371 #[tokio::test]
1372 async fn many_results_dynamic_concurrent() -> Result<()> {
1373     test_many_results(true, true).await
1374 }
1375 
1376 async fn test_many_results(dynamic: bool, concurrent: bool) -> Result<()> {
1377     let (ret, async_opts) = if concurrent {
1378         (
1379             r#"
1380                    call $task-return
1381                    i32.const 0
1382             "#,
1383             r#"async (callback (func $i "callback"))"#,
1384         )
1385     } else {
1386         ("", "")
1387     };
1388 
1389     let my_nan = CANON_32BIT_NAN | 1;
1390 
1391     let component = format!(
1392         r#"(component
1393             (core module $libc
1394                 (memory (export "memory") 1)
1395 
1396                 {REALLOC_AND_FREE}
1397             )
1398             (core instance $libc (instantiate $libc))
1399             (core module $m
1400                 (import "libc" "memory" (memory 1))
1401                 (import "libc" "realloc" (func $realloc (param i32 i32 i32 i32) (result i32)))
1402                 (import "" "task.return" (func $task-return (param i32)))
1403                 (func (export "foo") (result i32)
1404                     (local $base i32)
1405                     (local $string i32)
1406                     (local $list i32)
1407 
1408                     (local.set $base
1409                         (call $realloc
1410                             (i32.const 0)
1411                             (i32.const 0)
1412                             (i32.const 8)
1413                             (i32.const 72)))
1414 
1415                     (i32.store8 offset=0
1416                         (local.get $base)
1417                         (i32.const -100))
1418 
1419                     (i64.store offset=8
1420                         (local.get $base)
1421                         (i64.const 9223372036854775807))
1422 
1423                     (f32.store offset=16
1424                         (local.get $base)
1425                         (f32.reinterpret_i32 (i32.const {my_nan})))
1426 
1427                     (i32.store8 offset=20
1428                         (local.get $base)
1429                         (i32.const 38))
1430 
1431                     (i32.store16 offset=22
1432                         (local.get $base)
1433                         (i32.const 18831))
1434 
1435                     (local.set $string
1436                         (call $realloc
1437                             (i32.const 0)
1438                             (i32.const 0)
1439                             (i32.const 1)
1440                             (i32.const 6)))
1441 
1442                     (i32.store8 offset=0
1443                         (local.get $string)
1444                         (i32.const 97)) ;; 'a'
1445                     (i32.store8 offset=1
1446                         (local.get $string)
1447                         (i32.const 98)) ;; 'b'
1448                     (i32.store8 offset=2
1449                         (local.get $string)
1450                         (i32.const 99)) ;; 'c'
1451                     (i32.store8 offset=3
1452                         (local.get $string)
1453                         (i32.const 100)) ;; 'd'
1454                     (i32.store8 offset=4
1455                         (local.get $string)
1456                         (i32.const 101)) ;; 'e'
1457                     (i32.store8 offset=5
1458                         (local.get $string)
1459                         (i32.const 102)) ;; 'f'
1460 
1461                     (i32.store offset=24
1462                         (local.get $base)
1463                         (local.get $string))
1464 
1465                     (i32.store offset=28
1466                         (local.get $base)
1467                         (i32.const 2))
1468 
1469                     (local.set $list
1470                         (call $realloc
1471                             (i32.const 0)
1472                             (i32.const 0)
1473                             (i32.const 4)
1474                             (i32.const 32)))
1475 
1476                     (i32.store offset=0
1477                         (local.get $list)
1478                         (i32.const 1))
1479                     (i32.store offset=4
1480                         (local.get $list)
1481                         (i32.const 2))
1482                     (i32.store offset=8
1483                         (local.get $list)
1484                         (i32.const 3))
1485                     (i32.store offset=12
1486                         (local.get $list)
1487                         (i32.const 4))
1488                     (i32.store offset=16
1489                         (local.get $list)
1490                         (i32.const 5))
1491                     (i32.store offset=20
1492                         (local.get $list)
1493                         (i32.const 6))
1494                     (i32.store offset=24
1495                         (local.get $list)
1496                         (i32.const 7))
1497                     (i32.store offset=28
1498                         (local.get $list)
1499                         (i32.const 8))
1500 
1501                     (i32.store offset=32
1502                         (local.get $base)
1503                         (local.get $list))
1504 
1505                     (i32.store offset=36
1506                         (local.get $base)
1507                         (i32.const 8))
1508 
1509                     (i32.store8 offset=40
1510                         (local.get $base)
1511                         (i32.const 1))
1512 
1513                     (i32.store8 offset=41
1514                         (local.get $base)
1515                         (i32.const 0))
1516 
1517                     (i32.store offset=44
1518                         (local.get $base)
1519                         (i32.const 128681)) ;; '��'
1520 
1521                     (local.set $list
1522                         (call $realloc
1523                             (i32.const 0)
1524                             (i32.const 0)
1525                             (i32.const 1)
1526                             (i32.const 5)))
1527 
1528                     (i32.store8 offset=0
1529                         (local.get $list)
1530                         (i32.const 0))
1531                     (i32.store8 offset=1
1532                         (local.get $list)
1533                         (i32.const 1))
1534                     (i32.store8 offset=2
1535                         (local.get $list)
1536                         (i32.const 0))
1537                     (i32.store8 offset=3
1538                         (local.get $list)
1539                         (i32.const 1))
1540                     (i32.store8 offset=4
1541                         (local.get $list)
1542                         (i32.const 1))
1543 
1544                     (i32.store offset=48
1545                         (local.get $base)
1546                         (local.get $list))
1547 
1548                     (i32.store offset=52
1549                         (local.get $base)
1550                         (i32.const 5))
1551 
1552                     (local.set $list
1553                         (call $realloc
1554                             (i32.const 0)
1555                             (i32.const 0)
1556                             (i32.const 4)
1557                             (i32.const 20)))
1558 
1559                     (i32.store offset=0
1560                         (local.get $list)
1561                         (i32.const 127820)) ;; '��'
1562                     (i32.store offset=4
1563                         (local.get $list)
1564                         (i32.const 129360)) ;; '��'
1565                     (i32.store offset=8
1566                         (local.get $list)
1567                         (i32.const 127831)) ;; '��'
1568                     (i32.store offset=12
1569                         (local.get $list)
1570                         (i32.const 127833)) ;; '��'
1571                     (i32.store offset=16
1572                         (local.get $list)
1573                         (i32.const 127841)) ;; '��'
1574 
1575                     (i32.store offset=56
1576                         (local.get $base)
1577                         (local.get $list))
1578 
1579                     (i32.store offset=60
1580                         (local.get $base)
1581                         (i32.const 5))
1582 
1583                     (local.set $list
1584                         (call $realloc
1585                             (i32.const 0)
1586                             (i32.const 0)
1587                             (i32.const 4)
1588                             (i32.const 16)))
1589 
1590                     (i32.store offset=0
1591                         (local.get $list)
1592                         (i32.add (local.get $string) (i32.const 2)))
1593                     (i32.store offset=4
1594                         (local.get $list)
1595                         (i32.const 2))
1596                     (i32.store offset=8
1597                         (local.get $list)
1598                         (i32.add (local.get $string) (i32.const 4)))
1599                     (i32.store offset=12
1600                         (local.get $list)
1601                         (i32.const 2))
1602 
1603                     (i32.store offset=64
1604                         (local.get $base)
1605                         (local.get $list))
1606 
1607                     (i32.store offset=68
1608                         (local.get $base)
1609                         (i32.const 2))
1610 
1611                     local.get $base
1612 
1613                     {ret}
1614                 )
1615                 (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
1616             )
1617             (type $tuple (tuple
1618                 s8
1619                 u64
1620                 float32
1621                 u8
1622                 s16
1623                 string
1624                 (list u32)
1625                 bool
1626                 bool
1627                 char
1628                 (list bool)
1629                 (list char)
1630                 (list string)
1631             ))
1632             (core func $task-return (canon task.return
1633                 (result $tuple)
1634                 (memory $libc "memory")
1635             ))
1636             (core instance $i (instantiate $m
1637                 (with "" (instance (export "task.return" (func $task-return))))
1638                 (with "libc" (instance $libc))
1639             ))
1640 
1641             (type $t (func (result $tuple)))
1642             (func (export "many-results") (type $t)
1643                 (canon lift
1644                     (core func $i "foo")
1645                     (memory $libc "memory")
1646                     (realloc (func $libc "realloc"))
1647                     {async_opts}
1648                 )
1649             )
1650         )"#
1651     );
1652 
1653     let mut config = Config::new();
1654     config.wasm_component_model_async(true);
1655     config.async_support(true);
1656     let engine = &Engine::new(&config)?;
1657     let component = Component::new(&engine, component)?;
1658     let mut store = Store::new(&engine, ());
1659 
1660     let instance = Linker::new(&engine)
1661         .instantiate_async(&mut store, &component)
1662         .await?;
1663 
1664     let expected = (
1665         -100i8,
1666         u64::MAX / 2,
1667         f32::from_bits(CANON_32BIT_NAN | 1),
1668         38u8,
1669         18831i16,
1670         "ab".to_string(),
1671         vec![1u32, 2, 3, 4, 5, 6, 7, 8],
1672         true,
1673         false,
1674         '��',
1675         vec![false, true, false, true, true],
1676         vec!['��', '��', '��', '��', '��'],
1677         vec!["cd".to_string(), "ef".to_string()],
1678     );
1679 
1680     let actual = if dynamic {
1681         let func = instance.get_func(&mut store, "many-results").unwrap();
1682 
1683         let mut results = vec![Val::Bool(false)];
1684         if concurrent {
1685             instance
1686                 .run_concurrent(&mut store, async |store| {
1687                     func.call_concurrent(store, &[], &mut results).await
1688                 })
1689                 .await??;
1690         } else {
1691             func.call_async(&mut store, &[], &mut results).await?;
1692         };
1693         let mut results = results.into_iter();
1694 
1695         let Some(Val::Tuple(results)) = results.next() else {
1696             panic!()
1697         };
1698         let mut results = results.into_iter();
1699         let Some(Val::S8(p1)) = results.next() else {
1700             panic!()
1701         };
1702         let Some(Val::U64(p2)) = results.next() else {
1703             panic!()
1704         };
1705         let Some(Val::Float32(p3)) = results.next() else {
1706             panic!()
1707         };
1708         let Some(Val::U8(p4)) = results.next() else {
1709             panic!()
1710         };
1711         let Some(Val::S16(p5)) = results.next() else {
1712             panic!()
1713         };
1714         let Some(Val::String(p6)) = results.next() else {
1715             panic!()
1716         };
1717         let Some(Val::List(p7)) = results.next() else {
1718             panic!()
1719         };
1720         let p7 = p7
1721             .into_iter()
1722             .map(|v| if let Val::U32(v) = v { v } else { panic!() })
1723             .collect();
1724         let Some(Val::Bool(p8)) = results.next() else {
1725             panic!()
1726         };
1727         let Some(Val::Bool(p9)) = results.next() else {
1728             panic!()
1729         };
1730         let Some(Val::Char(p0)) = results.next() else {
1731             panic!()
1732         };
1733         let Some(Val::List(pa)) = results.next() else {
1734             panic!()
1735         };
1736         let pa = pa
1737             .into_iter()
1738             .map(|v| if let Val::Bool(v) = v { v } else { panic!() })
1739             .collect();
1740         let Some(Val::List(pb)) = results.next() else {
1741             panic!()
1742         };
1743         let pb = pb
1744             .into_iter()
1745             .map(|v| if let Val::Char(v) = v { v } else { panic!() })
1746             .collect();
1747         let Some(Val::List(pc)) = results.next() else {
1748             panic!()
1749         };
1750         let pc = pc
1751             .into_iter()
1752             .map(|v| if let Val::String(v) = v { v } else { panic!() })
1753             .collect();
1754 
1755         (p1, p2, p3, p4, p5, p6, p7, p8, p9, p0, pa, pb, pc)
1756     } else {
1757         let func = instance.get_typed_func::<(), ((
1758             i8,
1759             u64,
1760             f32,
1761             u8,
1762             i16,
1763             String,
1764             Vec<u32>,
1765             bool,
1766             bool,
1767             char,
1768             Vec<bool>,
1769             Vec<char>,
1770             Vec<String>,
1771         ),)>(&mut store, "many-results")?;
1772 
1773         if concurrent {
1774             instance
1775                 .run_concurrent(&mut store, async move |accessor| {
1776                     func.call_concurrent(accessor, ()).await
1777                 })
1778                 .await??
1779                 .0
1780         } else {
1781             func.call_async(&mut store, ()).await?.0
1782         }
1783     };
1784 
1785     assert_eq!(expected.0, actual.0);
1786     assert_eq!(expected.1, actual.1);
1787     assert!(expected.2.is_nan());
1788     assert!(actual.2.is_nan());
1789     assert_eq!(expected.3, actual.3);
1790     assert_eq!(expected.4, actual.4);
1791     assert_eq!(expected.5, actual.5);
1792     assert_eq!(expected.6, actual.6);
1793     assert_eq!(expected.7, actual.7);
1794     assert_eq!(expected.8, actual.8);
1795     assert_eq!(expected.9, actual.9);
1796     assert_eq!(expected.10, actual.10);
1797     assert_eq!(expected.11, actual.11);
1798     assert_eq!(expected.12, actual.12);
1799 
1800     Ok(())
1801 }
1802 
1803 #[test]
1804 fn some_traps() -> Result<()> {
1805     let middle_of_memory = (i32::MAX / 2) & (!0xff);
1806     let component = format!(
1807         r#"(component
1808             (core module $m
1809                 (memory (export "memory") 1)
1810                 (func (export "take-many") (param i32))
1811                 (func (export "take-list") (param i32 i32))
1812 
1813                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1814                     unreachable)
1815             )
1816             (core instance $i (instantiate $m))
1817 
1818             (func (export "take-list-unreachable") (param "a" (list u8))
1819                 (canon lift (core func $i "take-list") (memory $i "memory") (realloc (func $i "realloc")))
1820             )
1821             (func (export "take-string-unreachable") (param "a" string)
1822                 (canon lift (core func $i "take-list") (memory $i "memory") (realloc (func $i "realloc")))
1823             )
1824 
1825             (type $t (func
1826                 (param "s1" string)
1827                 (param "s2" string)
1828                 (param "s3" string)
1829                 (param "s4" string)
1830                 (param "s5" string)
1831                 (param "s6" string)
1832                 (param "s7" string)
1833                 (param "s8" string)
1834                 (param "s9" string)
1835                 (param "s10" string)
1836             ))
1837             (func (export "take-many-unreachable") (type $t)
1838                 (canon lift (core func $i "take-many") (memory $i "memory") (realloc (func $i "realloc")))
1839             )
1840 
1841             (core module $m2
1842                 (memory (export "memory") 1)
1843                 (func (export "take-many") (param i32))
1844                 (func (export "take-list") (param i32 i32))
1845 
1846                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1847                     i32.const {middle_of_memory})
1848             )
1849             (core instance $i2 (instantiate $m2))
1850 
1851             (func (export "take-list-base-oob") (param "a" (list u8))
1852                 (canon lift (core func $i2 "take-list") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1853             )
1854             (func (export "take-string-base-oob") (param "a" string)
1855                 (canon lift (core func $i2 "take-list") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1856             )
1857             (func (export "take-many-base-oob") (type $t)
1858                 (canon lift (core func $i2 "take-many") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1859             )
1860 
1861             (core module $m3
1862                 (memory (export "memory") 1)
1863                 (func (export "take-many") (param i32))
1864                 (func (export "take-list") (param i32 i32))
1865 
1866                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1867                     i32.const 65532)
1868             )
1869             (core instance $i3 (instantiate $m3))
1870 
1871             (func (export "take-list-end-oob") (param "a" (list u8))
1872                 (canon lift (core func $i3 "take-list") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1873             )
1874             (func (export "take-string-end-oob") (param "a" string)
1875                 (canon lift (core func $i3 "take-list") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1876             )
1877             (func (export "take-many-end-oob") (type $t)
1878                 (canon lift (core func $i3 "take-many") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1879             )
1880 
1881             (core module $m4
1882                 (memory (export "memory") 1)
1883                 (func (export "take-many") (param i32))
1884 
1885                 (global $cnt (mut i32) (i32.const 0))
1886                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1887                     global.get $cnt
1888                     if (result i32)
1889                         i32.const 100000
1890                     else
1891                         i32.const 1
1892                         global.set $cnt
1893                         i32.const 0
1894                     end
1895                 )
1896             )
1897             (core instance $i4 (instantiate $m4))
1898 
1899             (func (export "take-many-second-oob") (type $t)
1900                 (canon lift (core func $i4 "take-many") (memory $i4 "memory") (realloc (func $i4 "realloc")))
1901             )
1902         )"#
1903     );
1904 
1905     let engine = super::engine();
1906     let component = Component::new(&engine, component)?;
1907     let mut store = Store::new(&engine, ());
1908     let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
1909 
1910     // This should fail when calling the allocator function for the argument
1911     let err = instance(&mut store)?
1912         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-unreachable")?
1913         .call(&mut store, (&[],))
1914         .unwrap_err()
1915         .downcast::<Trap>()?;
1916     assert_eq!(err, Trap::UnreachableCodeReached);
1917 
1918     // This should fail when calling the allocator function for the argument
1919     let err = instance(&mut store)?
1920         .get_typed_func::<(&str,), ()>(&mut store, "take-string-unreachable")?
1921         .call(&mut store, ("",))
1922         .unwrap_err()
1923         .downcast::<Trap>()?;
1924     assert_eq!(err, Trap::UnreachableCodeReached);
1925 
1926     // This should fail when calling the allocator function for the space
1927     // to store the arguments (before arguments are even lowered)
1928     let err = instance(&mut store)?
1929         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1930             &mut store,
1931             "take-many-unreachable",
1932         )?
1933         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1934         .unwrap_err()
1935         .downcast::<Trap>()?;
1936     assert_eq!(err, Trap::UnreachableCodeReached);
1937 
1938     // Assert that when the base pointer returned by malloc is out of bounds
1939     // that errors are reported as such. Both empty and lists with contents
1940     // should all be invalid here.
1941     //
1942     // FIXME(WebAssembly/component-model#32) confirm the semantics here are
1943     // what's desired.
1944     #[track_caller]
1945     fn assert_oob(err: &anyhow::Error) {
1946         assert!(
1947             err.to_string()
1948                 .contains("realloc return: beyond end of memory"),
1949             "{err:?}",
1950         );
1951     }
1952     let err = instance(&mut store)?
1953         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
1954         .call(&mut store, (&[],))
1955         .unwrap_err();
1956     assert_oob(&err);
1957     let err = instance(&mut store)?
1958         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
1959         .call(&mut store, (&[1],))
1960         .unwrap_err();
1961     assert_oob(&err);
1962     let err = instance(&mut store)?
1963         .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
1964         .call(&mut store, ("",))
1965         .unwrap_err();
1966     assert_oob(&err);
1967     let err = instance(&mut store)?
1968         .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
1969         .call(&mut store, ("x",))
1970         .unwrap_err();
1971     assert_oob(&err);
1972     let err = instance(&mut store)?
1973         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1974             &mut store,
1975             "take-many-base-oob",
1976         )?
1977         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1978         .unwrap_err();
1979     assert_oob(&err);
1980 
1981     // Test here that when the returned pointer from malloc is one byte from the
1982     // end of memory that empty things are fine, but larger things are not.
1983 
1984     instance(&mut store)?
1985         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1986         .call_and_post_return(&mut store, (&[],))?;
1987     instance(&mut store)?
1988         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1989         .call_and_post_return(&mut store, (&[1, 2, 3, 4],))?;
1990     let err = instance(&mut store)?
1991         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1992         .call(&mut store, (&[1, 2, 3, 4, 5],))
1993         .unwrap_err();
1994     assert_oob(&err);
1995     instance(&mut store)?
1996         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1997         .call_and_post_return(&mut store, ("",))?;
1998     instance(&mut store)?
1999         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
2000         .call_and_post_return(&mut store, ("abcd",))?;
2001     let err = instance(&mut store)?
2002         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
2003         .call(&mut store, ("abcde",))
2004         .unwrap_err();
2005     assert_oob(&err);
2006     let err = instance(&mut store)?
2007         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
2008             &mut store,
2009             "take-many-end-oob",
2010         )?
2011         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
2012         .unwrap_err();
2013     assert_oob(&err);
2014 
2015     // For this function the first allocation, the space to store all the
2016     // arguments, is in-bounds but then all further allocations, such as for
2017     // each individual string, are all out of bounds.
2018     let err = instance(&mut store)?
2019         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
2020             &mut store,
2021             "take-many-second-oob",
2022         )?
2023         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
2024         .unwrap_err();
2025     assert_oob(&err);
2026     let err = instance(&mut store)?
2027         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
2028             &mut store,
2029             "take-many-second-oob",
2030         )?
2031         .call(&mut store, ("", "", "", "", "", "", "", "", "", "x"))
2032         .unwrap_err();
2033     assert_oob(&err);
2034     Ok(())
2035 }
2036 
2037 #[test]
2038 fn char_bool_memory() -> Result<()> {
2039     let component = format!(
2040         r#"(component
2041             (core module $m
2042                 (memory (export "memory") 1)
2043                 (func (export "ret-tuple") (param i32 i32) (result i32)
2044                     (local $base i32)
2045 
2046                     ;; Allocate space for the return
2047                     (local.set $base
2048                         (call $realloc
2049                             (i32.const 0)
2050                             (i32.const 0)
2051                             (i32.const 4)
2052                             (i32.const 8)))
2053 
2054                     ;; store the boolean
2055                     (i32.store offset=0
2056                         (local.get $base)
2057                         (local.get 0))
2058 
2059                     ;; store the char
2060                     (i32.store offset=4
2061                         (local.get $base)
2062                         (local.get 1))
2063 
2064                     (local.get $base)
2065                 )
2066 
2067                 {REALLOC_AND_FREE}
2068             )
2069             (core instance $i (instantiate $m))
2070 
2071             (func (export "ret-tuple") (param "a" u32) (param "b" u32) (result (tuple bool char))
2072                 (canon lift (core func $i "ret-tuple")
2073                     (memory $i "memory")
2074                     (realloc (func $i "realloc")))
2075             )
2076         )"#
2077     );
2078 
2079     let engine = super::engine();
2080     let component = Component::new(&engine, component)?;
2081     let mut store = Store::new(&engine, ());
2082     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
2083     let func = instance.get_typed_func::<(u32, u32), ((bool, char),)>(&mut store, "ret-tuple")?;
2084 
2085     let (ret,) = func.call(&mut store, (0, 'a' as u32))?;
2086     assert_eq!(ret, (false, 'a'));
2087     func.post_return(&mut store)?;
2088 
2089     let (ret,) = func.call(&mut store, (1, '��' as u32))?;
2090     assert_eq!(ret, (true, '��'));
2091     func.post_return(&mut store)?;
2092 
2093     let (ret,) = func.call(&mut store, (2, 'a' as u32))?;
2094     assert_eq!(ret, (true, 'a'));
2095     func.post_return(&mut store)?;
2096 
2097     assert!(func.call(&mut store, (0, 0xd800)).is_err());
2098 
2099     Ok(())
2100 }
2101 
2102 #[test]
2103 fn string_list_oob() -> Result<()> {
2104     let component = format!(
2105         r#"(component
2106             (core module $m
2107                 (memory (export "memory") 1)
2108                 (func (export "ret-list") (result i32)
2109                     (local $base i32)
2110 
2111                     ;; Allocate space for the return
2112                     (local.set $base
2113                         (call $realloc
2114                             (i32.const 0)
2115                             (i32.const 0)
2116                             (i32.const 4)
2117                             (i32.const 8)))
2118 
2119                     (i32.store offset=0
2120                         (local.get $base)
2121                         (i32.const 100000))
2122                     (i32.store offset=4
2123                         (local.get $base)
2124                         (i32.const 1))
2125 
2126                     (local.get $base)
2127                 )
2128 
2129                 {REALLOC_AND_FREE}
2130             )
2131             (core instance $i (instantiate $m))
2132 
2133             (func (export "ret-list-u8") (result (list u8))
2134                 (canon lift (core func $i "ret-list")
2135                     (memory $i "memory")
2136                     (realloc (func $i "realloc"))
2137                 )
2138             )
2139             (func (export "ret-string") (result string)
2140                 (canon lift (core func $i "ret-list")
2141                     (memory $i "memory")
2142                     (realloc (func $i "realloc"))
2143                 )
2144             )
2145         )"#
2146     );
2147 
2148     let engine = super::engine();
2149     let component = Component::new(&engine, component)?;
2150     let mut store = Store::new(&engine, ());
2151     let ret_list_u8 = Linker::new(&engine)
2152         .instantiate(&mut store, &component)?
2153         .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "ret-list-u8")?;
2154     let ret_string = Linker::new(&engine)
2155         .instantiate(&mut store, &component)?
2156         .get_typed_func::<(), (WasmStr,)>(&mut store, "ret-string")?;
2157 
2158     let err = ret_list_u8.call(&mut store, ()).err().unwrap();
2159     assert!(err.to_string().contains("out of bounds"), "{}", err);
2160 
2161     let err = ret_string.call(&mut store, ()).err().unwrap();
2162     assert!(err.to_string().contains("out of bounds"), "{}", err);
2163 
2164     Ok(())
2165 }
2166 
2167 #[test]
2168 fn tuples() -> Result<()> {
2169     let component = format!(
2170         r#"(component
2171             (core module $m
2172                 (memory (export "memory") 1)
2173                 (func (export "foo")
2174                     (param i32 f64 i32)
2175                     (result i32)
2176 
2177                     local.get 0
2178                     i32.const 0
2179                     i32.ne
2180                     if unreachable end
2181 
2182                     local.get 1
2183                     f64.const 1
2184                     f64.ne
2185                     if unreachable end
2186 
2187                     local.get 2
2188                     i32.const 2
2189                     i32.ne
2190                     if unreachable end
2191 
2192                     i32.const 3
2193                 )
2194             )
2195             (core instance $i (instantiate $m))
2196 
2197             (func (export "foo")
2198                 (param "a" (tuple s32 float64))
2199                 (param "b" (tuple s8))
2200                 (result (tuple u16))
2201                 (canon lift (core func $i "foo"))
2202             )
2203         )"#
2204     );
2205 
2206     let engine = super::engine();
2207     let component = Component::new(&engine, component)?;
2208     let mut store = Store::new(&engine, ());
2209     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
2210     let foo = instance.get_typed_func::<((i32, f64), (i8,)), ((u16,),)>(&mut store, "foo")?;
2211     assert_eq!(foo.call(&mut store, ((0, 1.0), (2,)))?, ((3,),));
2212 
2213     Ok(())
2214 }
2215 
2216 #[test]
2217 fn option() -> Result<()> {
2218     let component = format!(
2219         r#"(component
2220             (core module $m
2221                 (memory (export "memory") 1)
2222                 (func (export "pass1") (param i32 i32) (result i32)
2223                     (local $base i32)
2224                     (local.set $base
2225                         (call $realloc
2226                             (i32.const 0)
2227                             (i32.const 0)
2228                             (i32.const 4)
2229                             (i32.const 8)))
2230 
2231                     (i32.store offset=0
2232                         (local.get $base)
2233                         (local.get 0))
2234                     (i32.store offset=4
2235                         (local.get $base)
2236                         (local.get 1))
2237 
2238                     (local.get $base)
2239                 )
2240                 (func (export "pass2") (param i32 i32 i32) (result i32)
2241                     (local $base i32)
2242                     (local.set $base
2243                         (call $realloc
2244                             (i32.const 0)
2245                             (i32.const 0)
2246                             (i32.const 4)
2247                             (i32.const 12)))
2248 
2249                     (i32.store offset=0
2250                         (local.get $base)
2251                         (local.get 0))
2252                     (i32.store offset=4
2253                         (local.get $base)
2254                         (local.get 1))
2255                     (i32.store offset=8
2256                         (local.get $base)
2257                         (local.get 2))
2258 
2259                     (local.get $base)
2260                 )
2261 
2262                 {REALLOC_AND_FREE}
2263             )
2264             (core instance $i (instantiate $m))
2265 
2266             (func (export "option-u8-to-tuple") (param "a" (option u8)) (result (tuple u32 u32))
2267                 (canon lift (core func $i "pass1") (memory $i "memory"))
2268             )
2269             (func (export "option-u32-to-tuple") (param "a" (option u32)) (result (tuple u32 u32))
2270                 (canon lift (core func $i "pass1") (memory $i "memory"))
2271             )
2272             (func (export "option-string-to-tuple") (param "a" (option string)) (result (tuple u32 string))
2273                 (canon lift
2274                     (core func $i "pass2")
2275                     (memory $i "memory")
2276                     (realloc (func $i "realloc"))
2277                 )
2278             )
2279             (func (export "to-option-u8") (param "a" u32) (param "b" u32) (result (option u8))
2280                 (canon lift (core func $i "pass1") (memory $i "memory"))
2281             )
2282             (func (export "to-option-u32") (param "a" u32) (param "b" u32) (result (option u32))
2283                 (canon lift
2284                     (core func $i "pass1")
2285                     (memory $i "memory")
2286                 )
2287             )
2288             (func (export "to-option-string") (param "a" u32) (param "b" string) (result (option string))
2289                 (canon lift
2290                     (core func $i "pass2")
2291                     (memory $i "memory")
2292                     (realloc (func $i "realloc"))
2293                 )
2294             )
2295         )"#
2296     );
2297 
2298     let engine = super::engine();
2299     let component = Component::new(&engine, component)?;
2300     let mut store = Store::new(&engine, ());
2301     let linker = Linker::new(&engine);
2302     let instance = linker.instantiate(&mut store, &component)?;
2303 
2304     let option_u8_to_tuple = instance
2305         .get_typed_func::<(Option<u8>,), ((u32, u32),)>(&mut store, "option-u8-to-tuple")?;
2306     assert_eq!(option_u8_to_tuple.call(&mut store, (None,))?, ((0, 0),));
2307     option_u8_to_tuple.post_return(&mut store)?;
2308     assert_eq!(option_u8_to_tuple.call(&mut store, (Some(0),))?, ((1, 0),));
2309     option_u8_to_tuple.post_return(&mut store)?;
2310     assert_eq!(
2311         option_u8_to_tuple.call(&mut store, (Some(100),))?,
2312         ((1, 100),)
2313     );
2314     option_u8_to_tuple.post_return(&mut store)?;
2315 
2316     let option_u32_to_tuple = instance
2317         .get_typed_func::<(Option<u32>,), ((u32, u32),)>(&mut store, "option-u32-to-tuple")?;
2318     assert_eq!(option_u32_to_tuple.call(&mut store, (None,))?, ((0, 0),));
2319     option_u32_to_tuple.post_return(&mut store)?;
2320     assert_eq!(option_u32_to_tuple.call(&mut store, (Some(0),))?, ((1, 0),));
2321     option_u32_to_tuple.post_return(&mut store)?;
2322     assert_eq!(
2323         option_u32_to_tuple.call(&mut store, (Some(100),))?,
2324         ((1, 100),)
2325     );
2326     option_u32_to_tuple.post_return(&mut store)?;
2327 
2328     let option_string_to_tuple = instance.get_typed_func::<(Option<&str>,), ((u32, WasmStr),)>(
2329         &mut store,
2330         "option-string-to-tuple",
2331     )?;
2332     let ((a, b),) = option_string_to_tuple.call(&mut store, (None,))?;
2333     assert_eq!(a, 0);
2334     assert_eq!(b.to_str(&store)?, "");
2335     option_string_to_tuple.post_return(&mut store)?;
2336     let ((a, b),) = option_string_to_tuple.call(&mut store, (Some(""),))?;
2337     assert_eq!(a, 1);
2338     assert_eq!(b.to_str(&store)?, "");
2339     option_string_to_tuple.post_return(&mut store)?;
2340     let ((a, b),) = option_string_to_tuple.call(&mut store, (Some("hello"),))?;
2341     assert_eq!(a, 1);
2342     assert_eq!(b.to_str(&store)?, "hello");
2343     option_string_to_tuple.post_return(&mut store)?;
2344 
2345     let instance = linker.instantiate(&mut store, &component)?;
2346     let to_option_u8 =
2347         instance.get_typed_func::<(u32, u32), (Option<u8>,)>(&mut store, "to-option-u8")?;
2348     assert_eq!(to_option_u8.call(&mut store, (0x00_00, 0))?, (None,));
2349     to_option_u8.post_return(&mut store)?;
2350     assert_eq!(to_option_u8.call(&mut store, (0x00_01, 0))?, (Some(0),));
2351     to_option_u8.post_return(&mut store)?;
2352     assert_eq!(to_option_u8.call(&mut store, (0xfd_01, 0))?, (Some(0xfd),));
2353     to_option_u8.post_return(&mut store)?;
2354     assert!(to_option_u8.call(&mut store, (0x00_02, 0)).is_err());
2355 
2356     let instance = linker.instantiate(&mut store, &component)?;
2357     let to_option_u32 =
2358         instance.get_typed_func::<(u32, u32), (Option<u32>,)>(&mut store, "to-option-u32")?;
2359     assert_eq!(to_option_u32.call(&mut store, (0, 0))?, (None,));
2360     to_option_u32.post_return(&mut store)?;
2361     assert_eq!(to_option_u32.call(&mut store, (1, 0))?, (Some(0),));
2362     to_option_u32.post_return(&mut store)?;
2363     assert_eq!(
2364         to_option_u32.call(&mut store, (1, 0x1234fead))?,
2365         (Some(0x1234fead),)
2366     );
2367     to_option_u32.post_return(&mut store)?;
2368     assert!(to_option_u32.call(&mut store, (2, 0)).is_err());
2369 
2370     let instance = linker.instantiate(&mut store, &component)?;
2371     let to_option_string = instance
2372         .get_typed_func::<(u32, &str), (Option<WasmStr>,)>(&mut store, "to-option-string")?;
2373     let ret = to_option_string.call(&mut store, (0, ""))?.0;
2374     assert!(ret.is_none());
2375     to_option_string.post_return(&mut store)?;
2376     let ret = to_option_string.call(&mut store, (1, ""))?.0;
2377     assert_eq!(ret.unwrap().to_str(&store)?, "");
2378     to_option_string.post_return(&mut store)?;
2379     let ret = to_option_string.call(&mut store, (1, "cheesecake"))?.0;
2380     assert_eq!(ret.unwrap().to_str(&store)?, "cheesecake");
2381     to_option_string.post_return(&mut store)?;
2382     assert!(to_option_string.call(&mut store, (2, "")).is_err());
2383 
2384     Ok(())
2385 }
2386 
2387 #[test]
2388 fn expected() -> Result<()> {
2389     let component = format!(
2390         r#"(component
2391             (core module $m
2392                 (memory (export "memory") 1)
2393                 (func (export "pass0") (param i32) (result i32)
2394                     local.get 0
2395                 )
2396                 (func (export "pass1") (param i32 i32) (result i32)
2397                     (local $base i32)
2398                     (local.set $base
2399                         (call $realloc
2400                             (i32.const 0)
2401                             (i32.const 0)
2402                             (i32.const 4)
2403                             (i32.const 8)))
2404 
2405                     (i32.store offset=0
2406                         (local.get $base)
2407                         (local.get 0))
2408                     (i32.store offset=4
2409                         (local.get $base)
2410                         (local.get 1))
2411 
2412                     (local.get $base)
2413                 )
2414                 (func (export "pass2") (param i32 i32 i32) (result i32)
2415                     (local $base i32)
2416                     (local.set $base
2417                         (call $realloc
2418                             (i32.const 0)
2419                             (i32.const 0)
2420                             (i32.const 4)
2421                             (i32.const 12)))
2422 
2423                     (i32.store offset=0
2424                         (local.get $base)
2425                         (local.get 0))
2426                     (i32.store offset=4
2427                         (local.get $base)
2428                         (local.get 1))
2429                     (i32.store offset=8
2430                         (local.get $base)
2431                         (local.get 2))
2432 
2433                     (local.get $base)
2434                 )
2435 
2436                 {REALLOC_AND_FREE}
2437             )
2438             (core instance $i (instantiate $m))
2439 
2440             (func (export "take-expected-unit") (param "a" (result)) (result u32)
2441                 (canon lift (core func $i "pass0"))
2442             )
2443             (func (export "take-expected-u8-f32") (param "a" (result u8 (error float32))) (result (tuple u32 u32))
2444                 (canon lift (core func $i "pass1") (memory $i "memory"))
2445             )
2446             (type $list (list u8))
2447             (func (export "take-expected-string") (param "a" (result string (error $list))) (result (tuple u32 string))
2448                 (canon lift
2449                     (core func $i "pass2")
2450                     (memory $i "memory")
2451                     (realloc (func $i "realloc"))
2452                 )
2453             )
2454             (func (export "to-expected-unit") (param "a" u32) (result (result))
2455                 (canon lift (core func $i "pass0"))
2456             )
2457             (func (export "to-expected-s16-f32") (param "a" u32) (param "b" u32) (result (result s16 (error float32)))
2458                 (canon lift
2459                     (core func $i "pass1")
2460                     (memory $i "memory")
2461                     (realloc (func $i "realloc"))
2462                 )
2463             )
2464         )"#
2465     );
2466 
2467     let engine = super::engine();
2468     let component = Component::new(&engine, component)?;
2469     let mut store = Store::new(&engine, ());
2470     let linker = Linker::new(&engine);
2471     let instance = linker.instantiate(&mut store, &component)?;
2472     let take_expected_unit =
2473         instance.get_typed_func::<(Result<(), ()>,), (u32,)>(&mut store, "take-expected-unit")?;
2474     assert_eq!(take_expected_unit.call(&mut store, (Ok(()),))?, (0,));
2475     take_expected_unit.post_return(&mut store)?;
2476     assert_eq!(take_expected_unit.call(&mut store, (Err(()),))?, (1,));
2477     take_expected_unit.post_return(&mut store)?;
2478 
2479     let take_expected_u8_f32 = instance
2480         .get_typed_func::<(Result<u8, f32>,), ((u32, u32),)>(&mut store, "take-expected-u8-f32")?;
2481     assert_eq!(take_expected_u8_f32.call(&mut store, (Ok(1),))?, ((0, 1),));
2482     take_expected_u8_f32.post_return(&mut store)?;
2483     assert_eq!(
2484         take_expected_u8_f32.call(&mut store, (Err(2.0),))?,
2485         ((1, 2.0f32.to_bits()),)
2486     );
2487     take_expected_u8_f32.post_return(&mut store)?;
2488 
2489     let take_expected_string = instance
2490         .get_typed_func::<(Result<&str, &[u8]>,), ((u32, WasmStr),)>(
2491             &mut store,
2492             "take-expected-string",
2493         )?;
2494     let ((a, b),) = take_expected_string.call(&mut store, (Ok("hello"),))?;
2495     assert_eq!(a, 0);
2496     assert_eq!(b.to_str(&store)?, "hello");
2497     take_expected_string.post_return(&mut store)?;
2498     let ((a, b),) = take_expected_string.call(&mut store, (Err(b"goodbye"),))?;
2499     assert_eq!(a, 1);
2500     assert_eq!(b.to_str(&store)?, "goodbye");
2501     take_expected_string.post_return(&mut store)?;
2502 
2503     let instance = linker.instantiate(&mut store, &component)?;
2504     let to_expected_unit =
2505         instance.get_typed_func::<(u32,), (Result<(), ()>,)>(&mut store, "to-expected-unit")?;
2506     assert_eq!(to_expected_unit.call(&mut store, (0,))?, (Ok(()),));
2507     to_expected_unit.post_return(&mut store)?;
2508     assert_eq!(to_expected_unit.call(&mut store, (1,))?, (Err(()),));
2509     to_expected_unit.post_return(&mut store)?;
2510     let err = to_expected_unit.call(&mut store, (2,)).unwrap_err();
2511     assert!(err.to_string().contains("invalid expected"), "{}", err);
2512 
2513     let instance = linker.instantiate(&mut store, &component)?;
2514     let to_expected_s16_f32 = instance
2515         .get_typed_func::<(u32, u32), (Result<i16, f32>,)>(&mut store, "to-expected-s16-f32")?;
2516     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 0))?, (Ok(0),));
2517     to_expected_s16_f32.post_return(&mut store)?;
2518     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 100))?, (Ok(100),));
2519     to_expected_s16_f32.post_return(&mut store)?;
2520     assert_eq!(
2521         to_expected_s16_f32.call(&mut store, (1, 1.0f32.to_bits()))?,
2522         (Err(1.0),)
2523     );
2524     to_expected_s16_f32.post_return(&mut store)?;
2525     let ret = to_expected_s16_f32
2526         .call(&mut store, (1, CANON_32BIT_NAN | 1))?
2527         .0;
2528     assert_eq!(ret.unwrap_err().to_bits(), CANON_32BIT_NAN | 1);
2529     to_expected_s16_f32.post_return(&mut store)?;
2530     assert!(to_expected_s16_f32.call(&mut store, (2, 0)).is_err());
2531 
2532     Ok(())
2533 }
2534 
2535 #[test]
2536 fn fancy_list() -> Result<()> {
2537     let component = format!(
2538         r#"(component
2539             (core module $m
2540                 (memory (export "memory") 1)
2541                 (func (export "take") (param i32 i32) (result i32)
2542                     (local $base i32)
2543                     (local.set $base
2544                         (call $realloc
2545                             (i32.const 0)
2546                             (i32.const 0)
2547                             (i32.const 4)
2548                             (i32.const 16)))
2549 
2550                     (i32.store offset=0
2551                         (local.get $base)
2552                         (local.get 0))
2553                     (i32.store offset=4
2554                         (local.get $base)
2555                         (local.get 1))
2556                     (i32.store offset=8
2557                         (local.get $base)
2558                         (i32.const 0))
2559                     (i32.store offset=12
2560                         (local.get $base)
2561                         (i32.mul
2562                             (memory.size)
2563                             (i32.const 65536)))
2564 
2565                     (local.get $base)
2566                 )
2567 
2568                 {REALLOC_AND_FREE}
2569             )
2570             (core instance $i (instantiate $m))
2571 
2572             (type $a (option u8))
2573             (type $b (result (error string)))
2574             (type $input (list (tuple $a $b)))
2575             (func (export "take")
2576                 (param "a" $input)
2577                 (result (tuple u32 u32 (list u8)))
2578                 (canon lift
2579                     (core func $i "take")
2580                     (memory $i "memory")
2581                     (realloc (func $i "realloc"))
2582                 )
2583             )
2584         )"#
2585     );
2586 
2587     let engine = super::engine();
2588     let component = Component::new(&engine, component)?;
2589     let mut store = Store::new(&engine, ());
2590     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
2591 
2592     let func = instance
2593         .get_typed_func::<(&[(Option<u8>, Result<(), &str>)],), ((u32, u32, WasmList<u8>),)>(
2594             &mut store, "take",
2595         )?;
2596 
2597     let input = [
2598         (None, Ok(())),
2599         (Some(2), Err("hello there")),
2600         (Some(200), Err("general kenobi")),
2601     ];
2602     let ((ptr, len, list),) = func.call(&mut store, (&input,))?;
2603     let memory = list.as_le_slice(&store);
2604     let ptr = usize::try_from(ptr).unwrap();
2605     let len = usize::try_from(len).unwrap();
2606     let mut array = &memory[ptr..][..len * 16];
2607 
2608     for (a, b) in input.iter() {
2609         match a {
2610             Some(val) => {
2611                 assert_eq!(*array.take_n::<2>(), [1, *val]);
2612             }
2613             None => {
2614                 assert_eq!(*array.take_n::<1>(), [0]);
2615                 array.skip::<1>();
2616             }
2617         }
2618         array.skip::<2>();
2619         match b {
2620             Ok(()) => {
2621                 assert_eq!(*array.take_n::<1>(), [0]);
2622                 array.skip::<11>();
2623             }
2624             Err(s) => {
2625                 assert_eq!(*array.take_n::<1>(), [1]);
2626                 array.skip::<3>();
2627                 assert_eq!(array.ptr_len(memory, 1), s.as_bytes());
2628             }
2629         }
2630     }
2631     assert!(array.is_empty());
2632 
2633     Ok(())
2634 }
2635 
2636 trait SliceExt<'a> {
2637     fn take_n<const N: usize>(&mut self) -> &'a [u8; N];
2638 
2639     fn skip<const N: usize>(&mut self) {
2640         self.take_n::<N>();
2641     }
2642 
2643     fn ptr_len<'b>(&mut self, all_memory: &'b [u8], size: usize) -> &'b [u8] {
2644         let ptr = u32::from_le_bytes(*self.take_n::<4>());
2645         let len = u32::from_le_bytes(*self.take_n::<4>());
2646         let ptr = usize::try_from(ptr).unwrap();
2647         let len = usize::try_from(len).unwrap();
2648         &all_memory[ptr..][..len * size]
2649     }
2650 }
2651 
2652 impl<'a> SliceExt<'a> for &'a [u8] {
2653     fn take_n<const N: usize>(&mut self) -> &'a [u8; N] {
2654         let (a, b) = self.split_at(N);
2655         *self = b;
2656         a.try_into().unwrap()
2657     }
2658 }
2659 
2660 #[test]
2661 fn invalid_alignment() -> Result<()> {
2662     let component = format!(
2663         r#"(component
2664             (core module $m
2665                 (memory (export "memory") 1)
2666                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
2667                     i32.const 1)
2668 
2669                 (func (export "take-i32") (param i32))
2670                 (func (export "ret-1") (result i32) i32.const 1)
2671                 (func (export "ret-unaligned-list") (result i32)
2672                     (i32.store offset=0 (i32.const 8) (i32.const 1))
2673                     (i32.store offset=4 (i32.const 8) (i32.const 1))
2674                     i32.const 8)
2675             )
2676             (core instance $i (instantiate $m))
2677 
2678             (func (export "many-params")
2679                 (param "s1" string) (param "s2" string) (param "s3" string) (param "s4" string)
2680                 (param "s5" string) (param "s6" string) (param "s7" string) (param "s8" string)
2681                 (param "s9" string) (param "s10" string) (param "s11" string) (param "s12" string)
2682                 (canon lift
2683                     (core func $i "take-i32")
2684                     (memory $i "memory")
2685                     (realloc (func $i "realloc"))
2686                 )
2687             )
2688             (func (export "string-ret") (result string)
2689                 (canon lift
2690                     (core func $i "ret-1")
2691                     (memory $i "memory")
2692                     (realloc (func $i "realloc"))
2693                 )
2694             )
2695             (func (export "list-u32-ret") (result (list u32))
2696                 (canon lift
2697                     (core func $i "ret-unaligned-list")
2698                     (memory $i "memory")
2699                     (realloc (func $i "realloc"))
2700                 )
2701             )
2702         )"#
2703     );
2704 
2705     let engine = super::engine();
2706     let component = Component::new(&engine, component)?;
2707     let mut store = Store::new(&engine, ());
2708     let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
2709 
2710     let err = instance(&mut store)?
2711         .get_typed_func::<(
2712             &str,
2713             &str,
2714             &str,
2715             &str,
2716             &str,
2717             &str,
2718             &str,
2719             &str,
2720             &str,
2721             &str,
2722             &str,
2723             &str,
2724         ), ()>(&mut store, "many-params")?
2725         .call(&mut store, ("", "", "", "", "", "", "", "", "", "", "", ""))
2726         .unwrap_err();
2727     assert!(
2728         err.to_string()
2729             .contains("realloc return: result not aligned"),
2730         "{}",
2731         err
2732     );
2733 
2734     let err = instance(&mut store)?
2735         .get_typed_func::<(), (WasmStr,)>(&mut store, "string-ret")?
2736         .call(&mut store, ())
2737         .err()
2738         .unwrap();
2739     assert!(
2740         err.to_string().contains("return pointer not aligned"),
2741         "{}",
2742         err
2743     );
2744 
2745     let err = instance(&mut store)?
2746         .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32-ret")?
2747         .call(&mut store, ())
2748         .err()
2749         .unwrap();
2750     assert!(
2751         err.to_string().contains("list pointer is not aligned"),
2752         "{}",
2753         err
2754     );
2755 
2756     Ok(())
2757 }
2758 
2759 #[test]
2760 fn drop_component_still_works() -> Result<()> {
2761     let component = r#"
2762         (component
2763             (import "f" (func $f))
2764 
2765             (core func $f_lower
2766                 (canon lower (func $f))
2767             )
2768             (core module $m
2769                 (import "" "" (func $f))
2770 
2771                 (func $f2
2772                     call $f
2773                     call $f
2774                 )
2775 
2776                 (export "f" (func $f2))
2777             )
2778             (core instance $i (instantiate $m
2779                 (with "" (instance
2780                     (export "" (func $f_lower))
2781                 ))
2782             ))
2783             (func (export "g")
2784                 (canon lift
2785                     (core func $i "f")
2786                 )
2787             )
2788         )
2789     "#;
2790 
2791     let (mut store, instance) = {
2792         let engine = super::engine();
2793         let component = Component::new(&engine, component)?;
2794         let mut store = Store::new(&engine, 0);
2795         let mut linker = Linker::new(&engine);
2796         linker.root().func_wrap(
2797             "f",
2798             |mut store: StoreContextMut<'_, u32>, _: ()| -> Result<()> {
2799                 *store.data_mut() += 1;
2800                 Ok(())
2801             },
2802         )?;
2803         let instance = linker.instantiate(&mut store, &component)?;
2804         (store, instance)
2805     };
2806 
2807     let f = instance.get_typed_func::<(), ()>(&mut store, "g")?;
2808     assert_eq!(*store.data(), 0);
2809     f.call(&mut store, ())?;
2810     assert_eq!(*store.data(), 2);
2811 
2812     Ok(())
2813 }
2814 
2815 #[test]
2816 fn raw_slice_of_various_types() -> Result<()> {
2817     let component = r#"
2818         (component
2819             (core module $m
2820                 (memory (export "memory") 1)
2821 
2822                 (func (export "list8") (result i32)
2823                     (call $setup_list (i32.const 16))
2824                 )
2825                 (func (export "list16") (result i32)
2826                     (call $setup_list (i32.const 8))
2827                 )
2828                 (func (export "list32") (result i32)
2829                     (call $setup_list (i32.const 4))
2830                 )
2831                 (func (export "list64") (result i32)
2832                     (call $setup_list (i32.const 2))
2833                 )
2834 
2835                 (func $setup_list (param i32) (result i32)
2836                     (i32.store offset=0 (i32.const 100) (i32.const 8))
2837                     (i32.store offset=4 (i32.const 100) (local.get 0))
2838                     i32.const 100
2839                 )
2840 
2841                 (data (i32.const 8) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f")
2842             )
2843             (core instance $i (instantiate $m))
2844             (func (export "list-u8") (result (list u8))
2845                 (canon lift (core func $i "list8") (memory $i "memory"))
2846             )
2847             (func (export "list-i8") (result (list s8))
2848                 (canon lift (core func $i "list8") (memory $i "memory"))
2849             )
2850             (func (export "list-u16") (result (list u16))
2851                 (canon lift (core func $i "list16") (memory $i "memory"))
2852             )
2853             (func (export "list-i16") (result (list s16))
2854                 (canon lift (core func $i "list16") (memory $i "memory"))
2855             )
2856             (func (export "list-u32") (result (list u32))
2857                 (canon lift (core func $i "list32") (memory $i "memory"))
2858             )
2859             (func (export "list-i32") (result (list s32))
2860                 (canon lift (core func $i "list32") (memory $i "memory"))
2861             )
2862             (func (export "list-u64") (result (list u64))
2863                 (canon lift (core func $i "list64") (memory $i "memory"))
2864             )
2865             (func (export "list-i64") (result (list s64))
2866                 (canon lift (core func $i "list64") (memory $i "memory"))
2867             )
2868         )
2869     "#;
2870 
2871     let (mut store, instance) = {
2872         let engine = super::engine();
2873         let component = Component::new(&engine, component)?;
2874         let mut store = Store::new(&engine, ());
2875         let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
2876         (store, instance)
2877     };
2878 
2879     let list = instance
2880         .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "list-u8")?
2881         .call_and_post_return(&mut store, ())?
2882         .0;
2883     assert_eq!(
2884         list.as_le_slice(&store),
2885         [
2886             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2887             0x0e, 0x0f,
2888         ]
2889     );
2890     let list = instance
2891         .get_typed_func::<(), (WasmList<i8>,)>(&mut store, "list-i8")?
2892         .call_and_post_return(&mut store, ())?
2893         .0;
2894     assert_eq!(
2895         list.as_le_slice(&store),
2896         [
2897             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2898             0x0e, 0x0f,
2899         ]
2900     );
2901 
2902     let list = instance
2903         .get_typed_func::<(), (WasmList<u16>,)>(&mut store, "list-u16")?
2904         .call_and_post_return(&mut store, ())?
2905         .0;
2906     assert_eq!(
2907         list.as_le_slice(&store),
2908         [
2909             u16::to_le(0x01_00),
2910             u16::to_le(0x03_02),
2911             u16::to_le(0x05_04),
2912             u16::to_le(0x07_06),
2913             u16::to_le(0x09_08),
2914             u16::to_le(0x0b_0a),
2915             u16::to_le(0x0d_0c),
2916             u16::to_le(0x0f_0e),
2917         ]
2918     );
2919     let list = instance
2920         .get_typed_func::<(), (WasmList<i16>,)>(&mut store, "list-i16")?
2921         .call_and_post_return(&mut store, ())?
2922         .0;
2923     assert_eq!(
2924         list.as_le_slice(&store),
2925         [
2926             i16::to_le(0x01_00),
2927             i16::to_le(0x03_02),
2928             i16::to_le(0x05_04),
2929             i16::to_le(0x07_06),
2930             i16::to_le(0x09_08),
2931             i16::to_le(0x0b_0a),
2932             i16::to_le(0x0d_0c),
2933             i16::to_le(0x0f_0e),
2934         ]
2935     );
2936     let list = instance
2937         .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32")?
2938         .call_and_post_return(&mut store, ())?
2939         .0;
2940     assert_eq!(
2941         list.as_le_slice(&store),
2942         [
2943             u32::to_le(0x03_02_01_00),
2944             u32::to_le(0x07_06_05_04),
2945             u32::to_le(0x0b_0a_09_08),
2946             u32::to_le(0x0f_0e_0d_0c),
2947         ]
2948     );
2949     let list = instance
2950         .get_typed_func::<(), (WasmList<i32>,)>(&mut store, "list-i32")?
2951         .call_and_post_return(&mut store, ())?
2952         .0;
2953     assert_eq!(
2954         list.as_le_slice(&store),
2955         [
2956             i32::to_le(0x03_02_01_00),
2957             i32::to_le(0x07_06_05_04),
2958             i32::to_le(0x0b_0a_09_08),
2959             i32::to_le(0x0f_0e_0d_0c),
2960         ]
2961     );
2962     let list = instance
2963         .get_typed_func::<(), (WasmList<u64>,)>(&mut store, "list-u64")?
2964         .call_and_post_return(&mut store, ())?
2965         .0;
2966     assert_eq!(
2967         list.as_le_slice(&store),
2968         [
2969             u64::to_le(0x07_06_05_04_03_02_01_00),
2970             u64::to_le(0x0f_0e_0d_0c_0b_0a_09_08),
2971         ]
2972     );
2973     let list = instance
2974         .get_typed_func::<(), (WasmList<i64>,)>(&mut store, "list-i64")?
2975         .call_and_post_return(&mut store, ())?
2976         .0;
2977     assert_eq!(
2978         list.as_le_slice(&store),
2979         [
2980             i64::to_le(0x07_06_05_04_03_02_01_00),
2981             i64::to_le(0x0f_0e_0d_0c_0b_0a_09_08),
2982         ]
2983     );
2984 
2985     Ok(())
2986 }
2987 
2988 #[test]
2989 fn lower_then_lift() -> Result<()> {
2990     // First test simple integers when the import/export ABI happen to line up
2991     let component = r#"
2992 (component $c
2993   (import "f" (func $f (result u32)))
2994 
2995   (core func $f_lower
2996     (canon lower (func $f))
2997   )
2998   (func $f2 (result s32)
2999     (canon lift (core func $f_lower))
3000   )
3001   (export "f2" (func $f2))
3002 )
3003     "#;
3004 
3005     let engine = super::engine();
3006     let component = Component::new(&engine, component)?;
3007     let mut store = Store::new(&engine, ());
3008     let mut linker = Linker::new(&engine);
3009     linker.root().func_wrap("f", |_, _: ()| Ok((2u32,)))?;
3010     let instance = linker.instantiate(&mut store, &component)?;
3011 
3012     let f = instance.get_typed_func::<(), (i32,)>(&mut store, "f2")?;
3013     assert_eq!(f.call(&mut store, ())?, (2,));
3014 
3015     // First test strings when the import/export ABI happen to line up
3016     let component = format!(
3017         r#"
3018 (component $c
3019   (import "s" (func $f (param "a" string)))
3020 
3021   (core module $libc
3022     (memory (export "memory") 1)
3023     {REALLOC_AND_FREE}
3024   )
3025   (core instance $libc (instantiate $libc))
3026 
3027   (core func $f_lower
3028     (canon lower (func $f) (memory $libc "memory"))
3029   )
3030   (func $f2 (param "a" string)
3031     (canon lift (core func $f_lower)
3032         (memory $libc "memory")
3033         (realloc (func $libc "realloc"))
3034     )
3035   )
3036   (export "f" (func $f2))
3037 )
3038     "#
3039     );
3040 
3041     let component = Component::new(&engine, component)?;
3042     let mut store = Store::new(&engine, ());
3043     linker
3044         .root()
3045         .func_wrap("s", |store: StoreContextMut<'_, ()>, (x,): (WasmStr,)| {
3046             assert_eq!(x.to_str(&store)?, "hello");
3047             Ok(())
3048         })?;
3049     let instance = linker.instantiate(&mut store, &component)?;
3050 
3051     let f = instance.get_typed_func::<(&str,), ()>(&mut store, "f")?;
3052     f.call(&mut store, ("hello",))?;
3053 
3054     // Next test "type punning" where return values are reinterpreted just
3055     // because the return ABI happens to line up.
3056     let component = format!(
3057         r#"
3058 (component $c
3059   (import "s2" (func $f (param "a" string) (result u32)))
3060 
3061   (core module $libc
3062     (memory (export "memory") 1)
3063     {REALLOC_AND_FREE}
3064   )
3065   (core instance $libc (instantiate $libc))
3066 
3067   (core func $f_lower
3068     (canon lower (func $f) (memory $libc "memory"))
3069   )
3070   (func $f2 (param "a" string) (result string)
3071     (canon lift (core func $f_lower)
3072         (memory $libc "memory")
3073         (realloc (func $libc "realloc"))
3074     )
3075   )
3076   (export "f" (func $f2))
3077 )
3078     "#
3079     );
3080 
3081     let component = Component::new(&engine, component)?;
3082     let mut store = Store::new(&engine, ());
3083     linker
3084         .root()
3085         .func_wrap("s2", |store: StoreContextMut<'_, ()>, (x,): (WasmStr,)| {
3086             assert_eq!(x.to_str(&store)?, "hello");
3087             Ok((u32::MAX,))
3088         })?;
3089     let instance = linker.instantiate(&mut store, &component)?;
3090 
3091     let f = instance.get_typed_func::<(&str,), (WasmStr,)>(&mut store, "f")?;
3092     let err = f.call(&mut store, ("hello",)).err().unwrap();
3093     assert!(
3094         err.to_string().contains("return pointer not aligned"),
3095         "{}",
3096         err
3097     );
3098 
3099     Ok(())
3100 }
3101 
3102 #[test]
3103 fn errors_that_poison_instance() -> Result<()> {
3104     let component = format!(
3105         r#"
3106 (component $c
3107   (core module $m1
3108     (func (export "f1") unreachable)
3109     (func (export "f2"))
3110   )
3111   (core instance $m1 (instantiate $m1))
3112   (func (export "f1") (canon lift (core func $m1 "f1")))
3113   (func (export "f2") (canon lift (core func $m1 "f2")))
3114 
3115   (core module $m2
3116     (func (export "f") (param i32 i32))
3117     (func (export "r") (param i32 i32 i32 i32) (result i32) unreachable)
3118     (memory (export "m") 1)
3119   )
3120   (core instance $m2 (instantiate $m2))
3121   (func (export "f3") (param "a" string)
3122     (canon lift (core func $m2 "f") (realloc (func $m2 "r")) (memory $m2 "m"))
3123   )
3124 
3125   (core module $m3
3126     (func (export "f") (result i32) i32.const 1)
3127     (memory (export "m") 1)
3128   )
3129   (core instance $m3 (instantiate $m3))
3130   (func (export "f4") (result string)
3131     (canon lift (core func $m3 "f") (memory $m3 "m"))
3132   )
3133 )
3134     "#
3135     );
3136 
3137     let engine = super::engine();
3138     let component = Component::new(&engine, component)?;
3139     let mut store = Store::new(&engine, ());
3140     let linker = Linker::new(&engine);
3141     let instance = linker.instantiate(&mut store, &component)?;
3142     let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?;
3143     let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?;
3144     assert_unreachable(f1.call(&mut store, ()));
3145     assert_poisoned(f1.call(&mut store, ()));
3146     assert_poisoned(f2.call(&mut store, ()));
3147 
3148     let instance = linker.instantiate(&mut store, &component)?;
3149     let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?;
3150     assert_unreachable(f3.call(&mut store, ("x",)));
3151     assert_poisoned(f3.call(&mut store, ("x",)));
3152 
3153     let instance = linker.instantiate(&mut store, &component)?;
3154     let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?;
3155     assert!(f4.call(&mut store, ()).is_err());
3156     assert_poisoned(f4.call(&mut store, ()));
3157 
3158     return Ok(());
3159 
3160     #[track_caller]
3161     fn assert_unreachable<T>(err: Result<T>) {
3162         let err = match err {
3163             Ok(_) => panic!("expected an error"),
3164             Err(e) => e,
3165         };
3166         assert_eq!(
3167             err.downcast::<Trap>().unwrap(),
3168             Trap::UnreachableCodeReached
3169         );
3170     }
3171 
3172     #[track_caller]
3173     fn assert_poisoned<T>(err: Result<T>) {
3174         let err = match err {
3175             Ok(_) => panic!("expected an error"),
3176             Err(e) => e,
3177         };
3178         assert_eq!(
3179             err.downcast_ref::<Trap>(),
3180             Some(&Trap::CannotEnterComponent),
3181             "{err}",
3182         );
3183     }
3184 }
3185 
3186 #[test]
3187 fn run_export_with_internal_adapter() -> Result<()> {
3188     let component = r#"
3189 (component
3190   (type $t (func (param "a" u32) (result u32)))
3191   (component $a
3192     (core module $m
3193       (func (export "add-five") (param i32) (result i32)
3194         local.get 0
3195         i32.const 5
3196         i32.add)
3197     )
3198     (core instance $m (instantiate $m))
3199     (func (export "add-five") (type $t) (canon lift (core func $m "add-five")))
3200   )
3201   (component $b
3202     (import "interface-v1" (instance $i
3203       (export "add-five" (func (type $t)))))
3204     (core module $m
3205       (func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32))
3206       (func) ;; causes index out of bounds
3207       (func (export "run") (result i32) i32.const 0 call $add-five)
3208     )
3209     (core func $add-five (canon lower (func $i "add-five")))
3210     (core instance $i (instantiate 0
3211       (with "interface-0.1.0" (instance
3212         (export "add-five" (func $add-five))
3213       ))
3214     ))
3215     (func (result u32) (canon lift (core func $i "run")))
3216     (export "run" (func 1))
3217   )
3218   (instance $a (instantiate $a))
3219   (instance $b (instantiate $b (with "interface-v1" (instance $a))))
3220   (export "run" (func $b "run"))
3221 )
3222 "#;
3223     let engine = super::engine();
3224     let component = Component::new(&engine, component)?;
3225     let mut store = Store::new(&engine, ());
3226     let linker = Linker::new(&engine);
3227     let instance = linker.instantiate(&mut store, &component)?;
3228     let run = instance.get_typed_func::<(), (u32,)>(&mut store, "run")?;
3229     assert_eq!(run.call(&mut store, ())?, (5,));
3230     Ok(())
3231 }
3232