xref: /wasmtime-44.0.1/tests/all/linker.rs (revision 39e910be)
1 use std::cell::Cell;
2 use std::rc::Rc;
3 use std::sync::Arc;
4 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
5 use wasmtime::*;
6 
7 #[test]
8 #[cfg_attr(miri, ignore)]
link_undefined() -> Result<()>9 fn link_undefined() -> Result<()> {
10     let mut store = Store::<()>::default();
11     let linker = Linker::new(store.engine());
12     let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
13     assert!(linker.instantiate(&mut store, &module).is_err());
14     let module = Module::new(store.engine(), r#"(module (import "" "" (global i32)))"#)?;
15     assert!(linker.instantiate(&mut store, &module).is_err());
16     let module = Module::new(store.engine(), r#"(module (import "" "" (memory 1)))"#)?;
17     assert!(linker.instantiate(&mut store, &module).is_err());
18     let module = Module::new(
19         store.engine(),
20         r#"(module (import "" "" (table 1 funcref)))"#,
21     )?;
22     assert!(linker.instantiate(&mut store, &module).is_err());
23     Ok(())
24 }
25 
26 #[test]
27 #[cfg_attr(miri, ignore)]
test_unknown_import_error() -> Result<()>28 fn test_unknown_import_error() -> Result<()> {
29     let mut store = Store::<()>::default();
30     let linker = Linker::new(store.engine());
31     let module = Module::new(
32         store.engine(),
33         r#"(module (import "unknown-module" "unknown-name" (func)))"#,
34     )?;
35     let err = linker
36         .instantiate(&mut store, &module)
37         .expect_err("should fail");
38     let unknown_import: UnknownImportError = err.downcast()?;
39     assert_eq!(unknown_import.module(), "unknown-module");
40     assert_eq!(unknown_import.name(), "unknown-name");
41     unknown_import.ty().unwrap_func();
42     Ok(())
43 }
44 
45 #[test]
link_twice_bad() -> Result<()>46 fn link_twice_bad() -> Result<()> {
47     let mut store = Store::<()>::default();
48     let mut linker = Linker::<()>::new(store.engine());
49 
50     // functions
51     linker.func_wrap("f", "", || {})?;
52     assert!(linker.func_wrap("f", "", || {}).is_err());
53     assert!(
54         linker
55             .func_wrap("f", "", || -> Result<()> { loop {} })
56             .is_err()
57     );
58 
59     // globals
60     let ty = GlobalType::new(ValType::I32, Mutability::Const);
61     let global = Global::new(&mut store, ty, Val::I32(0))?;
62     linker.define(&mut store, "g", "1", global)?;
63     assert!(linker.define(&mut store, "g", "1", global).is_err());
64 
65     let ty = GlobalType::new(ValType::I32, Mutability::Var);
66     let global = Global::new(&mut store, ty, Val::I32(0))?;
67     linker.define(&mut store, "g", "2", global)?;
68     assert!(linker.define(&mut store, "g", "2", global).is_err());
69 
70     let ty = GlobalType::new(ValType::I64, Mutability::Const);
71     let global = Global::new(&mut store, ty, Val::I64(0))?;
72     linker.define(&mut store, "g", "3", global)?;
73     assert!(linker.define(&mut store, "g", "3", global).is_err());
74 
75     // memories
76     let ty = MemoryType::new(1, None);
77     let memory = Memory::new(&mut store, ty)?;
78     linker.define(&mut store, "m", "", memory)?;
79     assert!(linker.define(&mut store, "m", "", memory).is_err());
80     let ty = MemoryType::new(2, None);
81     let memory = Memory::new(&mut store, ty)?;
82     assert!(linker.define(&mut store, "m", "", memory).is_err());
83 
84     // tables
85     let ty = TableType::new(RefType::FUNCREF, 1, None);
86     let table = Table::new(&mut store, ty, Ref::Func(None))?;
87     linker.define(&mut store, "t", "", table)?;
88     assert!(linker.define(&mut store, "t", "", table).is_err());
89     let ty = TableType::new(RefType::FUNCREF, 2, None);
90     let table = Table::new(&mut store, ty, Ref::Func(None))?;
91     assert!(linker.define(&mut store, "t", "", table).is_err());
92     Ok(())
93 }
94 
95 #[test]
96 #[cfg_attr(miri, ignore)]
function_interposition() -> Result<()>97 fn function_interposition() -> Result<()> {
98     let mut store = Store::<()>::default();
99     let mut linker = Linker::new(store.engine());
100     linker.allow_shadowing(true);
101     let mut module = Module::new(
102         store.engine(),
103         r#"(module (func (export "green") (result i32) (i32.const 7)))"#,
104     )?;
105     for _ in 0..4 {
106         let instance = linker.instantiate(&mut store, &module)?;
107         let green = instance.get_export(&mut store, "green").unwrap().clone();
108         linker.define(&mut store, "red", "green", green)?;
109         module = Module::new(
110             store.engine(),
111             r#"(module
112                 (import "red" "green" (func (result i32)))
113                 (func (export "green") (result i32) (i32.mul (call 0) (i32.const 2)))
114             )"#,
115         )?;
116     }
117     let instance = linker.instantiate(&mut store, &module)?;
118     let func = instance
119         .get_export(&mut store, "green")
120         .unwrap()
121         .into_func()
122         .unwrap();
123     let func = func.typed::<(), i32>(&store)?;
124     assert_eq!(func.call(&mut store, ())?, 112);
125     Ok(())
126 }
127 
128 // Same as `function_interposition`, but the linker's name for the function
129 // differs from the module's name.
130 #[test]
131 #[cfg_attr(miri, ignore)]
function_interposition_renamed() -> Result<()>132 fn function_interposition_renamed() -> Result<()> {
133     let mut store = Store::<()>::default();
134     let mut linker = Linker::new(store.engine());
135     linker.allow_shadowing(true);
136     let mut module = Module::new(
137         store.engine(),
138         r#"(module (func (export "export") (result i32) (i32.const 7)))"#,
139     )?;
140     for _ in 0..4 {
141         let instance = linker.instantiate(&mut store, &module)?;
142         let export = instance.get_export(&mut store, "export").unwrap().clone();
143         linker.define(&mut store, "red", "green", export)?;
144         module = Module::new(
145             store.engine(),
146             r#"(module
147                 (import "red" "green" (func (result i32)))
148                 (func (export "export") (result i32) (i32.mul (call 0) (i32.const 2)))
149             )"#,
150         )?;
151     }
152     let instance = linker.instantiate(&mut store, &module)?;
153     let func = instance.get_func(&mut store, "export").unwrap();
154     let func = func.typed::<(), i32>(&store)?;
155     assert_eq!(func.call(&mut store, ())?, 112);
156     Ok(())
157 }
158 
159 // Similar to `function_interposition`, but use `Linker::instance` instead of
160 // `Linker::define`.
161 #[test]
162 #[cfg_attr(miri, ignore)]
module_interposition() -> Result<()>163 fn module_interposition() -> Result<()> {
164     let mut store = Store::<()>::default();
165     let mut linker = Linker::new(store.engine());
166     linker.allow_shadowing(true);
167     let mut module = Module::new(
168         store.engine(),
169         r#"(module (func (export "export") (result i32) (i32.const 7)))"#,
170     )?;
171     for _ in 0..4 {
172         let instance = linker.instantiate(&mut store, &module)?;
173         linker.instance(&mut store, "instance", instance)?;
174         module = Module::new(
175             store.engine(),
176             r#"(module
177                 (import "instance" "export" (func (result i32)))
178                 (func (export "export") (result i32) (i32.mul (call 0) (i32.const 2)))
179             )"#,
180         )?;
181     }
182     let instance = linker.instantiate(&mut store, &module)?;
183     let func = instance
184         .get_export(&mut store, "export")
185         .unwrap()
186         .into_func()
187         .unwrap();
188     let func = func.typed::<(), i32>(&store)?;
189     assert_eq!(func.call(&mut store, ())?, 112);
190     Ok(())
191 }
192 
193 #[test]
194 #[cfg_attr(miri, ignore)]
allow_unknown_exports() -> Result<()>195 fn allow_unknown_exports() -> Result<()> {
196     let mut store = Store::<()>::default();
197     let mut linker = Linker::new(store.engine());
198     let module = Module::new(
199         store.engine(),
200         r#"(module (func (export "_start")) (global (export "g") i32 (i32.const 0)))"#,
201     )?;
202 
203     assert!(linker.module(&mut store, "module", &module).is_err());
204 
205     let mut linker = Linker::new(store.engine());
206     linker.allow_unknown_exports(true);
207     linker.module(&mut store, "module", &module)?;
208 
209     Ok(())
210 }
211 
212 #[test]
213 #[cfg_attr(miri, ignore)]
no_leak() -> Result<()>214 fn no_leak() -> Result<()> {
215     struct DropMe(Rc<Cell<bool>>);
216 
217     impl Drop for DropMe {
218         fn drop(&mut self) {
219             self.0.set(true);
220         }
221     }
222 
223     let flag = Rc::new(Cell::new(false));
224     {
225         let mut store = Store::new(&Engine::default(), DropMe(flag.clone()));
226         let mut linker = Linker::new(store.engine());
227         let module = Module::new(
228             store.engine(),
229             r#"
230                 (module
231                     (func (export "_start"))
232                 )
233             "#,
234         )?;
235         linker.module(&mut store, "a", &module)?;
236     }
237     assert!(flag.get(), "store was leaked");
238     Ok(())
239 }
240 
241 #[test]
242 #[cfg_attr(miri, ignore)]
no_leak_with_imports() -> Result<()>243 fn no_leak_with_imports() -> Result<()> {
244     struct DropMe(Arc<AtomicUsize>);
245 
246     impl Drop for DropMe {
247         fn drop(&mut self) {
248             self.0.fetch_add(1, SeqCst);
249         }
250     }
251 
252     let flag = Arc::new(AtomicUsize::new(0));
253     {
254         let mut store = Store::new(&Engine::default(), DropMe(flag.clone()));
255         let mut linker = Linker::new(store.engine());
256         let drop_me = DropMe(flag.clone());
257         linker.func_wrap("", "", move || {
258             let _ = &drop_me;
259         })?;
260         let module = Module::new(
261             store.engine(),
262             r#"
263                 (module
264                     (import "" "" (func))
265                     (func (export "_start"))
266                 )
267             "#,
268         )?;
269         linker.module(&mut store, "a", &module)?;
270     }
271     assert!(flag.load(SeqCst) == 2, "something was leaked");
272     Ok(())
273 }
274 
275 #[test]
276 #[cfg_attr(miri, ignore)]
get_host_function() -> Result<()>277 fn get_host_function() -> Result<()> {
278     let engine = Engine::default();
279     let module = Module::new(&engine, r#"(module (import "mod" "f1" (func)))"#)?;
280 
281     let mut linker = Linker::new(&engine);
282     linker.func_wrap("mod", "f1", || {})?;
283     let mut store = Store::new(&engine, ());
284     assert!(
285         linker
286             .get_by_import(&mut store, &module.imports().nth(0).unwrap())
287             .is_some()
288     );
289 
290     Ok(())
291 }
292 
293 #[test]
funcs_live_on_to_fight_another_day() -> Result<()>294 fn funcs_live_on_to_fight_another_day() -> Result<()> {
295     struct DropMe(Arc<AtomicUsize>);
296 
297     impl Drop for DropMe {
298         fn drop(&mut self) {
299             self.0.fetch_add(1, SeqCst);
300         }
301     }
302 
303     let flag = Arc::new(AtomicUsize::new(0));
304     let engine = Engine::default();
305     let mut linker = Linker::new(&engine);
306     let drop_me = DropMe(flag.clone());
307     linker.func_wrap("", "", move || {
308         let _ = &drop_me;
309     })?;
310     assert_eq!(flag.load(SeqCst), 0);
311 
312     let get_and_call = || -> Result<()> {
313         assert_eq!(flag.load(SeqCst), 0);
314         let mut store = Store::new(&engine, ());
315         let func = linker.get(&mut store, "", "").unwrap();
316         func.into_func().unwrap().call(&mut store, &[], &mut [])?;
317         assert_eq!(flag.load(SeqCst), 0);
318         Ok(())
319     };
320 
321     get_and_call()?;
322     get_and_call()?;
323     drop(linker);
324     assert_eq!(flag.load(SeqCst), 1);
325     Ok(())
326 }
327 
328 #[test]
alias_one() -> Result<()>329 fn alias_one() -> Result<()> {
330     let mut store = Store::<()>::default();
331     let mut linker = Linker::new(store.engine());
332     assert!(linker.alias("a", "b", "c", "d").is_err());
333     linker.func_wrap("a", "b", || {})?;
334     assert!(linker.alias("a", "b", "c", "d").is_ok());
335     assert!(linker.get(&mut store, "a", "b").is_ok());
336     assert!(linker.get(&mut store, "c", "d").is_ok());
337     Ok(())
338 }
339 
340 #[test]
341 #[cfg_attr(miri, ignore)]
instance_pre() -> Result<()>342 fn instance_pre() -> Result<()> {
343     let engine = Engine::default();
344     let mut linker = Linker::new(&engine);
345     linker.func_wrap("", "", || {})?;
346 
347     let module = Module::new(&engine, r#"(module (import "" "" (func)))"#)?;
348     let instance_pre = linker.instantiate_pre(&module)?;
349     instance_pre.instantiate(&mut Store::new(&engine, ()))?;
350     instance_pre.instantiate(&mut Store::new(&engine, ()))?;
351 
352     let mut store = Store::new(&engine, ());
353     let global = Global::new(
354         &mut store,
355         GlobalType::new(ValType::I32, Mutability::Const),
356         1.into(),
357     )?;
358     linker.define(&mut store, "", "g", global)?;
359 
360     let module = Module::new(
361         &engine,
362         r#"(module
363             (import "" "" (func))
364             (import "" "g" (global i32))
365         )"#,
366     )?;
367     let instance_pre = linker.instantiate_pre(&module)?;
368     instance_pre.instantiate(&mut store)?;
369     instance_pre.instantiate(&mut store)?;
370     Ok(())
371 }
372 
373 #[test]
374 #[cfg_attr(miri, ignore)]
test_trapping_unknown_import() -> Result<()>375 fn test_trapping_unknown_import() -> Result<()> {
376     const WAT: &str = r#"
377     (module
378       (type $t0 (func))
379       (import "" "imp" (func $.imp (type $t0)))
380       (func $run call $.imp)
381       (func $other)
382       (export "run" (func $run))
383       (export "other" (func $other))
384     )
385     "#;
386 
387     let mut store = Store::<()>::default();
388     let module = Module::new(store.engine(), WAT).expect("failed to create module");
389     let mut linker = Linker::new(store.engine());
390 
391     linker.define_unknown_imports_as_traps(&module)?;
392     let instance = linker.instantiate(&mut store, &module)?;
393 
394     // "run" calls an import function which will not be defined, so it should trap
395     let run_func = instance
396         .get_func(&mut store, "run")
397         .expect("expected a run func in the module");
398 
399     let err = run_func.call(&mut store, &[], &mut []).unwrap_err();
400     assert!(err.is::<UnknownImportError>());
401 
402     // "other" does not call the import function, so it should not trap
403     let other_func = instance
404         .get_func(&mut store, "other")
405         .expect("expected an other func in the module");
406 
407     other_func.call(&mut store, &[], &mut [])?;
408 
409     Ok(())
410 }
411 
412 #[test]
413 #[cfg_attr(miri, ignore)]
test_default_value_unknown_import() -> Result<()>414 fn test_default_value_unknown_import() -> Result<()> {
415     const WAT: &str = r#"
416       (module
417         (import "unknown" "func" (func $unknown_func (result i64 f32 externref)))
418         (func (export "run") (result i64 f32 externref)
419           call $unknown_func
420         )
421       )
422     "#;
423 
424     let mut store = Store::<()>::default();
425     let module = Module::new(store.engine(), WAT).expect("failed to create module");
426     let mut linker = Linker::new(store.engine());
427 
428     linker.define_unknown_imports_as_default_values(&mut store, &module)?;
429     let instance = linker.instantiate(&mut store, &module)?;
430 
431     // "run" calls an import function which will not be defined, so it should
432     // return default values.
433     let run_func = instance
434         .get_func(&mut store, "run")
435         .expect("expected a run func in the module");
436 
437     let mut results = vec![Val::I32(1), Val::I32(2), Val::I32(3)];
438     run_func.call(&mut store, &[], &mut results)?;
439 
440     assert_eq!(results[0].i64(), Some(0));
441     assert_eq!(results[1].f32(), Some(0.0));
442     assert!(results[2].externref().unwrap().is_none());
443 
444     Ok(())
445 }
446 
447 #[test]
448 #[cfg_attr(miri, ignore)]
linker_instantiate_with_concrete_func_refs() -> Result<()>449 fn linker_instantiate_with_concrete_func_refs() -> Result<()> {
450     let mut config = Config::new();
451     config.wasm_function_references(true);
452     let engine = Engine::new(&config)?;
453 
454     let module = Module::new(
455         &engine,
456         r#"
457             (module
458                 (type $a (func (result i32)))
459                 (type $b (func (result (ref null $a))))
460                 (type $c (func (result (ref null $b))))
461 
462                 (import "env" "f" (func $f (result (ref null $c))))
463 
464                 (func (export "g") (result funcref)
465                     call $f
466                 )
467             )
468         "#,
469     )?;
470 
471     let a = FuncType::new(&engine, None, Some(ValType::I32));
472     let ref_null_a = ValType::from(RefType::new(true, HeapType::ConcreteFunc(a.clone())));
473 
474     let b = FuncType::new(&engine, None, Some(ref_null_a));
475     let ref_null_b = ValType::from(RefType::new(true, HeapType::ConcreteFunc(b.clone())));
476 
477     let c = FuncType::new(&engine, None, Some(ref_null_b));
478     let ref_null_c = ValType::from(RefType::new(true, HeapType::ConcreteFunc(c.clone())));
479 
480     let mut store = Store::new(&engine, ());
481     let a_func = Func::new(&mut store, a, |_caller, _args, results| {
482         results[0] = Val::I32(0x1234_5678);
483         Ok(())
484     });
485 
486     let b_func = Func::new(&mut store, b, move |_caller, _args, results| {
487         results[0] = Val::FuncRef(Some(a_func));
488         Ok(())
489     });
490 
491     let c_func = Func::new(&mut store, c, move |_caller, _args, results| {
492         results[0] = Val::FuncRef(Some(b_func));
493         Ok(())
494     });
495 
496     let mut linker = Linker::new(&engine);
497     linker.func_new(
498         "env",
499         "f",
500         FuncType::new(&engine, None, Some(ref_null_c)),
501         move |_caller, _args, results| {
502             results[0] = Val::FuncRef(Some(c_func));
503             Ok(())
504         },
505     )?;
506 
507     let instance = linker.instantiate(&mut store, &module)?;
508 
509     let g = instance.get_typed_func::<(), Option<Func>>(&mut store, "g")?;
510 
511     let c = g.call(&mut store, ())?;
512     let c = c.expect("func ref c is non null");
513     let c = c.typed::<(), Option<Func>>(&mut store)?;
514 
515     let b = c.call(&mut store, ())?;
516     let b = b.expect("func ref b is non null");
517     let b = b.typed::<(), Option<Func>>(&mut store)?;
518 
519     let a = b.call(&mut store, ())?;
520     let a = a.expect("func ref a is non null");
521     let a = a.typed::<(), u32>(&mut store)?;
522 
523     let x = a.call(&mut store, ())?;
524     assert_eq!(x, 0x1234_5678);
525 
526     Ok(())
527 }
528 
529 #[test]
530 #[cfg_attr(miri, ignore)]
linker_defines_func_subtype() -> Result<()>531 fn linker_defines_func_subtype() -> Result<()> {
532     let _ = env_logger::try_init();
533 
534     let mut config = Config::new();
535     config.wasm_function_references(true);
536     config.wasm_gc(true);
537     let engine = Engine::new(&config)?;
538 
539     let ft0 = FuncType::with_finality_and_supertype(
540         &engine,
541         Finality::NonFinal,
542         None,
543         [ValType::NULLFUNCREF],
544         [],
545     )?;
546     let ft1 = FuncType::with_finality_and_supertype(
547         &engine,
548         Finality::NonFinal,
549         Some(&ft0),
550         [ValType::FUNCREF],
551         [],
552     )?;
553 
554     let ft2 = FuncType::with_finality_and_supertype(
555         &engine,
556         Finality::NonFinal,
557         None,
558         [],
559         [ValType::FUNCREF],
560     )?;
561     let ft3 = FuncType::with_finality_and_supertype(
562         &engine,
563         Finality::NonFinal,
564         Some(&ft2),
565         [],
566         [ValType::NULLFUNCREF],
567     )?;
568 
569     let nop = FuncType::new(&engine, [], []);
570     let ft4 = FuncType::with_finality_and_supertype(
571         &engine,
572         Finality::NonFinal,
573         None,
574         [ValType::NULLFUNCREF],
575         [ValType::FUNCREF],
576     )?;
577     let ft5 = FuncType::with_finality_and_supertype(
578         &engine,
579         Finality::NonFinal,
580         Some(&ft4),
581         [ValType::Ref(RefType::new(
582             true,
583             HeapType::ConcreteFunc(nop.clone()),
584         ))],
585         [ValType::Ref(RefType::new(
586             true,
587             HeapType::ConcreteFunc(nop.clone()),
588         ))],
589     )?;
590 
591     let mut linker = Linker::new(&engine);
592     linker.func_new("env", "f", ft1, |_caller, _args, _results| Ok(()))?;
593     linker.func_new("env", "g", ft3, |_caller, _args, _results| Ok(()))?;
594     linker.func_new("env", "h", ft5, |_caller, _args, _results| Ok(()))?;
595 
596     let module = Module::new(
597         &engine,
598         r#"
599             (module
600                 (type $ft0 (sub (func (param nullfuncref))))
601                 (type $ft2 (sub (func (result funcref))))
602                 (type $ft4 (sub (func (param nullfuncref) (result funcref))))
603 
604                 (import "env" "f" (func (type $ft0)))
605                 (import "env" "g" (func (type $ft2)))
606                 (import "env" "h" (func (type $ft4)))
607             )
608         "#,
609     )?;
610 
611     let mut store = Store::new(&engine, ());
612     let _ = linker.instantiate(&mut store, &module)?;
613 
614     Ok(())
615 }
616 
617 #[test]
618 #[cfg_attr(miri, ignore)]
linker_defines_global_subtype_const_ok() -> Result<()>619 fn linker_defines_global_subtype_const_ok() -> Result<()> {
620     let mut config = Config::new();
621     config.wasm_function_references(true);
622     let engine = Engine::new(&config)?;
623     let mut store = Store::new(&engine, ());
624     let mut linker = Linker::new(&engine);
625 
626     let module = Module::new(
627         &engine,
628         r#"
629             (module
630                 (import "env" "g" (global funcref))
631             )
632         "#,
633     )?;
634 
635     let g = Global::new(
636         &mut store,
637         GlobalType::new(ValType::NULLFUNCREF, Mutability::Const),
638         Val::FuncRef(None),
639     )?;
640     linker.define(&store, "env", "g", g)?;
641 
642     let _ = linker.instantiate(&mut store, &module)?;
643     Ok(())
644 }
645 
646 #[test]
647 #[cfg_attr(miri, ignore)]
linker_defines_global_subtype_const_err() -> Result<()>648 fn linker_defines_global_subtype_const_err() -> Result<()> {
649     let mut config = Config::new();
650     config.wasm_function_references(true);
651     config.wasm_gc(true);
652     let engine = Engine::new(&config)?;
653     let mut store = Store::new(&engine, ());
654     let mut linker = Linker::new(&engine);
655 
656     let module = Module::new(
657         &engine,
658         r#"
659             (module
660                 (import "env" "g" (global nullfuncref))
661             )
662         "#,
663     )?;
664 
665     // funcref </: nullfuncref
666     let g = Global::new(
667         &mut store,
668         GlobalType::new(ValType::FUNCREF, Mutability::Const),
669         Val::FuncRef(None),
670     )?;
671     linker.define(&store, "env", "g", g)?;
672 
673     let e = linker.instantiate(&mut store, &module).unwrap_err();
674     assert_eq!(e.to_string(), "incompatible import type for `env::g`");
675 
676     Ok(())
677 }
678 
679 #[test]
680 #[cfg_attr(miri, ignore)]
linker_defines_global_subtype_mut_err() -> Result<()>681 fn linker_defines_global_subtype_mut_err() -> Result<()> {
682     let mut config = Config::new();
683     config.wasm_function_references(true);
684     let engine = Engine::new(&config)?;
685     let mut store = Store::new(&engine, ());
686 
687     let module = Module::new(
688         &engine,
689         r#"
690             (module
691                 (type $nop (func))
692                 (import "env" "g" (global (mut (ref null $nop))))
693             )
694         "#,
695     )?;
696 
697     // Supertype, not precise type.
698     let mut linker = Linker::new(&engine);
699     let g = Global::new(
700         &mut store,
701         GlobalType::new(ValType::FUNCREF, Mutability::Var),
702         Val::FuncRef(None),
703     )?;
704     linker.define(&store, "env", "g", g)?;
705     let e = linker.instantiate(&mut store, &module).unwrap_err();
706     assert_eq!(e.to_string(), "incompatible import type for `env::g`");
707 
708     // Subtype, not precise type.
709     let mut linker = Linker::new(&engine);
710     let g = Global::new(
711         &mut store,
712         GlobalType::new(ValType::NULLFUNCREF, Mutability::Var),
713         Val::FuncRef(None),
714     )?;
715     linker.define(&store, "env", "g", g)?;
716     let e = linker.instantiate(&mut store, &module).unwrap_err();
717     assert_eq!(e.to_string(), "incompatible import type for `env::g`");
718 
719     // Not mutable.
720     let mut linker = Linker::new(&engine);
721     let nop = FuncType::new(&engine, None, None);
722     let ref_null_nop = ValType::from(RefType::new(true, HeapType::ConcreteFunc(nop)));
723     let g = Global::new(
724         &mut store,
725         GlobalType::new(ref_null_nop, Mutability::Const),
726         Val::FuncRef(None),
727     )?;
728     linker.define(&store, "env", "g", g)?;
729     let e = linker.instantiate(&mut store, &module).unwrap_err();
730     assert_eq!(e.to_string(), "incompatible import type for `env::g`");
731 
732     Ok(())
733 }
734 
735 #[test]
736 #[cfg_attr(miri, ignore)]
linker_defines_table_subtype_err() -> Result<()>737 fn linker_defines_table_subtype_err() -> Result<()> {
738     let mut config = Config::new();
739     config.wasm_function_references(true);
740     let engine = Engine::new(&config)?;
741     let mut store = Store::new(&engine, ());
742 
743     let module = Module::new(
744         &engine,
745         r#"
746             (module
747                 (type $nop (func))
748                 (import "env" "t" (table 0 (ref null $nop)))
749             )
750         "#,
751     )?;
752 
753     // Supertype, not precise type.
754     let mut linker = Linker::new(&engine);
755     let t = Table::new(
756         &mut store,
757         TableType::new(RefType::FUNCREF, 0, None),
758         Ref::Func(None),
759     )?;
760     linker.define(&store, "env", "t", t)?;
761     let e = linker.instantiate(&mut store, &module).unwrap_err();
762     assert_eq!(e.to_string(), "incompatible import type for `env::t`");
763 
764     // Subtype, not precise type.
765     let mut linker = Linker::new(&engine);
766     let t = Table::new(
767         &mut store,
768         TableType::new(RefType::NULLFUNCREF, 0, None),
769         Ref::Func(None),
770     )?;
771     linker.define(&store, "env", "t", t)?;
772     let e = linker.instantiate(&mut store, &module).unwrap_err();
773     assert_eq!(e.to_string(), "incompatible import type for `env::t`");
774 
775     Ok(())
776 }
777 
778 // Regression test for a soundness bug in StringPool::try_clone() introduced
779 // in wasmtime 43.0.0: cloning a StringPool (and thus a Linker) copied the
780 // map's &'static str keys that pointed into the *original* pool's string
781 // storage. After the original was dropped those keys became dangling, causing
782 // get_atom() on the clone to silently fail to find registered imports.
783 #[test]
784 #[cfg_attr(miri, ignore)]
linker_clone_drop_original_then_instantiate() -> Result<()>785 fn linker_clone_drop_original_then_instantiate() -> Result<()> {
786     let engine = Engine::default();
787     let wat = r#"(module
788         (import "env" "answer" (func (result i32)))
789         (func (export "run") (result i32)
790             call 0
791         )
792     )"#;
793     let module = Module::new(&engine, wat)?;
794 
795     let original = {
796         let mut l: Linker<()> = Linker::new(&engine);
797         l.func_wrap("env", "answer", || -> i32 { 42 })?;
798         l
799     };
800 
801     let clone = original.clone();
802     // Dropping the original must not invalidate the clone's string pool.
803     drop(original);
804 
805     let mut store = Store::new(&engine, ());
806     let instance = clone.instantiate(&mut store, &module)?;
807     let f = instance.get_typed_func::<(), i32>(&mut store, "run")?;
808     assert_eq!(f.call(&mut store, ())?, 42);
809     Ok(())
810 }
811