1 #![cfg(not(miri))]
2 
3 use super::{TypedFuncExt, REALLOC_AND_FREE};
4 use anyhow::Result;
5 use std::rc::Rc;
6 use std::sync::Arc;
7 use wasmtime::component::*;
8 use wasmtime::{Engine, Store, StoreContextMut, Trap};
9 
10 const CANON_32BIT_NAN: u32 = 0b01111111110000000000000000000000;
11 const CANON_64BIT_NAN: u64 = 0b0111111111111000000000000000000000000000000000000000000000000000;
12 
13 #[test]
14 fn thunks() -> Result<()> {
15     let component = r#"
16         (component
17             (core module $m
18                 (func (export "thunk"))
19                 (func (export "thunk-trap") unreachable)
20             )
21             (core instance $i (instantiate $m))
22             (func (export "thunk")
23                 (canon lift (core func $i "thunk"))
24             )
25             (func (export "thunk-trap")
26                 (canon lift (core func $i "thunk-trap"))
27             )
28         )
29     "#;
30 
31     let engine = super::engine();
32     let component = Component::new(&engine, component)?;
33     let mut store = Store::new(&engine, ());
34     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
35     instance
36         .get_typed_func::<(), ()>(&mut store, "thunk")?
37         .call_and_post_return(&mut store, ())?;
38     let err = instance
39         .get_typed_func::<(), ()>(&mut store, "thunk-trap")?
40         .call(&mut store, ())
41         .unwrap_err();
42     assert_eq!(err.downcast::<Trap>()?, Trap::UnreachableCodeReached);
43 
44     Ok(())
45 }
46 
47 #[test]
48 fn typecheck() -> Result<()> {
49     let component = r#"
50         (component
51             (core module $m
52                 (func (export "thunk"))
53                 (func (export "take-string") (param i32 i32))
54                 (func (export "two-args") (param i32 i32 i32))
55                 (func (export "ret-one") (result i32) unreachable)
56 
57                 (memory (export "memory") 1)
58                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
59                     unreachable)
60             )
61             (core instance $i (instantiate (module $m)))
62             (func (export "thunk")
63                 (canon lift (core func $i "thunk"))
64             )
65             (func (export "take-string") (param "a" string)
66                 (canon lift (core func $i "take-string") (memory $i "memory") (realloc (func $i "realloc")))
67             )
68             (func (export "take-two-args") (param "a" s32) (param "b" (list u8))
69                 (canon lift (core func $i "two-args") (memory $i "memory") (realloc (func $i "realloc")))
70             )
71             (func (export "ret-tuple") (result (tuple u8 s8))
72                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
73             )
74             (func (export "ret-tuple1") (result (tuple u32))
75                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
76             )
77             (func (export "ret-string") (result string)
78                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
79             )
80             (func (export "ret-list-u8") (result (list u8))
81                 (canon lift (core func $i "ret-one") (memory $i "memory") (realloc (func $i "realloc")))
82             )
83         )
84     "#;
85 
86     let engine = Engine::default();
87     let component = Component::new(&engine, component)?;
88     let mut store = Store::new(&engine, ());
89     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
90     let thunk = instance.get_func(&mut store, "thunk").unwrap();
91     let take_string = instance.get_func(&mut store, "take-string").unwrap();
92     let take_two_args = instance.get_func(&mut store, "take-two-args").unwrap();
93     let ret_tuple = instance.get_func(&mut store, "ret-tuple").unwrap();
94     let ret_tuple1 = instance.get_func(&mut store, "ret-tuple1").unwrap();
95     let ret_string = instance.get_func(&mut store, "ret-string").unwrap();
96     let ret_list_u8 = instance.get_func(&mut store, "ret-list-u8").unwrap();
97     assert!(thunk.typed::<(), (u32,)>(&store).is_err());
98     assert!(thunk.typed::<(u32,), ()>(&store).is_err());
99     assert!(thunk.typed::<(), ()>(&store).is_ok());
100     assert!(take_string.typed::<(), ()>(&store).is_err());
101     assert!(take_string.typed::<(String,), ()>(&store).is_ok());
102     assert!(take_string.typed::<(&str,), ()>(&store).is_ok());
103     assert!(take_string.typed::<(&[u8],), ()>(&store).is_err());
104     assert!(take_two_args.typed::<(), ()>(&store).is_err());
105     assert!(take_two_args.typed::<(i32, &[u8]), (u32,)>(&store).is_err());
106     assert!(take_two_args.typed::<(u32, &[u8]), ()>(&store).is_err());
107     assert!(take_two_args.typed::<(i32, &[u8]), ()>(&store).is_ok());
108     assert!(ret_tuple.typed::<(), ()>(&store).is_err());
109     assert!(ret_tuple.typed::<(), (u8,)>(&store).is_err());
110     assert!(ret_tuple.typed::<(), ((u8, i8),)>(&store).is_ok());
111     assert!(ret_tuple1.typed::<(), ((u32,),)>(&store).is_ok());
112     assert!(ret_tuple1.typed::<(), (u32,)>(&store).is_err());
113     assert!(ret_string.typed::<(), ()>(&store).is_err());
114     assert!(ret_string.typed::<(), (WasmStr,)>(&store).is_ok());
115     assert!(ret_list_u8.typed::<(), (WasmList<u16>,)>(&store).is_err());
116     assert!(ret_list_u8.typed::<(), (WasmList<i8>,)>(&store).is_err());
117     assert!(ret_list_u8.typed::<(), (WasmList<u8>,)>(&store).is_ok());
118 
119     Ok(())
120 }
121 
122 #[test]
123 fn integers() -> Result<()> {
124     let component = r#"
125         (component
126             (core module $m
127                 (func (export "take-i32-100") (param i32)
128                     local.get 0
129                     i32.const 100
130                     i32.eq
131                     br_if 0
132                     unreachable
133                 )
134                 (func (export "take-i64-100") (param i64)
135                     local.get 0
136                     i64.const 100
137                     i64.eq
138                     br_if 0
139                     unreachable
140                 )
141                 (func (export "ret-i32-0") (result i32) i32.const 0)
142                 (func (export "ret-i64-0") (result i64) i64.const 0)
143                 (func (export "ret-i32-minus-1") (result i32) i32.const -1)
144                 (func (export "ret-i64-minus-1") (result i64) i64.const -1)
145                 (func (export "ret-i32-100000") (result i32) i32.const 100000)
146             )
147             (core instance $i (instantiate (module $m)))
148             (func (export "take-u8") (param "a" u8) (canon lift (core func $i "take-i32-100")))
149             (func (export "take-s8") (param "a" s8) (canon lift (core func $i "take-i32-100")))
150             (func (export "take-u16") (param "a" u16) (canon lift (core func $i "take-i32-100")))
151             (func (export "take-s16") (param "a" s16) (canon lift (core func $i "take-i32-100")))
152             (func (export "take-u32") (param "a" u32) (canon lift (core func $i "take-i32-100")))
153             (func (export "take-s32") (param "a" s32) (canon lift (core func $i "take-i32-100")))
154             (func (export "take-u64") (param "a" u64) (canon lift (core func $i "take-i64-100")))
155             (func (export "take-s64") (param "a" s64) (canon lift (core func $i "take-i64-100")))
156 
157             (func (export "ret-u8") (result u8) (canon lift (core func $i "ret-i32-0")))
158             (func (export "ret-s8") (result s8) (canon lift (core func $i "ret-i32-0")))
159             (func (export "ret-u16") (result u16) (canon lift (core func $i "ret-i32-0")))
160             (func (export "ret-s16") (result s16) (canon lift (core func $i "ret-i32-0")))
161             (func (export "ret-u32") (result u32) (canon lift (core func $i "ret-i32-0")))
162             (func (export "ret-s32") (result s32) (canon lift (core func $i "ret-i32-0")))
163             (func (export "ret-u64") (result u64) (canon lift (core func $i "ret-i64-0")))
164             (func (export "ret-s64") (result s64) (canon lift (core func $i "ret-i64-0")))
165 
166             (func (export "retm1-u8") (result u8) (canon lift (core func $i "ret-i32-minus-1")))
167             (func (export "retm1-s8") (result s8) (canon lift (core func $i "ret-i32-minus-1")))
168             (func (export "retm1-u16") (result u16) (canon lift (core func $i "ret-i32-minus-1")))
169             (func (export "retm1-s16") (result s16) (canon lift (core func $i "ret-i32-minus-1")))
170             (func (export "retm1-u32") (result u32) (canon lift (core func $i "ret-i32-minus-1")))
171             (func (export "retm1-s32") (result s32) (canon lift (core func $i "ret-i32-minus-1")))
172             (func (export "retm1-u64") (result u64) (canon lift (core func $i "ret-i64-minus-1")))
173             (func (export "retm1-s64") (result s64) (canon lift (core func $i "ret-i64-minus-1")))
174 
175             (func (export "retbig-u8") (result u8) (canon lift (core func $i "ret-i32-100000")))
176             (func (export "retbig-s8") (result s8) (canon lift (core func $i "ret-i32-100000")))
177             (func (export "retbig-u16") (result u16) (canon lift (core func $i "ret-i32-100000")))
178             (func (export "retbig-s16") (result s16) (canon lift (core func $i "ret-i32-100000")))
179             (func (export "retbig-u32") (result u32) (canon lift (core func $i "ret-i32-100000")))
180             (func (export "retbig-s32") (result s32) (canon lift (core func $i "ret-i32-100000")))
181         )
182     "#;
183 
184     let engine = super::engine();
185     let component = Component::new(&engine, component)?;
186     let mut store = Store::new(&engine, ());
187     let new_instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
188     let instance = new_instance(&mut store)?;
189 
190     // Passing in 100 is valid for all primitives
191     instance
192         .get_typed_func::<(u8,), ()>(&mut store, "take-u8")?
193         .call_and_post_return(&mut store, (100,))?;
194     instance
195         .get_typed_func::<(i8,), ()>(&mut store, "take-s8")?
196         .call_and_post_return(&mut store, (100,))?;
197     instance
198         .get_typed_func::<(u16,), ()>(&mut store, "take-u16")?
199         .call_and_post_return(&mut store, (100,))?;
200     instance
201         .get_typed_func::<(i16,), ()>(&mut store, "take-s16")?
202         .call_and_post_return(&mut store, (100,))?;
203     instance
204         .get_typed_func::<(u32,), ()>(&mut store, "take-u32")?
205         .call_and_post_return(&mut store, (100,))?;
206     instance
207         .get_typed_func::<(i32,), ()>(&mut store, "take-s32")?
208         .call_and_post_return(&mut store, (100,))?;
209     instance
210         .get_typed_func::<(u64,), ()>(&mut store, "take-u64")?
211         .call_and_post_return(&mut store, (100,))?;
212     instance
213         .get_typed_func::<(i64,), ()>(&mut store, "take-s64")?
214         .call_and_post_return(&mut store, (100,))?;
215 
216     // This specific wasm instance traps if any value other than 100 is passed
217     new_instance(&mut store)?
218         .get_typed_func::<(u8,), ()>(&mut store, "take-u8")?
219         .call(&mut store, (101,))
220         .unwrap_err()
221         .downcast::<Trap>()?;
222     new_instance(&mut store)?
223         .get_typed_func::<(i8,), ()>(&mut store, "take-s8")?
224         .call(&mut store, (101,))
225         .unwrap_err()
226         .downcast::<Trap>()?;
227     new_instance(&mut store)?
228         .get_typed_func::<(u16,), ()>(&mut store, "take-u16")?
229         .call(&mut store, (101,))
230         .unwrap_err()
231         .downcast::<Trap>()?;
232     new_instance(&mut store)?
233         .get_typed_func::<(i16,), ()>(&mut store, "take-s16")?
234         .call(&mut store, (101,))
235         .unwrap_err()
236         .downcast::<Trap>()?;
237     new_instance(&mut store)?
238         .get_typed_func::<(u32,), ()>(&mut store, "take-u32")?
239         .call(&mut store, (101,))
240         .unwrap_err()
241         .downcast::<Trap>()?;
242     new_instance(&mut store)?
243         .get_typed_func::<(i32,), ()>(&mut store, "take-s32")?
244         .call(&mut store, (101,))
245         .unwrap_err()
246         .downcast::<Trap>()?;
247     new_instance(&mut store)?
248         .get_typed_func::<(u64,), ()>(&mut store, "take-u64")?
249         .call(&mut store, (101,))
250         .unwrap_err()
251         .downcast::<Trap>()?;
252     new_instance(&mut store)?
253         .get_typed_func::<(i64,), ()>(&mut store, "take-s64")?
254         .call(&mut store, (101,))
255         .unwrap_err()
256         .downcast::<Trap>()?;
257 
258     // Zero can be returned as any integer
259     assert_eq!(
260         instance
261             .get_typed_func::<(), (u8,)>(&mut store, "ret-u8")?
262             .call_and_post_return(&mut store, ())?,
263         (0,)
264     );
265     assert_eq!(
266         instance
267             .get_typed_func::<(), (i8,)>(&mut store, "ret-s8")?
268             .call_and_post_return(&mut store, ())?,
269         (0,)
270     );
271     assert_eq!(
272         instance
273             .get_typed_func::<(), (u16,)>(&mut store, "ret-u16")?
274             .call_and_post_return(&mut store, ())?,
275         (0,)
276     );
277     assert_eq!(
278         instance
279             .get_typed_func::<(), (i16,)>(&mut store, "ret-s16")?
280             .call_and_post_return(&mut store, ())?,
281         (0,)
282     );
283     assert_eq!(
284         instance
285             .get_typed_func::<(), (u32,)>(&mut store, "ret-u32")?
286             .call_and_post_return(&mut store, ())?,
287         (0,)
288     );
289     assert_eq!(
290         instance
291             .get_typed_func::<(), (i32,)>(&mut store, "ret-s32")?
292             .call_and_post_return(&mut store, ())?,
293         (0,)
294     );
295     assert_eq!(
296         instance
297             .get_typed_func::<(), (u64,)>(&mut store, "ret-u64")?
298             .call_and_post_return(&mut store, ())?,
299         (0,)
300     );
301     assert_eq!(
302         instance
303             .get_typed_func::<(), (i64,)>(&mut store, "ret-s64")?
304             .call_and_post_return(&mut store, ())?,
305         (0,)
306     );
307 
308     // Returning -1 should reinterpret the bytes as defined by each type.
309     assert_eq!(
310         instance
311             .get_typed_func::<(), (u8,)>(&mut store, "retm1-u8")?
312             .call_and_post_return(&mut store, ())?,
313         (0xff,)
314     );
315     assert_eq!(
316         instance
317             .get_typed_func::<(), (i8,)>(&mut store, "retm1-s8")?
318             .call_and_post_return(&mut store, ())?,
319         (-1,)
320     );
321     assert_eq!(
322         instance
323             .get_typed_func::<(), (u16,)>(&mut store, "retm1-u16")?
324             .call_and_post_return(&mut store, ())?,
325         (0xffff,)
326     );
327     assert_eq!(
328         instance
329             .get_typed_func::<(), (i16,)>(&mut store, "retm1-s16")?
330             .call_and_post_return(&mut store, ())?,
331         (-1,)
332     );
333     assert_eq!(
334         instance
335             .get_typed_func::<(), (u32,)>(&mut store, "retm1-u32")?
336             .call_and_post_return(&mut store, ())?,
337         (0xffffffff,)
338     );
339     assert_eq!(
340         instance
341             .get_typed_func::<(), (i32,)>(&mut store, "retm1-s32")?
342             .call_and_post_return(&mut store, ())?,
343         (-1,)
344     );
345     assert_eq!(
346         instance
347             .get_typed_func::<(), (u64,)>(&mut store, "retm1-u64")?
348             .call_and_post_return(&mut store, ())?,
349         (0xffffffff_ffffffff,)
350     );
351     assert_eq!(
352         instance
353             .get_typed_func::<(), (i64,)>(&mut store, "retm1-s64")?
354             .call_and_post_return(&mut store, ())?,
355         (-1,)
356     );
357 
358     // Returning 100000 should chop off bytes as necessary
359     let ret: u32 = 100000;
360     assert_eq!(
361         instance
362             .get_typed_func::<(), (u8,)>(&mut store, "retbig-u8")?
363             .call_and_post_return(&mut store, ())?,
364         (ret as u8,),
365     );
366     assert_eq!(
367         instance
368             .get_typed_func::<(), (i8,)>(&mut store, "retbig-s8")?
369             .call_and_post_return(&mut store, ())?,
370         (ret as i8,),
371     );
372     assert_eq!(
373         instance
374             .get_typed_func::<(), (u16,)>(&mut store, "retbig-u16")?
375             .call_and_post_return(&mut store, ())?,
376         (ret as u16,),
377     );
378     assert_eq!(
379         instance
380             .get_typed_func::<(), (i16,)>(&mut store, "retbig-s16")?
381             .call_and_post_return(&mut store, ())?,
382         (ret as i16,),
383     );
384     assert_eq!(
385         instance
386             .get_typed_func::<(), (u32,)>(&mut store, "retbig-u32")?
387             .call_and_post_return(&mut store, ())?,
388         (ret,),
389     );
390     assert_eq!(
391         instance
392             .get_typed_func::<(), (i32,)>(&mut store, "retbig-s32")?
393             .call_and_post_return(&mut store, ())?,
394         (ret as i32,),
395     );
396 
397     Ok(())
398 }
399 
400 #[test]
401 fn type_layers() -> Result<()> {
402     let component = r#"
403         (component
404             (core module $m
405                 (func (export "take-i32-100") (param i32)
406                     local.get 0
407                     i32.const 2
408                     i32.eq
409                     br_if 0
410                     unreachable
411                 )
412             )
413             (core instance $i (instantiate $m))
414             (func (export "take-u32") (param "a" u32) (canon lift (core func $i "take-i32-100")))
415         )
416     "#;
417 
418     let engine = super::engine();
419     let component = Component::new(&engine, component)?;
420     let mut store = Store::new(&engine, ());
421     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
422 
423     instance
424         .get_typed_func::<(Box<u32>,), ()>(&mut store, "take-u32")?
425         .call_and_post_return(&mut store, (Box::new(2),))?;
426     instance
427         .get_typed_func::<(&u32,), ()>(&mut store, "take-u32")?
428         .call_and_post_return(&mut store, (&2,))?;
429     instance
430         .get_typed_func::<(Rc<u32>,), ()>(&mut store, "take-u32")?
431         .call_and_post_return(&mut store, (Rc::new(2),))?;
432     instance
433         .get_typed_func::<(Arc<u32>,), ()>(&mut store, "take-u32")?
434         .call_and_post_return(&mut store, (Arc::new(2),))?;
435     instance
436         .get_typed_func::<(&Box<Arc<Rc<u32>>>,), ()>(&mut store, "take-u32")?
437         .call_and_post_return(&mut store, (&Box::new(Arc::new(Rc::new(2))),))?;
438 
439     Ok(())
440 }
441 
442 #[test]
443 fn floats() -> Result<()> {
444     let component = r#"
445         (component
446             (core module $m
447                 (func (export "i32.reinterpret_f32") (param f32) (result i32)
448                     local.get 0
449                     i32.reinterpret_f32
450                 )
451                 (func (export "i64.reinterpret_f64") (param f64) (result i64)
452                     local.get 0
453                     i64.reinterpret_f64
454                 )
455                 (func (export "f32.reinterpret_i32") (param i32) (result f32)
456                     local.get 0
457                     f32.reinterpret_i32
458                 )
459                 (func (export "f64.reinterpret_i64") (param i64) (result f64)
460                     local.get 0
461                     f64.reinterpret_i64
462                 )
463             )
464             (core instance $i (instantiate $m))
465 
466             (func (export "f32-to-u32") (param "a" float32) (result u32)
467                 (canon lift (core func $i "i32.reinterpret_f32"))
468             )
469             (func (export "f64-to-u64") (param "a" float64) (result u64)
470                 (canon lift (core func $i "i64.reinterpret_f64"))
471             )
472             (func (export "u32-to-f32") (param "a" u32) (result float32)
473                 (canon lift (core func $i "f32.reinterpret_i32"))
474             )
475             (func (export "u64-to-f64") (param "a" u64) (result float64)
476                 (canon lift (core func $i "f64.reinterpret_i64"))
477             )
478         )
479     "#;
480 
481     let engine = super::engine();
482     let component = Component::new(&engine, component)?;
483     let mut store = Store::new(&engine, ());
484     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
485     let f32_to_u32 = instance.get_typed_func::<(f32,), (u32,)>(&mut store, "f32-to-u32")?;
486     let f64_to_u64 = instance.get_typed_func::<(f64,), (u64,)>(&mut store, "f64-to-u64")?;
487     let u32_to_f32 = instance.get_typed_func::<(u32,), (f32,)>(&mut store, "u32-to-f32")?;
488     let u64_to_f64 = instance.get_typed_func::<(u64,), (f64,)>(&mut store, "u64-to-f64")?;
489 
490     assert_eq!(f32_to_u32.call(&mut store, (1.0,))?, (1.0f32.to_bits(),));
491     f32_to_u32.post_return(&mut store)?;
492     assert_eq!(f64_to_u64.call(&mut store, (2.0,))?, (2.0f64.to_bits(),));
493     f64_to_u64.post_return(&mut store)?;
494     assert_eq!(u32_to_f32.call(&mut store, (3.0f32.to_bits(),))?, (3.0,));
495     u32_to_f32.post_return(&mut store)?;
496     assert_eq!(u64_to_f64.call(&mut store, (4.0f64.to_bits(),))?, (4.0,));
497     u64_to_f64.post_return(&mut store)?;
498 
499     assert_eq!(
500         u32_to_f32
501             .call(&mut store, (CANON_32BIT_NAN | 1,))?
502             .0
503             .to_bits(),
504         CANON_32BIT_NAN | 1
505     );
506     u32_to_f32.post_return(&mut store)?;
507     assert_eq!(
508         u64_to_f64
509             .call(&mut store, (CANON_64BIT_NAN | 1,))?
510             .0
511             .to_bits(),
512         CANON_64BIT_NAN | 1,
513     );
514     u64_to_f64.post_return(&mut store)?;
515 
516     assert_eq!(
517         f32_to_u32.call(&mut store, (f32::from_bits(CANON_32BIT_NAN | 1),))?,
518         (CANON_32BIT_NAN | 1,)
519     );
520     f32_to_u32.post_return(&mut store)?;
521     assert_eq!(
522         f64_to_u64.call(&mut store, (f64::from_bits(CANON_64BIT_NAN | 1),))?,
523         (CANON_64BIT_NAN | 1,)
524     );
525     f64_to_u64.post_return(&mut store)?;
526 
527     Ok(())
528 }
529 
530 #[test]
531 fn bools() -> Result<()> {
532     let component = r#"
533         (component
534             (core module $m
535                 (func (export "pass") (param i32) (result i32) local.get 0)
536             )
537             (core instance $i (instantiate $m))
538 
539             (func (export "u32-to-bool") (param "a" u32) (result bool)
540                 (canon lift (core func $i "pass"))
541             )
542             (func (export "bool-to-u32") (param "a" bool) (result u32)
543                 (canon lift (core func $i "pass"))
544             )
545         )
546     "#;
547 
548     let engine = super::engine();
549     let component = Component::new(&engine, component)?;
550     let mut store = Store::new(&engine, ());
551     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
552     let u32_to_bool = instance.get_typed_func::<(u32,), (bool,)>(&mut store, "u32-to-bool")?;
553     let bool_to_u32 = instance.get_typed_func::<(bool,), (u32,)>(&mut store, "bool-to-u32")?;
554 
555     assert_eq!(bool_to_u32.call(&mut store, (false,))?, (0,));
556     bool_to_u32.post_return(&mut store)?;
557     assert_eq!(bool_to_u32.call(&mut store, (true,))?, (1,));
558     bool_to_u32.post_return(&mut store)?;
559     assert_eq!(u32_to_bool.call(&mut store, (0,))?, (false,));
560     u32_to_bool.post_return(&mut store)?;
561     assert_eq!(u32_to_bool.call(&mut store, (1,))?, (true,));
562     u32_to_bool.post_return(&mut store)?;
563     assert_eq!(u32_to_bool.call(&mut store, (2,))?, (true,));
564     u32_to_bool.post_return(&mut store)?;
565 
566     Ok(())
567 }
568 
569 #[test]
570 fn chars() -> Result<()> {
571     let component = r#"
572         (component
573             (core module $m
574                 (func (export "pass") (param i32) (result i32) local.get 0)
575             )
576             (core instance $i (instantiate $m))
577 
578             (func (export "u32-to-char") (param "a" u32) (result char)
579                 (canon lift (core func $i "pass"))
580             )
581             (func (export "char-to-u32") (param "a" char) (result u32)
582                 (canon lift (core func $i "pass"))
583             )
584         )
585     "#;
586 
587     let engine = super::engine();
588     let component = Component::new(&engine, component)?;
589     let mut store = Store::new(&engine, ());
590     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
591     let u32_to_char = instance.get_typed_func::<(u32,), (char,)>(&mut store, "u32-to-char")?;
592     let char_to_u32 = instance.get_typed_func::<(char,), (u32,)>(&mut store, "char-to-u32")?;
593 
594     let mut roundtrip = |x: char| -> Result<()> {
595         assert_eq!(char_to_u32.call(&mut store, (x,))?, (x as u32,));
596         char_to_u32.post_return(&mut store)?;
597         assert_eq!(u32_to_char.call(&mut store, (x as u32,))?, (x,));
598         u32_to_char.post_return(&mut store)?;
599         Ok(())
600     };
601 
602     roundtrip('x')?;
603     roundtrip('a')?;
604     roundtrip('\0')?;
605     roundtrip('\n')?;
606     roundtrip('��')?;
607 
608     let u32_to_char = |store: &mut Store<()>| {
609         Linker::new(&engine)
610             .instantiate(&mut *store, &component)?
611             .get_typed_func::<(u32,), (char,)>(&mut *store, "u32-to-char")
612     };
613     let err = u32_to_char(&mut store)?
614         .call(&mut store, (0xd800,))
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, (0xdfff,))
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, (0x110000,))
623         .unwrap_err();
624     assert!(err.to_string().contains("integer out of range"), "{}", err);
625     let err = u32_to_char(&mut store)?
626         .call(&mut store, (u32::MAX,))
627         .unwrap_err();
628     assert!(err.to_string().contains("integer out of range"), "{}", err);
629 
630     Ok(())
631 }
632 
633 #[test]
634 fn tuple_result() -> Result<()> {
635     let component = r#"
636         (component
637             (core module $m
638                 (memory (export "memory") 1)
639                 (func (export "foo") (param i32 i32 f32 f64) (result i32)
640                     (local $base i32)
641                     (local.set $base (i32.const 8))
642                     (i32.store8 offset=0 (local.get $base) (local.get 0))
643                     (i32.store16 offset=2 (local.get $base) (local.get 1))
644                     (f32.store offset=4 (local.get $base) (local.get 2))
645                     (f64.store offset=8 (local.get $base) (local.get 3))
646                     local.get $base
647                 )
648 
649                 (func (export "invalid") (result i32)
650                     i32.const -8
651                 )
652             )
653             (core instance $i (instantiate $m))
654 
655             (type $result (tuple s8 u16 float32 float64))
656             (func (export "tuple")
657                 (param "a" s8) (param "b" u16) (param "c" float32) (param "d" float64) (result $result)
658                 (canon lift (core func $i "foo") (memory $i "memory"))
659             )
660             (func (export "invalid") (result $result)
661                 (canon lift (core func $i "invalid") (memory $i "memory"))
662             )
663         )
664     "#;
665 
666     let engine = super::engine();
667     let component = Component::new(&engine, component)?;
668     let mut store = Store::new(&engine, ());
669     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
670 
671     let input = (-1, 100, 3.0, 100.0);
672     let output = instance
673         .get_typed_func::<(i8, u16, f32, f64), ((i8, u16, f32, f64),)>(&mut store, "tuple")?
674         .call_and_post_return(&mut store, input)?;
675     assert_eq!((input,), output);
676 
677     let invalid_func =
678         instance.get_typed_func::<(), ((i8, u16, f32, f64),)>(&mut store, "invalid")?;
679     let err = invalid_func.call(&mut store, ()).err().unwrap();
680     assert!(
681         err.to_string().contains("pointer out of bounds of memory"),
682         "{}",
683         err
684     );
685 
686     Ok(())
687 }
688 
689 #[test]
690 fn strings() -> Result<()> {
691     let component = format!(
692         r#"(component
693             (core module $m
694                 (memory (export "memory") 1)
695                 (func (export "roundtrip") (param i32 i32) (result i32)
696                     (local $base i32)
697                     (local.set $base
698                         (call $realloc
699                             (i32.const 0)
700                             (i32.const 0)
701                             (i32.const 4)
702                             (i32.const 8)))
703                     (i32.store offset=0
704                         (local.get $base)
705                         (local.get 0))
706                     (i32.store offset=4
707                         (local.get $base)
708                         (local.get 1))
709                     (local.get $base)
710                 )
711 
712                 {REALLOC_AND_FREE}
713             )
714             (core instance $i (instantiate $m))
715 
716             (func (export "list8-to-str") (param "a" (list u8)) (result string)
717                 (canon lift
718                     (core func $i "roundtrip")
719                     (memory $i "memory")
720                     (realloc (func $i "realloc"))
721                 )
722             )
723             (func (export "str-to-list8") (param "a" string) (result (list u8))
724                 (canon lift
725                     (core func $i "roundtrip")
726                     (memory $i "memory")
727                     (realloc (func $i "realloc"))
728                 )
729             )
730             (func (export "list16-to-str") (param "a" (list u16)) (result string)
731                 (canon lift
732                     (core func $i "roundtrip")
733                     string-encoding=utf16
734                     (memory $i "memory")
735                     (realloc (func $i "realloc"))
736                 )
737             )
738             (func (export "str-to-list16") (param "a" string) (result (list u16))
739                 (canon lift
740                     (core func $i "roundtrip")
741                     string-encoding=utf16
742                     (memory $i "memory")
743                     (realloc (func $i "realloc"))
744                 )
745             )
746         )"#
747     );
748 
749     let engine = super::engine();
750     let component = Component::new(&engine, component)?;
751     let mut store = Store::new(&engine, ());
752     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
753     let list8_to_str =
754         instance.get_typed_func::<(&[u8],), (WasmStr,)>(&mut store, "list8-to-str")?;
755     let str_to_list8 =
756         instance.get_typed_func::<(&str,), (WasmList<u8>,)>(&mut store, "str-to-list8")?;
757     let list16_to_str =
758         instance.get_typed_func::<(&[u16],), (WasmStr,)>(&mut store, "list16-to-str")?;
759     let str_to_list16 =
760         instance.get_typed_func::<(&str,), (WasmList<u16>,)>(&mut store, "str-to-list16")?;
761 
762     let mut roundtrip = |x: &str| -> Result<()> {
763         let ret = list8_to_str.call(&mut store, (x.as_bytes(),))?.0;
764         assert_eq!(ret.to_str(&store)?, x);
765         list8_to_str.post_return(&mut store)?;
766 
767         let utf16 = x.encode_utf16().collect::<Vec<_>>();
768         let ret = list16_to_str.call(&mut store, (&utf16[..],))?.0;
769         assert_eq!(ret.to_str(&store)?, x);
770         list16_to_str.post_return(&mut store)?;
771 
772         let ret = str_to_list8.call(&mut store, (x,))?.0;
773         assert_eq!(
774             ret.iter(&mut store).collect::<Result<Vec<_>>>()?,
775             x.as_bytes()
776         );
777         str_to_list8.post_return(&mut store)?;
778 
779         let ret = str_to_list16.call(&mut store, (x,))?.0;
780         assert_eq!(ret.iter(&mut store).collect::<Result<Vec<_>>>()?, utf16,);
781         str_to_list16.post_return(&mut store)?;
782 
783         Ok(())
784     };
785 
786     roundtrip("")?;
787     roundtrip("foo")?;
788     roundtrip("hello there")?;
789     roundtrip("��")?;
790     roundtrip("Löwe 老虎 Léopard")?;
791 
792     let ret = list8_to_str.call(&mut store, (b"\xff",))?.0;
793     let err = ret.to_str(&store).unwrap_err();
794     assert!(err.to_string().contains("invalid utf-8"), "{}", err);
795     list8_to_str.post_return(&mut store)?;
796 
797     let ret = list8_to_str
798         .call(&mut store, (b"hello there \xff invalid",))?
799         .0;
800     let err = ret.to_str(&store).unwrap_err();
801     assert!(err.to_string().contains("invalid utf-8"), "{}", err);
802     list8_to_str.post_return(&mut store)?;
803 
804     let ret = list16_to_str.call(&mut store, (&[0xd800],))?.0;
805     let err = ret.to_str(&store).unwrap_err();
806     assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
807     list16_to_str.post_return(&mut store)?;
808 
809     let ret = list16_to_str.call(&mut store, (&[0xdfff],))?.0;
810     let err = ret.to_str(&store).unwrap_err();
811     assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
812     list16_to_str.post_return(&mut store)?;
813 
814     let ret = list16_to_str.call(&mut store, (&[0xd800, 0xff00],))?.0;
815     let err = ret.to_str(&store).unwrap_err();
816     assert!(err.to_string().contains("unpaired surrogate"), "{}", err);
817     list16_to_str.post_return(&mut store)?;
818 
819     Ok(())
820 }
821 
822 #[test]
823 fn many_parameters() -> Result<()> {
824     let component = format!(
825         r#"(component
826             (core module $m
827                 (memory (export "memory") 1)
828                 (func (export "foo") (param i32) (result i32)
829                     (local $base i32)
830 
831                     ;; Allocate space for the return
832                     (local.set $base
833                         (call $realloc
834                             (i32.const 0)
835                             (i32.const 0)
836                             (i32.const 4)
837                             (i32.const 12)))
838 
839                     ;; Store the pointer/length of the entire linear memory
840                     ;; so we have access to everything.
841                     (i32.store offset=0
842                         (local.get $base)
843                         (i32.const 0))
844                     (i32.store offset=4
845                         (local.get $base)
846                         (i32.mul
847                             (memory.size)
848                             (i32.const 65536)))
849 
850                     ;; And also store our pointer parameter
851                     (i32.store offset=8
852                         (local.get $base)
853                         (local.get 0))
854 
855                     (local.get $base)
856                 )
857 
858                 {REALLOC_AND_FREE}
859             )
860             (core instance $i (instantiate $m))
861 
862             (type $t (func
863                 (param "p1" s8)              ;; offset  0, size 1
864                 (param "p2" u64)             ;; offset  8, size 8
865                 (param "p3" float32)         ;; offset 16, size 4
866                 (param "p4" u8)              ;; offset 20, size 1
867                 (param "p5" s16)             ;; offset 22, size 2
868                 (param "p6" string)          ;; offset 24, size 8
869                 (param "p7" (list u32))      ;; offset 32, size 8
870                 (param "p8" bool)            ;; offset 40, size 1
871                 (param "p0" bool)            ;; offset 40, size 1
872                 (param "pa" char)            ;; offset 44, size 4
873                 (param "pb" (list bool))     ;; offset 48, size 8
874                 (param "pc" (list char))     ;; offset 56, size 8
875                 (param "pd" (list string))   ;; offset 64, size 8
876 
877                 (result (tuple (list u8) u32))
878             ))
879             (func (export "many-param") (type $t)
880                 (canon lift
881                     (core func $i "foo")
882                     (memory $i "memory")
883                     (realloc (func $i "realloc"))
884                 )
885             )
886         )"#
887     );
888 
889     let engine = super::engine();
890     let component = Component::new(&engine, component)?;
891     let mut store = Store::new(&engine, ());
892     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
893     let func = instance.get_typed_func::<(
894         i8,
895         u64,
896         f32,
897         u8,
898         i16,
899         &str,
900         &[u32],
901         bool,
902         bool,
903         char,
904         &[bool],
905         &[char],
906         &[&str],
907     ), ((WasmList<u8>, u32),)>(&mut store, "many-param")?;
908 
909     let input = (
910         -100,
911         u64::MAX / 2,
912         f32::from_bits(CANON_32BIT_NAN | 1),
913         38,
914         18831,
915         "this is the first string",
916         [1, 2, 3, 4, 5, 6, 7, 8].as_slice(),
917         true,
918         false,
919         '��',
920         [false, true, false, true, true].as_slice(),
921         ['��', '��', '��', '��', '��'].as_slice(),
922         [
923             "the quick",
924             "brown fox",
925             "was too lazy",
926             "to jump over the dog",
927             "what a demanding dog",
928         ]
929         .as_slice(),
930     );
931     let ((memory, pointer),) = func.call(&mut store, input)?;
932     let memory = memory.as_le_slice(&store);
933 
934     let mut actual = &memory[pointer as usize..][..72];
935     assert_eq!(i8::from_le_bytes(*actual.take_n::<1>()), input.0);
936     actual.skip::<7>();
937     assert_eq!(u64::from_le_bytes(*actual.take_n::<8>()), input.1);
938     assert_eq!(
939         u32::from_le_bytes(*actual.take_n::<4>()),
940         CANON_32BIT_NAN | 1
941     );
942     assert_eq!(u8::from_le_bytes(*actual.take_n::<1>()), input.3);
943     actual.skip::<1>();
944     assert_eq!(i16::from_le_bytes(*actual.take_n::<2>()), input.4);
945     assert_eq!(actual.ptr_len(memory, 1), input.5.as_bytes());
946     let mut mem = actual.ptr_len(memory, 4);
947     for expected in input.6.iter() {
948         assert_eq!(u32::from_le_bytes(*mem.take_n::<4>()), *expected);
949     }
950     assert!(mem.is_empty());
951     assert_eq!(actual.take_n::<1>(), &[input.7 as u8]);
952     assert_eq!(actual.take_n::<1>(), &[input.8 as u8]);
953     actual.skip::<2>();
954     assert_eq!(u32::from_le_bytes(*actual.take_n::<4>()), input.9 as u32);
955 
956     // (list bool)
957     mem = actual.ptr_len(memory, 1);
958     for expected in input.10.iter() {
959         assert_eq!(mem.take_n::<1>(), &[*expected as u8]);
960     }
961     assert!(mem.is_empty());
962 
963     // (list char)
964     mem = actual.ptr_len(memory, 4);
965     for expected in input.11.iter() {
966         assert_eq!(u32::from_le_bytes(*mem.take_n::<4>()), *expected as u32);
967     }
968     assert!(mem.is_empty());
969 
970     // (list string)
971     mem = actual.ptr_len(memory, 8);
972     for expected in input.12.iter() {
973         let actual = mem.ptr_len(memory, 1);
974         assert_eq!(actual, expected.as_bytes());
975     }
976     assert!(mem.is_empty());
977     assert!(actual.is_empty());
978 
979     Ok(())
980 }
981 
982 #[test]
983 fn some_traps() -> Result<()> {
984     let middle_of_memory = (i32::MAX / 2) & (!0xff);
985     let component = format!(
986         r#"(component
987             (core module $m
988                 (memory (export "memory") 1)
989                 (func (export "take-many") (param i32))
990                 (func (export "take-list") (param i32 i32))
991 
992                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
993                     unreachable)
994             )
995             (core instance $i (instantiate $m))
996 
997             (func (export "take-list-unreachable") (param "a" (list u8))
998                 (canon lift (core func $i "take-list") (memory $i "memory") (realloc (func $i "realloc")))
999             )
1000             (func (export "take-string-unreachable") (param "a" string)
1001                 (canon lift (core func $i "take-list") (memory $i "memory") (realloc (func $i "realloc")))
1002             )
1003 
1004             (type $t (func
1005                 (param "s1" string)
1006                 (param "s2" string)
1007                 (param "s3" string)
1008                 (param "s4" string)
1009                 (param "s5" string)
1010                 (param "s6" string)
1011                 (param "s7" string)
1012                 (param "s8" string)
1013                 (param "s9" string)
1014                 (param "s10" string)
1015             ))
1016             (func (export "take-many-unreachable") (type $t)
1017                 (canon lift (core func $i "take-many") (memory $i "memory") (realloc (func $i "realloc")))
1018             )
1019 
1020             (core module $m2
1021                 (memory (export "memory") 1)
1022                 (func (export "take-many") (param i32))
1023                 (func (export "take-list") (param i32 i32))
1024 
1025                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1026                     i32.const {middle_of_memory})
1027             )
1028             (core instance $i2 (instantiate $m2))
1029 
1030             (func (export "take-list-base-oob") (param "a" (list u8))
1031                 (canon lift (core func $i2 "take-list") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1032             )
1033             (func (export "take-string-base-oob") (param "a" string)
1034                 (canon lift (core func $i2 "take-list") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1035             )
1036             (func (export "take-many-base-oob") (type $t)
1037                 (canon lift (core func $i2 "take-many") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1038             )
1039 
1040             (core module $m3
1041                 (memory (export "memory") 1)
1042                 (func (export "take-many") (param i32))
1043                 (func (export "take-list") (param i32 i32))
1044 
1045                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1046                     i32.const 65532)
1047             )
1048             (core instance $i3 (instantiate $m3))
1049 
1050             (func (export "take-list-end-oob") (param "a" (list u8))
1051                 (canon lift (core func $i3 "take-list") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1052             )
1053             (func (export "take-string-end-oob") (param "a" string)
1054                 (canon lift (core func $i3 "take-list") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1055             )
1056             (func (export "take-many-end-oob") (type $t)
1057                 (canon lift (core func $i3 "take-many") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1058             )
1059 
1060             (core module $m4
1061                 (memory (export "memory") 1)
1062                 (func (export "take-many") (param i32))
1063 
1064                 (global $cnt (mut i32) (i32.const 0))
1065                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1066                     global.get $cnt
1067                     if (result i32)
1068                         i32.const 100000
1069                     else
1070                         i32.const 1
1071                         global.set $cnt
1072                         i32.const 0
1073                     end
1074                 )
1075             )
1076             (core instance $i4 (instantiate $m4))
1077 
1078             (func (export "take-many-second-oob") (type $t)
1079                 (canon lift (core func $i4 "take-many") (memory $i4 "memory") (realloc (func $i4 "realloc")))
1080             )
1081         )"#
1082     );
1083 
1084     let engine = super::engine();
1085     let component = Component::new(&engine, component)?;
1086     let mut store = Store::new(&engine, ());
1087     let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
1088 
1089     // This should fail when calling the allocator function for the argument
1090     let err = instance(&mut store)?
1091         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-unreachable")?
1092         .call(&mut store, (&[],))
1093         .unwrap_err()
1094         .downcast::<Trap>()?;
1095     assert_eq!(err, Trap::UnreachableCodeReached);
1096 
1097     // This should fail when calling the allocator function for the argument
1098     let err = instance(&mut store)?
1099         .get_typed_func::<(&str,), ()>(&mut store, "take-string-unreachable")?
1100         .call(&mut store, ("",))
1101         .unwrap_err()
1102         .downcast::<Trap>()?;
1103     assert_eq!(err, Trap::UnreachableCodeReached);
1104 
1105     // This should fail when calling the allocator function for the space
1106     // to store the arguments (before arguments are even lowered)
1107     let err = instance(&mut store)?
1108         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1109             &mut store,
1110             "take-many-unreachable",
1111         )?
1112         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1113         .unwrap_err()
1114         .downcast::<Trap>()?;
1115     assert_eq!(err, Trap::UnreachableCodeReached);
1116 
1117     // Assert that when the base pointer returned by malloc is out of bounds
1118     // that errors are reported as such. Both empty and lists with contents
1119     // should all be invalid here.
1120     //
1121     // FIXME(WebAssembly/component-model#32) confirm the semantics here are
1122     // what's desired.
1123     #[track_caller]
1124     fn assert_oob(err: &anyhow::Error) {
1125         assert!(
1126             err.to_string()
1127                 .contains("realloc return: beyond end of memory"),
1128             "{err:?}",
1129         );
1130     }
1131     let err = instance(&mut store)?
1132         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
1133         .call(&mut store, (&[],))
1134         .unwrap_err();
1135     assert_oob(&err);
1136     let err = instance(&mut store)?
1137         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
1138         .call(&mut store, (&[1],))
1139         .unwrap_err();
1140     assert_oob(&err);
1141     let err = instance(&mut store)?
1142         .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
1143         .call(&mut store, ("",))
1144         .unwrap_err();
1145     assert_oob(&err);
1146     let err = instance(&mut store)?
1147         .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
1148         .call(&mut store, ("x",))
1149         .unwrap_err();
1150     assert_oob(&err);
1151     let err = instance(&mut store)?
1152         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1153             &mut store,
1154             "take-many-base-oob",
1155         )?
1156         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1157         .unwrap_err();
1158     assert_oob(&err);
1159 
1160     // Test here that when the returned pointer from malloc is one byte from the
1161     // end of memory that empty things are fine, but larger things are not.
1162 
1163     instance(&mut store)?
1164         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1165         .call_and_post_return(&mut store, (&[],))?;
1166     instance(&mut store)?
1167         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1168         .call_and_post_return(&mut store, (&[1, 2, 3, 4],))?;
1169     let err = instance(&mut store)?
1170         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1171         .call(&mut store, (&[1, 2, 3, 4, 5],))
1172         .unwrap_err();
1173     assert_oob(&err);
1174     instance(&mut store)?
1175         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1176         .call_and_post_return(&mut store, ("",))?;
1177     instance(&mut store)?
1178         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1179         .call_and_post_return(&mut store, ("abcd",))?;
1180     let err = instance(&mut store)?
1181         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1182         .call(&mut store, ("abcde",))
1183         .unwrap_err();
1184     assert_oob(&err);
1185     let err = instance(&mut store)?
1186         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1187             &mut store,
1188             "take-many-end-oob",
1189         )?
1190         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1191         .unwrap_err();
1192     assert_oob(&err);
1193 
1194     // For this function the first allocation, the space to store all the
1195     // arguments, is in-bounds but then all further allocations, such as for
1196     // each individual string, are all out of bounds.
1197     let err = instance(&mut store)?
1198         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1199             &mut store,
1200             "take-many-second-oob",
1201         )?
1202         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1203         .unwrap_err();
1204     assert_oob(&err);
1205     let err = instance(&mut store)?
1206         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1207             &mut store,
1208             "take-many-second-oob",
1209         )?
1210         .call(&mut store, ("", "", "", "", "", "", "", "", "", "x"))
1211         .unwrap_err();
1212     assert_oob(&err);
1213     Ok(())
1214 }
1215 
1216 #[test]
1217 fn char_bool_memory() -> Result<()> {
1218     let component = format!(
1219         r#"(component
1220             (core module $m
1221                 (memory (export "memory") 1)
1222                 (func (export "ret-tuple") (param i32 i32) (result i32)
1223                     (local $base i32)
1224 
1225                     ;; Allocate space for the return
1226                     (local.set $base
1227                         (call $realloc
1228                             (i32.const 0)
1229                             (i32.const 0)
1230                             (i32.const 4)
1231                             (i32.const 8)))
1232 
1233                     ;; store the boolean
1234                     (i32.store offset=0
1235                         (local.get $base)
1236                         (local.get 0))
1237 
1238                     ;; store the char
1239                     (i32.store offset=4
1240                         (local.get $base)
1241                         (local.get 1))
1242 
1243                     (local.get $base)
1244                 )
1245 
1246                 {REALLOC_AND_FREE}
1247             )
1248             (core instance $i (instantiate $m))
1249 
1250             (func (export "ret-tuple") (param "a" u32) (param "b" u32) (result (tuple bool char))
1251                 (canon lift (core func $i "ret-tuple")
1252                     (memory $i "memory")
1253                     (realloc (func $i "realloc")))
1254             )
1255         )"#
1256     );
1257 
1258     let engine = super::engine();
1259     let component = Component::new(&engine, component)?;
1260     let mut store = Store::new(&engine, ());
1261     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1262     let func = instance.get_typed_func::<(u32, u32), ((bool, char),)>(&mut store, "ret-tuple")?;
1263 
1264     let (ret,) = func.call(&mut store, (0, 'a' as u32))?;
1265     assert_eq!(ret, (false, 'a'));
1266     func.post_return(&mut store)?;
1267 
1268     let (ret,) = func.call(&mut store, (1, '��' as u32))?;
1269     assert_eq!(ret, (true, '��'));
1270     func.post_return(&mut store)?;
1271 
1272     let (ret,) = func.call(&mut store, (2, 'a' as u32))?;
1273     assert_eq!(ret, (true, 'a'));
1274     func.post_return(&mut store)?;
1275 
1276     assert!(func.call(&mut store, (0, 0xd800)).is_err());
1277 
1278     Ok(())
1279 }
1280 
1281 #[test]
1282 fn string_list_oob() -> Result<()> {
1283     let component = format!(
1284         r#"(component
1285             (core module $m
1286                 (memory (export "memory") 1)
1287                 (func (export "ret-list") (result i32)
1288                     (local $base i32)
1289 
1290                     ;; Allocate space for the return
1291                     (local.set $base
1292                         (call $realloc
1293                             (i32.const 0)
1294                             (i32.const 0)
1295                             (i32.const 4)
1296                             (i32.const 8)))
1297 
1298                     (i32.store offset=0
1299                         (local.get $base)
1300                         (i32.const 100000))
1301                     (i32.store offset=4
1302                         (local.get $base)
1303                         (i32.const 1))
1304 
1305                     (local.get $base)
1306                 )
1307 
1308                 {REALLOC_AND_FREE}
1309             )
1310             (core instance $i (instantiate $m))
1311 
1312             (func (export "ret-list-u8") (result (list u8))
1313                 (canon lift (core func $i "ret-list")
1314                     (memory $i "memory")
1315                     (realloc (func $i "realloc"))
1316                 )
1317             )
1318             (func (export "ret-string") (result string)
1319                 (canon lift (core func $i "ret-list")
1320                     (memory $i "memory")
1321                     (realloc (func $i "realloc"))
1322                 )
1323             )
1324         )"#
1325     );
1326 
1327     let engine = super::engine();
1328     let component = Component::new(&engine, component)?;
1329     let mut store = Store::new(&engine, ());
1330     let ret_list_u8 = Linker::new(&engine)
1331         .instantiate(&mut store, &component)?
1332         .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "ret-list-u8")?;
1333     let ret_string = Linker::new(&engine)
1334         .instantiate(&mut store, &component)?
1335         .get_typed_func::<(), (WasmStr,)>(&mut store, "ret-string")?;
1336 
1337     let err = ret_list_u8.call(&mut store, ()).err().unwrap();
1338     assert!(err.to_string().contains("out of bounds"), "{}", err);
1339 
1340     let err = ret_string.call(&mut store, ()).err().unwrap();
1341     assert!(err.to_string().contains("out of bounds"), "{}", err);
1342 
1343     Ok(())
1344 }
1345 
1346 #[test]
1347 fn tuples() -> Result<()> {
1348     let component = format!(
1349         r#"(component
1350             (core module $m
1351                 (memory (export "memory") 1)
1352                 (func (export "foo")
1353                     (param i32 f64 i32)
1354                     (result i32)
1355 
1356                     local.get 0
1357                     i32.const 0
1358                     i32.ne
1359                     if unreachable end
1360 
1361                     local.get 1
1362                     f64.const 1
1363                     f64.ne
1364                     if unreachable end
1365 
1366                     local.get 2
1367                     i32.const 2
1368                     i32.ne
1369                     if unreachable end
1370 
1371                     i32.const 3
1372                 )
1373             )
1374             (core instance $i (instantiate $m))
1375 
1376             (func (export "foo")
1377                 (param "a" (tuple s32 float64))
1378                 (param "b" (tuple s8))
1379                 (result (tuple u16))
1380                 (canon lift (core func $i "foo"))
1381             )
1382         )"#
1383     );
1384 
1385     let engine = super::engine();
1386     let component = Component::new(&engine, component)?;
1387     let mut store = Store::new(&engine, ());
1388     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1389     let foo = instance.get_typed_func::<((i32, f64), (i8,)), ((u16,),)>(&mut store, "foo")?;
1390     assert_eq!(foo.call(&mut store, ((0, 1.0), (2,)))?, ((3,),));
1391 
1392     Ok(())
1393 }
1394 
1395 #[test]
1396 fn option() -> Result<()> {
1397     let component = format!(
1398         r#"(component
1399             (core module $m
1400                 (memory (export "memory") 1)
1401                 (func (export "pass1") (param i32 i32) (result i32)
1402                     (local $base i32)
1403                     (local.set $base
1404                         (call $realloc
1405                             (i32.const 0)
1406                             (i32.const 0)
1407                             (i32.const 4)
1408                             (i32.const 8)))
1409 
1410                     (i32.store offset=0
1411                         (local.get $base)
1412                         (local.get 0))
1413                     (i32.store offset=4
1414                         (local.get $base)
1415                         (local.get 1))
1416 
1417                     (local.get $base)
1418                 )
1419                 (func (export "pass2") (param i32 i32 i32) (result i32)
1420                     (local $base i32)
1421                     (local.set $base
1422                         (call $realloc
1423                             (i32.const 0)
1424                             (i32.const 0)
1425                             (i32.const 4)
1426                             (i32.const 12)))
1427 
1428                     (i32.store offset=0
1429                         (local.get $base)
1430                         (local.get 0))
1431                     (i32.store offset=4
1432                         (local.get $base)
1433                         (local.get 1))
1434                     (i32.store offset=8
1435                         (local.get $base)
1436                         (local.get 2))
1437 
1438                     (local.get $base)
1439                 )
1440 
1441                 {REALLOC_AND_FREE}
1442             )
1443             (core instance $i (instantiate $m))
1444 
1445             (func (export "option-u8-to-tuple") (param "a" (option u8)) (result (tuple u32 u32))
1446                 (canon lift (core func $i "pass1") (memory $i "memory"))
1447             )
1448             (func (export "option-u32-to-tuple") (param "a" (option u32)) (result (tuple u32 u32))
1449                 (canon lift (core func $i "pass1") (memory $i "memory"))
1450             )
1451             (func (export "option-string-to-tuple") (param "a" (option string)) (result (tuple u32 string))
1452                 (canon lift
1453                     (core func $i "pass2")
1454                     (memory $i "memory")
1455                     (realloc (func $i "realloc"))
1456                 )
1457             )
1458             (func (export "to-option-u8") (param "a" u32) (param "b" u32) (result (option u8))
1459                 (canon lift (core func $i "pass1") (memory $i "memory"))
1460             )
1461             (func (export "to-option-u32") (param "a" u32) (param "b" u32) (result (option u32))
1462                 (canon lift
1463                     (core func $i "pass1")
1464                     (memory $i "memory")
1465                 )
1466             )
1467             (func (export "to-option-string") (param "a" u32) (param "b" string) (result (option string))
1468                 (canon lift
1469                     (core func $i "pass2")
1470                     (memory $i "memory")
1471                     (realloc (func $i "realloc"))
1472                 )
1473             )
1474         )"#
1475     );
1476 
1477     let engine = super::engine();
1478     let component = Component::new(&engine, component)?;
1479     let mut store = Store::new(&engine, ());
1480     let linker = Linker::new(&engine);
1481     let instance = linker.instantiate(&mut store, &component)?;
1482 
1483     let option_u8_to_tuple = instance
1484         .get_typed_func::<(Option<u8>,), ((u32, u32),)>(&mut store, "option-u8-to-tuple")?;
1485     assert_eq!(option_u8_to_tuple.call(&mut store, (None,))?, ((0, 0),));
1486     option_u8_to_tuple.post_return(&mut store)?;
1487     assert_eq!(option_u8_to_tuple.call(&mut store, (Some(0),))?, ((1, 0),));
1488     option_u8_to_tuple.post_return(&mut store)?;
1489     assert_eq!(
1490         option_u8_to_tuple.call(&mut store, (Some(100),))?,
1491         ((1, 100),)
1492     );
1493     option_u8_to_tuple.post_return(&mut store)?;
1494 
1495     let option_u32_to_tuple = instance
1496         .get_typed_func::<(Option<u32>,), ((u32, u32),)>(&mut store, "option-u32-to-tuple")?;
1497     assert_eq!(option_u32_to_tuple.call(&mut store, (None,))?, ((0, 0),));
1498     option_u32_to_tuple.post_return(&mut store)?;
1499     assert_eq!(option_u32_to_tuple.call(&mut store, (Some(0),))?, ((1, 0),));
1500     option_u32_to_tuple.post_return(&mut store)?;
1501     assert_eq!(
1502         option_u32_to_tuple.call(&mut store, (Some(100),))?,
1503         ((1, 100),)
1504     );
1505     option_u32_to_tuple.post_return(&mut store)?;
1506 
1507     let option_string_to_tuple = instance.get_typed_func::<(Option<&str>,), ((u32, WasmStr),)>(
1508         &mut store,
1509         "option-string-to-tuple",
1510     )?;
1511     let ((a, b),) = option_string_to_tuple.call(&mut store, (None,))?;
1512     assert_eq!(a, 0);
1513     assert_eq!(b.to_str(&store)?, "");
1514     option_string_to_tuple.post_return(&mut store)?;
1515     let ((a, b),) = option_string_to_tuple.call(&mut store, (Some(""),))?;
1516     assert_eq!(a, 1);
1517     assert_eq!(b.to_str(&store)?, "");
1518     option_string_to_tuple.post_return(&mut store)?;
1519     let ((a, b),) = option_string_to_tuple.call(&mut store, (Some("hello"),))?;
1520     assert_eq!(a, 1);
1521     assert_eq!(b.to_str(&store)?, "hello");
1522     option_string_to_tuple.post_return(&mut store)?;
1523 
1524     let instance = linker.instantiate(&mut store, &component)?;
1525     let to_option_u8 =
1526         instance.get_typed_func::<(u32, u32), (Option<u8>,)>(&mut store, "to-option-u8")?;
1527     assert_eq!(to_option_u8.call(&mut store, (0x00_00, 0))?, (None,));
1528     to_option_u8.post_return(&mut store)?;
1529     assert_eq!(to_option_u8.call(&mut store, (0x00_01, 0))?, (Some(0),));
1530     to_option_u8.post_return(&mut store)?;
1531     assert_eq!(to_option_u8.call(&mut store, (0xfd_01, 0))?, (Some(0xfd),));
1532     to_option_u8.post_return(&mut store)?;
1533     assert!(to_option_u8.call(&mut store, (0x00_02, 0)).is_err());
1534 
1535     let instance = linker.instantiate(&mut store, &component)?;
1536     let to_option_u32 =
1537         instance.get_typed_func::<(u32, u32), (Option<u32>,)>(&mut store, "to-option-u32")?;
1538     assert_eq!(to_option_u32.call(&mut store, (0, 0))?, (None,));
1539     to_option_u32.post_return(&mut store)?;
1540     assert_eq!(to_option_u32.call(&mut store, (1, 0))?, (Some(0),));
1541     to_option_u32.post_return(&mut store)?;
1542     assert_eq!(
1543         to_option_u32.call(&mut store, (1, 0x1234fead))?,
1544         (Some(0x1234fead),)
1545     );
1546     to_option_u32.post_return(&mut store)?;
1547     assert!(to_option_u32.call(&mut store, (2, 0)).is_err());
1548 
1549     let instance = linker.instantiate(&mut store, &component)?;
1550     let to_option_string = instance
1551         .get_typed_func::<(u32, &str), (Option<WasmStr>,)>(&mut store, "to-option-string")?;
1552     let ret = to_option_string.call(&mut store, (0, ""))?.0;
1553     assert!(ret.is_none());
1554     to_option_string.post_return(&mut store)?;
1555     let ret = to_option_string.call(&mut store, (1, ""))?.0;
1556     assert_eq!(ret.unwrap().to_str(&store)?, "");
1557     to_option_string.post_return(&mut store)?;
1558     let ret = to_option_string.call(&mut store, (1, "cheesecake"))?.0;
1559     assert_eq!(ret.unwrap().to_str(&store)?, "cheesecake");
1560     to_option_string.post_return(&mut store)?;
1561     assert!(to_option_string.call(&mut store, (2, "")).is_err());
1562 
1563     Ok(())
1564 }
1565 
1566 #[test]
1567 fn expected() -> Result<()> {
1568     let component = format!(
1569         r#"(component
1570             (core module $m
1571                 (memory (export "memory") 1)
1572                 (func (export "pass0") (param i32) (result i32)
1573                     local.get 0
1574                 )
1575                 (func (export "pass1") (param i32 i32) (result i32)
1576                     (local $base i32)
1577                     (local.set $base
1578                         (call $realloc
1579                             (i32.const 0)
1580                             (i32.const 0)
1581                             (i32.const 4)
1582                             (i32.const 8)))
1583 
1584                     (i32.store offset=0
1585                         (local.get $base)
1586                         (local.get 0))
1587                     (i32.store offset=4
1588                         (local.get $base)
1589                         (local.get 1))
1590 
1591                     (local.get $base)
1592                 )
1593                 (func (export "pass2") (param i32 i32 i32) (result i32)
1594                     (local $base i32)
1595                     (local.set $base
1596                         (call $realloc
1597                             (i32.const 0)
1598                             (i32.const 0)
1599                             (i32.const 4)
1600                             (i32.const 12)))
1601 
1602                     (i32.store offset=0
1603                         (local.get $base)
1604                         (local.get 0))
1605                     (i32.store offset=4
1606                         (local.get $base)
1607                         (local.get 1))
1608                     (i32.store offset=8
1609                         (local.get $base)
1610                         (local.get 2))
1611 
1612                     (local.get $base)
1613                 )
1614 
1615                 {REALLOC_AND_FREE}
1616             )
1617             (core instance $i (instantiate $m))
1618 
1619             (func (export "take-expected-unit") (param "a" (result)) (result u32)
1620                 (canon lift (core func $i "pass0"))
1621             )
1622             (func (export "take-expected-u8-f32") (param "a" (result u8 (error float32))) (result (tuple u32 u32))
1623                 (canon lift (core func $i "pass1") (memory $i "memory"))
1624             )
1625             (type $list (list u8))
1626             (func (export "take-expected-string") (param "a" (result string (error $list))) (result (tuple u32 string))
1627                 (canon lift
1628                     (core func $i "pass2")
1629                     (memory $i "memory")
1630                     (realloc (func $i "realloc"))
1631                 )
1632             )
1633             (func (export "to-expected-unit") (param "a" u32) (result (result))
1634                 (canon lift (core func $i "pass0"))
1635             )
1636             (func (export "to-expected-s16-f32") (param "a" u32) (param "b" u32) (result (result s16 (error float32)))
1637                 (canon lift
1638                     (core func $i "pass1")
1639                     (memory $i "memory")
1640                     (realloc (func $i "realloc"))
1641                 )
1642             )
1643         )"#
1644     );
1645 
1646     let engine = super::engine();
1647     let component = Component::new(&engine, component)?;
1648     let mut store = Store::new(&engine, ());
1649     let linker = Linker::new(&engine);
1650     let instance = linker.instantiate(&mut store, &component)?;
1651     let take_expected_unit =
1652         instance.get_typed_func::<(Result<(), ()>,), (u32,)>(&mut store, "take-expected-unit")?;
1653     assert_eq!(take_expected_unit.call(&mut store, (Ok(()),))?, (0,));
1654     take_expected_unit.post_return(&mut store)?;
1655     assert_eq!(take_expected_unit.call(&mut store, (Err(()),))?, (1,));
1656     take_expected_unit.post_return(&mut store)?;
1657 
1658     let take_expected_u8_f32 = instance
1659         .get_typed_func::<(Result<u8, f32>,), ((u32, u32),)>(&mut store, "take-expected-u8-f32")?;
1660     assert_eq!(take_expected_u8_f32.call(&mut store, (Ok(1),))?, ((0, 1),));
1661     take_expected_u8_f32.post_return(&mut store)?;
1662     assert_eq!(
1663         take_expected_u8_f32.call(&mut store, (Err(2.0),))?,
1664         ((1, 2.0f32.to_bits()),)
1665     );
1666     take_expected_u8_f32.post_return(&mut store)?;
1667 
1668     let take_expected_string = instance
1669         .get_typed_func::<(Result<&str, &[u8]>,), ((u32, WasmStr),)>(
1670             &mut store,
1671             "take-expected-string",
1672         )?;
1673     let ((a, b),) = take_expected_string.call(&mut store, (Ok("hello"),))?;
1674     assert_eq!(a, 0);
1675     assert_eq!(b.to_str(&store)?, "hello");
1676     take_expected_string.post_return(&mut store)?;
1677     let ((a, b),) = take_expected_string.call(&mut store, (Err(b"goodbye"),))?;
1678     assert_eq!(a, 1);
1679     assert_eq!(b.to_str(&store)?, "goodbye");
1680     take_expected_string.post_return(&mut store)?;
1681 
1682     let instance = linker.instantiate(&mut store, &component)?;
1683     let to_expected_unit =
1684         instance.get_typed_func::<(u32,), (Result<(), ()>,)>(&mut store, "to-expected-unit")?;
1685     assert_eq!(to_expected_unit.call(&mut store, (0,))?, (Ok(()),));
1686     to_expected_unit.post_return(&mut store)?;
1687     assert_eq!(to_expected_unit.call(&mut store, (1,))?, (Err(()),));
1688     to_expected_unit.post_return(&mut store)?;
1689     let err = to_expected_unit.call(&mut store, (2,)).unwrap_err();
1690     assert!(err.to_string().contains("invalid expected"), "{}", err);
1691 
1692     let instance = linker.instantiate(&mut store, &component)?;
1693     let to_expected_s16_f32 = instance
1694         .get_typed_func::<(u32, u32), (Result<i16, f32>,)>(&mut store, "to-expected-s16-f32")?;
1695     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 0))?, (Ok(0),));
1696     to_expected_s16_f32.post_return(&mut store)?;
1697     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 100))?, (Ok(100),));
1698     to_expected_s16_f32.post_return(&mut store)?;
1699     assert_eq!(
1700         to_expected_s16_f32.call(&mut store, (1, 1.0f32.to_bits()))?,
1701         (Err(1.0),)
1702     );
1703     to_expected_s16_f32.post_return(&mut store)?;
1704     let ret = to_expected_s16_f32
1705         .call(&mut store, (1, CANON_32BIT_NAN | 1))?
1706         .0;
1707     assert_eq!(ret.unwrap_err().to_bits(), CANON_32BIT_NAN | 1);
1708     to_expected_s16_f32.post_return(&mut store)?;
1709     assert!(to_expected_s16_f32.call(&mut store, (2, 0)).is_err());
1710 
1711     Ok(())
1712 }
1713 
1714 #[test]
1715 fn fancy_list() -> Result<()> {
1716     let component = format!(
1717         r#"(component
1718             (core module $m
1719                 (memory (export "memory") 1)
1720                 (func (export "take") (param i32 i32) (result i32)
1721                     (local $base i32)
1722                     (local.set $base
1723                         (call $realloc
1724                             (i32.const 0)
1725                             (i32.const 0)
1726                             (i32.const 4)
1727                             (i32.const 16)))
1728 
1729                     (i32.store offset=0
1730                         (local.get $base)
1731                         (local.get 0))
1732                     (i32.store offset=4
1733                         (local.get $base)
1734                         (local.get 1))
1735                     (i32.store offset=8
1736                         (local.get $base)
1737                         (i32.const 0))
1738                     (i32.store offset=12
1739                         (local.get $base)
1740                         (i32.mul
1741                             (memory.size)
1742                             (i32.const 65536)))
1743 
1744                     (local.get $base)
1745                 )
1746 
1747                 {REALLOC_AND_FREE}
1748             )
1749             (core instance $i (instantiate $m))
1750 
1751             (type $a (option u8))
1752             (type $b (result (error string)))
1753             (type $input (list (tuple $a $b)))
1754             (func (export "take")
1755                 (param "a" $input)
1756                 (result (tuple u32 u32 (list u8)))
1757                 (canon lift
1758                     (core func $i "take")
1759                     (memory $i "memory")
1760                     (realloc (func $i "realloc"))
1761                 )
1762             )
1763         )"#
1764     );
1765 
1766     let engine = super::engine();
1767     let component = Component::new(&engine, component)?;
1768     let mut store = Store::new(&engine, ());
1769     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1770 
1771     let func = instance
1772         .get_typed_func::<(&[(Option<u8>, Result<(), &str>)],), ((u32, u32, WasmList<u8>),)>(
1773             &mut store, "take",
1774         )?;
1775 
1776     let input = [
1777         (None, Ok(())),
1778         (Some(2), Err("hello there")),
1779         (Some(200), Err("general kenobi")),
1780     ];
1781     let ((ptr, len, list),) = func.call(&mut store, (&input,))?;
1782     let memory = list.as_le_slice(&store);
1783     let ptr = usize::try_from(ptr).unwrap();
1784     let len = usize::try_from(len).unwrap();
1785     let mut array = &memory[ptr..][..len * 16];
1786 
1787     for (a, b) in input.iter() {
1788         match a {
1789             Some(val) => {
1790                 assert_eq!(*array.take_n::<2>(), [1, *val]);
1791             }
1792             None => {
1793                 assert_eq!(*array.take_n::<1>(), [0]);
1794                 array.skip::<1>();
1795             }
1796         }
1797         array.skip::<2>();
1798         match b {
1799             Ok(()) => {
1800                 assert_eq!(*array.take_n::<1>(), [0]);
1801                 array.skip::<11>();
1802             }
1803             Err(s) => {
1804                 assert_eq!(*array.take_n::<1>(), [1]);
1805                 array.skip::<3>();
1806                 assert_eq!(array.ptr_len(memory, 1), s.as_bytes());
1807             }
1808         }
1809     }
1810     assert!(array.is_empty());
1811 
1812     Ok(())
1813 }
1814 
1815 trait SliceExt<'a> {
1816     fn take_n<const N: usize>(&mut self) -> &'a [u8; N];
1817 
1818     fn skip<const N: usize>(&mut self) {
1819         self.take_n::<N>();
1820     }
1821 
1822     fn ptr_len<'b>(&mut self, all_memory: &'b [u8], size: usize) -> &'b [u8] {
1823         let ptr = u32::from_le_bytes(*self.take_n::<4>());
1824         let len = u32::from_le_bytes(*self.take_n::<4>());
1825         let ptr = usize::try_from(ptr).unwrap();
1826         let len = usize::try_from(len).unwrap();
1827         &all_memory[ptr..][..len * size]
1828     }
1829 }
1830 
1831 impl<'a> SliceExt<'a> for &'a [u8] {
1832     fn take_n<const N: usize>(&mut self) -> &'a [u8; N] {
1833         let (a, b) = self.split_at(N);
1834         *self = b;
1835         a.try_into().unwrap()
1836     }
1837 }
1838 
1839 #[test]
1840 fn invalid_alignment() -> Result<()> {
1841     let component = format!(
1842         r#"(component
1843             (core module $m
1844                 (memory (export "memory") 1)
1845                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1846                     i32.const 1)
1847 
1848                 (func (export "take-i32") (param i32))
1849                 (func (export "ret-1") (result i32) i32.const 1)
1850                 (func (export "ret-unaligned-list") (result i32)
1851                     (i32.store offset=0 (i32.const 8) (i32.const 1))
1852                     (i32.store offset=4 (i32.const 8) (i32.const 1))
1853                     i32.const 8)
1854             )
1855             (core instance $i (instantiate $m))
1856 
1857             (func (export "many-params")
1858                 (param "s1" string) (param "s2" string) (param "s3" string) (param "s4" string)
1859                 (param "s5" string) (param "s6" string) (param "s7" string) (param "s8" string)
1860                 (param "s9" string) (param "s10" string) (param "s11" string) (param "s12" string)
1861                 (canon lift
1862                     (core func $i "take-i32")
1863                     (memory $i "memory")
1864                     (realloc (func $i "realloc"))
1865                 )
1866             )
1867             (func (export "string-ret") (result string)
1868                 (canon lift
1869                     (core func $i "ret-1")
1870                     (memory $i "memory")
1871                     (realloc (func $i "realloc"))
1872                 )
1873             )
1874             (func (export "list-u32-ret") (result (list u32))
1875                 (canon lift
1876                     (core func $i "ret-unaligned-list")
1877                     (memory $i "memory")
1878                     (realloc (func $i "realloc"))
1879                 )
1880             )
1881         )"#
1882     );
1883 
1884     let engine = super::engine();
1885     let component = Component::new(&engine, component)?;
1886     let mut store = Store::new(&engine, ());
1887     let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
1888 
1889     let err = instance(&mut store)?
1890         .get_typed_func::<(
1891             &str,
1892             &str,
1893             &str,
1894             &str,
1895             &str,
1896             &str,
1897             &str,
1898             &str,
1899             &str,
1900             &str,
1901             &str,
1902             &str,
1903         ), ()>(&mut store, "many-params")?
1904         .call(&mut store, ("", "", "", "", "", "", "", "", "", "", "", ""))
1905         .unwrap_err();
1906     assert!(
1907         err.to_string()
1908             .contains("realloc return: result not aligned"),
1909         "{}",
1910         err
1911     );
1912 
1913     let err = instance(&mut store)?
1914         .get_typed_func::<(), (WasmStr,)>(&mut store, "string-ret")?
1915         .call(&mut store, ())
1916         .err()
1917         .unwrap();
1918     assert!(
1919         err.to_string().contains("return pointer not aligned"),
1920         "{}",
1921         err
1922     );
1923 
1924     let err = instance(&mut store)?
1925         .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32-ret")?
1926         .call(&mut store, ())
1927         .err()
1928         .unwrap();
1929     assert!(
1930         err.to_string().contains("list pointer is not aligned"),
1931         "{}",
1932         err
1933     );
1934 
1935     Ok(())
1936 }
1937 
1938 #[test]
1939 fn drop_component_still_works() -> Result<()> {
1940     let component = r#"
1941         (component
1942             (import "f" (func $f))
1943 
1944             (core func $f_lower
1945                 (canon lower (func $f))
1946             )
1947             (core module $m
1948                 (import "" "" (func $f))
1949 
1950                 (func $f2
1951                     call $f
1952                     call $f
1953                 )
1954 
1955                 (export "f" (func $f2))
1956             )
1957             (core instance $i (instantiate $m
1958                 (with "" (instance
1959                     (export "" (func $f_lower))
1960                 ))
1961             ))
1962             (func (export "g")
1963                 (canon lift
1964                     (core func $i "f")
1965                 )
1966             )
1967         )
1968     "#;
1969 
1970     let (mut store, instance) = {
1971         let engine = super::engine();
1972         let component = Component::new(&engine, component)?;
1973         let mut store = Store::new(&engine, 0);
1974         let mut linker = Linker::new(&engine);
1975         linker.root().func_wrap(
1976             "f",
1977             |mut store: StoreContextMut<'_, u32>, _: ()| -> Result<()> {
1978                 *store.data_mut() += 1;
1979                 Ok(())
1980             },
1981         )?;
1982         let instance = linker.instantiate(&mut store, &component)?;
1983         (store, instance)
1984     };
1985 
1986     let f = instance.get_typed_func::<(), ()>(&mut store, "g")?;
1987     assert_eq!(*store.data(), 0);
1988     f.call(&mut store, ())?;
1989     assert_eq!(*store.data(), 2);
1990 
1991     Ok(())
1992 }
1993 
1994 #[test]
1995 fn raw_slice_of_various_types() -> Result<()> {
1996     let component = r#"
1997         (component
1998             (core module $m
1999                 (memory (export "memory") 1)
2000 
2001                 (func (export "list8") (result i32)
2002                     (call $setup_list (i32.const 16))
2003                 )
2004                 (func (export "list16") (result i32)
2005                     (call $setup_list (i32.const 8))
2006                 )
2007                 (func (export "list32") (result i32)
2008                     (call $setup_list (i32.const 4))
2009                 )
2010                 (func (export "list64") (result i32)
2011                     (call $setup_list (i32.const 2))
2012                 )
2013 
2014                 (func $setup_list (param i32) (result i32)
2015                     (i32.store offset=0 (i32.const 100) (i32.const 8))
2016                     (i32.store offset=4 (i32.const 100) (local.get 0))
2017                     i32.const 100
2018                 )
2019 
2020                 (data (i32.const 8) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f")
2021             )
2022             (core instance $i (instantiate $m))
2023             (func (export "list-u8") (result (list u8))
2024                 (canon lift (core func $i "list8") (memory $i "memory"))
2025             )
2026             (func (export "list-i8") (result (list s8))
2027                 (canon lift (core func $i "list8") (memory $i "memory"))
2028             )
2029             (func (export "list-u16") (result (list u16))
2030                 (canon lift (core func $i "list16") (memory $i "memory"))
2031             )
2032             (func (export "list-i16") (result (list s16))
2033                 (canon lift (core func $i "list16") (memory $i "memory"))
2034             )
2035             (func (export "list-u32") (result (list u32))
2036                 (canon lift (core func $i "list32") (memory $i "memory"))
2037             )
2038             (func (export "list-i32") (result (list s32))
2039                 (canon lift (core func $i "list32") (memory $i "memory"))
2040             )
2041             (func (export "list-u64") (result (list u64))
2042                 (canon lift (core func $i "list64") (memory $i "memory"))
2043             )
2044             (func (export "list-i64") (result (list s64))
2045                 (canon lift (core func $i "list64") (memory $i "memory"))
2046             )
2047         )
2048     "#;
2049 
2050     let (mut store, instance) = {
2051         let engine = super::engine();
2052         let component = Component::new(&engine, component)?;
2053         let mut store = Store::new(&engine, ());
2054         let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
2055         (store, instance)
2056     };
2057 
2058     let list = instance
2059         .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "list-u8")?
2060         .call_and_post_return(&mut store, ())?
2061         .0;
2062     assert_eq!(
2063         list.as_le_slice(&store),
2064         [
2065             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2066             0x0e, 0x0f,
2067         ]
2068     );
2069     let list = instance
2070         .get_typed_func::<(), (WasmList<i8>,)>(&mut store, "list-i8")?
2071         .call_and_post_return(&mut store, ())?
2072         .0;
2073     assert_eq!(
2074         list.as_le_slice(&store),
2075         [
2076             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2077             0x0e, 0x0f,
2078         ]
2079     );
2080 
2081     let list = instance
2082         .get_typed_func::<(), (WasmList<u16>,)>(&mut store, "list-u16")?
2083         .call_and_post_return(&mut store, ())?
2084         .0;
2085     assert_eq!(
2086         list.as_le_slice(&store),
2087         [
2088             u16::to_le(0x01_00),
2089             u16::to_le(0x03_02),
2090             u16::to_le(0x05_04),
2091             u16::to_le(0x07_06),
2092             u16::to_le(0x09_08),
2093             u16::to_le(0x0b_0a),
2094             u16::to_le(0x0d_0c),
2095             u16::to_le(0x0f_0e),
2096         ]
2097     );
2098     let list = instance
2099         .get_typed_func::<(), (WasmList<i16>,)>(&mut store, "list-i16")?
2100         .call_and_post_return(&mut store, ())?
2101         .0;
2102     assert_eq!(
2103         list.as_le_slice(&store),
2104         [
2105             i16::to_le(0x01_00),
2106             i16::to_le(0x03_02),
2107             i16::to_le(0x05_04),
2108             i16::to_le(0x07_06),
2109             i16::to_le(0x09_08),
2110             i16::to_le(0x0b_0a),
2111             i16::to_le(0x0d_0c),
2112             i16::to_le(0x0f_0e),
2113         ]
2114     );
2115     let list = instance
2116         .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32")?
2117         .call_and_post_return(&mut store, ())?
2118         .0;
2119     assert_eq!(
2120         list.as_le_slice(&store),
2121         [
2122             u32::to_le(0x03_02_01_00),
2123             u32::to_le(0x07_06_05_04),
2124             u32::to_le(0x0b_0a_09_08),
2125             u32::to_le(0x0f_0e_0d_0c),
2126         ]
2127     );
2128     let list = instance
2129         .get_typed_func::<(), (WasmList<i32>,)>(&mut store, "list-i32")?
2130         .call_and_post_return(&mut store, ())?
2131         .0;
2132     assert_eq!(
2133         list.as_le_slice(&store),
2134         [
2135             i32::to_le(0x03_02_01_00),
2136             i32::to_le(0x07_06_05_04),
2137             i32::to_le(0x0b_0a_09_08),
2138             i32::to_le(0x0f_0e_0d_0c),
2139         ]
2140     );
2141     let list = instance
2142         .get_typed_func::<(), (WasmList<u64>,)>(&mut store, "list-u64")?
2143         .call_and_post_return(&mut store, ())?
2144         .0;
2145     assert_eq!(
2146         list.as_le_slice(&store),
2147         [
2148             u64::to_le(0x07_06_05_04_03_02_01_00),
2149             u64::to_le(0x0f_0e_0d_0c_0b_0a_09_08),
2150         ]
2151     );
2152     let list = instance
2153         .get_typed_func::<(), (WasmList<i64>,)>(&mut store, "list-i64")?
2154         .call_and_post_return(&mut store, ())?
2155         .0;
2156     assert_eq!(
2157         list.as_le_slice(&store),
2158         [
2159             i64::to_le(0x07_06_05_04_03_02_01_00),
2160             i64::to_le(0x0f_0e_0d_0c_0b_0a_09_08),
2161         ]
2162     );
2163 
2164     Ok(())
2165 }
2166 
2167 #[test]
2168 fn lower_then_lift() -> Result<()> {
2169     // First test simple integers when the import/export ABI happen to line up
2170     let component = r#"
2171 (component $c
2172   (import "f" (func $f (result u32)))
2173 
2174   (core func $f_lower
2175     (canon lower (func $f))
2176   )
2177   (func $f2 (result s32)
2178     (canon lift (core func $f_lower))
2179   )
2180   (export "f2" (func $f2))
2181 )
2182     "#;
2183 
2184     let engine = super::engine();
2185     let component = Component::new(&engine, component)?;
2186     let mut store = Store::new(&engine, ());
2187     let mut linker = Linker::new(&engine);
2188     linker.root().func_wrap("f", |_, _: ()| Ok((2u32,)))?;
2189     let instance = linker.instantiate(&mut store, &component)?;
2190 
2191     let f = instance.get_typed_func::<(), (i32,)>(&mut store, "f2")?;
2192     assert_eq!(f.call(&mut store, ())?, (2,));
2193 
2194     // First test strings when the import/export ABI happen to line up
2195     let component = format!(
2196         r#"
2197 (component $c
2198   (import "s" (func $f (param "a" string)))
2199 
2200   (core module $libc
2201     (memory (export "memory") 1)
2202     {REALLOC_AND_FREE}
2203   )
2204   (core instance $libc (instantiate $libc))
2205 
2206   (core func $f_lower
2207     (canon lower (func $f) (memory $libc "memory"))
2208   )
2209   (func $f2 (param "a" string)
2210     (canon lift (core func $f_lower)
2211         (memory $libc "memory")
2212         (realloc (func $libc "realloc"))
2213     )
2214   )
2215   (export "f" (func $f2))
2216 )
2217     "#
2218     );
2219 
2220     let component = Component::new(&engine, component)?;
2221     let mut store = Store::new(&engine, ());
2222     linker
2223         .root()
2224         .func_wrap("s", |store: StoreContextMut<'_, ()>, (x,): (WasmStr,)| {
2225             assert_eq!(x.to_str(&store)?, "hello");
2226             Ok(())
2227         })?;
2228     let instance = linker.instantiate(&mut store, &component)?;
2229 
2230     let f = instance.get_typed_func::<(&str,), ()>(&mut store, "f")?;
2231     f.call(&mut store, ("hello",))?;
2232 
2233     // Next test "type punning" where return values are reinterpreted just
2234     // because the return ABI happens to line up.
2235     let component = format!(
2236         r#"
2237 (component $c
2238   (import "s2" (func $f (param "a" string) (result u32)))
2239 
2240   (core module $libc
2241     (memory (export "memory") 1)
2242     {REALLOC_AND_FREE}
2243   )
2244   (core instance $libc (instantiate $libc))
2245 
2246   (core func $f_lower
2247     (canon lower (func $f) (memory $libc "memory"))
2248   )
2249   (func $f2 (param "a" string) (result string)
2250     (canon lift (core func $f_lower)
2251         (memory $libc "memory")
2252         (realloc (func $libc "realloc"))
2253     )
2254   )
2255   (export "f" (func $f2))
2256 )
2257     "#
2258     );
2259 
2260     let component = Component::new(&engine, component)?;
2261     let mut store = Store::new(&engine, ());
2262     linker
2263         .root()
2264         .func_wrap("s2", |store: StoreContextMut<'_, ()>, (x,): (WasmStr,)| {
2265             assert_eq!(x.to_str(&store)?, "hello");
2266             Ok((u32::MAX,))
2267         })?;
2268     let instance = linker.instantiate(&mut store, &component)?;
2269 
2270     let f = instance.get_typed_func::<(&str,), (WasmStr,)>(&mut store, "f")?;
2271     let err = f.call(&mut store, ("hello",)).err().unwrap();
2272     assert!(
2273         err.to_string().contains("return pointer not aligned"),
2274         "{}",
2275         err
2276     );
2277 
2278     Ok(())
2279 }
2280 
2281 #[test]
2282 fn errors_that_poison_instance() -> Result<()> {
2283     let component = format!(
2284         r#"
2285 (component $c
2286   (core module $m1
2287     (func (export "f1") unreachable)
2288     (func (export "f2"))
2289   )
2290   (core instance $m1 (instantiate $m1))
2291   (func (export "f1") (canon lift (core func $m1 "f1")))
2292   (func (export "f2") (canon lift (core func $m1 "f2")))
2293 
2294   (core module $m2
2295     (func (export "f") (param i32 i32))
2296     (func (export "r") (param i32 i32 i32 i32) (result i32) unreachable)
2297     (memory (export "m") 1)
2298   )
2299   (core instance $m2 (instantiate $m2))
2300   (func (export "f3") (param "a" string)
2301     (canon lift (core func $m2 "f") (realloc (func $m2 "r")) (memory $m2 "m"))
2302   )
2303 
2304   (core module $m3
2305     (func (export "f") (result i32) i32.const 1)
2306     (memory (export "m") 1)
2307   )
2308   (core instance $m3 (instantiate $m3))
2309   (func (export "f4") (result string)
2310     (canon lift (core func $m3 "f") (memory $m3 "m"))
2311   )
2312 )
2313     "#
2314     );
2315 
2316     let engine = super::engine();
2317     let component = Component::new(&engine, component)?;
2318     let mut store = Store::new(&engine, ());
2319     let linker = Linker::new(&engine);
2320     let instance = linker.instantiate(&mut store, &component)?;
2321     let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?;
2322     let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?;
2323     assert_unreachable(f1.call(&mut store, ()));
2324     assert_poisoned(f1.call(&mut store, ()));
2325     assert_poisoned(f2.call(&mut store, ()));
2326 
2327     let instance = linker.instantiate(&mut store, &component)?;
2328     let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?;
2329     assert_unreachable(f3.call(&mut store, ("x",)));
2330     assert_poisoned(f3.call(&mut store, ("x",)));
2331 
2332     let instance = linker.instantiate(&mut store, &component)?;
2333     let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?;
2334     assert!(f4.call(&mut store, ()).is_err());
2335     assert_poisoned(f4.call(&mut store, ()));
2336 
2337     return Ok(());
2338 
2339     #[track_caller]
2340     fn assert_unreachable<T>(err: Result<T>) {
2341         let err = match err {
2342             Ok(_) => panic!("expected an error"),
2343             Err(e) => e,
2344         };
2345         assert_eq!(
2346             err.downcast::<Trap>().unwrap(),
2347             Trap::UnreachableCodeReached
2348         );
2349     }
2350 
2351     #[track_caller]
2352     fn assert_poisoned<T>(err: Result<T>) {
2353         let err = match err {
2354             Ok(_) => panic!("expected an error"),
2355             Err(e) => e,
2356         };
2357         assert_eq!(
2358             err.downcast_ref::<Trap>(),
2359             Some(&Trap::CannotEnterComponent),
2360             "{err}",
2361         );
2362     }
2363 }
2364 
2365 #[test]
2366 fn run_export_with_internal_adapter() -> Result<()> {
2367     let component = r#"
2368 (component
2369   (type $t (func (param "a" u32) (result u32)))
2370   (component $a
2371     (core module $m
2372       (func (export "add-five") (param i32) (result i32)
2373         local.get 0
2374         i32.const 5
2375         i32.add)
2376     )
2377     (core instance $m (instantiate $m))
2378     (func (export "add-five") (type $t) (canon lift (core func $m "add-five")))
2379   )
2380   (component $b
2381     (import "interface-v1" (instance $i
2382       (export "add-five" (func (type $t)))))
2383     (core module $m
2384       (func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32))
2385       (func) ;; causes index out of bounds
2386       (func (export "run") (result i32) i32.const 0 call $add-five)
2387     )
2388     (core func $add-five (canon lower (func $i "add-five")))
2389     (core instance $i (instantiate 0
2390       (with "interface-0.1.0" (instance
2391         (export "add-five" (func $add-five))
2392       ))
2393     ))
2394     (func (result u32) (canon lift (core func $i "run")))
2395     (export "run" (func 1))
2396   )
2397   (instance $a (instantiate $a))
2398   (instance $b (instantiate $b (with "interface-v1" (instance $a))))
2399   (export "run" (func $b "run"))
2400 )
2401 "#;
2402     let engine = super::engine();
2403     let component = Component::new(&engine, component)?;
2404     let mut store = Store::new(&engine, ());
2405     let linker = Linker::new(&engine);
2406     let instance = linker.instantiate(&mut store, &component)?;
2407     let run = instance.get_typed_func::<(), (u32,)>(&mut store, "run")?;
2408     assert_eq!(run.call(&mut store, ())?, (5,));
2409     Ok(())
2410 }
2411