diff --git a/lib/src/executor/vm/tests.rs b/lib/src/executor/vm/tests.rs index b00ebac85a..4b300ce3e5 100644 --- a/lib/src/executor/vm/tests.rs +++ b/lib/src/executor/vm/tests.rs @@ -679,6 +679,73 @@ fn globals_reinitialized_after_reset() { } } -// TODO: test for memory reads and writes, including within host functions +#[test] +fn memory_zeroed_after_reset() { + let module_bytes = wat::parse_str( + r#" + (module + (import "env" "memory" (memory $mem 1024 4096)) + (func (export "hello")) + ) + "#, + ) + .unwrap(); + + for exec_hint in super::ExecHint::available_engines() { + let module = super::Module::new(&module_bytes, exec_hint).unwrap(); + let prototype = super::VirtualMachinePrototype::new(&module, |_, _, _| Ok(0)).unwrap(); + + let mut vm = prototype.prepare(); + vm.write_memory(11, &[5, 6]).unwrap(); + + let mut vm = vm.start("hello", &[]).unwrap(); + assert_eq!(vm.read_memory(12, 1).unwrap().as_ref()[0], 6); + vm.write_memory(12, &[7]).unwrap(); + assert_eq!(vm.read_memory(12, 1).unwrap().as_ref()[0], 7); + + assert!(matches!( + vm.run(None), + Ok(super::ExecOutcome::Finished { + return_value: Ok(None), + }) + )); + + assert_eq!(vm.read_memory(11, 2).unwrap().as_ref(), &[5, 7]); -// TODO: test that the memory gets reinitialized when reusing the prototype + let prototype = vm.into_prototype(); + let vm = prototype.prepare(); + assert_eq!(vm.read_memory(11, 2).unwrap().as_ref(), &[0, 0]); + assert_eq!(vm.read_memory(12, 1).unwrap().as_ref(), &[0]); + + let vm = vm.start("hello", &[]).unwrap(); + assert_eq!(vm.read_memory(11, 2).unwrap().as_ref(), &[0, 0]); + assert_eq!(vm.read_memory(12, 1).unwrap().as_ref(), &[0]); + } +} + +#[test] +fn memory_zeroed_after_prepare() { + let module_bytes = wat::parse_str( + r#" + (module + (import "env" "memory" (memory $mem 1024 4096)) + (func (export "hello")) + ) + "#, + ) + .unwrap(); + + for exec_hint in super::ExecHint::available_engines() { + let module = super::Module::new(&module_bytes, exec_hint).unwrap(); + let prototype = super::VirtualMachinePrototype::new(&module, |_, _, _| Ok(0)).unwrap(); + + let mut vm = prototype.prepare(); + assert_eq!(vm.read_memory(11, 2).unwrap().as_ref(), &[0, 0]); + vm.write_memory(11, &[5, 6]).unwrap(); + + let vm = vm.into_prototype().prepare(); + assert_eq!(vm.read_memory(11, 2).unwrap().as_ref(), &[0, 0]); + } +} + +// TODO: test for memory reads and writes, including within host functions diff --git a/wasm-node/CHANGELOG.md b/wasm-node/CHANGELOG.md index c38aabf383..62eb78571f 100644 --- a/wasm-node/CHANGELOG.md +++ b/wasm-node/CHANGELOG.md @@ -4,6 +4,7 @@ ### Changed +- The memory of the Wasm virtual machine is now properly zeroed between runs. ([#211](https://github.com/smol-dot/smoldot/pull/211)) - The Wasm virtual machine no longer tries to grab a table symbol named `__indirect_function_table`. This removes support for an old Substrate feature that no longer exists. ([#181](https://github.com/smol-dot/smoldot/pull/181)) - The signature of host functions called by the Wasm runtime is now checked when the Wasm code is compiled rather than when the functions are called. ([#183](https://github.com/smol-dot/smoldot/pull/183)) - When a Wasm function is being called, the parameters of the function are now allocated using the same allocator as used during the execution (`ext_allocator_malloc_version_1` and `ext_allocator_free_version_1`) rather than being written at a specific location in memory. This is consistent with what Substrate is doing, and makes it legal for a Wasm runtime to call `ext_allocator_free_version_1` on the input data if desired. ([#188](https://github.com/smol-dot/smoldot/pull/188))