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