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