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::{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 "a" u8) (result "b" 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 = super::engine();
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
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,
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,)
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,)
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 "all-memory" (list u8))
878                 (result "pointer" u32)
879             ))
880             (func (export "many-param") (type $t)
881                 (canon lift
882                     (core func $i "foo")
883                     (memory $i "memory")
884                     (realloc (func $i "realloc"))
885                 )
886             )
887         )"#
888     );
889 
890     let engine = super::engine();
891     let component = Component::new(&engine, component)?;
892     let mut store = Store::new(&engine, ());
893     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
894     let func = instance.get_typed_func::<(
895         i8,
896         u64,
897         f32,
898         u8,
899         i16,
900         &str,
901         &[u32],
902         bool,
903         bool,
904         char,
905         &[bool],
906         &[char],
907         &[&str],
908     ), (WasmList<u8>, u32)>(&mut store, "many-param")?;
909 
910     let input = (
911         -100,
912         u64::MAX / 2,
913         f32::from_bits(CANON_32BIT_NAN | 1),
914         38,
915         18831,
916         "this is the first string",
917         [1, 2, 3, 4, 5, 6, 7, 8].as_slice(),
918         true,
919         false,
920         '��',
921         [false, true, false, true, true].as_slice(),
922         ['��', '��', '��', '��', '��'].as_slice(),
923         [
924             "the quick",
925             "brown fox",
926             "was too lazy",
927             "to jump over the dog",
928             "what a demanding dog",
929         ]
930         .as_slice(),
931     );
932     let (memory, pointer) = func.call(&mut store, input)?;
933     let memory = memory.as_le_slice(&store);
934 
935     let mut actual = &memory[pointer as usize..][..72];
936     assert_eq!(i8::from_le_bytes(*actual.take_n::<1>()), input.0);
937     actual.skip::<7>();
938     assert_eq!(u64::from_le_bytes(*actual.take_n::<8>()), input.1);
939     assert_eq!(u32::from_le_bytes(*actual.take_n::<4>()), CANON_32BIT_NAN);
940     assert_eq!(u8::from_le_bytes(*actual.take_n::<1>()), input.3);
941     actual.skip::<1>();
942     assert_eq!(i16::from_le_bytes(*actual.take_n::<2>()), input.4);
943     assert_eq!(actual.ptr_len(memory, 1), input.5.as_bytes());
944     let mut mem = actual.ptr_len(memory, 4);
945     for expected in input.6.iter() {
946         assert_eq!(u32::from_le_bytes(*mem.take_n::<4>()), *expected);
947     }
948     assert!(mem.is_empty());
949     assert_eq!(actual.take_n::<1>(), &[input.7 as u8]);
950     assert_eq!(actual.take_n::<1>(), &[input.8 as u8]);
951     actual.skip::<2>();
952     assert_eq!(u32::from_le_bytes(*actual.take_n::<4>()), input.9 as u32);
953 
954     // (list bool)
955     mem = actual.ptr_len(memory, 1);
956     for expected in input.10.iter() {
957         assert_eq!(mem.take_n::<1>(), &[*expected as u8]);
958     }
959     assert!(mem.is_empty());
960 
961     // (list char)
962     mem = actual.ptr_len(memory, 4);
963     for expected in input.11.iter() {
964         assert_eq!(u32::from_le_bytes(*mem.take_n::<4>()), *expected as u32);
965     }
966     assert!(mem.is_empty());
967 
968     // (list string)
969     mem = actual.ptr_len(memory, 8);
970     for expected in input.12.iter() {
971         let actual = mem.ptr_len(memory, 1);
972         assert_eq!(actual, expected.as_bytes());
973     }
974     assert!(mem.is_empty());
975     assert!(actual.is_empty());
976 
977     Ok(())
978 }
979 
980 #[test]
981 fn some_traps() -> Result<()> {
982     let middle_of_memory = (i32::MAX / 2) & (!0xff);
983     let component = format!(
984         r#"(component
985             (core module $m
986                 (memory (export "memory") 1)
987                 (func (export "take-many") (param i32))
988                 (func (export "take-list") (param i32 i32))
989 
990                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
991                     unreachable)
992             )
993             (core instance $i (instantiate $m))
994 
995             (func (export "take-list-unreachable") (param "a" (list u8))
996                 (canon lift (core func $i "take-list") (memory $i "memory") (realloc (func $i "realloc")))
997             )
998             (func (export "take-string-unreachable") (param "a" string)
999                 (canon lift (core func $i "take-list") (memory $i "memory") (realloc (func $i "realloc")))
1000             )
1001 
1002             (type $t (func
1003                 (param "s1" string)
1004                 (param "s2" string)
1005                 (param "s3" string)
1006                 (param "s4" string)
1007                 (param "s5" string)
1008                 (param "s6" string)
1009                 (param "s7" string)
1010                 (param "s8" string)
1011                 (param "s9" string)
1012                 (param "s10" string)
1013             ))
1014             (func (export "take-many-unreachable") (type $t)
1015                 (canon lift (core func $i "take-many") (memory $i "memory") (realloc (func $i "realloc")))
1016             )
1017 
1018             (core module $m2
1019                 (memory (export "memory") 1)
1020                 (func (export "take-many") (param i32))
1021                 (func (export "take-list") (param i32 i32))
1022 
1023                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1024                     i32.const {middle_of_memory})
1025             )
1026             (core instance $i2 (instantiate $m2))
1027 
1028             (func (export "take-list-base-oob") (param "a" (list u8))
1029                 (canon lift (core func $i2 "take-list") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1030             )
1031             (func (export "take-string-base-oob") (param "a" string)
1032                 (canon lift (core func $i2 "take-list") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1033             )
1034             (func (export "take-many-base-oob") (type $t)
1035                 (canon lift (core func $i2 "take-many") (memory $i2 "memory") (realloc (func $i2 "realloc")))
1036             )
1037 
1038             (core module $m3
1039                 (memory (export "memory") 1)
1040                 (func (export "take-many") (param i32))
1041                 (func (export "take-list") (param i32 i32))
1042 
1043                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1044                     i32.const 65532)
1045             )
1046             (core instance $i3 (instantiate $m3))
1047 
1048             (func (export "take-list-end-oob") (param "a" (list u8))
1049                 (canon lift (core func $i3 "take-list") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1050             )
1051             (func (export "take-string-end-oob") (param "a" string)
1052                 (canon lift (core func $i3 "take-list") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1053             )
1054             (func (export "take-many-end-oob") (type $t)
1055                 (canon lift (core func $i3 "take-many") (memory $i3 "memory") (realloc (func $i3 "realloc")))
1056             )
1057 
1058             (core module $m4
1059                 (memory (export "memory") 1)
1060                 (func (export "take-many") (param i32))
1061 
1062                 (global $cnt (mut i32) (i32.const 0))
1063                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1064                     global.get $cnt
1065                     if (result i32)
1066                         i32.const 100000
1067                     else
1068                         i32.const 1
1069                         global.set $cnt
1070                         i32.const 0
1071                     end
1072                 )
1073             )
1074             (core instance $i4 (instantiate $m4))
1075 
1076             (func (export "take-many-second-oob") (type $t)
1077                 (canon lift (core func $i4 "take-many") (memory $i4 "memory") (realloc (func $i4 "realloc")))
1078             )
1079         )"#
1080     );
1081 
1082     let engine = super::engine();
1083     let component = Component::new(&engine, component)?;
1084     let mut store = Store::new(&engine, ());
1085     let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
1086 
1087     // This should fail when calling the allocator function for the argument
1088     let err = instance(&mut store)?
1089         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-unreachable")?
1090         .call(&mut store, (&[],))
1091         .unwrap_err()
1092         .downcast::<Trap>()?;
1093     assert_eq!(err, Trap::UnreachableCodeReached);
1094 
1095     // This should fail when calling the allocator function for the argument
1096     let err = instance(&mut store)?
1097         .get_typed_func::<(&str,), ()>(&mut store, "take-string-unreachable")?
1098         .call(&mut store, ("",))
1099         .unwrap_err()
1100         .downcast::<Trap>()?;
1101     assert_eq!(err, Trap::UnreachableCodeReached);
1102 
1103     // This should fail when calling the allocator function for the space
1104     // to store the arguments (before arguments are even lowered)
1105     let err = instance(&mut store)?
1106         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1107             &mut store,
1108             "take-many-unreachable",
1109         )?
1110         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1111         .unwrap_err()
1112         .downcast::<Trap>()?;
1113     assert_eq!(err, Trap::UnreachableCodeReached);
1114 
1115     // Assert that when the base pointer returned by malloc is out of bounds
1116     // that errors are reported as such. Both empty and lists with contents
1117     // should all be invalid here.
1118     //
1119     // FIXME(WebAssembly/component-model#32) confirm the semantics here are
1120     // what's desired.
1121     #[track_caller]
1122     fn assert_oob(err: &anyhow::Error) {
1123         assert!(
1124             err.to_string()
1125                 .contains("realloc return: beyond end of memory"),
1126             "{:?}",
1127             err,
1128         );
1129     }
1130     let err = instance(&mut store)?
1131         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
1132         .call(&mut store, (&[],))
1133         .unwrap_err();
1134     assert_oob(&err);
1135     let err = instance(&mut store)?
1136         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-base-oob")?
1137         .call(&mut store, (&[1],))
1138         .unwrap_err();
1139     assert_oob(&err);
1140     let err = instance(&mut store)?
1141         .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
1142         .call(&mut store, ("",))
1143         .unwrap_err();
1144     assert_oob(&err);
1145     let err = instance(&mut store)?
1146         .get_typed_func::<(&str,), ()>(&mut store, "take-string-base-oob")?
1147         .call(&mut store, ("x",))
1148         .unwrap_err();
1149     assert_oob(&err);
1150     let err = instance(&mut store)?
1151         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1152             &mut store,
1153             "take-many-base-oob",
1154         )?
1155         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1156         .unwrap_err();
1157     assert_oob(&err);
1158 
1159     // Test here that when the returned pointer from malloc is one byte from the
1160     // end of memory that empty things are fine, but larger things are not.
1161 
1162     instance(&mut store)?
1163         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1164         .call_and_post_return(&mut store, (&[],))?;
1165     instance(&mut store)?
1166         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1167         .call_and_post_return(&mut store, (&[1, 2, 3, 4],))?;
1168     let err = instance(&mut store)?
1169         .get_typed_func::<(&[u8],), ()>(&mut store, "take-list-end-oob")?
1170         .call(&mut store, (&[1, 2, 3, 4, 5],))
1171         .unwrap_err();
1172     assert_oob(&err);
1173     instance(&mut store)?
1174         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1175         .call_and_post_return(&mut store, ("",))?;
1176     instance(&mut store)?
1177         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1178         .call_and_post_return(&mut store, ("abcd",))?;
1179     let err = instance(&mut store)?
1180         .get_typed_func::<(&str,), ()>(&mut store, "take-string-end-oob")?
1181         .call(&mut store, ("abcde",))
1182         .unwrap_err();
1183     assert_oob(&err);
1184     let err = instance(&mut store)?
1185         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1186             &mut store,
1187             "take-many-end-oob",
1188         )?
1189         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1190         .unwrap_err();
1191     assert_oob(&err);
1192 
1193     // For this function the first allocation, the space to store all the
1194     // arguments, is in-bounds but then all further allocations, such as for
1195     // each individual string, are all out of bounds.
1196     let err = instance(&mut store)?
1197         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1198             &mut store,
1199             "take-many-second-oob",
1200         )?
1201         .call(&mut store, ("", "", "", "", "", "", "", "", "", ""))
1202         .unwrap_err();
1203     assert_oob(&err);
1204     let err = instance(&mut store)?
1205         .get_typed_func::<(&str, &str, &str, &str, &str, &str, &str, &str, &str, &str), ()>(
1206             &mut store,
1207             "take-many-second-oob",
1208         )?
1209         .call(&mut store, ("", "", "", "", "", "", "", "", "", "x"))
1210         .unwrap_err();
1211     assert_oob(&err);
1212     Ok(())
1213 }
1214 
1215 #[test]
1216 fn char_bool_memory() -> Result<()> {
1217     let component = format!(
1218         r#"(component
1219             (core module $m
1220                 (memory (export "memory") 1)
1221                 (func (export "ret-tuple") (param i32 i32) (result i32)
1222                     (local $base i32)
1223 
1224                     ;; Allocate space for the return
1225                     (local.set $base
1226                         (call $realloc
1227                             (i32.const 0)
1228                             (i32.const 0)
1229                             (i32.const 4)
1230                             (i32.const 8)))
1231 
1232                     ;; store the boolean
1233                     (i32.store offset=0
1234                         (local.get $base)
1235                         (local.get 0))
1236 
1237                     ;; store the char
1238                     (i32.store offset=4
1239                         (local.get $base)
1240                         (local.get 1))
1241 
1242                     (local.get $base)
1243                 )
1244 
1245                 {REALLOC_AND_FREE}
1246             )
1247             (core instance $i (instantiate $m))
1248 
1249             (func (export "ret-tuple") (param "a" u32) (param "b" u32) (result "c" bool) (result "d" char)
1250                 (canon lift (core func $i "ret-tuple")
1251                     (memory $i "memory")
1252                     (realloc (func $i "realloc")))
1253             )
1254         )"#
1255     );
1256 
1257     let engine = super::engine();
1258     let component = Component::new(&engine, component)?;
1259     let mut store = Store::new(&engine, ());
1260     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1261     let func = instance.get_typed_func::<(u32, u32), (bool, char)>(&mut store, "ret-tuple")?;
1262 
1263     let ret = func.call(&mut store, (0, 'a' as u32))?;
1264     assert_eq!(ret, (false, 'a'));
1265     func.post_return(&mut store)?;
1266 
1267     let ret = func.call(&mut store, (1, '��' as u32))?;
1268     assert_eq!(ret, (true, '��'));
1269     func.post_return(&mut store)?;
1270 
1271     let ret = func.call(&mut store, (2, 'a' as u32))?;
1272     assert_eq!(ret, (true, 'a'));
1273     func.post_return(&mut store)?;
1274 
1275     assert!(func.call(&mut store, (0, 0xd800)).is_err());
1276 
1277     Ok(())
1278 }
1279 
1280 #[test]
1281 fn string_list_oob() -> Result<()> {
1282     let component = format!(
1283         r#"(component
1284             (core module $m
1285                 (memory (export "memory") 1)
1286                 (func (export "ret-list") (result i32)
1287                     (local $base i32)
1288 
1289                     ;; Allocate space for the return
1290                     (local.set $base
1291                         (call $realloc
1292                             (i32.const 0)
1293                             (i32.const 0)
1294                             (i32.const 4)
1295                             (i32.const 8)))
1296 
1297                     (i32.store offset=0
1298                         (local.get $base)
1299                         (i32.const 100000))
1300                     (i32.store offset=4
1301                         (local.get $base)
1302                         (i32.const 1))
1303 
1304                     (local.get $base)
1305                 )
1306 
1307                 {REALLOC_AND_FREE}
1308             )
1309             (core instance $i (instantiate $m))
1310 
1311             (func (export "ret-list-u8") (result (list u8))
1312                 (canon lift (core func $i "ret-list")
1313                     (memory $i "memory")
1314                     (realloc (func $i "realloc"))
1315                 )
1316             )
1317             (func (export "ret-string") (result string)
1318                 (canon lift (core func $i "ret-list")
1319                     (memory $i "memory")
1320                     (realloc (func $i "realloc"))
1321                 )
1322             )
1323         )"#
1324     );
1325 
1326     let engine = super::engine();
1327     let component = Component::new(&engine, component)?;
1328     let mut store = Store::new(&engine, ());
1329     let ret_list_u8 = Linker::new(&engine)
1330         .instantiate(&mut store, &component)?
1331         .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "ret-list-u8")?;
1332     let ret_string = Linker::new(&engine)
1333         .instantiate(&mut store, &component)?
1334         .get_typed_func::<(), (WasmStr,)>(&mut store, "ret-string")?;
1335 
1336     let err = ret_list_u8.call(&mut store, ()).err().unwrap();
1337     assert!(err.to_string().contains("out of bounds"), "{}", err);
1338 
1339     let err = ret_string.call(&mut store, ()).err().unwrap();
1340     assert!(err.to_string().contains("out of bounds"), "{}", err);
1341 
1342     Ok(())
1343 }
1344 
1345 #[test]
1346 fn tuples() -> Result<()> {
1347     let component = format!(
1348         r#"(component
1349             (core module $m
1350                 (memory (export "memory") 1)
1351                 (func (export "foo")
1352                     (param i32 f64 i32)
1353                     (result i32)
1354 
1355                     local.get 0
1356                     i32.const 0
1357                     i32.ne
1358                     if unreachable end
1359 
1360                     local.get 1
1361                     f64.const 1
1362                     f64.ne
1363                     if unreachable end
1364 
1365                     local.get 2
1366                     i32.const 2
1367                     i32.ne
1368                     if unreachable end
1369 
1370                     i32.const 3
1371                 )
1372             )
1373             (core instance $i (instantiate $m))
1374 
1375             (func (export "foo")
1376                 (param "a" (tuple s32 float64))
1377                 (param "b" (tuple s8))
1378                 (result (tuple u16))
1379                 (canon lift (core func $i "foo"))
1380             )
1381         )"#
1382     );
1383 
1384     let engine = super::engine();
1385     let component = Component::new(&engine, component)?;
1386     let mut store = Store::new(&engine, ());
1387     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1388     let foo = instance.get_typed_func::<((i32, f64), (i8,)), ((u16,),)>(&mut store, "foo")?;
1389     assert_eq!(foo.call(&mut store, ((0, 1.0), (2,)))?, ((3,),));
1390 
1391     Ok(())
1392 }
1393 
1394 #[test]
1395 fn option() -> Result<()> {
1396     let component = format!(
1397         r#"(component
1398             (core module $m
1399                 (memory (export "memory") 1)
1400                 (func (export "pass1") (param i32 i32) (result i32)
1401                     (local $base i32)
1402                     (local.set $base
1403                         (call $realloc
1404                             (i32.const 0)
1405                             (i32.const 0)
1406                             (i32.const 4)
1407                             (i32.const 8)))
1408 
1409                     (i32.store offset=0
1410                         (local.get $base)
1411                         (local.get 0))
1412                     (i32.store offset=4
1413                         (local.get $base)
1414                         (local.get 1))
1415 
1416                     (local.get $base)
1417                 )
1418                 (func (export "pass2") (param i32 i32 i32) (result i32)
1419                     (local $base i32)
1420                     (local.set $base
1421                         (call $realloc
1422                             (i32.const 0)
1423                             (i32.const 0)
1424                             (i32.const 4)
1425                             (i32.const 12)))
1426 
1427                     (i32.store offset=0
1428                         (local.get $base)
1429                         (local.get 0))
1430                     (i32.store offset=4
1431                         (local.get $base)
1432                         (local.get 1))
1433                     (i32.store offset=8
1434                         (local.get $base)
1435                         (local.get 2))
1436 
1437                     (local.get $base)
1438                 )
1439 
1440                 {REALLOC_AND_FREE}
1441             )
1442             (core instance $i (instantiate $m))
1443 
1444             (func (export "option-u8-to-tuple") (param "a" (option u8)) (result "a" u32) (result "b" u32)
1445                 (canon lift (core func $i "pass1") (memory $i "memory"))
1446             )
1447             (func (export "option-u32-to-tuple") (param "a" (option u32)) (result "a" u32) (result "b" u32)
1448                 (canon lift (core func $i "pass1") (memory $i "memory"))
1449             )
1450             (func (export "option-string-to-tuple") (param "a" (option string)) (result "a" u32) (result "b" string)
1451                 (canon lift
1452                     (core func $i "pass2")
1453                     (memory $i "memory")
1454                     (realloc (func $i "realloc"))
1455                 )
1456             )
1457             (func (export "to-option-u8") (param "a" u32) (param "b" u32) (result (option u8))
1458                 (canon lift (core func $i "pass1") (memory $i "memory"))
1459             )
1460             (func (export "to-option-u32") (param "a" u32) (param "b" u32) (result (option u32))
1461                 (canon lift
1462                     (core func $i "pass1")
1463                     (memory $i "memory")
1464                 )
1465             )
1466             (func (export "to-option-string") (param "a" u32) (param "b" string) (result (option string))
1467                 (canon lift
1468                     (core func $i "pass2")
1469                     (memory $i "memory")
1470                     (realloc (func $i "realloc"))
1471                 )
1472             )
1473         )"#
1474     );
1475 
1476     let engine = super::engine();
1477     let component = Component::new(&engine, component)?;
1478     let mut store = Store::new(&engine, ());
1479     let linker = Linker::new(&engine);
1480     let instance = linker.instantiate(&mut store, &component)?;
1481 
1482     let option_u8_to_tuple =
1483         instance.get_typed_func::<(Option<u8>,), (u32, u32)>(&mut store, "option-u8-to-tuple")?;
1484     assert_eq!(option_u8_to_tuple.call(&mut store, (None,))?, (0, 0));
1485     option_u8_to_tuple.post_return(&mut store)?;
1486     assert_eq!(option_u8_to_tuple.call(&mut store, (Some(0),))?, (1, 0));
1487     option_u8_to_tuple.post_return(&mut store)?;
1488     assert_eq!(option_u8_to_tuple.call(&mut store, (Some(100),))?, (1, 100));
1489     option_u8_to_tuple.post_return(&mut store)?;
1490 
1491     let option_u32_to_tuple =
1492         instance.get_typed_func::<(Option<u32>,), (u32, u32)>(&mut store, "option-u32-to-tuple")?;
1493     assert_eq!(option_u32_to_tuple.call(&mut store, (None,))?, (0, 0));
1494     option_u32_to_tuple.post_return(&mut store)?;
1495     assert_eq!(option_u32_to_tuple.call(&mut store, (Some(0),))?, (1, 0));
1496     option_u32_to_tuple.post_return(&mut store)?;
1497     assert_eq!(
1498         option_u32_to_tuple.call(&mut store, (Some(100),))?,
1499         (1, 100)
1500     );
1501     option_u32_to_tuple.post_return(&mut store)?;
1502 
1503     let option_string_to_tuple = instance
1504         .get_typed_func::<(Option<&str>,), (u32, WasmStr)>(&mut store, "option-string-to-tuple")?;
1505     let (a, b) = option_string_to_tuple.call(&mut store, (None,))?;
1506     assert_eq!(a, 0);
1507     assert_eq!(b.to_str(&store)?, "");
1508     option_string_to_tuple.post_return(&mut store)?;
1509     let (a, b) = option_string_to_tuple.call(&mut store, (Some(""),))?;
1510     assert_eq!(a, 1);
1511     assert_eq!(b.to_str(&store)?, "");
1512     option_string_to_tuple.post_return(&mut store)?;
1513     let (a, b) = option_string_to_tuple.call(&mut store, (Some("hello"),))?;
1514     assert_eq!(a, 1);
1515     assert_eq!(b.to_str(&store)?, "hello");
1516     option_string_to_tuple.post_return(&mut store)?;
1517 
1518     let instance = linker.instantiate(&mut store, &component)?;
1519     let to_option_u8 =
1520         instance.get_typed_func::<(u32, u32), (Option<u8>,)>(&mut store, "to-option-u8")?;
1521     assert_eq!(to_option_u8.call(&mut store, (0x00_00, 0))?, (None,));
1522     to_option_u8.post_return(&mut store)?;
1523     assert_eq!(to_option_u8.call(&mut store, (0x00_01, 0))?, (Some(0),));
1524     to_option_u8.post_return(&mut store)?;
1525     assert_eq!(to_option_u8.call(&mut store, (0xfd_01, 0))?, (Some(0xfd),));
1526     to_option_u8.post_return(&mut store)?;
1527     assert!(to_option_u8.call(&mut store, (0x00_02, 0)).is_err());
1528 
1529     let instance = linker.instantiate(&mut store, &component)?;
1530     let to_option_u32 =
1531         instance.get_typed_func::<(u32, u32), (Option<u32>,)>(&mut store, "to-option-u32")?;
1532     assert_eq!(to_option_u32.call(&mut store, (0, 0))?, (None,));
1533     to_option_u32.post_return(&mut store)?;
1534     assert_eq!(to_option_u32.call(&mut store, (1, 0))?, (Some(0),));
1535     to_option_u32.post_return(&mut store)?;
1536     assert_eq!(
1537         to_option_u32.call(&mut store, (1, 0x1234fead))?,
1538         (Some(0x1234fead),)
1539     );
1540     to_option_u32.post_return(&mut store)?;
1541     assert!(to_option_u32.call(&mut store, (2, 0)).is_err());
1542 
1543     let instance = linker.instantiate(&mut store, &component)?;
1544     let to_option_string = instance
1545         .get_typed_func::<(u32, &str), (Option<WasmStr>,)>(&mut store, "to-option-string")?;
1546     let ret = to_option_string.call(&mut store, (0, ""))?.0;
1547     assert!(ret.is_none());
1548     to_option_string.post_return(&mut store)?;
1549     let ret = to_option_string.call(&mut store, (1, ""))?.0;
1550     assert_eq!(ret.unwrap().to_str(&store)?, "");
1551     to_option_string.post_return(&mut store)?;
1552     let ret = to_option_string.call(&mut store, (1, "cheesecake"))?.0;
1553     assert_eq!(ret.unwrap().to_str(&store)?, "cheesecake");
1554     to_option_string.post_return(&mut store)?;
1555     assert!(to_option_string.call(&mut store, (2, "")).is_err());
1556 
1557     Ok(())
1558 }
1559 
1560 #[test]
1561 fn expected() -> Result<()> {
1562     let component = format!(
1563         r#"(component
1564             (core module $m
1565                 (memory (export "memory") 1)
1566                 (func (export "pass0") (param i32) (result i32)
1567                     local.get 0
1568                 )
1569                 (func (export "pass1") (param i32 i32) (result i32)
1570                     (local $base i32)
1571                     (local.set $base
1572                         (call $realloc
1573                             (i32.const 0)
1574                             (i32.const 0)
1575                             (i32.const 4)
1576                             (i32.const 8)))
1577 
1578                     (i32.store offset=0
1579                         (local.get $base)
1580                         (local.get 0))
1581                     (i32.store offset=4
1582                         (local.get $base)
1583                         (local.get 1))
1584 
1585                     (local.get $base)
1586                 )
1587                 (func (export "pass2") (param i32 i32 i32) (result i32)
1588                     (local $base i32)
1589                     (local.set $base
1590                         (call $realloc
1591                             (i32.const 0)
1592                             (i32.const 0)
1593                             (i32.const 4)
1594                             (i32.const 12)))
1595 
1596                     (i32.store offset=0
1597                         (local.get $base)
1598                         (local.get 0))
1599                     (i32.store offset=4
1600                         (local.get $base)
1601                         (local.get 1))
1602                     (i32.store offset=8
1603                         (local.get $base)
1604                         (local.get 2))
1605 
1606                     (local.get $base)
1607                 )
1608 
1609                 {REALLOC_AND_FREE}
1610             )
1611             (core instance $i (instantiate $m))
1612 
1613             (func (export "take-expected-unit") (param "a" (result)) (result u32)
1614                 (canon lift (core func $i "pass0"))
1615             )
1616             (func (export "take-expected-u8-f32") (param "a" (result u8 (error float32))) (result "a" u32) (result "b" u32)
1617                 (canon lift (core func $i "pass1") (memory $i "memory"))
1618             )
1619             (type $list (list u8))
1620             (func (export "take-expected-string") (param "a" (result string (error $list))) (result "a" u32) (result "b" string)
1621                 (canon lift
1622                     (core func $i "pass2")
1623                     (memory $i "memory")
1624                     (realloc (func $i "realloc"))
1625                 )
1626             )
1627             (func (export "to-expected-unit") (param "a" u32) (result (result))
1628                 (canon lift (core func $i "pass0"))
1629             )
1630             (func (export "to-expected-s16-f32") (param "a" u32) (param "b" u32) (result (result s16 (error float32)))
1631                 (canon lift
1632                     (core func $i "pass1")
1633                     (memory $i "memory")
1634                     (realloc (func $i "realloc"))
1635                 )
1636             )
1637         )"#
1638     );
1639 
1640     let engine = super::engine();
1641     let component = Component::new(&engine, component)?;
1642     let mut store = Store::new(&engine, ());
1643     let linker = Linker::new(&engine);
1644     let instance = linker.instantiate(&mut store, &component)?;
1645     let take_expected_unit =
1646         instance.get_typed_func::<(Result<(), ()>,), (u32,)>(&mut store, "take-expected-unit")?;
1647     assert_eq!(take_expected_unit.call(&mut store, (Ok(()),))?, (0,));
1648     take_expected_unit.post_return(&mut store)?;
1649     assert_eq!(take_expected_unit.call(&mut store, (Err(()),))?, (1,));
1650     take_expected_unit.post_return(&mut store)?;
1651 
1652     let take_expected_u8_f32 = instance
1653         .get_typed_func::<(Result<u8, f32>,), (u32, u32)>(&mut store, "take-expected-u8-f32")?;
1654     assert_eq!(take_expected_u8_f32.call(&mut store, (Ok(1),))?, (0, 1));
1655     take_expected_u8_f32.post_return(&mut store)?;
1656     assert_eq!(
1657         take_expected_u8_f32.call(&mut store, (Err(2.0),))?,
1658         (1, 2.0f32.to_bits())
1659     );
1660     take_expected_u8_f32.post_return(&mut store)?;
1661 
1662     let take_expected_string = instance.get_typed_func::<(Result<&str, &[u8]>,), (u32, WasmStr)>(
1663         &mut store,
1664         "take-expected-string",
1665     )?;
1666     let (a, b) = take_expected_string.call(&mut store, (Ok("hello"),))?;
1667     assert_eq!(a, 0);
1668     assert_eq!(b.to_str(&store)?, "hello");
1669     take_expected_string.post_return(&mut store)?;
1670     let (a, b) = take_expected_string.call(&mut store, (Err(b"goodbye"),))?;
1671     assert_eq!(a, 1);
1672     assert_eq!(b.to_str(&store)?, "goodbye");
1673     take_expected_string.post_return(&mut store)?;
1674 
1675     let instance = linker.instantiate(&mut store, &component)?;
1676     let to_expected_unit =
1677         instance.get_typed_func::<(u32,), (Result<(), ()>,)>(&mut store, "to-expected-unit")?;
1678     assert_eq!(to_expected_unit.call(&mut store, (0,))?, (Ok(()),));
1679     to_expected_unit.post_return(&mut store)?;
1680     assert_eq!(to_expected_unit.call(&mut store, (1,))?, (Err(()),));
1681     to_expected_unit.post_return(&mut store)?;
1682     let err = to_expected_unit.call(&mut store, (2,)).unwrap_err();
1683     assert!(err.to_string().contains("invalid expected"), "{}", err);
1684 
1685     let instance = linker.instantiate(&mut store, &component)?;
1686     let to_expected_s16_f32 = instance
1687         .get_typed_func::<(u32, u32), (Result<i16, f32>,)>(&mut store, "to-expected-s16-f32")?;
1688     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 0))?, (Ok(0),));
1689     to_expected_s16_f32.post_return(&mut store)?;
1690     assert_eq!(to_expected_s16_f32.call(&mut store, (0, 100))?, (Ok(100),));
1691     to_expected_s16_f32.post_return(&mut store)?;
1692     assert_eq!(
1693         to_expected_s16_f32.call(&mut store, (1, 1.0f32.to_bits()))?,
1694         (Err(1.0),)
1695     );
1696     to_expected_s16_f32.post_return(&mut store)?;
1697     let ret = to_expected_s16_f32
1698         .call(&mut store, (1, CANON_32BIT_NAN | 1))?
1699         .0;
1700     assert_eq!(ret.unwrap_err().to_bits(), CANON_32BIT_NAN);
1701     to_expected_s16_f32.post_return(&mut store)?;
1702     assert!(to_expected_s16_f32.call(&mut store, (2, 0)).is_err());
1703 
1704     Ok(())
1705 }
1706 
1707 #[test]
1708 fn fancy_list() -> Result<()> {
1709     let component = format!(
1710         r#"(component
1711             (core module $m
1712                 (memory (export "memory") 1)
1713                 (func (export "take") (param i32 i32) (result i32)
1714                     (local $base i32)
1715                     (local.set $base
1716                         (call $realloc
1717                             (i32.const 0)
1718                             (i32.const 0)
1719                             (i32.const 4)
1720                             (i32.const 16)))
1721 
1722                     (i32.store offset=0
1723                         (local.get $base)
1724                         (local.get 0))
1725                     (i32.store offset=4
1726                         (local.get $base)
1727                         (local.get 1))
1728                     (i32.store offset=8
1729                         (local.get $base)
1730                         (i32.const 0))
1731                     (i32.store offset=12
1732                         (local.get $base)
1733                         (i32.mul
1734                             (memory.size)
1735                             (i32.const 65536)))
1736 
1737                     (local.get $base)
1738                 )
1739 
1740                 {REALLOC_AND_FREE}
1741             )
1742             (core instance $i (instantiate $m))
1743 
1744             (type $a (option u8))
1745             (type $b (result (error string)))
1746             (type $input (list (tuple $a $b)))
1747             (func (export "take")
1748                 (param "a" $input)
1749                 (result "ptr" u32)
1750                 (result "len" u32)
1751                 (result "list" (list u8))
1752                 (canon lift
1753                     (core func $i "take")
1754                     (memory $i "memory")
1755                     (realloc (func $i "realloc"))
1756                 )
1757             )
1758         )"#
1759     );
1760 
1761     let engine = super::engine();
1762     let component = Component::new(&engine, component)?;
1763     let mut store = Store::new(&engine, ());
1764     let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1765 
1766     let func = instance
1767         .get_typed_func::<(&[(Option<u8>, Result<(), &str>)],), (u32, u32, WasmList<u8>)>(
1768             &mut store, "take",
1769         )?;
1770 
1771     let input = [
1772         (None, Ok(())),
1773         (Some(2), Err("hello there")),
1774         (Some(200), Err("general kenobi")),
1775     ];
1776     let (ptr, len, list) = func.call(&mut store, (&input,))?;
1777     let memory = list.as_le_slice(&store);
1778     let ptr = usize::try_from(ptr).unwrap();
1779     let len = usize::try_from(len).unwrap();
1780     let mut array = &memory[ptr..][..len * 16];
1781 
1782     for (a, b) in input.iter() {
1783         match a {
1784             Some(val) => {
1785                 assert_eq!(*array.take_n::<2>(), [1, *val]);
1786             }
1787             None => {
1788                 assert_eq!(*array.take_n::<1>(), [0]);
1789                 array.skip::<1>();
1790             }
1791         }
1792         array.skip::<2>();
1793         match b {
1794             Ok(()) => {
1795                 assert_eq!(*array.take_n::<1>(), [0]);
1796                 array.skip::<11>();
1797             }
1798             Err(s) => {
1799                 assert_eq!(*array.take_n::<1>(), [1]);
1800                 array.skip::<3>();
1801                 assert_eq!(array.ptr_len(memory, 1), s.as_bytes());
1802             }
1803         }
1804     }
1805     assert!(array.is_empty());
1806 
1807     Ok(())
1808 }
1809 
1810 trait SliceExt<'a> {
1811     fn take_n<const N: usize>(&mut self) -> &'a [u8; N];
1812 
1813     fn skip<const N: usize>(&mut self) {
1814         self.take_n::<N>();
1815     }
1816 
1817     fn ptr_len<'b>(&mut self, all_memory: &'b [u8], size: usize) -> &'b [u8] {
1818         let ptr = u32::from_le_bytes(*self.take_n::<4>());
1819         let len = u32::from_le_bytes(*self.take_n::<4>());
1820         let ptr = usize::try_from(ptr).unwrap();
1821         let len = usize::try_from(len).unwrap();
1822         &all_memory[ptr..][..len * size]
1823     }
1824 }
1825 
1826 impl<'a> SliceExt<'a> for &'a [u8] {
1827     fn take_n<const N: usize>(&mut self) -> &'a [u8; N] {
1828         let (a, b) = self.split_at(N);
1829         *self = b;
1830         a.try_into().unwrap()
1831     }
1832 }
1833 
1834 #[test]
1835 fn invalid_alignment() -> Result<()> {
1836     let component = format!(
1837         r#"(component
1838             (core module $m
1839                 (memory (export "memory") 1)
1840                 (func (export "realloc") (param i32 i32 i32 i32) (result i32)
1841                     i32.const 1)
1842 
1843                 (func (export "take-i32") (param i32))
1844                 (func (export "ret-1") (result i32) i32.const 1)
1845                 (func (export "ret-unaligned-list") (result i32)
1846                     (i32.store offset=0 (i32.const 8) (i32.const 1))
1847                     (i32.store offset=4 (i32.const 8) (i32.const 1))
1848                     i32.const 8)
1849             )
1850             (core instance $i (instantiate $m))
1851 
1852             (func (export "many-params")
1853                 (param "s1" string) (param "s2" string) (param "s3" string) (param "s4" string)
1854                 (param "s5" string) (param "s6" string) (param "s7" string) (param "s8" string)
1855                 (param "s9" string) (param "s10" string) (param "s11" string) (param "s12" string)
1856                 (canon lift
1857                     (core func $i "take-i32")
1858                     (memory $i "memory")
1859                     (realloc (func $i "realloc"))
1860                 )
1861             )
1862             (func (export "string-ret") (result string)
1863                 (canon lift
1864                     (core func $i "ret-1")
1865                     (memory $i "memory")
1866                     (realloc (func $i "realloc"))
1867                 )
1868             )
1869             (func (export "list-u32-ret") (result (list u32))
1870                 (canon lift
1871                     (core func $i "ret-unaligned-list")
1872                     (memory $i "memory")
1873                     (realloc (func $i "realloc"))
1874                 )
1875             )
1876         )"#
1877     );
1878 
1879     let engine = super::engine();
1880     let component = Component::new(&engine, component)?;
1881     let mut store = Store::new(&engine, ());
1882     let instance = |store: &mut Store<()>| Linker::new(&engine).instantiate(store, &component);
1883 
1884     let err = instance(&mut store)?
1885         .get_typed_func::<(
1886             &str,
1887             &str,
1888             &str,
1889             &str,
1890             &str,
1891             &str,
1892             &str,
1893             &str,
1894             &str,
1895             &str,
1896             &str,
1897             &str,
1898         ), ()>(&mut store, "many-params")?
1899         .call(&mut store, ("", "", "", "", "", "", "", "", "", "", "", ""))
1900         .unwrap_err();
1901     assert!(
1902         err.to_string()
1903             .contains("realloc return: result not aligned"),
1904         "{}",
1905         err
1906     );
1907 
1908     let err = instance(&mut store)?
1909         .get_typed_func::<(), (WasmStr,)>(&mut store, "string-ret")?
1910         .call(&mut store, ())
1911         .err()
1912         .unwrap();
1913     assert!(
1914         err.to_string().contains("return pointer not aligned"),
1915         "{}",
1916         err
1917     );
1918 
1919     let err = instance(&mut store)?
1920         .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32-ret")?
1921         .call(&mut store, ())
1922         .err()
1923         .unwrap();
1924     assert!(
1925         err.to_string().contains("list pointer is not aligned"),
1926         "{}",
1927         err
1928     );
1929 
1930     Ok(())
1931 }
1932 
1933 #[test]
1934 fn drop_component_still_works() -> Result<()> {
1935     let component = r#"
1936         (component
1937             (import "f" (func $f))
1938 
1939             (core func $f_lower
1940                 (canon lower (func $f))
1941             )
1942             (core module $m
1943                 (import "" "" (func $f))
1944 
1945                 (func $f2
1946                     call $f
1947                     call $f
1948                 )
1949 
1950                 (export "f" (func $f2))
1951             )
1952             (core instance $i (instantiate $m
1953                 (with "" (instance
1954                     (export "" (func $f_lower))
1955                 ))
1956             ))
1957             (func (export "g")
1958                 (canon lift
1959                     (core func $i "f")
1960                 )
1961             )
1962         )
1963     "#;
1964 
1965     let (mut store, instance) = {
1966         let engine = super::engine();
1967         let component = Component::new(&engine, component)?;
1968         let mut store = Store::new(&engine, 0);
1969         let mut linker = Linker::new(&engine);
1970         linker.root().func_wrap(
1971             "f",
1972             |mut store: StoreContextMut<'_, u32>, _: ()| -> Result<()> {
1973                 *store.data_mut() += 1;
1974                 Ok(())
1975             },
1976         )?;
1977         let instance = linker.instantiate(&mut store, &component)?;
1978         (store, instance)
1979     };
1980 
1981     let f = instance.get_typed_func::<(), ()>(&mut store, "g")?;
1982     assert_eq!(*store.data(), 0);
1983     f.call(&mut store, ())?;
1984     assert_eq!(*store.data(), 2);
1985 
1986     Ok(())
1987 }
1988 
1989 #[test]
1990 fn raw_slice_of_various_types() -> Result<()> {
1991     let component = r#"
1992         (component
1993             (core module $m
1994                 (memory (export "memory") 1)
1995 
1996                 (func (export "list8") (result i32)
1997                     (call $setup_list (i32.const 16))
1998                 )
1999                 (func (export "list16") (result i32)
2000                     (call $setup_list (i32.const 8))
2001                 )
2002                 (func (export "list32") (result i32)
2003                     (call $setup_list (i32.const 4))
2004                 )
2005                 (func (export "list64") (result i32)
2006                     (call $setup_list (i32.const 2))
2007                 )
2008 
2009                 (func $setup_list (param i32) (result i32)
2010                     (i32.store offset=0 (i32.const 100) (i32.const 8))
2011                     (i32.store offset=4 (i32.const 100) (local.get 0))
2012                     i32.const 100
2013                 )
2014 
2015                 (data (i32.const 8) "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f")
2016             )
2017             (core instance $i (instantiate $m))
2018             (func (export "list-u8") (result (list u8))
2019                 (canon lift (core func $i "list8") (memory $i "memory"))
2020             )
2021             (func (export "list-i8") (result (list s8))
2022                 (canon lift (core func $i "list8") (memory $i "memory"))
2023             )
2024             (func (export "list-u16") (result (list u16))
2025                 (canon lift (core func $i "list16") (memory $i "memory"))
2026             )
2027             (func (export "list-i16") (result (list s16))
2028                 (canon lift (core func $i "list16") (memory $i "memory"))
2029             )
2030             (func (export "list-u32") (result (list u32))
2031                 (canon lift (core func $i "list32") (memory $i "memory"))
2032             )
2033             (func (export "list-i32") (result (list s32))
2034                 (canon lift (core func $i "list32") (memory $i "memory"))
2035             )
2036             (func (export "list-u64") (result (list u64))
2037                 (canon lift (core func $i "list64") (memory $i "memory"))
2038             )
2039             (func (export "list-i64") (result (list s64))
2040                 (canon lift (core func $i "list64") (memory $i "memory"))
2041             )
2042         )
2043     "#;
2044 
2045     let (mut store, instance) = {
2046         let engine = super::engine();
2047         let component = Component::new(&engine, component)?;
2048         let mut store = Store::new(&engine, ());
2049         let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
2050         (store, instance)
2051     };
2052 
2053     let list = instance
2054         .get_typed_func::<(), (WasmList<u8>,)>(&mut store, "list-u8")?
2055         .call_and_post_return(&mut store, ())?
2056         .0;
2057     assert_eq!(
2058         list.as_le_slice(&store),
2059         [
2060             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2061             0x0e, 0x0f,
2062         ]
2063     );
2064     let list = instance
2065         .get_typed_func::<(), (WasmList<i8>,)>(&mut store, "list-i8")?
2066         .call_and_post_return(&mut store, ())?
2067         .0;
2068     assert_eq!(
2069         list.as_le_slice(&store),
2070         [
2071             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
2072             0x0e, 0x0f,
2073         ]
2074     );
2075 
2076     let list = instance
2077         .get_typed_func::<(), (WasmList<u16>,)>(&mut store, "list-u16")?
2078         .call_and_post_return(&mut store, ())?
2079         .0;
2080     assert_eq!(
2081         list.as_le_slice(&store),
2082         [
2083             u16::to_le(0x01_00),
2084             u16::to_le(0x03_02),
2085             u16::to_le(0x05_04),
2086             u16::to_le(0x07_06),
2087             u16::to_le(0x09_08),
2088             u16::to_le(0x0b_0a),
2089             u16::to_le(0x0d_0c),
2090             u16::to_le(0x0f_0e),
2091         ]
2092     );
2093     let list = instance
2094         .get_typed_func::<(), (WasmList<i16>,)>(&mut store, "list-i16")?
2095         .call_and_post_return(&mut store, ())?
2096         .0;
2097     assert_eq!(
2098         list.as_le_slice(&store),
2099         [
2100             i16::to_le(0x01_00),
2101             i16::to_le(0x03_02),
2102             i16::to_le(0x05_04),
2103             i16::to_le(0x07_06),
2104             i16::to_le(0x09_08),
2105             i16::to_le(0x0b_0a),
2106             i16::to_le(0x0d_0c),
2107             i16::to_le(0x0f_0e),
2108         ]
2109     );
2110     let list = instance
2111         .get_typed_func::<(), (WasmList<u32>,)>(&mut store, "list-u32")?
2112         .call_and_post_return(&mut store, ())?
2113         .0;
2114     assert_eq!(
2115         list.as_le_slice(&store),
2116         [
2117             u32::to_le(0x03_02_01_00),
2118             u32::to_le(0x07_06_05_04),
2119             u32::to_le(0x0b_0a_09_08),
2120             u32::to_le(0x0f_0e_0d_0c),
2121         ]
2122     );
2123     let list = instance
2124         .get_typed_func::<(), (WasmList<i32>,)>(&mut store, "list-i32")?
2125         .call_and_post_return(&mut store, ())?
2126         .0;
2127     assert_eq!(
2128         list.as_le_slice(&store),
2129         [
2130             i32::to_le(0x03_02_01_00),
2131             i32::to_le(0x07_06_05_04),
2132             i32::to_le(0x0b_0a_09_08),
2133             i32::to_le(0x0f_0e_0d_0c),
2134         ]
2135     );
2136     let list = instance
2137         .get_typed_func::<(), (WasmList<u64>,)>(&mut store, "list-u64")?
2138         .call_and_post_return(&mut store, ())?
2139         .0;
2140     assert_eq!(
2141         list.as_le_slice(&store),
2142         [
2143             u64::to_le(0x07_06_05_04_03_02_01_00),
2144             u64::to_le(0x0f_0e_0d_0c_0b_0a_09_08),
2145         ]
2146     );
2147     let list = instance
2148         .get_typed_func::<(), (WasmList<i64>,)>(&mut store, "list-i64")?
2149         .call_and_post_return(&mut store, ())?
2150         .0;
2151     assert_eq!(
2152         list.as_le_slice(&store),
2153         [
2154             i64::to_le(0x07_06_05_04_03_02_01_00),
2155             i64::to_le(0x0f_0e_0d_0c_0b_0a_09_08),
2156         ]
2157     );
2158 
2159     Ok(())
2160 }
2161 
2162 #[test]
2163 fn lower_then_lift() -> Result<()> {
2164     // First test simple integers when the import/export ABI happen to line up
2165     let component = r#"
2166 (component $c
2167   (import "f" (func $f (result u32)))
2168 
2169   (core func $f_lower
2170     (canon lower (func $f))
2171   )
2172   (func $f2 (result s32)
2173     (canon lift (core func $f_lower))
2174   )
2175   (export "f2" (func $f2))
2176 )
2177     "#;
2178 
2179     let engine = super::engine();
2180     let component = Component::new(&engine, component)?;
2181     let mut store = Store::new(&engine, ());
2182     let mut linker = Linker::new(&engine);
2183     linker.root().func_wrap("f", |_, _: ()| Ok((2u32,)))?;
2184     let instance = linker.instantiate(&mut store, &component)?;
2185 
2186     let f = instance.get_typed_func::<(), (i32,)>(&mut store, "f2")?;
2187     assert_eq!(f.call(&mut store, ())?, (2,));
2188 
2189     // First test strings when the import/export ABI happen to line up
2190     let component = format!(
2191         r#"
2192 (component $c
2193   (import "s" (func $f (param "a" string)))
2194 
2195   (core module $libc
2196     (memory (export "memory") 1)
2197     {REALLOC_AND_FREE}
2198   )
2199   (core instance $libc (instantiate $libc))
2200 
2201   (core func $f_lower
2202     (canon lower (func $f) (memory $libc "memory"))
2203   )
2204   (func $f2 (param "a" string)
2205     (canon lift (core func $f_lower)
2206         (memory $libc "memory")
2207         (realloc (func $libc "realloc"))
2208     )
2209   )
2210   (export "f" (func $f2))
2211 )
2212     "#
2213     );
2214 
2215     let component = Component::new(&engine, component)?;
2216     let mut store = Store::new(&engine, ());
2217     linker
2218         .root()
2219         .func_wrap("s", |store: StoreContextMut<'_, ()>, (x,): (WasmStr,)| {
2220             assert_eq!(x.to_str(&store)?, "hello");
2221             Ok(())
2222         })?;
2223     let instance = linker.instantiate(&mut store, &component)?;
2224 
2225     let f = instance.get_typed_func::<(&str,), ()>(&mut store, "f")?;
2226     f.call(&mut store, ("hello",))?;
2227 
2228     // Next test "type punning" where return values are reinterpreted just
2229     // because the return ABI happens to line up.
2230     let component = format!(
2231         r#"
2232 (component $c
2233   (import "s2" (func $f (param "a" string) (result u32)))
2234 
2235   (core module $libc
2236     (memory (export "memory") 1)
2237     {REALLOC_AND_FREE}
2238   )
2239   (core instance $libc (instantiate $libc))
2240 
2241   (core func $f_lower
2242     (canon lower (func $f) (memory $libc "memory"))
2243   )
2244   (func $f2 (param "a" string) (result string)
2245     (canon lift (core func $f_lower)
2246         (memory $libc "memory")
2247         (realloc (func $libc "realloc"))
2248     )
2249   )
2250   (export "f" (func $f2))
2251 )
2252     "#
2253     );
2254 
2255     let component = Component::new(&engine, component)?;
2256     let mut store = Store::new(&engine, ());
2257     linker
2258         .root()
2259         .func_wrap("s2", |store: StoreContextMut<'_, ()>, (x,): (WasmStr,)| {
2260             assert_eq!(x.to_str(&store)?, "hello");
2261             Ok((u32::MAX,))
2262         })?;
2263     let instance = linker.instantiate(&mut store, &component)?;
2264 
2265     let f = instance.get_typed_func::<(&str,), (WasmStr,)>(&mut store, "f")?;
2266     let err = f.call(&mut store, ("hello",)).err().unwrap();
2267     assert!(
2268         err.to_string().contains("return pointer not aligned"),
2269         "{}",
2270         err
2271     );
2272 
2273     Ok(())
2274 }
2275 
2276 #[test]
2277 fn errors_that_poison_instance() -> Result<()> {
2278     let component = format!(
2279         r#"
2280 (component $c
2281   (core module $m1
2282     (func (export "f1") unreachable)
2283     (func (export "f2"))
2284   )
2285   (core instance $m1 (instantiate $m1))
2286   (func (export "f1") (canon lift (core func $m1 "f1")))
2287   (func (export "f2") (canon lift (core func $m1 "f2")))
2288 
2289   (core module $m2
2290     (func (export "f") (param i32 i32))
2291     (func (export "r") (param i32 i32 i32 i32) (result i32) unreachable)
2292     (memory (export "m") 1)
2293   )
2294   (core instance $m2 (instantiate $m2))
2295   (func (export "f3") (param "a" string)
2296     (canon lift (core func $m2 "f") (realloc (func $m2 "r")) (memory $m2 "m"))
2297   )
2298 
2299   (core module $m3
2300     (func (export "f") (result i32) i32.const 1)
2301     (memory (export "m") 1)
2302   )
2303   (core instance $m3 (instantiate $m3))
2304   (func (export "f4") (result string)
2305     (canon lift (core func $m3 "f") (memory $m3 "m"))
2306   )
2307 )
2308     "#
2309     );
2310 
2311     let engine = super::engine();
2312     let component = Component::new(&engine, component)?;
2313     let mut store = Store::new(&engine, ());
2314     let linker = Linker::new(&engine);
2315     let instance = linker.instantiate(&mut store, &component)?;
2316     let f1 = instance.get_typed_func::<(), ()>(&mut store, "f1")?;
2317     let f2 = instance.get_typed_func::<(), ()>(&mut store, "f2")?;
2318     assert_unreachable(f1.call(&mut store, ()));
2319     assert_poisoned(f1.call(&mut store, ()));
2320     assert_poisoned(f2.call(&mut store, ()));
2321 
2322     let instance = linker.instantiate(&mut store, &component)?;
2323     let f3 = instance.get_typed_func::<(&str,), ()>(&mut store, "f3")?;
2324     assert_unreachable(f3.call(&mut store, ("x",)));
2325     assert_poisoned(f3.call(&mut store, ("x",)));
2326 
2327     let instance = linker.instantiate(&mut store, &component)?;
2328     let f4 = instance.get_typed_func::<(), (WasmStr,)>(&mut store, "f4")?;
2329     assert!(f4.call(&mut store, ()).is_err());
2330     assert_poisoned(f4.call(&mut store, ()));
2331 
2332     return Ok(());
2333 
2334     #[track_caller]
2335     fn assert_unreachable<T>(err: Result<T>) {
2336         let err = match err {
2337             Ok(_) => panic!("expected an error"),
2338             Err(e) => e,
2339         };
2340         assert_eq!(
2341             err.downcast::<Trap>().unwrap(),
2342             Trap::UnreachableCodeReached
2343         );
2344     }
2345 
2346     #[track_caller]
2347     fn assert_poisoned<T>(err: Result<T>) {
2348         let err = match err {
2349             Ok(_) => panic!("expected an error"),
2350             Err(e) => e,
2351         };
2352         assert_eq!(
2353             err.downcast_ref::<Trap>(),
2354             Some(&Trap::CannotEnterComponent),
2355             "{err}",
2356         );
2357     }
2358 }
2359 
2360 #[test]
2361 fn run_export_with_internal_adapter() -> Result<()> {
2362     let component = r#"
2363 (component
2364   (type $t (func (param "a" u32) (result u32)))
2365   (component $a
2366     (core module $m
2367       (func (export "add-five") (param i32) (result i32)
2368         local.get 0
2369         i32.const 5
2370         i32.add)
2371     )
2372     (core instance $m (instantiate $m))
2373     (func (export "add-five") (type $t) (canon lift (core func $m "add-five")))
2374   )
2375   (component $b
2376     (import "interface-v1" (instance $i
2377       (export "add-five" (func (type $t)))))
2378     (core module $m
2379       (func $add-five (import "interface-0.1.0" "add-five") (param i32) (result i32))
2380       (func) ;; causes index out of bounds
2381       (func (export "run") (result i32) i32.const 0 call $add-five)
2382     )
2383     (core func $add-five (canon lower (func $i "add-five")))
2384     (core instance $i (instantiate 0
2385       (with "interface-0.1.0" (instance
2386         (export "add-five" (func $add-five))
2387       ))
2388     ))
2389     (func (result u32) (canon lift (core func $i "run")))
2390     (export "run" (func 1))
2391   )
2392   (instance $a (instantiate $a))
2393   (instance $b (instantiate $b (with "interface-v1" (instance $a))))
2394   (export "run" (func $b "run"))
2395 )
2396 "#;
2397     let engine = super::engine();
2398     let component = Component::new(&engine, component)?;
2399     let mut store = Store::new(&engine, ());
2400     let linker = Linker::new(&engine);
2401     let instance = linker.instantiate(&mut store, &component)?;
2402     let run = instance.get_typed_func::<(), (u32,)>(&mut store, "run")?;
2403     assert_eq!(run.call(&mut store, ())?, (5,));
2404     Ok(())
2405 }
2406