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