Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wizer/tests/all/tests.rs
2459 views
1
use anyhow::{Context, Result};
2
use std::process::Command;
3
use wasm_encoder::ConstExpr;
4
use wasmtime::{Config, Engine, Instance, Linker, Module, Store};
5
use wasmtime_wasi::{WasiCtxBuilder, p1};
6
use wasmtime_wizer::Wizer;
7
use wat::parse_str as wat_to_wasm;
8
9
async fn run_wat(args: &[wasmtime::Val], expected: i32, wat: &str) -> Result<()> {
10
let _ = env_logger::try_init();
11
let wasm = wat_to_wasm(wat)?;
12
wizen_and_run_wasm(args, expected, &wasm, get_wizer()).await
13
}
14
15
fn get_wizer() -> Wizer {
16
Wizer::new()
17
}
18
19
fn store() -> Result<Store<p1::WasiP1Ctx>> {
20
let mut wasi = WasiCtxBuilder::new();
21
let mut config = Config::new();
22
config.async_support(true);
23
config.relaxed_simd_deterministic(true);
24
let engine = Engine::new(&config)?;
25
Ok(Store::new(&engine, wasi.build_p1()))
26
}
27
28
async fn instantiate(store: &mut Store<p1::WasiP1Ctx>, module: &Module) -> Result<Instance> {
29
let mut linker = Linker::new(store.engine());
30
p1::add_to_linker_async(&mut linker, |x| x)?;
31
linker.define_unknown_imports_as_traps(module)?;
32
linker.instantiate_async(store, module).await
33
}
34
35
async fn wizen_and_run_wasm(
36
args: &[wasmtime::Val],
37
expected: i32,
38
wasm: &[u8],
39
wizer: Wizer,
40
) -> Result<()> {
41
let _ = env_logger::try_init();
42
43
log::debug!(
44
"=== PreWizened Wasm ==========================================================\n\
45
{}\n\
46
===========================================================================",
47
wasmprinter::print_bytes(&wasm).unwrap()
48
);
49
let mut store = store()?;
50
let wasm = wizer.run(&mut store, &wasm, instantiate).await?;
51
log::debug!(
52
"=== Wizened Wasm ==========================================================\n\
53
{}\n\
54
===========================================================================",
55
wasmprinter::print_bytes(&wasm).unwrap()
56
);
57
if log::log_enabled!(log::Level::Debug) {
58
std::fs::write("test.wasm", &wasm).unwrap();
59
}
60
61
let module =
62
wasmtime::Module::new(store.engine(), wasm).context("Wasm test case failed to compile")?;
63
64
let mut linker = wasmtime::Linker::new(store.engine());
65
let thunk = wasmtime::Func::wrap(&mut store, || {});
66
linker
67
.define_name(&mut store, "dummy_func", thunk)?
68
.define(&mut store, "env", "f", thunk)?
69
.define_name(&mut store, "f", thunk)?
70
.define(&mut store, "x", "f", thunk)?;
71
72
p1::add_to_linker_async(&mut linker, |wasi| wasi)?;
73
74
let instance = linker.instantiate_async(&mut store, &module).await?;
75
76
let run = instance
77
.get_func(&mut store, "run")
78
.ok_or_else(|| anyhow::anyhow!("the test Wasm module does not export a `run` function"))?;
79
80
let mut actual = vec![wasmtime::Val::I32(0)];
81
run.call_async(&mut store, args, &mut actual).await?;
82
anyhow::ensure!(actual.len() == 1, "expected one result");
83
let actual = match actual[0] {
84
wasmtime::Val::I32(x) => x,
85
_ => anyhow::bail!("expected an i32 result"),
86
};
87
anyhow::ensure!(
88
expected == actual,
89
"expected `{expected}`, found `{actual}`",
90
);
91
92
Ok(())
93
}
94
95
async fn fails_wizening(wat: &str) -> Result<()> {
96
let _ = env_logger::try_init();
97
98
let wasm = wat_to_wasm(wat)?;
99
100
let mut features = wasmparser::WasmFeatures::WASM2;
101
features.set(wasmparser::WasmFeatures::MULTI_MEMORY, true);
102
103
let mut validator = wasmparser::Validator::new_with_features(features);
104
validator
105
.validate_all(&wasm)
106
.context("initial Wasm should be valid")?;
107
108
anyhow::ensure!(
109
get_wizer()
110
.run(&mut store()?, &wasm, instantiate)
111
.await
112
.is_err(),
113
"Expected an error when wizening, but didn't get one"
114
);
115
Ok(())
116
}
117
118
#[tokio::test]
119
async fn basic_global() -> Result<()> {
120
run_wat(
121
&[],
122
42,
123
r#"
124
(module
125
(global $g (mut i32) i32.const 0)
126
(func (export "wizer-initialize")
127
i32.const 42
128
global.set $g)
129
(func (export "run") (result i32)
130
global.get $g))
131
"#,
132
)
133
.await
134
}
135
136
#[tokio::test]
137
async fn basic_memory() -> Result<()> {
138
run_wat(
139
&[],
140
42,
141
r#"
142
(module
143
(memory 1)
144
(func (export "wizer-initialize")
145
i32.const 0
146
i32.const 42
147
i32.store offset=1337)
148
(func (export "run") (result i32)
149
i32.const 0
150
i32.load offset=1337))
151
"#,
152
)
153
.await
154
}
155
156
#[tokio::test]
157
async fn multi_memory() -> Result<()> {
158
run_wat(
159
&[],
160
42,
161
r#"
162
(module
163
(memory $m1 1)
164
(memory $m2 1)
165
(func (export "wizer-initialize")
166
i32.const 0
167
i32.const 41
168
i32.store $m1 offset=1337
169
i32.const 0
170
i32.const 1
171
i32.store $m2 offset=1337)
172
(func (export "run") (result i32)
173
i32.const 0
174
i32.load $m1 offset=1337
175
i32.const 0
176
i32.load $m2 offset=1337
177
i32.add))
178
"#,
179
)
180
.await
181
}
182
#[tokio::test]
183
async fn reject_imported_memory() -> Result<()> {
184
fails_wizening(
185
r#"
186
(module
187
(import "" "" (memory 1)))
188
"#,
189
)
190
.await
191
}
192
193
#[tokio::test]
194
async fn reject_imported_global() -> Result<()> {
195
fails_wizening(
196
r#"
197
(module
198
(import "" "" (global i32)))
199
"#,
200
)
201
.await
202
}
203
204
#[tokio::test]
205
async fn reject_imported_table() -> Result<()> {
206
fails_wizening(
207
r#"
208
(module
209
(import "" "" (table 0 externref)))
210
"#,
211
)
212
.await
213
}
214
215
#[tokio::test]
216
async fn reject_table_copy() -> Result<()> {
217
let result = run_wat(
218
&[],
219
42,
220
r#"
221
(module
222
(table 3 funcref)
223
224
(func $f (result i32) (i32.const 0))
225
(func $g (result i32) (i32.const 0))
226
(func $h (result i32) (i32.const 0))
227
228
(func (export "main")
229
i32.const 0
230
i32.const 1
231
i32.const 1
232
table.copy)
233
234
(elem (i32.const 0) $f $g $h)
235
)
236
"#,
237
)
238
.await;
239
assert!(result.is_err());
240
241
let err = result.unwrap_err();
242
assert!(
243
err.to_string()
244
.contains("unsupported `table.copy` instruction")
245
);
246
247
Ok(())
248
}
249
250
#[tokio::test]
251
async fn reject_table_get_set() -> Result<()> {
252
let wat = r#"
253
(module
254
(table 3 funcref)
255
256
(func $f (result i32) (i32.const 0))
257
(func $g (result i32) (i32.const 0))
258
(func $h (result i32) (i32.const 0))
259
260
(func (export "main")
261
i32.const 0
262
i32.const 1
263
table.get
264
table.set)
265
266
(elem (i32.const 0) $f $g $h)
267
)
268
"#;
269
270
let _ = env_logger::try_init();
271
let wizer = Wizer::new();
272
let wasm = wat_to_wasm(wat)?;
273
let result = wizen_and_run_wasm(&[], 42, &wasm, wizer).await;
274
275
assert!(result.is_err());
276
277
let err = result.unwrap_err();
278
assert!(
279
err.to_string()
280
.contains("unsupported `table.set` instruction"),
281
"bad error: {err}",
282
);
283
284
Ok(())
285
}
286
287
#[tokio::test]
288
async fn reject_table_get_set_with_reference_types_enabled() -> Result<()> {
289
let result = run_wat(
290
&[],
291
42,
292
r#"
293
(module
294
(table 3 funcref)
295
296
(func $f (result i32) (i32.const 0))
297
(func $g (result i32) (i32.const 0))
298
(func $h (result i32) (i32.const 0))
299
300
(func (export "main")
301
i32.const 0
302
i32.const 1
303
table.get
304
table.set)
305
306
(elem (i32.const 0) $f $g $h)
307
)"#,
308
)
309
.await;
310
assert!(result.is_err());
311
312
let err = result.unwrap_err();
313
assert!(
314
err.to_string()
315
.contains("unsupported `table.set` instruction"),
316
);
317
318
Ok(())
319
}
320
321
#[tokio::test]
322
async fn reject_table_grow_with_reference_types_enabled() -> anyhow::Result<()> {
323
let wat = r#"
324
(module
325
(elem declare func $f)
326
(func $f)
327
(table 0 funcref)
328
(func (export "_initialize") (result i32)
329
ref.func $f
330
i32.const 1
331
table.grow
332
)
333
)"#;
334
335
let _ = env_logger::try_init();
336
let wizer = Wizer::new();
337
let wasm = wat_to_wasm(wat)?;
338
let result = wizen_and_run_wasm(&[], 42, &wasm, wizer).await;
339
340
assert!(result.is_err());
341
342
let err = result.unwrap_err();
343
assert!(
344
err.to_string()
345
.contains("unsupported `table.grow` instruction")
346
);
347
348
Ok(())
349
}
350
351
#[tokio::test]
352
async fn indirect_call_with_reference_types() -> anyhow::Result<()> {
353
let wat = r#"
354
(module
355
(type $sig (func (result i32)))
356
(table 0 funcref)
357
(table $table1 1 funcref)
358
(elem (table $table1) (i32.const 0) func $f)
359
(func $f (type $sig)
360
i32.const 42
361
)
362
(func (export "wizer-initialize"))
363
(func (export "run") (result i32)
364
i32.const 0
365
call_indirect $table1 (type $sig)
366
)
367
)"#;
368
369
let _ = env_logger::try_init();
370
let wizer = Wizer::new();
371
let wasm = wat_to_wasm(wat)?;
372
wizen_and_run_wasm(&[], 42, &wasm, wizer).await
373
}
374
375
#[tokio::test]
376
async fn reject_table_init() -> Result<()> {
377
let result = run_wat(
378
&[],
379
42,
380
r#"
381
(module
382
(table 3 funcref)
383
384
(func $f (result i32) (i32.const 0))
385
(func $g (result i32) (i32.const 0))
386
(func $h (result i32) (i32.const 0))
387
388
(elem $elem func $f $g $h)
389
390
(func (export "main")
391
i32.const 0
392
i32.const 0
393
i32.const 3
394
table.init $elem)
395
)
396
"#,
397
)
398
.await;
399
assert!(result.is_err());
400
401
let err = result.unwrap_err();
402
assert!(
403
err.to_string()
404
.contains("unsupported `table.init` instruction")
405
);
406
407
Ok(())
408
}
409
410
#[tokio::test]
411
async fn reject_elem_drop() -> Result<()> {
412
let result = run_wat(
413
&[],
414
42,
415
r#"
416
(module
417
(table 3 funcref)
418
419
(func $f (result i32) (i32.const 0))
420
(func $g (result i32) (i32.const 0))
421
(func $h (result i32) (i32.const 0))
422
423
(elem $elem func $f $g $h)
424
425
(func (export "main")
426
elem.drop $elem)
427
)
428
"#,
429
)
430
.await;
431
assert!(result.is_err());
432
433
let err = result.unwrap_err();
434
assert!(
435
err.to_string()
436
.contains("unsupported `elem.drop` instruction")
437
);
438
439
Ok(())
440
}
441
442
#[tokio::test]
443
async fn reject_data_drop() -> Result<()> {
444
let result = run_wat(
445
&[],
446
42,
447
r#"
448
(module
449
(memory 1)
450
(data $data "hello, wizer!")
451
452
(func (export "main")
453
data.drop $data)
454
)
455
"#,
456
)
457
.await;
458
assert!(result.is_err());
459
460
let err = result.unwrap_err();
461
assert!(
462
err.to_string()
463
.contains("unsupported `data.drop` instruction")
464
);
465
466
Ok(())
467
}
468
469
#[tokio::test]
470
async fn rust_regex() -> Result<()> {
471
let status = Command::new("cargo")
472
.args(&["build", "--target=wasm32-wasip1", "-q"])
473
.current_dir("./tests/regex-test")
474
.env_remove("CARGO_ENCODED_RUSTFLAGS")
475
.env_remove("RUSTFLAGS")
476
.status()
477
.expect("failed to build regex test case");
478
assert!(status.success());
479
wizen_and_run_wasm(
480
&[wasmtime::Val::I32(13)],
481
42,
482
&std::fs::read("../../target/wasm32-wasip1/debug/regex_test.wasm")
483
.expect("failed to read regex test case"),
484
get_wizer(),
485
)
486
.await
487
}
488
489
#[tokio::test]
490
async fn data_segment_at_end_of_memory() -> Result<()> {
491
// Test that we properly synthesize data segments for data at the end of
492
// memory.
493
run_wat(
494
&[],
495
42,
496
r#"
497
(module
498
(memory 1)
499
(func (export "wizer-initialize")
500
;; Store 42 to the last byte in memory.
501
i32.const 0
502
i32.const 42
503
i32.store8 offset=65535
504
)
505
(func (export "run") (result i32)
506
i32.const 0
507
i32.load8_u offset=65535
508
)
509
)
510
"#,
511
)
512
.await
513
}
514
515
#[tokio::test]
516
async fn too_many_data_segments_for_engines() -> Result<()> {
517
run_wat(
518
&[],
519
42,
520
r#"
521
(module
522
;; Enough memory to create more segments than engines will allow:
523
;;
524
;; // The maximum number of segments that engines will allow a module to
525
;; // have.
526
;; let max_segments = 100_000;
527
;;
528
;; // The minimum gap that Wizer won't automatically merge two data
529
;; // segments (see `MIN_ACTIVE_SEGMENT_OVERHEAD`).
530
;; let wizer_min_gap = 6;
531
;;
532
;; // Wasm page size.
533
;; let wasm_page_size = 65_536;
534
;;
535
;; let num_pages = round_up(max_segments * wizer_min_gap / wasm_page_size);
536
(memory 10)
537
538
(func (export "wizer-initialize")
539
(local i32)
540
loop
541
(i32.ge_u (local.get 0) (i32.const 655360)) ;; 10 * wasm_page_size
542
if
543
return
544
end
545
546
(i32.store8 (local.get 0) (i32.const 42))
547
(local.set 0 (i32.add (local.get 0) (i32.const 6)))
548
br 0
549
end
550
)
551
(func (export "run") (result i32)
552
i32.const 0
553
i32.load8_u
554
)
555
)
556
"#,
557
)
558
.await
559
}
560
561
#[tokio::test]
562
async fn rename_functions() -> Result<()> {
563
let wat = r#"
564
(module
565
(func (export "wizer-initialize"))
566
(func (export "func_a") (result i32)
567
i32.const 1)
568
(func (export "func_b") (result i32)
569
i32.const 2)
570
(func (export "func_c") (result i32)
571
i32.const 3))
572
"#;
573
574
let wasm = wat_to_wasm(wat)?;
575
let mut wizer = Wizer::new();
576
wizer.func_rename("func_a", "func_b");
577
wizer.func_rename("func_b", "func_c");
578
let wasm = wizer.run(&mut store()?, &wasm, instantiate).await?;
579
let wat = wasmprinter::print_bytes(&wasm)?;
580
581
let expected_wat = r#"
582
(module
583
(type (;0;) (func))
584
(type (;1;) (func (result i32)))
585
(export "func_a" (func 2))
586
(export "func_b" (func 3))
587
(func (;0;) (type 0))
588
(func (;1;) (type 1) (result i32)
589
i32.const 1
590
)
591
(func (;2;) (type 1) (result i32)
592
i32.const 2
593
)
594
(func (;3;) (type 1) (result i32)
595
i32.const 3
596
)
597
)
598
"#;
599
600
assert_eq!(wat.trim(), expected_wat.trim());
601
Ok(())
602
}
603
604
#[tokio::test]
605
async fn wasi_reactor() -> anyhow::Result<()> {
606
run_wat(
607
&[],
608
42,
609
r#"
610
(module
611
(global $g (mut i32) i32.const 0)
612
(func (export "_initialize")
613
i32.const 6
614
global.set $g
615
)
616
(func (export "wizer-initialize")
617
global.get $g
618
i32.const 7
619
i32.mul
620
global.set $g)
621
(func (export "run") (result i32)
622
global.get $g
623
)
624
)
625
"#,
626
)
627
.await
628
}
629
630
#[tokio::test]
631
async fn wasi_reactor_initializer_as_init_func() -> anyhow::Result<()> {
632
let wat = r#"
633
(module
634
(global $g (mut i32) i32.const 0)
635
(func (export "_initialize")
636
global.get $g
637
i32.const 1
638
i32.add
639
global.set $g
640
)
641
(func (export "run") (result i32)
642
global.get $g
643
)
644
)"#;
645
646
let _ = env_logger::try_init();
647
let mut wizer = Wizer::new();
648
wizer.init_func("_initialize");
649
let wasm = wat_to_wasm(wat)?;
650
// we expect `_initialize` to be called _exactly_ once
651
wizen_and_run_wasm(&[], 1, &wasm, wizer).await
652
}
653
654
#[tokio::test]
655
async fn wasi_reactor_initializer_with_keep_init() -> anyhow::Result<()> {
656
let wat = r#"
657
(module
658
(global $g (mut i32) i32.const 0)
659
(func (export "_initialize")
660
i32.const 1
661
global.set $g
662
)
663
(func (export "wizer-initialize")
664
i32.const 2
665
global.set $g)
666
(func (export "run") (result i32)
667
global.get $g
668
)
669
)"#;
670
671
let _ = env_logger::try_init();
672
let mut wizer = Wizer::new();
673
wizer.keep_init_func(true);
674
let wasm = wat_to_wasm(wat)?;
675
// we expect `_initialize` to be un-exported and not called at run
676
wizen_and_run_wasm(&[], 2, &wasm, wizer).await
677
}
678
679
#[tokio::test]
680
async fn call_undefined_import_function_during_init() -> Result<()> {
681
fails_wizening(
682
r#"
683
(module
684
(import "x" "f" (func $import))
685
(func (export "wizer-initialize")
686
(call $import)
687
)
688
)
689
"#,
690
)
691
.await
692
}
693
694
#[tokio::test]
695
async fn allow_undefined_import_function() -> Result<()> {
696
run_wat(
697
&[],
698
42,
699
r#"
700
(module
701
(import "x" "f" (func $import))
702
(func (export "wizer-initialize"))
703
(func (export "run") (result i32)
704
i32.const 42
705
)
706
)
707
"#,
708
)
709
.await
710
}
711
712
#[tokio::test]
713
async fn accept_bulk_memory_copy() -> Result<()> {
714
run_wat(
715
&[],
716
('h' as i32) + ('w' as i32),
717
r#"
718
(module
719
(memory $memory (data "hello, wizer!"))
720
(func (export "wizer-initialize")
721
i32.const 42 ;; dst
722
i32.const 0 ;; src
723
i32.const 13 ;; size
724
memory.copy)
725
(func (export "run") (result i32)
726
i32.const 42
727
i32.load8_u
728
i32.const 42
729
i32.load8_u offset=7
730
i32.add))
731
"#,
732
)
733
.await
734
}
735
736
#[tokio::test]
737
async fn accept_bulk_memory_data_count() -> Result<()> {
738
let mut module = wasm_encoder::Module::new();
739
let mut types = wasm_encoder::TypeSection::new();
740
types.ty().func_type(&wasm_encoder::FuncType::new(
741
vec![],
742
vec![wasm_encoder::ValType::I32],
743
));
744
types
745
.ty()
746
.func_type(&wasm_encoder::FuncType::new(vec![], vec![]));
747
module.section(&types);
748
749
let mut functions = wasm_encoder::FunctionSection::new();
750
functions.function(0);
751
functions.function(1);
752
module.section(&functions);
753
754
let mut memory = wasm_encoder::MemorySection::new();
755
memory.memory(wasm_encoder::MemoryType {
756
minimum: 1,
757
maximum: Some(1),
758
memory64: false,
759
shared: false,
760
page_size_log2: None,
761
});
762
module.section(&memory);
763
764
let mut exports = wasm_encoder::ExportSection::new();
765
exports.export("run", wasm_encoder::ExportKind::Func, 0);
766
exports.export("wizer-initialize", wasm_encoder::ExportKind::Func, 1);
767
module.section(&exports);
768
769
module.section(&wasm_encoder::DataCountSection { count: 2 });
770
771
let mut code = wasm_encoder::CodeSection::new();
772
let mut func = wasm_encoder::Function::new(vec![]);
773
func.instruction(&wasm_encoder::Instruction::I32Const(42));
774
func.instruction(&wasm_encoder::Instruction::End);
775
code.function(&func);
776
777
let mut func = wasm_encoder::Function::new(vec![]);
778
func.instruction(&wasm_encoder::Instruction::End);
779
code.function(&func);
780
781
module.section(&code);
782
783
// We're expecting these two data segments to be merge into one, which will exercise wizer's
784
// ability to output the correct data count (1 instead of 2 above).
785
let mut data = wasm_encoder::DataSection::new();
786
data.active(0, &ConstExpr::i32_const(0), vec![0, 1, 2, 3]);
787
data.active(0, &ConstExpr::i32_const(4), vec![5, 6, 7, 8]);
788
module.section(&data);
789
790
wizen_and_run_wasm(&[], 42, &module.finish(), get_wizer())
791
.await
792
.unwrap();
793
Ok(())
794
}
795
796
#[tokio::test]
797
async fn accept_bulk_memory_fill() -> Result<()> {
798
run_wat(
799
&[],
800
77 + 77,
801
r#"
802
(module
803
(memory 1)
804
(func (export "wizer-initialize")
805
i32.const 42 ;; dst
806
i32.const 77 ;; value
807
i32.const 13 ;; size
808
memory.fill)
809
(func (export "run") (result i32)
810
i32.const 42
811
i32.load8_u
812
i32.const 42
813
i32.load8_u offset=7
814
i32.add))
815
"#,
816
)
817
.await
818
}
819
820
#[tokio::test]
821
async fn accept_bulk_memory_init() -> Result<()> {
822
run_wat(
823
&[],
824
('h' as i32) + ('w' as i32),
825
r#"
826
(module
827
(memory 1)
828
(data $data "hello, wizer!")
829
(func (export "wizer-initialize")
830
i32.const 42 ;; dst
831
i32.const 0 ;; offset
832
i32.const 13 ;; size
833
memory.init $data)
834
(func (export "run") (result i32)
835
i32.const 42
836
i32.load8_u
837
i32.const 42
838
i32.load8_u offset=7
839
i32.add))
840
"#,
841
)
842
.await
843
}
844
845
#[tokio::test]
846
async fn accept_simd128() -> Result<()> {
847
run_wat(
848
&[],
849
49,
850
r#"
851
(module
852
(global $g (mut v128) (v128.const i32x4 2 3 5 7))
853
(func (export "wizer-initialize")
854
global.get $g
855
global.get $g
856
i32x4.mul
857
global.set $g)
858
(func (export "run") (result i32)
859
global.get $g
860
i32x4.extract_lane 3))
861
"#,
862
)
863
.await
864
}
865
866
#[tokio::test]
867
async fn relaxed_simd_deterministic() -> Result<()> {
868
let _ = env_logger::try_init();
869
let wasm = wat_to_wasm(
870
r#"
871
(module
872
(global $g (mut i32) i32.const 0)
873
(func (export "wizer-initialize")
874
(v128.const f32x4 2796203.5 0.0 0.0 0.0)
875
(v128.const f32x4 3.0 0.0 0.0 0.0)
876
(v128.const f32x4 8388611.0 0.0 0.0 0.0)
877
f32x4.relaxed_madd
878
f32x4.extract_lane 0
879
i32.reinterpret_f32
880
global.set $g)
881
(func (export "run") (result i32)
882
global.get $g
883
)
884
)
885
"#,
886
)?;
887
let wizer = get_wizer();
888
889
// We'll get 0x4b000003 if we have the deterministic `relaxed_madd`
890
// semantics. We might get 0x4b000002 if we don't.
891
wizen_and_run_wasm(&[], 0x4b800003, &wasm, wizer).await
892
}
893
894
#[tokio::test]
895
async fn reject_mutable_globals_of_reference_types() -> Result<()> {
896
// Non-mutable globals are fine
897
run_wat(
898
&[],
899
42,
900
r#"
901
(module
902
(global funcref (ref.null func))
903
(func (export "wizer-initialize"))
904
(func (export "run") (result i32) i32.const 42)
905
)
906
"#,
907
)
908
.await?;
909
910
// Mutable globals are not fine
911
fails_wizening(
912
r#"
913
(module
914
(global (mut funcref) (ref.null func))
915
(func (export "wizer-initialize"))
916
(func (export "run") (result i32) i32.const 42)
917
)
918
"#,
919
)
920
.await?;
921
Ok(())
922
}
923
924
#[tokio::test]
925
async fn mixture_of_globals() -> Result<()> {
926
let _ = env_logger::try_init();
927
let wasm = wat_to_wasm(
928
r#"
929
(module
930
(global $g1 (mut i32) i32.const 1)
931
(global $g2 i32 i32.const 2)
932
(global $g3 (mut i32) i32.const 3)
933
(global $g4 i32 i32.const 4)
934
(func (export "wizer-initialize")
935
(global.set $g1 (i32.const 42))
936
(global.set $g3 (i32.const 43))
937
)
938
(func (export "run") (result i32)
939
global.get $g1
940
global.get $g2
941
global.get $g3
942
global.get $g4
943
i32.add
944
i32.add
945
i32.add
946
)
947
)
948
"#,
949
)?;
950
let wizer = get_wizer();
951
wizen_and_run_wasm(&[], 42 + 2 + 43 + 4, &wasm, wizer).await
952
}
953
954
#[tokio::test]
955
async fn memory_init_and_data_segments() -> Result<()> {
956
let _ = env_logger::try_init();
957
let wasm = wat_to_wasm(
958
r#"
959
(module
960
(memory 1)
961
962
(func (export "wizer-initialize")
963
i32.const 2
964
i32.const 0
965
i32.const 2
966
memory.init $a
967
)
968
969
(func (export "run") (result i32)
970
i32.const 4
971
i32.const 0
972
i32.const 2
973
memory.init $a
974
i32.const 6
975
i32.const 0
976
i32.const 2
977
memory.init $c
978
979
i32.const 0
980
i32.load
981
i32.const 4
982
i32.load
983
i32.add
984
)
985
986
(data $a "\01\02")
987
(data $b (i32.const 0) "\03\04")
988
(data $c "\05\06")
989
)
990
"#,
991
)?;
992
let wizer = get_wizer();
993
wizen_and_run_wasm(&[], 0x02010403 + 0x06050201, &wasm, wizer).await
994
}
995
996
#[tokio::test]
997
async fn memory64() -> Result<()> {
998
let _ = env_logger::try_init();
999
let wasm = wat_to_wasm(
1000
r#"
1001
(module
1002
(memory i64 1)
1003
1004
(func (export "wizer-initialize")
1005
i64.const 0
1006
i32.const 10
1007
i32.store
1008
)
1009
1010
(func (export "run") (result i32)
1011
i64.const 0
1012
i32.load
1013
)
1014
)
1015
"#,
1016
)?;
1017
let wizer = get_wizer();
1018
wizen_and_run_wasm(&[], 10, &wasm, wizer).await
1019
}
1020
1021