//! Tests for proof-carrying-code-based validation of memory accesses //! in Wasmtime/Cranelift-compiled Wasm, with various combinations of //! memory settings. #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] mod pcc_memory_tests { use wasmtime::*; const TESTS: &'static [&'static str] = &[ r#" local.get 0 i32.load8_u drop "#, r#" local.get 0 i32.load8_u offset=0x10000 drop "#, r#" local.get 0 i32.load16_u drop "#, r#" local.get 0 i32.load16_u offset=0x10000 drop "#, r#" local.get 0 i32.load drop "#, r#" local.get 0 i32.load offset=0x10000 drop "#, r#" local.get 0 i64.load drop "#, r#" local.get 0 i64.load offset=0x10000 drop "#, ]; #[test] #[cfg_attr(miri, ignore)] fn test_build() { let _ = env_logger::try_init(); const KIB: u64 = 1024; const MIB: u64 = 1024 * KIB; const GIB: u64 = 1024 * MIB; let mut bodies = vec![]; for (mem_min, mem_max) in [(1, 1), (10, 20)] { for &snippet in TESTS { bodies.push(format!( "(module (memory {mem_min} {mem_max}) (func (param i32) {snippet}))" )); } let all_snippets = TESTS .iter() .map(|s| s.to_owned()) .collect::>() .join("\n"); bodies.push(format!( "(module (memory {mem_min} {mem_max}) (func (param i32) {all_snippets}))" )); } for test in &bodies { for static_memory_maximum_size in [4 * GIB] { for guard_size in [2 * GIB] { for enable_spectre in [true /* not yet supported by PCC: false */] { for _memory_bits in [32 /* not yet supported by PCC: 64 */] { log::trace!("test:\n{}\n", test); log::trace!( "static {:x} guard {:x}", static_memory_maximum_size, guard_size ); let mut cfg = Config::new(); cfg.static_memory_maximum_size(static_memory_maximum_size); cfg.static_memory_guard_size(guard_size); cfg.dynamic_memory_guard_size(guard_size); cfg.cranelift_pcc(true); unsafe { cfg.cranelift_flag_set( "enable_heap_access_spectre_mitigation", &enable_spectre.to_string(), ); } // TODO: substitute memory32/memory64 into // test module. let engine = Engine::new(&cfg).unwrap(); let _module = Module::new(&engine, test) .expect("compilation with PCC should succeed"); } } } } } } }