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