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