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