From 5aa356f2221eb3876816e1506aa6eda41730a2f8 Mon Sep 17 00:00:00 2001 From: John Sharratt's Shared Account Date: Fri, 29 Jul 2022 22:54:14 +1000 Subject: [PATCH 1/2] Fixed a memory corruption issue with JS memory operations that were reusing invalid views --- Cargo.lock | 1 + examples/engine_cross_compilation.rs | 4 +- examples/engine_headless.rs | 4 +- examples/errors.rs | 2 +- examples/exports_function.rs | 2 +- examples/exports_global.rs | 2 +- examples/exports_memory.rs | 16 +- examples/features.rs | 2 +- examples/hello_world.rs | 2 +- examples/imports_exports.rs | 2 +- examples/imports_function.rs | 4 +- examples/imports_function_env.rs | 2 +- examples/imports_global.rs | 2 +- examples/instance.rs | 2 +- examples/memory.rs | 26 +- examples/metering.rs | 2 +- examples/platform_ios_headless.rs | 2 +- examples/table.rs | 2 +- examples/tunables_limit_memory.rs | 2 +- examples/wasi.rs | 4 +- examples/wasi_pipes.rs | 4 +- fuzz/fuzz_targets/universal_cranelift.rs | 2 +- lib/api/Cargo.toml | 1 + lib/api/src/js/externals/function.rs | 8 +- lib/api/src/js/externals/memory.rs | 184 +----- lib/api/src/js/externals/memory_view.rs | 186 +++++++ lib/api/src/js/externals/mod.rs | 2 + lib/api/src/js/externals/table.rs | 2 +- lib/api/src/js/mem_access.rs | 12 +- lib/api/src/js/mod.rs | 2 +- lib/api/src/js/module.rs | 1 - lib/api/src/js/native.rs | 2 +- lib/api/src/js/ptr.rs | 36 +- lib/api/src/js/store.rs | 3 +- lib/api/src/lib.rs | 1 + lib/api/src/sys/externals/memory.rs | 138 +---- lib/api/src/sys/externals/memory_view.rs | 150 +++++ lib/api/src/sys/externals/mod.rs | 2 + lib/api/src/sys/mem_access.rs | 13 +- lib/api/src/sys/mod.rs | 2 +- lib/api/src/sys/ptr.rs | 43 +- lib/api/tests/js_externals.rs | 30 +- lib/api/tests/js_instance.rs | 60 +- lib/api/tests/js_module.rs | 10 +- lib/api/tests/sys_externals.rs | 6 +- lib/c-api/src/wasm_c_api/externals/memory.rs | 9 +- lib/compiler/src/traits.rs | 2 +- lib/emscripten/src/env/mod.rs | 8 +- lib/emscripten/src/env/unix/mod.rs | 43 +- lib/emscripten/src/env/windows/mod.rs | 32 +- lib/emscripten/src/exec.rs | 8 +- lib/emscripten/src/io/mod.rs | 8 +- lib/emscripten/src/io/unix.rs | 6 +- lib/emscripten/src/lib.rs | 12 +- lib/emscripten/src/libc.rs | 2 +- lib/emscripten/src/macros.rs | 4 +- lib/emscripten/src/memory.rs | 22 +- lib/emscripten/src/signal.rs | 4 +- lib/emscripten/src/syscalls/mod.rs | 30 +- lib/emscripten/src/syscalls/unix.rs | 70 +-- lib/emscripten/src/syscalls/windows.rs | 6 +- lib/emscripten/src/time.rs | 24 +- lib/emscripten/src/utils.rs | 14 +- lib/emscripten/src/varargs.rs | 4 +- lib/wasi/src/lib.rs | 37 +- lib/wasi/src/macros.rs | 8 +- lib/wasi/src/state/pipe.rs | 15 +- lib/wasi/src/state/socket.rs | 77 ++- lib/wasi/src/syscalls/legacy/snapshot0.rs | 34 +- lib/wasi/src/syscalls/mod.rs | 553 ++++++++++--------- tests/compilers/issues.rs | 2 +- 71 files changed, 1053 insertions(+), 966 deletions(-) create mode 100644 lib/api/src/js/externals/memory_view.rs create mode 100644 lib/api/src/sys/externals/memory_view.rs diff --git a/Cargo.lock b/Cargo.lock index a5dd9e5729f..58489ba67b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2843,6 +2843,7 @@ dependencies = [ "target-lexicon 0.12.4", "tempfile", "thiserror", + "tracing", "wasm-bindgen", "wasm-bindgen-test", "wasmer-compiler", diff --git a/examples/engine_cross_compilation.rs b/examples/engine_cross_compilation.rs index de432d5cdb8..90216941823 100644 --- a/examples/engine_cross_compilation.rs +++ b/examples/engine_cross_compilation.rs @@ -69,10 +69,10 @@ fn main() -> Result<(), Box> { // That's where we specify the target for the compiler. // // Use the Universal engine. - let mut engine = EngineBuilder::new(compiler_config).set_target(Some(target)); + let engine = EngineBuilder::new(compiler_config).set_target(Some(target)); // Create a store, that holds the engine. - let mut store = Store::new(engine); + let store = Store::new(engine); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/engine_headless.rs b/examples/engine_headless.rs index 374ccb5600a..e11731f49e0 100644 --- a/examples/engine_headless.rs +++ b/examples/engine_headless.rs @@ -74,7 +74,7 @@ fn main() -> Result<(), Box> { let compiler = Cranelift::default(); // Create a store, that holds the engine. - let mut store = Store::new(compiler); + let store = Store::new(compiler); println!("Compiling module..."); // Let's compile the Wasm module. @@ -96,7 +96,7 @@ fn main() -> Result<(), Box> { // We create a headless Universal engine. let engine = EngineBuilder::headless(); let mut store = Store::new(engine); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Deserializing module..."); // Here we go. diff --git a/examples/errors.rs b/examples/errors.rs index ecbb0c02ac8..46fa0c05b28 100644 --- a/examples/errors.rs +++ b/examples/errors.rs @@ -39,7 +39,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/exports_function.rs b/examples/exports_function.rs index 12eaf36b1b1..7722e95c2dd 100644 --- a/examples/exports_function.rs +++ b/examples/exports_function.rs @@ -40,7 +40,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/exports_global.rs b/examples/exports_global.rs index 3a71368d871..f880e8b7a94 100644 --- a/examples/exports_global.rs +++ b/examples/exports_global.rs @@ -40,7 +40,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/exports_memory.rs b/examples/exports_memory.rs index 6bf9f7cae52..2eb1fb196ed 100644 --- a/examples/exports_memory.rs +++ b/examples/exports_memory.rs @@ -37,7 +37,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -57,14 +57,15 @@ fn main() -> Result<(), Box> { // // The Wasm module exports a memory under "mem". Let's get it. let memory = instance.exports.get_memory("mem")?; - + // Now that we have the exported memory, let's get some // information about it. // // The first thing we might be intersted in is the size of the memory. // Let's get it! - println!("Memory size (pages) {:?}", memory.size(&mut store)); - println!("Memory size (bytes) {:?}", memory.data_size(&mut store)); + let memory_view = memory.view(&store); + println!("Memory size (pages) {:?}", memory_view.size()); + println!("Memory size (bytes) {:?}", memory_view.data_size()); // Oh! Wait, before reading the contents, we need to know // where to find what we are looking for. @@ -79,8 +80,9 @@ fn main() -> Result<(), Box> { // // We will get bytes out of the memory so we need to // decode them into a string. + let memory_view = memory.view(&store); let str = ptr - .read_utf8_string(&mut store, memory, length as u32) + .read_utf8_string(&memory_view, length as u32) .unwrap(); println!("Memory contents: {:?}", str); @@ -90,7 +92,7 @@ fn main() -> Result<(), Box> { // To do that, we'll make a slice from our pointer and change the content // of each element. let new_str = b"Hello, Wasmer!"; - let values = ptr.slice(&mut store, memory, new_str.len() as u32).unwrap(); + let values = ptr.slice(&memory_view, new_str.len() as u32).unwrap(); for i in 0..new_str.len() { values.index(i as u64).write(new_str[i]).unwrap(); } @@ -103,7 +105,7 @@ fn main() -> Result<(), Box> { println!("New string length: {:?}", new_str.len()); let str = ptr - .read_utf8_string(&mut store, memory, new_str.len() as u32) + .read_utf8_string(&memory_view, new_str.len() as u32) .unwrap(); println!("New memory contents: {:?}", str); diff --git a/examples/features.rs b/examples/features.rs index aa3b9090118..1469f47b0de 100644 --- a/examples/features.rs +++ b/examples/features.rs @@ -41,7 +41,7 @@ fn main() -> anyhow::Result<()> { // Now, let's define the store, and compile the module. let mut store = Store::new(engine); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let module = Module::new(&store, wasm_bytes)?; // Finally, let's instantiate the module, and execute something diff --git a/examples/hello_world.rs b/examples/hello_world.rs index eaec3d75cfd..73ad8620a26 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -54,7 +54,7 @@ fn main() -> anyhow::Result<()> { // Next we'll set up our `Module` so that we can execute it. First, create // a `FunctionEnv` in which to instantiate our `Module`. - let mut context = FunctionEnv::new(&mut store, ()); + let context = FunctionEnv::new(&mut store, ()); // We define a function to act as our "env" "say_hello" function imported in the // Wasm program above. diff --git a/examples/imports_exports.rs b/examples/imports_exports.rs index 01b4c7ef89b..c8d18704194 100644 --- a/examples/imports_exports.rs +++ b/examples/imports_exports.rs @@ -44,7 +44,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/imports_function.rs b/examples/imports_function.rs index c111cfeb8c5..d454cc8d057 100644 --- a/examples/imports_function.rs +++ b/examples/imports_function.rs @@ -45,9 +45,9 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env1 = FunctionEnv::new(&mut store, ()); + let env1 = FunctionEnv::new(&mut store, ()); struct MyEnv; - let mut env2 = FunctionEnv::new(&mut store, MyEnv {}); + let env2 = FunctionEnv::new(&mut store, MyEnv {}); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/imports_function_env.rs b/examples/imports_function_env.rs index df7ee8b26a0..e56e45bbbf6 100644 --- a/examples/imports_function_env.rs +++ b/examples/imports_function_env.rs @@ -87,7 +87,7 @@ fn main() -> Result<(), Box> { *counter_ref } - let mut env = FunctionEnv::new( + let env = FunctionEnv::new( &mut store, Env { counter: shared_counter.clone(), diff --git a/examples/imports_global.rs b/examples/imports_global.rs index 9ae571bf482..2609161716a 100644 --- a/examples/imports_global.rs +++ b/examples/imports_global.rs @@ -40,7 +40,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/instance.rs b/examples/instance.rs index cff03d54875..faff810ebeb 100644 --- a/examples/instance.rs +++ b/examples/instance.rs @@ -39,7 +39,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/memory.rs b/examples/memory.rs index 3204e5a2229..c90fbdd91aa 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -59,7 +59,7 @@ fn main() -> anyhow::Result<()> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -83,7 +83,7 @@ fn main() -> anyhow::Result<()> { let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_typed_function(&mut store, "set_at")?; let memory = instance.exports.get_memory("memory")?; - + // We now have an instance ready to be used. // // We will start by querying the most intersting information @@ -95,15 +95,18 @@ fn main() -> anyhow::Result<()> { // The size in bytes can be found either by querying its pages or by // querying the memory directly. println!("Querying memory size..."); - assert_eq!(memory.size(&mut store), Pages::from(1)); - assert_eq!(memory.size(&mut store).bytes(), Bytes::from(65536 as usize)); - assert_eq!(memory.data_size(&mut store), 65536); - + let memory_view = memory.view(&store); + assert_eq!(memory_view.size(), Pages::from(1)); + assert_eq!(memory_view.size().bytes(), Bytes::from(65536 as usize)); + assert_eq!(memory_view.data_size(), 65536); + // Sometimes, the guest module may also export a function to let you // query the memory. Here we have a `mem_size` function, let's try it: let result = mem_size.call(&mut store)?; + + let memory_view = memory.view(&store); println!("Memory size: {:?}", result); - assert_eq!(Pages::from(result as u32), memory.size(&mut store)); + assert_eq!(Pages::from(result as u32), memory_view.size()); // Now that we know the size of our memory, it's time to see how wa // can change this. @@ -111,11 +114,14 @@ fn main() -> anyhow::Result<()> { // A memory can be grown to allow storing more things into it. Let's // see how we can do that: println!("Growing memory..."); + // Here we are requesting two more pages for our memory. memory.grow(&mut store, 2)?; - assert_eq!(memory.size(&mut store), Pages::from(3)); - assert_eq!(memory.data_size(&mut store), 65536 * 3); - + + let memory_view = memory.view(&store); + assert_eq!(memory_view.size(), Pages::from(3)); + assert_eq!(memory_view.data_size(), 65536 * 3); + // Now that we know how to query and adjust the size of the memory, // let's see how wa can write to it or read from it. // diff --git a/examples/metering.rs b/examples/metering.rs index d9eb765f086..39dadf9d358 100644 --- a/examples/metering.rs +++ b/examples/metering.rs @@ -72,7 +72,7 @@ fn main() -> anyhow::Result<()> { // We use our previously create compiler configuration // with the Universal engine. let mut store = Store::new(EngineBuilder::new(compiler_config)); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/platform_ios_headless.rs b/examples/platform_ios_headless.rs index 94639ae46e9..7b133b2db03 100644 --- a/examples/platform_ios_headless.rs +++ b/examples/platform_ios_headless.rs @@ -11,7 +11,7 @@ //! ``` //! //! Ready? - +#![allow(unused)] use std::path::Path; use std::str::FromStr; use wasmer::{wat2wasm, Module, RuntimeError, Store}; diff --git a/examples/table.rs b/examples/table.rs index 922b8f30032..17a5b50e666 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -52,7 +52,7 @@ fn main() -> anyhow::Result<()> { // We set up our store with an engine and a compiler. let mut store = Store::new(Cranelift::default()); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); // Then compile our Wasm. let module = Module::new(&store, wasm_bytes)?; let import_object = imports! {}; diff --git a/examples/tunables_limit_memory.rs b/examples/tunables_limit_memory.rs index b6267431beb..b31b4b74d37 100644 --- a/examples/tunables_limit_memory.rs +++ b/examples/tunables_limit_memory.rs @@ -143,7 +143,7 @@ fn main() -> Result<(), Box> { // Create a store, that holds the engine and our custom tunables let mut store = Store::new_with_tunables(compiler, tunables); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); let module = Module::new(&store, wasm_bytes)?; diff --git a/examples/wasi.rs b/examples/wasi.rs index 2a8a047c447..e3232061148 100644 --- a/examples/wasi.rs +++ b/examples/wasi.rs @@ -15,7 +15,7 @@ //! //! Ready? -use wasmer::{FunctionEnv, Instance, Module, Store}; +use wasmer::{Instance, Module, Store}; use wasmer_compiler_cranelift::Cranelift; use wasmer_wasi::WasiState; @@ -39,7 +39,7 @@ fn main() -> Result<(), Box> { println!("Creating `WasiEnv`..."); // First, we create the `WasiEnv` - let mut wasi_env = WasiState::new("hello") + let wasi_env = WasiState::new("hello") // .args(&["world"]) // .env("KEY", "Value") .finalize(&mut store)?; diff --git a/examples/wasi_pipes.rs b/examples/wasi_pipes.rs index 84f1a9b6229..ed7ef03a075 100644 --- a/examples/wasi_pipes.rs +++ b/examples/wasi_pipes.rs @@ -12,7 +12,7 @@ //! Ready? use std::io::{Read, Write}; -use wasmer::{FunctionEnv, Instance, Module, Store}; +use wasmer::{Instance, Module, Store}; use wasmer_compiler_cranelift::Cranelift; use wasmer_wasi::{Pipe, WasiState}; @@ -38,7 +38,7 @@ fn main() -> Result<(), Box> { // First, we create the `WasiEnv` with the stdio pipes let mut input = Pipe::new(); let mut output = Pipe::new(); - let mut wasi_env = WasiState::new("hello") + let wasi_env = WasiState::new("hello") .stdin(Box::new(input.clone())) .stdout(Box::new(output.clone())) .finalize(&mut store)?; diff --git a/fuzz/fuzz_targets/universal_cranelift.rs b/fuzz/fuzz_targets/universal_cranelift.rs index c1303cf8778..f0e3a424ef1 100644 --- a/fuzz/fuzz_targets/universal_cranelift.rs +++ b/fuzz/fuzz_targets/universal_cranelift.rs @@ -43,7 +43,7 @@ fuzz_target!(|module: WasmSmithModule| { compiler.enable_verifier(); let mut store = Store::new(compiler); let module = Module::new(&store, &wasm_bytes).unwrap(); - match Instance::new(&module, &imports! {}) { + match Instance::new(&mut store, &module, &imports! {}) { Ok(_) => {} Err(e) => { let error_message = format!("{}", e); diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index de08fefe504..aeee50c53e2 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -26,6 +26,7 @@ indexmap = { version = "1.6", features = ["serde-1"] } cfg-if = "1.0" thiserror = "1.0" more-asserts = "0.2" +tracing = "0.1" # - Optional shared dependencies. wat = { version = "1.0", optional = true } diff --git a/lib/api/src/js/externals/function.rs b/lib/api/src/js/externals/function.rs index f5ee117cef9..e9477b39cbe 100644 --- a/lib/api/src/js/externals/function.rs +++ b/lib/api/src/js/externals/function.rs @@ -115,7 +115,7 @@ impl Function { let wrapped_func: JsValue = match function_type.results().len() { 0 => Closure::wrap(Box::new(move |args: &Array| { let mut store: StoreMut = unsafe { StoreMut::from_raw(raw_store as _) }; - let mut env: FunctionEnvMut = raw_env.clone().into_mut(&mut store); + let env: FunctionEnvMut = raw_env.clone().into_mut(&mut store); let wasm_arguments = function_type .params() .iter() @@ -129,7 +129,7 @@ impl Function { .into_js_value(), 1 => Closure::wrap(Box::new(move |args: &Array| { let mut store: StoreMut = unsafe { StoreMut::from_raw(raw_store as _) }; - let mut env: FunctionEnvMut = raw_env.clone().into_mut(&mut store); + let env: FunctionEnvMut = raw_env.clone().into_mut(&mut store); let wasm_arguments = function_type .params() .iter() @@ -143,7 +143,7 @@ impl Function { .into_js_value(), _n => Closure::wrap(Box::new(move |args: &Array| { let mut store: StoreMut = unsafe { StoreMut::from_raw(raw_store as _) }; - let mut env: FunctionEnvMut = raw_env.clone().into_mut(&mut store); + let env: FunctionEnvMut = raw_env.clone().into_mut(&mut store); let wasm_arguments = function_type .params() .iter() @@ -509,7 +509,7 @@ mod inner { use super::RuntimeError; use super::VMFunctionBody; use crate::js::function_env::{FunctionEnvMut, VMFunctionEnvironment}; - use crate::js::store::{AsStoreMut, InternalStoreHandle, StoreHandle, StoreInner, StoreMut}; + use crate::js::store::{AsStoreMut, InternalStoreHandle, StoreHandle, StoreMut}; use crate::js::FunctionEnv; use crate::js::NativeWasmTypeInto; use std::array::TryFromSliceError; diff --git a/lib/api/src/js/externals/memory.rs b/lib/api/src/js/externals/memory.rs index 9103eeb1814..65e657b2bdd 100644 --- a/lib/api/src/js/externals/memory.rs +++ b/lib/api/src/js/externals/memory.rs @@ -3,15 +3,17 @@ use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreObjects}; use crate::js::{MemoryAccessError, MemoryType}; -use std::convert::TryInto; use std::marker::PhantomData; use std::mem::MaybeUninit; use std::slice; use thiserror::Error; +use tracing::warn; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; -use wasmer_types::{Bytes, Pages}; +use wasmer_types::Pages; + +use super::MemoryView; /// Error type describing things that can go wrong when operating on Wasm Memories. #[derive(Error, Debug, Clone, PartialEq, Hash)] @@ -79,8 +81,6 @@ extern "C" { #[derive(Debug, Clone)] pub struct Memory { pub(crate) handle: StoreHandle, - #[allow(dead_code)] - view: js_sys::Uint8Array, } unsafe impl Send for Memory {} @@ -132,52 +132,10 @@ impl Memory { self.handle.get(store.as_store_ref().objects()).ty } - /// Returns the pointer to the raw bytes of the `Memory`. - #[doc(hidden)] - pub fn data_ptr(&self) -> *mut u8 { - unimplemented!("direct data pointer access is not possible in JavaScript"); - } - - /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self, store: &impl AsStoreRef) -> u64 { - js_sys::Reflect::get( - &self - .handle - .get(store.as_store_ref().objects()) - .memory - .buffer(), - &"byteLength".into(), - ) - .unwrap() - .as_f64() - .unwrap() as _ - } - - /// Returns the size (in [`Pages`]) of the `Memory`. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let mut store = Store::default(); - /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); - /// - /// assert_eq!(m.size(), Pages(1)); - /// ``` - pub fn size(&self, store: &impl AsStoreRef) -> Pages { - let bytes = js_sys::Reflect::get( - &self - .handle - .get(store.as_store_ref().objects()) - .memory - .buffer(), - &"byteLength".into(), - ) - .unwrap() - .as_f64() - .unwrap() as u64; - Bytes(bytes as usize).try_into().unwrap() + /// Creates a view into the memory that then allows for + /// read and write + pub fn view(&self, store: &impl AsStoreRef) -> MemoryView { + MemoryView::new(self, store) } /// Grow memory by the specified amount of WebAssembly [`Pages`] and return @@ -219,12 +177,13 @@ impl Memory { IntoPages: Into, { let pages = delta.into(); + warn!("memory grow {}", pages.0); let js_memory = &self.handle.get_mut(store.objects_mut()).memory; let our_js_memory: &JSMemory = JsCast::unchecked_from_js_ref(js_memory); let new_pages = our_js_memory.grow(pages.0).map_err(|err| { if err.is_instance_of::() { MemoryError::CouldNotGrow { - current: self.size(&store.as_store_ref()), + current: self.view(&store.as_store_ref()).size(), attempted_delta: pages, } } else { @@ -234,30 +193,9 @@ impl Memory { Ok(Pages(new_pages)) } - /// Used by tests - #[doc(hidden)] - pub fn uint8view(&self, store: &impl AsStoreRef) -> js_sys::Uint8Array { - js_sys::Uint8Array::new( - &self - .handle - .get(store.as_store_ref().objects()) - .memory - .buffer(), - ) - } - - pub(crate) fn buffer<'a>(&'a self, _store: &'a impl AsStoreRef) -> MemoryBuffer<'a> { - MemoryBuffer { - base: &self.view as *const _ as *mut _, - marker: PhantomData, - } - } - pub(crate) fn from_vm_export(store: &mut impl AsStoreMut, vm_memory: VMMemory) -> Self { - let view = js_sys::Uint8Array::new(&vm_memory.memory.buffer()); Self { handle: StoreHandle::new(store.objects_mut(), vm_memory), - view, } } @@ -265,108 +203,13 @@ impl Memory { store: &mut impl AsStoreMut, internal: InternalStoreHandle, ) -> Self { - let view = - js_sys::Uint8Array::new(&internal.get(store.as_store_ref().objects()).memory.buffer()); Self { handle: unsafe { StoreHandle::from_internal(store.as_store_ref().objects().id(), internal) }, - view, } } - /// Safely reads bytes from the memory at the given offset. - /// - /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned - /// to indicate an out-of-bounds access. - /// - /// This method is guaranteed to be safe (from the host side) in the face of - /// concurrent writes. - pub fn read( - &self, - _store: &impl AsStoreRef, - offset: u64, - data: &mut [u8], - ) -> Result<(), MemoryAccessError> { - let view = &self.view; - let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; - let len: u32 = data - .len() - .try_into() - .map_err(|_| MemoryAccessError::Overflow)?; - let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; - if end > view.length() { - Err(MemoryAccessError::HeapOutOfBounds)?; - } - view.subarray(offset, end).copy_to(data); - Ok(()) - } - - /// Safely reads bytes from the memory at the given offset. - /// - /// This method is similar to `read` but allows reading into an - /// uninitialized buffer. An initialized view of the buffer is returned. - /// - /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned - /// to indicate an out-of-bounds access. - /// - /// This method is guaranteed to be safe (from the host side) in the face of - /// concurrent writes. - pub fn read_uninit<'a>( - &self, - _store: &impl AsStoreRef, - offset: u64, - buf: &'a mut [MaybeUninit], - ) -> Result<&'a mut [u8], MemoryAccessError> { - let view = &self.view; - let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; - let len: u32 = buf - .len() - .try_into() - .map_err(|_| MemoryAccessError::Overflow)?; - let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; - if end > view.length() { - Err(MemoryAccessError::HeapOutOfBounds)?; - } - - // Zero-initialize the buffer to avoid undefined behavior with - // uninitialized data. - for elem in buf.iter_mut() { - *elem = MaybeUninit::new(0); - } - let buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len()) }; - - view.subarray(offset, end).copy_to(buf); - Ok(buf) - } - - /// Safely writes bytes to the memory at the given offset. - /// - /// If the write exceeds the bounds of the memory then a `MemoryAccessError` is - /// returned. - /// - /// This method is guaranteed to be safe (from the host side) in the face of - /// concurrent reads/writes. - pub fn write( - &self, - _store: &mut impl AsStoreMut, - offset: u64, - data: &[u8], - ) -> Result<(), MemoryAccessError> { - let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; - let len: u32 = data - .len() - .try_into() - .map_err(|_| MemoryAccessError::Overflow)?; - let view = &self.view; - let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; - if end > view.length() { - Err(MemoryAccessError::HeapOutOfBounds)?; - } - view.subarray(offset, end).copy_from(data); - Ok(()) - } - /// Checks whether this `Global` can be used with the given context. pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool { self.handle.store_id() == store.as_store_ref().objects().id() @@ -385,8 +228,8 @@ impl<'a> Exportable<'a> for Memory { /// Underlying buffer for a memory. #[derive(Copy, Clone)] pub(crate) struct MemoryBuffer<'a> { - base: *mut js_sys::Uint8Array, - marker: PhantomData<(&'a Memory, &'a StoreObjects)>, + pub(crate) base: *mut js_sys::Uint8Array, + pub(crate) marker: PhantomData<(&'a Memory, &'a StoreObjects)>, } impl<'a> MemoryBuffer<'a> { @@ -396,6 +239,7 @@ impl<'a> MemoryBuffer<'a> { .ok_or(MemoryAccessError::Overflow)?; let view = unsafe { &*(self.base) }; if end > view.length().into() { + warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, view.length()); return Err(MemoryAccessError::HeapOutOfBounds); } view.subarray(offset as _, end as _) @@ -413,6 +257,7 @@ impl<'a> MemoryBuffer<'a> { .ok_or(MemoryAccessError::Overflow)?; let view = unsafe { &*(self.base) }; if end > view.length().into() { + warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, view.length()); return Err(MemoryAccessError::HeapOutOfBounds); } let buf_ptr = buf.as_mut_ptr() as *mut u8; @@ -428,6 +273,7 @@ impl<'a> MemoryBuffer<'a> { .ok_or(MemoryAccessError::Overflow)?; let view = unsafe { &mut *(self.base) }; if end > view.length().into() { + warn!("attempted to write ({} bytes) beyond the bounds of the memory view ({} > {})", data.len(), end, view.length()); return Err(MemoryAccessError::HeapOutOfBounds); } view.subarray(offset as _, end as _).copy_from(data); diff --git a/lib/api/src/js/externals/memory_view.rs b/lib/api/src/js/externals/memory_view.rs new file mode 100644 index 00000000000..34fbb5f26be --- /dev/null +++ b/lib/api/src/js/externals/memory_view.rs @@ -0,0 +1,186 @@ +use crate::js::store::AsStoreRef; +use crate::js::MemoryAccessError; +use std::convert::TryInto; +use std::marker::PhantomData; +use std::mem::MaybeUninit; +use std::slice; +use tracing::warn; + +use wasmer_types::{Bytes, Pages}; + +use super::Memory; +use super::memory::MemoryBuffer; + +/// A WebAssembly `memory` view. +/// +/// A memory view is used to read and write to the linear memory. +/// +/// After a memory is grown a view must not be used anymore. Views are +/// created using the Memory.grow() method. +#[derive(Debug)] +pub struct MemoryView<'a> { + view: js_sys::Uint8Array, + size: u64, + marker: PhantomData<&'a Memory>, +} + +impl<'a> MemoryView<'a> +{ + pub(crate) fn new(memory: &Memory, store: &impl AsStoreRef) -> Self { + let buffer = memory + .handle + .get(store.as_store_ref().objects()) + .memory + .buffer(); + + let size = js_sys::Reflect::get( + &buffer, + &"byteLength".into(), + ) + .unwrap() + .as_f64() + .unwrap() as u64; + + let view = js_sys::Uint8Array::new( + &buffer, + ); + + Self { + view, + size, + marker: PhantomData, + } + } + + /// Returns the pointer to the raw bytes of the `Memory`. + #[doc(hidden)] + pub fn data_ptr(&self) -> *mut u8 { + unimplemented!("direct data pointer access is not possible in JavaScript"); + } + + /// Returns the size (in bytes) of the `Memory`. + pub fn data_size(&self) -> u64 { + self.size + } + + /// Returns the size (in [`Pages`]) of the `Memory`. + /// + /// # Example + /// + /// ``` + /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; + /// # let mut store = Store::default(); + /// # + /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); + /// + /// assert_eq!(m.size(), Pages(1)); + /// ``` + pub fn size(&self) -> Pages { + Bytes(self.size as usize).try_into().unwrap() + } + + /// Used by tests + #[doc(hidden)] + pub fn uint8view(&self) -> js_sys::Uint8Array { + self.view.clone() + } + + pub(crate) fn buffer(&self) -> MemoryBuffer<'a> { + MemoryBuffer { + base: &self.view as *const _ as *mut _, + marker: PhantomData, + } + } + + /// Safely reads bytes from the memory at the given offset. + /// + /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned + /// to indicate an out-of-bounds access. + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn read( + &self, + offset: u64, + data: &mut [u8], + ) -> Result<(), MemoryAccessError> { + let view = &self.view; + let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; + let len: u32 = data + .len() + .try_into() + .map_err(|_| MemoryAccessError::Overflow)?; + let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; + if end > view.length() { + warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", len, end, view.length()); + Err(MemoryAccessError::HeapOutOfBounds)?; + } + view.subarray(offset, end).copy_to(data); + Ok(()) + } + + /// Safely reads bytes from the memory at the given offset. + /// + /// This method is similar to `read` but allows reading into an + /// uninitialized buffer. An initialized view of the buffer is returned. + /// + /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned + /// to indicate an out-of-bounds access. + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn read_uninit( + &self, + offset: u64, + buf: &'a mut [MaybeUninit], + ) -> Result<&'a mut [u8], MemoryAccessError> { + let view = &self.view; + let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; + let len: u32 = buf + .len() + .try_into() + .map_err(|_| MemoryAccessError::Overflow)?; + let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; + if end > view.length() { + warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", len, end, view.length()); + Err(MemoryAccessError::HeapOutOfBounds)?; + } + + // Zero-initialize the buffer to avoid undefined behavior with + // uninitialized data. + for elem in buf.iter_mut() { + *elem = MaybeUninit::new(0); + } + let buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len()) }; + + view.subarray(offset, end).copy_to(buf); + Ok(buf) + } + + /// Safely writes bytes to the memory at the given offset. + /// + /// If the write exceeds the bounds of the memory then a `MemoryAccessError` is + /// returned. + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent reads/writes. + pub fn write( + &self, + offset: u64, + data: &[u8], + ) -> Result<(), MemoryAccessError> { + let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; + let len: u32 = data + .len() + .try_into() + .map_err(|_| MemoryAccessError::Overflow)?; + let view = &self.view; + let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; + if end > view.length() { + warn!("attempted to write ({} bytes) beyond the bounds of the memory view ({} > {})", len, end, view.length()); + Err(MemoryAccessError::HeapOutOfBounds)?; + } + view.subarray(offset, end).copy_from(data); + Ok(()) + } +} diff --git a/lib/api/src/js/externals/mod.rs b/lib/api/src/js/externals/mod.rs index a567d7ec991..4a3c8031508 100644 --- a/lib/api/src/js/externals/mod.rs +++ b/lib/api/src/js/externals/mod.rs @@ -1,11 +1,13 @@ pub(crate) mod function; mod global; pub(crate) mod memory; +pub(crate) mod memory_view; mod table; pub use self::function::{FromToNativeWasmType, Function, HostFunction, WasmTypeList}; pub use self::global::Global; pub use self::memory::{Memory, MemoryError}; +pub use self::memory_view::MemoryView; pub use self::table::Table; use crate::js::export::Export; diff --git a/lib/api/src/js/externals/table.rs b/lib/api/src/js/externals/table.rs index ec7565a8c5c..3cd9882fed6 100644 --- a/lib/api/src/js/externals/table.rs +++ b/lib/api/src/js/externals/table.rs @@ -128,7 +128,7 @@ impl Table { /// Returns an error if the `delta` is out of bounds for the table. pub fn grow( &self, - store: &mut AsStoreMut, + _store: &mut impl AsStoreMut, _delta: u32, _init: Value, ) -> Result { diff --git a/lib/api/src/js/mem_access.rs b/lib/api/src/js/mem_access.rs index be476b8bd41..c5e4e1f2658 100644 --- a/lib/api/src/js/mem_access.rs +++ b/lib/api/src/js/mem_access.rs @@ -1,7 +1,6 @@ use crate::js::externals::memory::MemoryBuffer; -use crate::js::store::AsStoreRef; use crate::js::RuntimeError; -use crate::js::{Memory, Memory32, Memory64, WasmPtr}; +use crate::js::{MemoryView, Memory32, Memory64, WasmPtr}; use std::{ convert::TryInto, fmt, @@ -61,9 +60,9 @@ pub struct WasmRef<'a, T: ValueType> { impl<'a, T: ValueType> WasmRef<'a, T> { /// Creates a new `WasmRef` at the given offset in a memory. #[inline] - pub fn new(store: &'a impl AsStoreRef, memory: &'a Memory, offset: u64) -> Self { + pub fn new(view: &'a MemoryView, offset: u64) -> Self { Self { - buffer: memory.buffer(store), + buffer: view.buffer(), offset, marker: PhantomData, } @@ -160,8 +159,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { /// Returns a `MemoryAccessError` if the slice length overflows. #[inline] pub fn new( - store: &'a impl AsStoreRef, - memory: &'a Memory, + memory: &'a MemoryView, offset: u64, len: u64, ) -> Result { @@ -172,7 +170,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { .checked_add(total_len) .ok_or(MemoryAccessError::Overflow)?; Ok(Self { - buffer: memory.buffer(store), + buffer: memory.buffer(), offset, len, marker: PhantomData, diff --git a/lib/api/src/js/mod.rs b/lib/api/src/js/mod.rs index 9863123c55b..2cbcfa1db7d 100644 --- a/lib/api/src/js/mod.rs +++ b/lib/api/src/js/mod.rs @@ -48,7 +48,7 @@ pub use crate::js::error::{DeserializeError, InstantiationError, SerializeError} pub use crate::js::export::Export; pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::js::externals::{ - Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, MemoryError, Table, + Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, MemoryView, MemoryError, Table, WasmTypeList, }; pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut}; diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 209f46dfd46..975d1bee5d5 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -5,7 +5,6 @@ use crate::js::error::{CompileError, InstantiationError}; use crate::js::error::{DeserializeError, SerializeError}; use crate::js::externals::Extern; use crate::js::imports::Imports; -use crate::js::store::Store; use crate::js::store::{AsStoreMut, StoreHandle}; use crate::js::types::{AsJs, ExportType, ImportType}; use crate::js::RuntimeError; diff --git a/lib/api/src/js/native.rs b/lib/api/src/js/native.rs index 6d34ca82425..d2056323d03 100644 --- a/lib/api/src/js/native.rs +++ b/lib/api/src/js/native.rs @@ -39,7 +39,7 @@ where #[allow(dead_code)] pub(crate) fn new( store: &mut impl AsStoreMut, - env: &FunctionEnv, + _env: &FunctionEnv, vm_function: VMFunction, ) -> Self { Self { diff --git a/lib/api/src/js/ptr.rs b/lib/api/src/js/ptr.rs index 1d3f79ffa56..3c0b5c3ca94 100644 --- a/lib/api/src/js/ptr.rs +++ b/lib/api/src/js/ptr.rs @@ -1,6 +1,5 @@ -use crate::js::store::AsStoreRef; use crate::js::NativeWasmTypeInto; -use crate::js::{externals::Memory, FromToNativeWasmType}; +use crate::js::{externals::MemoryView, FromToNativeWasmType}; use crate::js::{MemoryAccessError, WasmRef, WasmSlice}; use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; @@ -138,25 +137,24 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref<'a>(self, store: &'a impl AsStoreRef, memory: &'a Memory) -> WasmRef<'a, T> { - WasmRef::new(store, memory, self.offset.into()) + pub fn deref<'a>(self, view: &'a MemoryView) -> WasmRef<'a, T> { + WasmRef::new(view, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, store: &impl AsStoreRef, memory: &Memory) -> Result { - self.deref(store, memory).read() + pub fn read(self, view: &MemoryView) -> Result { + self.deref(view).read() } /// Writes to the address pointed to by this `WasmPtr` in a memory. #[inline] pub fn write( self, - store: &impl AsStoreRef, - memory: &Memory, + view: &MemoryView, val: T, ) -> Result<(), MemoryAccessError> { - self.deref(store, memory).write(val) + self.deref(view).write(val) } /// Creates a `WasmSlice` starting at this `WasmPtr` which allows reading @@ -167,11 +165,10 @@ impl WasmPtr { #[inline] pub fn slice<'a>( self, - store: &'a impl AsStoreRef, - memory: &'a Memory, + view: &'a MemoryView, len: M::Offset, ) -> Result, MemoryAccessError> { - WasmSlice::new(store, memory, self.offset.into(), len.into()) + WasmSlice::new(view, self.offset.into(), len.into()) } /// Reads a sequence of values from this `WasmPtr` until a value that @@ -181,14 +178,13 @@ impl WasmPtr { #[inline] pub fn read_until<'a>( self, - store: &'a impl AsStoreRef, - memory: &'a Memory, + view: &'a MemoryView, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { let mut vec = Vec::new(); for i in 0u64.. { let i = M::Offset::try_from(i).map_err(|_| MemoryAccessError::Overflow)?; - let val = self.add_offset(i)?.deref(store, memory).read()?; + let val = self.add_offset(i)?.deref(view).read()?; if end(&val) { break; } @@ -206,11 +202,10 @@ impl WasmPtr { #[inline] pub fn read_utf8_string<'a>( self, - store: &'a impl AsStoreRef, - memory: &'a Memory, + view: &'a MemoryView, len: M::Offset, ) -> Result { - let vec = self.slice(store, memory, len)?.read_to_vec()?; + let vec = self.slice(view, len)?.read_to_vec()?; Ok(String::from_utf8(vec)?) } @@ -221,10 +216,9 @@ impl WasmPtr { #[inline] pub fn read_utf8_string_with_nul<'a>( self, - store: &'a impl AsStoreRef, - memory: &'a Memory, + view: &'a MemoryView, ) -> Result { - let vec = self.read_until(store, memory, |&byte| byte == 0)?; + let vec = self.read_until(view, |&byte| byte == 0)?; Ok(String::from_utf8(vec)?) } } diff --git a/lib/api/src/js/store.rs b/lib/api/src/js/store.rs index c4bd1c6ace5..b6c10e84627 100644 --- a/lib/api/src/js/store.rs +++ b/lib/api/src/js/store.rs @@ -182,7 +182,6 @@ impl AsStoreMut for &'_ mut T { pub use objects::*; -use crate::js::FunctionEnv; mod objects { use crate::js::{ export::{VMFunction, VMGlobal, VMMemory, VMTable}, @@ -433,6 +432,7 @@ mod objects { /// Data used by the generated code is generally located inline within the /// `VMContext` for items defined in an instance. Host-defined objects are /// allocated separately and owned directly by the context. + #[allow(dead_code)] pub enum MaybeInstanceOwned { /// The data is owned here. Host(Box>), @@ -443,6 +443,7 @@ mod objects { impl MaybeInstanceOwned { /// Returns underlying pointer to the VM data. + #[allow(dead_code)] pub fn as_ptr(&self) -> NonNull { match self { MaybeInstanceOwned::Host(p) => unsafe { NonNull::new_unchecked(p.get()) }, diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index b26505906ee..7592337e8d2 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -25,6 +25,7 @@ clippy::use_self ) )] +#![allow(deprecated_cfg_attr_crate_type_name)] #![cfg_attr(feature = "js", crate_type = "cdylib")] //! [`Wasmer`](https://wasmer.io/) is the most popular diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 93ae55f1769..5cc57086e80 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -8,9 +8,12 @@ use std::marker::PhantomData; use std::mem; use std::mem::MaybeUninit; use std::slice; +use tracing::warn; use wasmer_types::Pages; use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, StoreObjects, VMExtern, VMMemory}; +use super::MemoryView; + /// A WebAssembly `memory` instance. /// /// A memory instance is the runtime representation of a linear memory. @@ -27,7 +30,7 @@ use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, StoreObjects, VME /// Spec: #[derive(Debug, Clone)] pub struct Memory { - handle: StoreHandle, + pub(crate) handle: StoreHandle, } impl Memory { @@ -72,61 +75,10 @@ impl Memory { self.handle.get(store.as_store_ref().objects()).ty() } - /// Returns the pointer to the raw bytes of the `Memory`. - // - // This used by wasmer-emscripten and wasmer-c-api, but should be treated - // as deprecated and not used in future code. - #[doc(hidden)] - pub fn data_ptr(&self, store: &impl AsStoreRef) -> *mut u8 { - self.buffer(store).base - } - - /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self, store: &impl AsStoreRef) -> u64 { - self.buffer(store).len.try_into().unwrap() - } - - /// Retrieve a slice of the memory contents. - /// - /// # Safety - /// - /// Until the returned slice is dropped, it is undefined behaviour to - /// modify the memory contents in any way including by calling a wasm - /// function that writes to the memory or by resizing the memory. - #[doc(hidden)] - pub unsafe fn data_unchecked(&self, store: &impl AsStoreRef) -> &[u8] { - self.data_unchecked_mut(store) - } - - /// Retrieve a mutable slice of the memory contents. - /// - /// # Safety - /// - /// This method provides interior mutability without an UnsafeCell. Until - /// the returned value is dropped, it is undefined behaviour to read or - /// write to the pointed-to memory in any way except through this slice, - /// including by calling a wasm function that reads the memory contents or - /// by resizing this Memory. - #[allow(clippy::mut_from_ref)] - #[doc(hidden)] - pub unsafe fn data_unchecked_mut(&self, store: &impl AsStoreRef) -> &mut [u8] { - slice::from_raw_parts_mut(self.buffer(store).base, self.buffer(store).len) - } - - /// Returns the size (in [`Pages`]) of the `Memory`. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let mut store = Store::default(); - /// # - /// let m = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap(); - /// - /// assert_eq!(m.size(&mut store), Pages(1)); - /// ``` - pub fn size(&self, store: &impl AsStoreRef) -> Pages { - self.handle.get(store.as_store_ref().objects()).size() + /// Creates a view into the memory that then allows for + /// read and write + pub fn view<'a>(&self, store: &'a impl AsStoreRef) -> MemoryView<'a> { + MemoryView::new(self, store) } /// Grow memory by the specified amount of WebAssembly [`Pages`] and return @@ -142,7 +94,7 @@ impl Memory { /// let p = m.grow(&mut store, 2).unwrap(); /// /// assert_eq!(p, Pages(1)); - /// assert_eq!(m.size(&mut store), Pages(3)); + /// assert_eq!(m.view(&mut store).size(), Pages(3)); /// ``` /// /// # Errors @@ -172,67 +124,6 @@ impl Memory { self.handle.get_mut(store.objects_mut()).grow(delta.into()) } - /// Safely reads bytes from the memory at the given offset. - /// - /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned - /// to indicate an out-of-bounds access. - /// - /// This method is guaranteed to be safe (from the host side) in the face of - /// concurrent writes. - pub fn read( - &self, - store: &impl AsStoreRef, - offset: u64, - buf: &mut [u8], - ) -> Result<(), MemoryAccessError> { - self.buffer(store).read(offset, buf) - } - - /// Safely reads bytes from the memory at the given offset. - /// - /// This method is similar to `read` but allows reading into an - /// uninitialized buffer. An initialized view of the buffer is returned. - /// - /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned - /// to indicate an out-of-bounds access. - /// - /// This method is guaranteed to be safe (from the host side) in the face of - /// concurrent writes. - pub fn read_uninit<'a>( - &self, - store: &impl AsStoreRef, - offset: u64, - buf: &'a mut [MaybeUninit], - ) -> Result<&'a mut [u8], MemoryAccessError> { - self.buffer(store).read_uninit(offset, buf) - } - - /// Safely writes bytes to the memory at the given offset. - /// - /// If the write exceeds the bounds of the memory then a `MemoryAccessError` is - /// returned. - /// - /// This method is guaranteed to be safe (from the host side) in the face of - /// concurrent reads/writes. - pub fn write( - &self, - store: &impl AsStoreRef, - offset: u64, - data: &[u8], - ) -> Result<(), MemoryAccessError> { - self.buffer(store).write(offset, data) - } - - pub(crate) fn buffer<'a>(&'a self, store: &'a impl AsStoreRef) -> MemoryBuffer<'a> { - let definition = self.handle.get(store.as_store_ref().objects()).vmmemory(); - let def = unsafe { definition.as_ref() }; - MemoryBuffer { - base: def.base, - len: def.current_length, - marker: PhantomData, - } - } - pub(crate) fn from_vm_extern( store: &impl AsStoreRef, internal: InternalStoreHandle, @@ -272,11 +163,11 @@ impl<'a> Exportable<'a> for Memory { } /// Underlying buffer for a memory. -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub(crate) struct MemoryBuffer<'a> { - base: *mut u8, - len: usize, - marker: PhantomData<(&'a Memory, &'a StoreObjects)>, + pub(crate) base: *mut u8, + pub(crate) len: usize, + pub(crate) marker: PhantomData<(&'a MemoryView<'a>, &'a StoreObjects)>, } impl<'a> MemoryBuffer<'a> { @@ -285,6 +176,7 @@ impl<'a> MemoryBuffer<'a> { .checked_add(buf.len() as u64) .ok_or(MemoryAccessError::Overflow)?; if end > self.len.try_into().unwrap() { + warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, self.len); return Err(MemoryAccessError::HeapOutOfBounds); } unsafe { @@ -302,6 +194,7 @@ impl<'a> MemoryBuffer<'a> { .checked_add(buf.len() as u64) .ok_or(MemoryAccessError::Overflow)?; if end > self.len.try_into().unwrap() { + warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, self.len); return Err(MemoryAccessError::HeapOutOfBounds); } let buf_ptr = buf.as_mut_ptr() as *mut u8; @@ -317,6 +210,7 @@ impl<'a> MemoryBuffer<'a> { .checked_add(data.len() as u64) .ok_or(MemoryAccessError::Overflow)?; if end > self.len.try_into().unwrap() { + warn!("attempted to write ({} bytes) beyond the bounds of the memory view ({} > {})", data.len(), end, self.len); return Err(MemoryAccessError::HeapOutOfBounds); } unsafe { diff --git a/lib/api/src/sys/externals/memory_view.rs b/lib/api/src/sys/externals/memory_view.rs new file mode 100644 index 00000000000..5e1eb247703 --- /dev/null +++ b/lib/api/src/sys/externals/memory_view.rs @@ -0,0 +1,150 @@ +use crate::sys::store::AsStoreRef; +use crate::MemoryAccessError; +use std::convert::TryInto; +use std::marker::PhantomData; +use std::mem::MaybeUninit; +use std::slice; +use wasmer_types::Pages; + +use super::Memory; +use super::memory::MemoryBuffer; + +/// A WebAssembly `memory` view. +/// +/// A memory view is used to read and write to the linear memory. +/// +/// After a memory is grown a view must not be used anymore. Views are +/// created using the Memory.grow() method. +#[derive(Debug)] +pub struct MemoryView<'a> { + pub(crate) buffer: MemoryBuffer<'a>, + pub(crate) size: Pages, +} + +impl<'a> MemoryView<'a> +{ + pub(crate) fn new(memory: &Memory, store: &'a impl AsStoreRef) -> Self { + let size = memory.handle.get(store.as_store_ref().objects()).size(); + + let definition = memory.handle.get(store.as_store_ref().objects()).vmmemory(); + let def = unsafe { definition.as_ref() }; + + Self { + buffer: MemoryBuffer { + base: def.base, + len: def.current_length, + marker: PhantomData, + }, + size, + } + } + + /// Returns the pointer to the raw bytes of the `Memory`. + // + // This used by wasmer-emscripten and wasmer-c-api, but should be treated + // as deprecated and not used in future code. + #[doc(hidden)] + pub fn data_ptr(&self) -> *mut u8 { + self.buffer.base + } + + /// Returns the size (in bytes) of the `Memory`. + pub fn data_size(&self) -> u64 { + self.buffer.len.try_into().unwrap() + } + + /// Retrieve a slice of the memory contents. + /// + /// # Safety + /// + /// Until the returned slice is dropped, it is undefined behaviour to + /// modify the memory contents in any way including by calling a wasm + /// function that writes to the memory or by resizing the memory. + #[doc(hidden)] + pub unsafe fn data_unchecked(&self) -> &[u8] { + self.data_unchecked_mut() + } + + /// Retrieve a mutable slice of the memory contents. + /// + /// # Safety + /// + /// This method provides interior mutability without an UnsafeCell. Until + /// the returned value is dropped, it is undefined behaviour to read or + /// write to the pointed-to memory in any way except through this slice, + /// including by calling a wasm function that reads the memory contents or + /// by resizing this Memory. + #[allow(clippy::mut_from_ref)] + #[doc(hidden)] + pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] { + slice::from_raw_parts_mut(self.buffer.base, self.buffer.len) + } + + /// Returns the size (in [`Pages`]) of the `Memory`. + /// + /// # Example + /// + /// ``` + /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; + /// # let mut store = Store::default(); + /// # + /// let m = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap(); + /// + /// assert_eq!(m.view(&mut store).size(), Pages(1)); + /// ``` + pub fn size(&self) -> Pages { + self.size + } + + pub(crate) fn buffer(&'a self) -> MemoryBuffer<'a> { + self.buffer.clone() + } + + /// Safely reads bytes from the memory at the given offset. + /// + /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned + /// to indicate an out-of-bounds access. + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn read( + &self, + offset: u64, + buf: &mut [u8], + ) -> Result<(), MemoryAccessError> { + self.buffer.read(offset, buf) + } + + /// Safely reads bytes from the memory at the given offset. + /// + /// This method is similar to `read` but allows reading into an + /// uninitialized buffer. An initialized view of the buffer is returned. + /// + /// The full buffer will be filled, otherwise a `MemoryAccessError` is returned + /// to indicate an out-of-bounds access. + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn read_uninit<'b>( + &self, + offset: u64, + buf: &'b mut [MaybeUninit], + ) -> Result<&'b mut [u8], MemoryAccessError> { + self.buffer.read_uninit(offset, buf) + } + + /// Safely writes bytes to the memory at the given offset. + /// + /// If the write exceeds the bounds of the memory then a `MemoryAccessError` is + /// returned. + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent reads/writes. + pub fn write( + &self, + offset: u64, + data: &[u8], + ) -> Result<(), MemoryAccessError> { + self.buffer.write(offset, data) + } +} diff --git a/lib/api/src/sys/externals/mod.rs b/lib/api/src/sys/externals/mod.rs index cd84be24192..e33518c8ccd 100644 --- a/lib/api/src/sys/externals/mod.rs +++ b/lib/api/src/sys/externals/mod.rs @@ -1,12 +1,14 @@ pub(crate) mod function; pub(crate) mod global; pub(crate) mod memory; +pub(crate) mod memory_view; pub(crate) mod table; pub use self::function::{FromToNativeWasmType, Function, HostFunction, WasmTypeList}; pub use self::global::Global; pub use self::memory::Memory; +pub use self::memory_view::MemoryView; pub use self::table::Table; use crate::sys::exports::{ExportError, Exportable}; diff --git a/lib/api/src/sys/mem_access.rs b/lib/api/src/sys/mem_access.rs index 270e1728c9a..e6de517af55 100644 --- a/lib/api/src/sys/mem_access.rs +++ b/lib/api/src/sys/mem_access.rs @@ -1,5 +1,6 @@ use crate::RuntimeError; -use crate::{Memory, Memory32, Memory64, MemorySize, WasmPtr}; +#[allow(unused_imports)] +use crate::{Memory, MemoryView, Memory32, Memory64, MemorySize, WasmPtr}; use std::{ convert::TryInto, fmt, @@ -13,7 +14,6 @@ use thiserror::Error; use wasmer_types::ValueType; use super::externals::memory::MemoryBuffer; -use super::store::AsStoreRef; /// Error for invalid [`Memory`] access. #[derive(Clone, Copy, Debug, Error)] @@ -62,9 +62,9 @@ pub struct WasmRef<'a, T: ValueType> { impl<'a, T: ValueType> WasmRef<'a, T> { /// Creates a new `WasmRef` at the given offset in a memory. #[inline] - pub fn new(store: &'a impl AsStoreRef, memory: &'a Memory, offset: u64) -> Self { + pub fn new(view: &'a MemoryView, offset: u64) -> Self { Self { - buffer: memory.buffer(store), + buffer: view.buffer.clone(), offset, marker: PhantomData, } @@ -161,8 +161,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { /// Returns a `MemoryAccessError` if the slice length overflows. #[inline] pub fn new( - store: &'a impl AsStoreRef, - memory: &'a Memory, + view: &'a MemoryView, offset: u64, len: u64, ) -> Result { @@ -173,7 +172,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { .checked_add(total_len) .ok_or(MemoryAccessError::Overflow)?; Ok(Self { - buffer: memory.buffer(store), + buffer: view.buffer(), offset, len, marker: PhantomData, diff --git a/lib/api/src/sys/mod.rs b/lib/api/src/sys/mod.rs index e2bfd38f805..1e18769b7be 100644 --- a/lib/api/src/sys/mod.rs +++ b/lib/api/src/sys/mod.rs @@ -16,7 +16,7 @@ mod value; pub use crate::sys::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::sys::extern_ref::ExternRef; pub use crate::sys::externals::{ - Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, Table, WasmTypeList, + Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, MemoryView, Table, WasmTypeList, }; pub use crate::sys::function_env::{FunctionEnv, FunctionEnvMut}; pub use crate::sys::imports::Imports; diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/sys/ptr.rs index d0ebdade26a..ad9f0568e62 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/sys/ptr.rs @@ -1,12 +1,10 @@ -use crate::sys::{externals::Memory, FromToNativeWasmType}; +use crate::sys::{externals::MemoryView, FromToNativeWasmType}; use crate::NativeWasmTypeInto; use crate::{MemoryAccessError, WasmRef, WasmSlice}; use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; use wasmer_types::ValueType; -use super::store::AsStoreRef; - pub use wasmer_types::Memory32; pub use wasmer_types::Memory64; pub use wasmer_types::MemorySize; @@ -23,7 +21,8 @@ pub type WasmPtr64 = WasmPtr; /// # use wasmer::WasmPtr; /// # use wasmer::FunctionEnvMut; /// pub fn host_import(mut env: FunctionEnvMut<()>, memory: Memory, ptr: WasmPtr) { -/// let derefed_ptr = ptr.deref(&mut env, &memory); +/// let memory = memory.view(&env); +/// let derefed_ptr = ptr.deref(&memory); /// let inner_val: u32 = derefed_ptr.read().expect("pointer in bounds"); /// println!("Got {} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); /// // update the value being pointed to @@ -50,7 +49,8 @@ pub type WasmPtr64 = WasmPtr; /// } /// /// fn update_vector_3(mut env: FunctionEnvMut<()>, memory: Memory, ptr: WasmPtr) { -/// let derefed_ptr = ptr.deref(&mut env, &memory); +/// let memory = memory.view(&env); +/// let derefed_ptr = ptr.deref(&memory); /// let mut inner_val: V3 = derefed_ptr.read().expect("pointer in bounds"); /// println!("Got {:?} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); /// // update the value being pointed to @@ -142,25 +142,24 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref<'a>(self, store: &'a impl AsStoreRef, memory: &'a Memory) -> WasmRef<'a, T> { - WasmRef::new(store, memory, self.offset.into()) + pub fn deref<'a>(self, view: &'a MemoryView) -> WasmRef<'a, T> { + WasmRef::new(view, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, store: &impl AsStoreRef, memory: &Memory) -> Result { - self.deref(&store, memory).read() + pub fn read(self, view: &MemoryView) -> Result { + self.deref(view).read() } /// Writes to the address pointed to by this `WasmPtr` in a memory. #[inline] pub fn write( self, - store: &impl AsStoreRef, - memory: &Memory, + view: &MemoryView, val: T, ) -> Result<(), MemoryAccessError> { - self.deref(&store, memory).write(val) + self.deref(view).write(val) } /// Creates a `WasmSlice` starting at this `WasmPtr` which allows reading @@ -171,11 +170,10 @@ impl WasmPtr { #[inline] pub fn slice<'a>( self, - store: &'a impl AsStoreRef, - memory: &'a Memory, + view: &'a MemoryView, len: M::Offset, ) -> Result, MemoryAccessError> { - WasmSlice::new(store, memory, self.offset.into(), len.into()) + WasmSlice::new(view, self.offset.into(), len.into()) } /// Reads a sequence of values from this `WasmPtr` until a value that @@ -185,14 +183,13 @@ impl WasmPtr { #[inline] pub fn read_until( self, - store: &impl AsStoreRef, - memory: &Memory, + view: &MemoryView, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { let mut vec = Vec::new(); for i in 0u64.. { let i = M::Offset::try_from(i).map_err(|_| MemoryAccessError::Overflow)?; - let val = self.add_offset(i)?.deref(&store, memory).read()?; + let val = self.add_offset(i)?.deref(view).read()?; if end(&val) { break; } @@ -210,11 +207,10 @@ impl WasmPtr { #[inline] pub fn read_utf8_string( self, - store: &impl AsStoreRef, - memory: &Memory, + view: &MemoryView, len: M::Offset, ) -> Result { - let vec = self.slice(&store, memory, len)?.read_to_vec()?; + let vec = self.slice(view, len)?.read_to_vec()?; Ok(String::from_utf8(vec)?) } @@ -225,10 +221,9 @@ impl WasmPtr { #[inline] pub fn read_utf8_string_with_nul( self, - store: &impl AsStoreRef, - memory: &Memory, + view: &MemoryView, ) -> Result { - let vec = self.read_until(store, memory, |&byte| byte == 0)?; + let vec = self.read_until(view, |&byte| byte == 0)?; Ok(String::from_utf8(vec)?) } } diff --git a/lib/api/tests/js_externals.rs b/lib/api/tests/js_externals.rs index c6a35db6372..41dacdabda1 100644 --- a/lib/api/tests/js_externals.rs +++ b/lib/api/tests/js_externals.rs @@ -6,7 +6,7 @@ mod js { #[wasm_bindgen_test] fn global_new() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let global = Global::new(&mut store, Value::I32(10)); assert_eq!( global.ty(&store), @@ -29,7 +29,7 @@ mod js { #[wasm_bindgen_test] fn global_get() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let global_i32 = Global::new(&mut store, Value::I32(10)); assert_eq!(global_i32.get(&store), Value::I32(10)); // 64-bit values are not yet fully supported in some versions of Node @@ -46,7 +46,7 @@ mod js { #[wasm_bindgen_test] fn global_set() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let global_i32 = Global::new(&mut store, Value::I32(10)); // Set on a constant should error assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); @@ -63,7 +63,7 @@ mod js { #[wasm_bindgen_test] fn table_new() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, @@ -144,29 +144,29 @@ mod js { #[wasm_bindgen_test] fn memory_new() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let memory_type = MemoryType { shared: false, minimum: Pages(0), maximum: Some(Pages(10)), }; let memory = Memory::new(&mut store, memory_type).unwrap(); - assert_eq!(memory.size(&store), Pages(0)); + assert_eq!(memory.view(&store).size(), Pages(0)); assert_eq!(memory.ty(&store), memory_type); } #[wasm_bindgen_test] fn memory_grow() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); let memory = Memory::new(&mut store, desc).unwrap(); - assert_eq!(memory.size(&store), Pages(10)); + assert_eq!(memory.view(&store).size(), Pages(10)); let result = memory.grow(&mut store, Pages(2)).unwrap(); assert_eq!(result, Pages(10)); - assert_eq!(memory.size(&store), Pages(12)); + assert_eq!(memory.view(&store).size(), Pages(12)); let result = memory.grow(&mut store, Pages(10)); assert!(result.is_err()); @@ -182,7 +182,7 @@ mod js { #[wasm_bindgen_test] fn function_new() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let function = Function::new_native(&mut store, &env, |_env: FunctionEnvMut<'_, ()>| {}); assert_eq!( function.ty(&store).clone(), @@ -229,7 +229,7 @@ mod js { struct MyEnv {} let my_env = MyEnv {}; - let mut env = FunctionEnv::new(&mut store, my_env); + let env = FunctionEnv::new(&mut store, my_env); let function = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| {}); assert_eq!( @@ -273,7 +273,7 @@ mod js { #[wasm_bindgen_test] fn function_new_dynamic() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); @@ -341,7 +341,7 @@ mod js { struct MyEnv {} let my_env = MyEnv {}; - let mut env = FunctionEnv::new(&mut store, my_env); + let env = FunctionEnv::new(&mut store, my_env); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); @@ -405,7 +405,7 @@ mod js { #[wasm_bindgen_test] fn native_function_works() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let function = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| {}); let typed_function: TypedFunction<(), ()> = function.native(&mut store).unwrap(); let result = typed_function.call(&mut store); @@ -444,7 +444,7 @@ mod js { #[wasm_bindgen_test] fn function_outlives_instance() { let mut store = Store::default(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let wat = r#"(module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs index 286e880e91a..6a1912037b6 100644 --- a/lib/api/tests/js_instance.rs +++ b/lib/api/tests/js_instance.rs @@ -41,19 +41,19 @@ mod js { .unwrap(); let import_object = imports! {}; - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("mem").unwrap(); assert!(memory.is_from_store(&store)); assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.size(&store), Pages(1)); - assert_eq!(memory.data_size(&store), 65536); + assert_eq!(memory.view(&store).size(), Pages(1)); + assert_eq!(memory.view(&store).data_size(), 65536); memory.grow(&mut store, Pages(1)).unwrap(); assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.size(&store), Pages(2)); - assert_eq!(memory.data_size(&store), 65536 * 2); + assert_eq!(memory.view(&store).size(), Pages(2)); + assert_eq!(memory.view(&store).data_size(), 65536 * 2); } #[wasm_bindgen_test] @@ -81,7 +81,7 @@ mod js { .unwrap(); let import_object = imports! {}; - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let get_magic = instance.exports.get_function("get_magic").unwrap(); @@ -121,7 +121,7 @@ mod js { ))], }) .unwrap(); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); @@ -238,7 +238,7 @@ mod js { multiplier: i32, } - let mut env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); + let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); let imported = Function::new(&mut store, &env, &imported_signature, |env, args| { @@ -293,7 +293,7 @@ mod js { return arg + 1; } - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let imported = Function::new_native(&mut store, &env, imported_fn); let import_object = imports! { @@ -348,7 +348,7 @@ mod js { return env.data().multiplier * arg; } - let mut env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); + let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); let imported = Function::new_native(&mut store, &env, imported_fn); @@ -403,11 +403,11 @@ mod js { fn imported_fn(env: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.uint8view(&env).get_index(0); + let memory_val = memory.view(&env).uint8view().get_index(0); return (memory_val as u32) * env.data().multiplier * arg; } - let mut env = FunctionEnv::new( + let env = FunctionEnv::new( &mut store, Env { multiplier: 3, @@ -424,12 +424,12 @@ mod js { let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.data_size(&store), 65536); - let memory_val = memory.uint8view(&store).get_index(0); + assert_eq!(memory.view(&store).data_size(), 65536); + let memory_val = memory.view(&store).uint8view() .get_index(0); assert_eq!(memory_val, 0); - memory.uint8view(&store).set_index(0, 2); - let memory_val = memory.uint8view(&store).get_index(0); + memory.view(&store).uint8view().set_index(0, 2); + let memory_val = memory.view(&store).uint8view().get_index(0); assert_eq!(memory_val, 2); env.as_mut(&mut store).memory = Some(memory.clone()); @@ -441,7 +441,7 @@ mod js { assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.uint8view(&store).set_index(0, 3); + memory.view(&store).uint8view().set_index(0, 3); let expected = vec![Val::I32(36)].into_boxed_slice(); assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } @@ -454,7 +454,7 @@ mod js { multiplier: u32, } - let mut env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); + let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); fn imported_fn( env: FunctionEnvMut<'_, Env>, @@ -511,12 +511,12 @@ mod js { args: &[Val], ) -> Result, RuntimeError> { let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.uint8view(&env).get_index(0); + let memory_val = memory.view(&env).uint8view().get_index(0); let value = (memory_val as u32) * env.data().multiplier * args[0].unwrap_i32() as u32; return Ok(vec![Val::I32(value as _)]); } - let mut env = FunctionEnv::new( + let env = FunctionEnv::new( &mut store, Env { multiplier: 3, @@ -535,12 +535,12 @@ mod js { let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.data_size(&store), 65536); - let memory_val = memory.uint8view(&store).get_index(0); + assert_eq!(memory.view(&store).data_size(), 65536); + let memory_val = memory.view(&store).uint8view().get_index(0); assert_eq!(memory_val, 0); - memory.uint8view(&store).set_index(0, 2); - let memory_val = memory.uint8view(&store).get_index(0); + memory.view(&store).uint8view().set_index(0, 2); + let memory_val = memory.view(&store).uint8view().get_index(0); assert_eq!(memory_val, 2); env.as_mut(&mut store).memory = Some(memory.clone()); @@ -552,7 +552,7 @@ mod js { assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.uint8view(&store).set_index(0, 3); + memory.view(&store).uint8view().set_index(0, 3); let expected = vec![Val::I32(36)].into_boxed_slice(); assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } @@ -585,7 +585,7 @@ mod js { ], }) .unwrap(); - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let global = Global::new_mut(&mut store, Value::I32(0)); let import_object = imports! { "" => { @@ -633,7 +633,7 @@ mod js { a + b } - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let import_object = imports! { "env" => { @@ -673,7 +673,7 @@ mod js { fn early_exit(_: FunctionEnvMut<'_, ()>) { panic!("Do panic") } - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); let import_object = imports! { "env" => { @@ -721,7 +721,7 @@ mod js { ) .unwrap(); - let mut env = FunctionEnv::new(&mut store, ()); + let env = FunctionEnv::new(&mut store, ()); use std::fmt; @@ -802,7 +802,7 @@ mod js { .unwrap(); let import_object = imports! {}; - let mut env = FunctionEnv::new(&mut store, ()); + let _env = FunctionEnv::new(&mut store, ()); let result = Instance::new(&mut store, &module, &import_object); let err = result.unwrap_err(); assert!(format!("{:?}", err).contains("zero")) diff --git a/lib/api/tests/js_module.rs b/lib/api/tests/js_module.rs index 3155e7e5f3b..4a1b36f369a 100644 --- a/lib/api/tests/js_module.rs +++ b/lib/api/tests/js_module.rs @@ -6,7 +6,7 @@ mod js { #[wasm_bindgen_test] fn module_get_name() { - let mut store = Store::default(); + let store = Store::default(); let wat = r#"(module)"#; let module = Module::new(&store, wat).unwrap(); assert_eq!(module.name(), None); @@ -14,7 +14,7 @@ mod js { #[wasm_bindgen_test] fn module_set_name() { - let mut store = Store::default(); + let store = Store::default(); let wat = r#"(module $name)"#; let mut module = Module::new(&store, wat).unwrap(); @@ -31,12 +31,12 @@ mod js { let binary = wat2wasm(wat).unwrap(); let js_bytes = unsafe { Uint8Array::view(&binary) }; let js_module = WebAssembly::Module::new(&js_bytes.into()).unwrap(); - let module: Module = js_module.into(); + let _module: Module = js_module.into(); } #[wasm_bindgen_test] fn imports() { - let mut store = Store::default(); + let store = Store::default(); let wat = r#"(module (import "host" "func" (func)) (import "host" "memory" (memory 1)) @@ -107,7 +107,7 @@ mod js { #[wasm_bindgen_test] fn exports() { - let mut store = Store::default(); + let store = Store::default(); let wat = r#"(module (func (export "func") nop) (memory (export "memory") 2) diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs index 4fd1f3328b0..a888d4e4918 100644 --- a/lib/api/tests/sys_externals.rs +++ b/lib/api/tests/sys_externals.rs @@ -153,7 +153,7 @@ mod sys { maximum: Some(Pages(10)), }; let memory = Memory::new(&mut store, memory_type)?; - assert_eq!(memory.size(&mut store), Pages(0)); + assert_eq!(memory.view(&mut store).size(), Pages(0)); assert_eq!(memory.ty(&mut store), memory_type); Ok(()) } @@ -163,11 +163,11 @@ mod sys { let mut store = Store::default(); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); let memory = Memory::new(&mut store, desc)?; - assert_eq!(memory.size(&mut store), Pages(10)); + assert_eq!(memory.view(&mut store).size(), Pages(10)); let result = memory.grow(&mut store, Pages(2)).unwrap(); assert_eq!(result, Pages(10)); - assert_eq!(memory.size(&mut store), Pages(12)); + assert_eq!(memory.view(&mut store).size(), Pages(12)); let result = memory.grow(&mut store, Pages(10)); assert_eq!( diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index 1b1bee25529..a919ec98cb5 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -66,7 +66,8 @@ pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 memory .extern_ .memory() - .data_ptr(&memory.extern_.store.store()) + .view(&memory.extern_.store.store()) + .data_ptr() } // size in bytes @@ -75,7 +76,8 @@ pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize memory .extern_ .memory() - .size(&memory.extern_.store.store()) + .view(&memory.extern_.store.store()) + .size() .bytes() .0 } @@ -86,7 +88,8 @@ pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { memory .extern_ .memory() - .size(&memory.extern_.store.store()) + .view(&memory.extern_.store.store()) + .size() .0 as _ } diff --git a/lib/compiler/src/traits.rs b/lib/compiler/src/traits.rs index 8b0cb748794..474ae61a03c 100644 --- a/lib/compiler/src/traits.rs +++ b/lib/compiler/src/traits.rs @@ -85,4 +85,4 @@ impl dyn ArtifactCreate + 'static { pub fn downcast_mut(&'_ mut self) -> Option<&'_ mut T> { self.upcast_any_mut().downcast_mut::() } -} +} \ No newline at end of file diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 645f989f3b3..32dfb5247bc 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -75,16 +75,16 @@ pub fn ___build_environment(mut ctx: FunctionEnvMut, environ: c_int) { debug!("emscripten::___build_environment {}", environ); const MAX_ENV_VALUES: u32 = 64; const TOTAL_ENV_SIZE: u32 = 1024; - let environment = emscripten_memory_pointer!(ctx, ctx.data().memory(0), environ) as *mut c_int; + let environment = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), environ) as *mut c_int; let (mut pool_offset, env_ptr, mut pool_ptr) = unsafe { let (pool_offset, _pool_slice): (u32, &mut [u8]) = allocate_on_stack(&mut ctx, TOTAL_ENV_SIZE as u32); let (env_offset, _env_slice): (u32, &mut [u8]) = allocate_on_stack(&mut ctx, (MAX_ENV_VALUES * 4) as u32); let env_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), env_offset) as *mut c_int; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), env_offset) as *mut c_int; let pool_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), pool_offset) as *mut u8; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), pool_offset) as *mut u8; *env_ptr = pool_offset as i32; *environment = env_offset as i32; @@ -136,7 +136,7 @@ pub fn _pathconf(ctx: FunctionEnvMut, path_addr: c_int, name: c_int) -> c "emscripten::_pathconf {} {} - UNIMPLEMENTED", path_addr, name ); - let _path = emscripten_memory_pointer!(ctx, ctx.data().memory(0), path_addr) as *const c_char; + let _path = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), path_addr) as *const c_char; match name { 0 => 32000, 1 | 2 | 3 => 255, diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index 66d6c64434e..50cc32d85d5 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -17,7 +17,7 @@ use wasmer::{FunctionEnvMut, WasmPtr}; pub fn _getenv(mut ctx: FunctionEnvMut, name: i32) -> u32 { debug!("emscripten::_getenv"); - let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); @@ -33,8 +33,8 @@ pub fn _getenv(mut ctx: FunctionEnvMut, name: i32) -> u32 { pub fn _setenv(ctx: FunctionEnvMut, name: c_int, value: c_int, overwrite: c_int) -> c_int { debug!("emscripten::_setenv"); - let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; - let value_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), value) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char; + let value_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), value) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); debug!("=> value({:?})", unsafe { CStr::from_ptr(value_addr) }); @@ -46,7 +46,7 @@ pub fn _setenv(ctx: FunctionEnvMut, name: c_int, value: c_int, overwrite: pub fn _putenv(ctx: FunctionEnvMut, name: c_int) -> c_int { debug!("emscripten::_putenv"); - let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); @@ -57,7 +57,7 @@ pub fn _putenv(ctx: FunctionEnvMut, name: c_int) -> c_int { pub fn _unsetenv(ctx: FunctionEnvMut, name: c_int) -> c_int { debug!("emscripten::_unsetenv"); - let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); @@ -82,8 +82,8 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { } let name = unsafe { - let memory = ctx.data().memory(0); - let memory_name_ptr = emscripten_memory_pointer!(ctx, memory, name_ptr) as *const c_char; + let memory = ctx.data().memory_view(0, &ctx); + let memory_name_ptr = emscripten_memory_pointer!(&memory, name_ptr) as *const c_char; CStr::from_ptr(memory_name_ptr) }; @@ -91,9 +91,9 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { let passwd = &*libc_getpwnam(name.as_ptr()); let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); let passwd_struct_ptr = - emscripten_memory_pointer!(ctx, memory, passwd_struct_offset) as *mut GuestPasswd; + emscripten_memory_pointer!(&memory, passwd_struct_offset) as *mut GuestPasswd; (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(&mut ctx, passwd.pw_name); (*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(&mut ctx, passwd.pw_passwd); (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(&mut ctx, passwd.pw_gecos); @@ -120,7 +120,7 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { let name = unsafe { let memory_name_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), name_ptr) as *const c_char; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name_ptr) as *const c_char; CStr::from_ptr(memory_name_ptr) }; @@ -129,7 +129,7 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { let group_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let group_struct_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), group_struct_offset) + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), group_struct_offset) as *mut GuestGroup; (*group_struct_ptr).gr_name = copy_cstr_into_wasm(&mut ctx, group.gr_name); (*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(&mut ctx, group.gr_passwd); @@ -153,10 +153,10 @@ pub fn _gai_strerror(mut ctx: FunctionEnvMut, ecode: i32) -> i32 { let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) }; let bytes = cstr.to_bytes_with_nul(); let string_on_guest: WasmPtr = call_malloc_with_cast(&mut ctx, bytes.len() as _); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); let writer = string_on_guest - .slice(&ctx, &memory, bytes.len() as _) + .slice(&memory, bytes.len() as _) .unwrap(); for (i, byte) in bytes.iter().enumerate() { writer.index(i as u64).write(*byte as _).unwrap(); @@ -174,7 +174,6 @@ pub fn _getaddrinfo( ) -> i32 { use libc::{addrinfo, freeaddrinfo}; debug!("emscripten::_getaddrinfo"); - let memory = ctx.data().memory(0); debug!(" => node = {}", { if node_ptr.is_null() { std::borrow::Cow::Borrowed("null") @@ -193,7 +192,7 @@ pub fn _getaddrinfo( let hints = if hints_ptr.is_null() { None } else { - let hints_guest = hints_ptr.deref(&ctx, &memory).read().unwrap(); + let hints_guest = hints_ptr.deref(&ctx.data().memory_view(0, &ctx)).read().unwrap(); Some(addrinfo { ai_flags: hints_guest.ai_flags, ai_family: hints_guest.ai_family, @@ -247,7 +246,8 @@ pub fn _getaddrinfo( // connect list if let Some(prev_guest) = previous_guest_node { - let derefed_prev_guest = prev_guest.deref(&ctx, &memory); + let memory = ctx.data().memory_view(0, &ctx); + let derefed_prev_guest = prev_guest.deref(&memory); let mut pg = derefed_prev_guest.read().unwrap(); pg.ai_next = current_guest_node_ptr; derefed_prev_guest.write(pg).unwrap(); @@ -262,7 +262,8 @@ pub fn _getaddrinfo( let guest_sockaddr_ptr: WasmPtr = call_malloc_with_cast(&mut ctx, host_addrlen as _); - let derefed_guest_sockaddr = guest_sockaddr_ptr.deref(&ctx, &memory); + let memory = ctx.data().memory_view(0, &ctx); + let derefed_guest_sockaddr = guest_sockaddr_ptr.deref(&memory); let mut gs = derefed_guest_sockaddr.read().unwrap(); gs.sa_family = (*host_sockaddr_ptr).sa_family as i16; gs.sa_data = (*host_sockaddr_ptr).sa_data; @@ -281,8 +282,9 @@ pub fn _getaddrinfo( let guest_canonname: WasmPtr = call_malloc_with_cast(&mut ctx, str_size as _); + let memory = ctx.data().memory_view(0, &ctx); let guest_canonname_writer = - guest_canonname.slice(&ctx, &memory, str_size as _).unwrap(); + guest_canonname.slice(&memory, str_size as _).unwrap(); for (i, b) in canonname_bytes.iter().enumerate() { guest_canonname_writer .index(i as u64) @@ -296,7 +298,8 @@ pub fn _getaddrinfo( } }; - let derefed_current_guest_node = current_guest_node_ptr.deref(&ctx, &memory); + let memory = ctx.data().memory_view(0, &ctx); + let derefed_current_guest_node = current_guest_node_ptr.deref(&memory); let mut cgn = derefed_current_guest_node.read().unwrap(); cgn.ai_flags = (*current_host_node).ai_flags; cgn.ai_family = (*current_host_node).ai_family; @@ -317,7 +320,7 @@ pub fn _getaddrinfo( }; res_val_ptr - .deref(&ctx, &memory) + .deref(&ctx.data().memory_view(0, &ctx)) .write(head_of_list) .unwrap(); diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index 8b35528496c..6476f877506 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -19,8 +19,8 @@ extern "C" { /// emscripten: _getenv // (name: *const char) -> *const c_char; pub fn _getenv(mut ctx: FunctionEnvMut, name: u32) -> u32 { debug!("emscripten::_getenv"); - let memory = ctx.data().memory(0); - let name_string = read_string_from_wasm(ctx.as_mut(), &memory, name); + let memory = ctx.data().memory_view(0, &ctx); + let name_string = read_string_from_wasm(&memory, name); debug!("=> name({:?})", name_string); let c_str = unsafe { getenv(name_string.as_ptr() as *const libc::c_char) }; if c_str.is_null() { @@ -30,12 +30,12 @@ pub fn _getenv(mut ctx: FunctionEnvMut, name: u32) -> u32 { } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(mut ctx: FunctionEnvMut, name: u32, value: u32, _overwrite: u32) -> c_int { +pub fn _setenv(ctx: FunctionEnvMut, name: u32, value: u32, _overwrite: u32) -> c_int { debug!("emscripten::_setenv"); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); // setenv does not exist on windows, so we hack it with _putenv - let name = read_string_from_wasm(ctx.as_mut(), &memory, name); - let value = read_string_from_wasm(ctx, &memory, value); + let name = read_string_from_wasm(&memory, name); + let value = read_string_from_wasm(&memory, value); let putenv_string = format!("{}={}", name, value); let putenv_cstring = CString::new(putenv_string).unwrap(); let putenv_raw_ptr = putenv_cstring.as_ptr(); @@ -47,8 +47,8 @@ pub fn _setenv(mut ctx: FunctionEnvMut, name: u32, value: u32, _overwrite /// emscripten: _putenv // (name: *const char); pub fn _putenv(ctx: FunctionEnvMut, name: c_int) -> c_int { debug!("emscripten::_putenv"); - let memory = ctx.data().memory(0); - let name_addr = emscripten_memory_pointer!(ctx, &memory, name) as *const c_char; + let memory = ctx.data().memory_view(0, &ctx); + let name_addr = emscripten_memory_pointer!(&memory, name) as *const c_char; debug!("=> name({:?})", unsafe { std::ffi::CStr::from_ptr(name_addr) }); @@ -58,8 +58,8 @@ pub fn _putenv(ctx: FunctionEnvMut, name: c_int) -> c_int { /// emscripten: _unsetenv // (name: *const char); pub fn _unsetenv(ctx: FunctionEnvMut, name: u32) -> c_int { debug!("emscripten::_unsetenv"); - let memory = ctx.data().memory(0); - let name = read_string_from_wasm(ctx, &memory, name); + let memory = ctx.data().memory_view(0, &ctx); + let name = read_string_from_wasm(&memory, name); // no unsetenv on windows, so use putenv with an empty value let unsetenv_string = format!("{}=", name); let unsetenv_cstring = CString::new(unsetenv_string).unwrap(); @@ -73,8 +73,7 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[cfg(not(feature = "debug"))] let _ = name_ptr; - let memory = ctx.data().memory(0); - + #[repr(C)] struct GuestPasswd { pw_name: u32, @@ -89,8 +88,9 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { // stub this in windows as it is not valid unsafe { let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); + let memory = ctx.data().memory_view(0, &ctx); let passwd_struct_ptr = - emscripten_memory_pointer!(ctx, memory, passwd_struct_offset) as *mut GuestPasswd; + emscripten_memory_pointer!(&memory, passwd_struct_offset) as *mut GuestPasswd; (*passwd_struct_ptr).pw_name = 0; (*passwd_struct_ptr).pw_passwd = 0; (*passwd_struct_ptr).pw_gecos = 0; @@ -108,8 +108,7 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[cfg(not(feature = "debug"))] let _ = name_ptr; - let memory = ctx.data().memory(0); - + #[repr(C)] struct GuestGroup { gr_name: u32, @@ -121,8 +120,9 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { // stub the group struct as it is not supported on windows unsafe { let group_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); + let memory = ctx.data().memory_view(0, &ctx); let group_struct_ptr = - emscripten_memory_pointer!(ctx, memory, group_struct_offset) as *mut GuestGroup; + emscripten_memory_pointer!(&memory, group_struct_offset) as *mut GuestGroup; (*group_struct_ptr).gr_name = 0; (*group_struct_ptr).gr_passwd = 0; (*group_struct_ptr).gr_gid = 0; diff --git a/lib/emscripten/src/exec.rs b/lib/emscripten/src/exec.rs index 5a159debe3e..9f7ffce798d 100644 --- a/lib/emscripten/src/exec.rs +++ b/lib/emscripten/src/exec.rs @@ -7,23 +7,23 @@ use wasmer::{FunctionEnvMut, WasmPtr}; pub fn execvp(ctx: FunctionEnvMut, command_name_offset: u32, argv_offset: u32) -> i32 { // a single reference to re-use - let emscripten_memory = ctx.data().memory(0); + let emscripten_memory = ctx.data().memory_view(0, &ctx); // read command name as string let command_name_string_vec = WasmPtr::::new(command_name_offset) - .read_until(&ctx, &emscripten_memory, |&byte| byte == 0) + .read_until(&emscripten_memory, |&byte| byte == 0) .unwrap(); let command_name_string = CString::new(command_name_string_vec).unwrap(); // get the array of args let argv = WasmPtr::>::new(argv_offset) - .read_until(&ctx, &emscripten_memory, |&ptr| ptr.is_null()) + .read_until(&emscripten_memory, |&ptr| ptr.is_null()) .unwrap(); let arg_strings: Vec = argv .into_iter() .map(|ptr| { let vec = ptr - .read_until(&ctx, &emscripten_memory, |&byte| byte == 0) + .read_until(&emscripten_memory, |&byte| byte == 0) .unwrap(); CString::new(vec).unwrap() }) diff --git a/lib/emscripten/src/io/mod.rs b/lib/emscripten/src/io/mod.rs index 7f5db3b27d2..52cbe7b3a6f 100644 --- a/lib/emscripten/src/io/mod.rs +++ b/lib/emscripten/src/io/mod.rs @@ -28,9 +28,9 @@ pub fn getprotobynumber(_ctx: FunctionEnvMut, _one: i32) -> i32 { /// sigdelset pub fn sigdelset(ctx: FunctionEnvMut, set: i32, signum: i32) -> i32 { debug!("emscripten::sigdelset"); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); #[allow(clippy::cast_ptr_alignment)] - let ptr = emscripten_memory_pointer!(ctx, memory, set) as *mut i32; + let ptr = emscripten_memory_pointer!(&memory, set) as *mut i32; unsafe { *ptr &= !(1 << (signum - 1)) } @@ -40,9 +40,9 @@ pub fn sigdelset(ctx: FunctionEnvMut, set: i32, signum: i32) -> i32 { /// sigfillset pub fn sigfillset(ctx: FunctionEnvMut, set: i32) -> i32 { debug!("emscripten::sigfillset"); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); #[allow(clippy::cast_ptr_alignment)] - let ptr = emscripten_memory_pointer!(ctx, memory, set) as *mut i32; + let ptr = emscripten_memory_pointer!(&memory, set) as *mut i32; unsafe { *ptr = -1; diff --git a/lib/emscripten/src/io/unix.rs b/lib/emscripten/src/io/unix.rs index 996ebe68e44..cd95bb4d42d 100644 --- a/lib/emscripten/src/io/unix.rs +++ b/lib/emscripten/src/io/unix.rs @@ -15,7 +15,7 @@ pub fn putchar(_ctx: FunctionEnvMut, chr: i32) { pub fn printf(ctx: FunctionEnvMut, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); unsafe { - let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), memory_offset) as _; + let addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), memory_offset) as _; _printf(addr, extra) } } @@ -23,7 +23,7 @@ pub fn printf(ctx: FunctionEnvMut, memory_offset: i32, extra: i32) -> i32 /// chroot pub fn chroot(ctx: FunctionEnvMut, name_ptr: i32) -> i32 { debug!("emscripten::chroot"); - let name = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name_ptr) as *const i8; + let name = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name_ptr) as *const i8; unsafe { _chroot(name as *const _) } } @@ -47,7 +47,7 @@ pub fn getpwuid(mut ctx: FunctionEnvMut, uid: i32) -> i32 { let passwd = &*_getpwuid(uid as _); let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let passwd_struct_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), passwd_struct_offset) + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), passwd_struct_offset) as *mut GuestPasswd; assert_eq!( passwd_struct_ptr as usize % std::mem::align_of::(), diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 0ca0884414d..69cf3068608 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -25,7 +25,7 @@ use std::sync::{Arc, Mutex, RwLock}; use wasmer::{ imports, namespace, AsStoreMut, ExportError, Exports, Function, FunctionEnv, FunctionEnvMut, FunctionType, Global, Imports, Instance, Memory, MemoryType, Module, Pages, RuntimeError, - Table, TableType, TypedFunction, Value, WasmPtr, + Table, TableType, TypedFunction, Value, WasmPtr, AsStoreRef, MemoryView, }; use wasmer_types::Type as ValType; @@ -108,6 +108,11 @@ impl EmEnv { (&*self.memory.read().unwrap()).as_ref().cloned().unwrap() } + /// Get a reference to the memory view + pub fn memory_view<'a>(&self, mem_idx: u32, store: &'a impl AsStoreRef) -> MemoryView<'a> { + self.memory(mem_idx).view(store) + } + pub fn set_functions(&mut self, funcs: EmscriptenFunctions) { self.funcs = Arc::new(Mutex::new(funcs)); } @@ -870,10 +875,11 @@ pub fn emscripten_set_up_memory( globals: &EmscriptenGlobalsData, ) -> Result<(), String> { ctx.as_mut(store).set_memory(memory.clone()); - let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(store, memory); + let memory = memory.view(store); + let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(&memory); let dynamic_base = globals.dynamic_base; - if dynamictop_ptr.offset() >= memory.data_size(store) { + if dynamictop_ptr.offset() >= memory.data_size() { return Err("dynamictop_ptr beyond memory len".to_string()); } dynamictop_ptr.write(dynamic_base as i32).unwrap(); diff --git a/lib/emscripten/src/libc.rs b/lib/emscripten/src/libc.rs index 52ef2effcd5..5e45d38c8bb 100644 --- a/lib/emscripten/src/libc.rs +++ b/lib/emscripten/src/libc.rs @@ -52,7 +52,7 @@ pub fn killpg(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { #[cfg(unix)] pub fn pathconf(ctx: FunctionEnvMut, path_ptr: i32, name: i32) -> i32 { debug!("emscripten::pathconf"); - let path = emscripten_memory_pointer!(ctx, ctx.data().memory(0), path_ptr) as *const i8; + let path = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), path_ptr) as *const i8; unsafe { libc::pathconf(path as *const _, name).try_into().unwrap() } } diff --git a/lib/emscripten/src/macros.rs b/lib/emscripten/src/macros.rs index 904721fbb19..4cd2550b17b 100644 --- a/lib/emscripten/src/macros.rs +++ b/lib/emscripten/src/macros.rs @@ -1,5 +1,5 @@ macro_rules! emscripten_memory_pointer { - ($ctx:expr, $memory:expr, $pointer:expr) => { - $memory.data_ptr(&$ctx).wrapping_add($pointer as usize) + ($memory:expr, $pointer:expr) => { + $memory.data_ptr().wrapping_add($pointer as usize) }; } diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index e3fe43a2db8..12b4eb67c62 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -11,8 +11,8 @@ pub fn _emscripten_memcpy_big(ctx: FunctionEnvMut, dest: u32, src: u32, l "emscripten::_emscripten_memcpy_big {}, {}, {}", dest, src, len ); - let dest_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), dest) as *mut c_void; - let src_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), src) as *mut c_void; + let dest_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), dest) as *mut c_void; + let src_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), src) as *mut c_void; unsafe { memcpy(dest_addr, src_addr, len as size_t); } @@ -20,7 +20,7 @@ pub fn _emscripten_memcpy_big(ctx: FunctionEnvMut, dest: u32, src: u32, l } fn get_heap_size(ctx: &FunctionEnvMut) -> u32 { - ctx.data().memory(0).size(&ctx).bytes().0 as u32 + ctx.data().memory_view(0, &ctx).size().bytes().0 as u32 } /// emscripten: _emscripten_get_heap_size @@ -42,7 +42,7 @@ fn align_up(mut val: usize, multiple: usize) -> usize { fn resize_heap(ctx: &mut FunctionEnvMut, requested_size: u32) -> u32 { debug!("emscripten::_emscripten_resize_heap {}", requested_size); - let current_memory_pages = ctx.data().memory(0).size(&ctx); + let current_memory_pages = ctx.data().memory_view(0, &ctx).size(); let current_memory = current_memory_pages.bytes().0 as u32; // implementation from emscripten @@ -85,14 +85,17 @@ pub fn sbrk(mut ctx: FunctionEnvMut, increment: i32) -> i32 { debug!("emscripten::sbrk"); // let old_dynamic_top = 0; // let new_dynamic_top = 0; - let memory = ctx.data().memory(0); let top_ptr = get_emscripten_data(&ctx) .as_ref() .unwrap() .globals .dynamictop_ptr; - let dynamictop_ptr = WasmPtr::::new(top_ptr).deref(&ctx, &memory); - let old_dynamic_top = dynamictop_ptr.read().unwrap(); + + let dynamictop_ptr = WasmPtr::::new(top_ptr); + let old_dynamic_top = { + let memory = ctx.data().memory_view(0, &ctx); + dynamictop_ptr.deref(&memory).read().unwrap() + }; let new_dynamic_top: i32 = old_dynamic_top + increment; let total_memory = get_heap_size(&ctx) as i32; debug!( @@ -114,7 +117,8 @@ pub fn sbrk(mut ctx: FunctionEnvMut, increment: i32) -> i32 { } } // re-borrow the top ptr - let dynamictop_ptr = WasmPtr::::new(top_ptr).deref(&ctx, &memory); + let memory = ctx.data().memory_view(0, &ctx); + let dynamictop_ptr = WasmPtr::::new(top_ptr).deref( &memory); dynamictop_ptr.write(new_dynamic_top).unwrap(); old_dynamic_top as _ } @@ -124,7 +128,7 @@ pub fn get_total_memory(ctx: FunctionEnvMut) -> u32 { debug!("emscripten::get_total_memory"); // instance.memories[0].current_pages() // TODO: Fix implementation - ctx.data().memory(0).size(&ctx).bytes().0 as u32 + ctx.data().memory_view(0, &ctx).size().bytes().0 as u32 } /// emscripten: enlargeMemory diff --git a/lib/emscripten/src/signal.rs b/lib/emscripten/src/signal.rs index 967a15a32d0..e11ec591953 100644 --- a/lib/emscripten/src/signal.rs +++ b/lib/emscripten/src/signal.rs @@ -5,7 +5,7 @@ use wasmer::FunctionEnvMut; #[allow(clippy::cast_ptr_alignment)] pub fn _sigemptyset(ctx: FunctionEnvMut, set: u32) -> i32 { debug!("emscripten::_sigemptyset"); - let set_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), set) as *mut u32; + let set_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), set) as *mut u32; unsafe { *set_addr = 0; } @@ -25,7 +25,7 @@ pub fn _siginterrupt(_ctx: FunctionEnvMut, _a: u32, _b: u32) -> i32 { #[allow(clippy::cast_ptr_alignment)] pub fn _sigaddset(ctx: FunctionEnvMut, set: u32, signum: u32) -> i32 { debug!("emscripten::_sigaddset {}, {}", set, signum); - let set_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), set) as *mut u32; + let set_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), set) as *mut u32; unsafe { *set_addr |= 1 << (signum - 1); } diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 2fb48f4350d..f8b526e11a9 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -67,7 +67,7 @@ pub fn ___syscall3(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs let buf: u32 = varargs.get(&ctx); let count: i32 = varargs.get(&ctx); debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); - let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut c_void; + let buf_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as *mut c_void; let ret = unsafe { read(fd, buf_addr, count as _) }; debug!("=> ret: {}", ret); ret as _ @@ -80,7 +80,7 @@ pub fn ___syscall4(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarAr let buf: i32 = varargs.get(&ctx); let count: i32 = varargs.get(&ctx); debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count); - let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *const c_void; + let buf_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as *const c_void; unsafe { write(fd, buf_addr, count as _) as i32 } } @@ -208,11 +208,11 @@ pub fn ___syscall42(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarA // offset to a file descriptor, which contains a read end and write end, 2 integers let fd_offset: u32 = varargs.get(&ctx); - let emscripten_memory = ctx.data().memory(0); + let emscripten_memory = ctx.data().memory_view(0, &ctx); // convert the file descriptor into a vec with two slots let mut fd_vec: [c_int; 2] = WasmPtr::<[c_int; 2]>::new(fd_offset) - .deref(&ctx, &emscripten_memory) + .deref(&emscripten_memory) .read() .unwrap(); @@ -354,9 +354,9 @@ pub fn ___syscall183(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: let path = get_current_directory(ctx.as_mut()); let path_string = path.unwrap().display().to_string(); let len = path_string.len(); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); - let buf_writer = buf_offset.slice(&ctx, &memory, len as u32 + 1).unwrap(); + let buf_writer = buf_offset.slice(&memory, len as u32 + 1).unwrap(); for (i, byte) in path_string.bytes().enumerate() { buf_writer.index(i as u64).write(byte as _).unwrap(); } @@ -384,7 +384,7 @@ pub fn ___syscall192(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: // ENOMEM return -12; } - let real_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), ptr) as *const u8; + let real_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), ptr) as *const u8; env::call_memset(&mut ctx, ptr, 0, len); for i in 0..(len as usize) { unsafe { @@ -410,9 +410,9 @@ pub fn ___syscall140(ctx: FunctionEnvMut, _which: i32, mut varargs: VarAr let whence: i32 = varargs.get(&ctx); let offset = offset_low; let ret = unsafe { lseek(fd, offset as _, whence) as i64 }; - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); - let result_ptr = result_ptr_value.deref(&ctx, &memory); + let result_ptr = result_ptr_value.deref(&memory); result_ptr.write(ret).unwrap(); debug!( @@ -448,10 +448,10 @@ pub fn ___syscall145(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var unsafe { for i in 0..iovcnt { let guest_iov_addr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), (iov + i * 8)) + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), (iov + i * 8)) as *mut GuestIovec; let iov_base = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), (*guest_iov_addr).iov_base) + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), (*guest_iov_addr).iov_base) as *mut c_void; let iov_len = (*guest_iov_addr).iov_len as _; // debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len); @@ -486,10 +486,10 @@ pub fn ___syscall146(ctx: FunctionEnvMut, _which: i32, mut varargs: VarAr for i in 0..iovcnt { unsafe { let guest_iov_addr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), (iov + i * 8)) + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), (iov + i * 8)) as *mut GuestIovec; let iov_base = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), (*guest_iov_addr).iov_base) + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), (*guest_iov_addr).iov_base) as *const c_void; let iov_len = (*guest_iov_addr).iov_len as _; // debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len); @@ -518,7 +518,7 @@ pub fn ___syscall191(ctx: FunctionEnvMut, _which: i32, mut varargs: VarAr _resource ); let rlim_emptr: i32 = varargs.get(&ctx); - let rlim_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), rlim_emptr) as *mut u8; + let rlim_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), rlim_emptr) as *mut u8; let rlim = unsafe { slice::from_raw_parts_mut(rlim_ptr, 16) }; // set all to RLIM_INIFINTY @@ -722,7 +722,7 @@ pub fn ___syscall340(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var if old_limit != 0 { // just report no limits - let buf_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), old_limit) as *mut u8; + let buf_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), old_limit) as *mut u8; let buf = unsafe { slice::from_raw_parts_mut(buf_ptr, 16) }; LittleEndian::write_i64(&mut *buf, val); diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 4ef741dd75e..b709ea18994 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -203,7 +203,7 @@ pub fn ___syscall77(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarA let resource: c_int = varargs.get(&ctx); let rusage_ptr: c_int = varargs.get(&ctx); #[allow(clippy::cast_ptr_alignment)] - let rusage = emscripten_memory_pointer!(ctx, ctx.data().memory(0), rusage_ptr) as *mut rusage; + let rusage = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), rusage_ptr) as *mut rusage; assert_eq!(8, mem::align_of_val(&rusage)); unsafe { getrusage(resource, rusage) } } @@ -312,7 +312,7 @@ pub fn ___syscall205(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let groups: c_int = varargs.get(&ctx); #[allow(clippy::cast_ptr_alignment)] - let gid_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), groups) as *mut gid_t; + let gid_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), groups) as *mut gid_t; assert_eq!(4, mem::align_of_val(&gid_ptr)); let result = unsafe { getgroups(ngroups_max, gid_ptr) }; debug!( @@ -347,7 +347,7 @@ pub fn ___syscall219(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let len: usize = varargs.get(&ctx); let advice: c_int = varargs.get(&ctx); - let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), addr_ptr) as *mut c_void; + let addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), addr_ptr) as *mut c_void; unsafe { madvise(addr, len, advice) } } @@ -487,7 +487,7 @@ pub fn ___syscall54(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarA | WASM_TCSETSW => { let argp: u32 = varargs.get(&ctx); let argp_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), argp) as *mut c_void; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), argp) as *mut c_void; let translated_request = translate_ioctl(request); let ret = unsafe { ioctl(fd, translated_request as _, argp_ptr) }; debug!( @@ -521,7 +521,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var debug!("emscripten::___syscall102 (socketcall) {}", _which); let call: u32 = varargs.get(&ctx); let mut socket_varargs: VarArgs = varargs.get(&ctx); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); // migrating to EmSockAddr, port being separate here is nice, should update that too #[repr(C)] @@ -586,7 +586,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let socket = socket_varargs.get(&ctx); let address: u32 = socket_varargs.get(&ctx); let address_len = socket_varargs.get(&ctx); - let address = emscripten_memory_pointer!(ctx, &memory, address) as *mut sockaddr; + let address = emscripten_memory_pointer!(&memory, address) as *mut sockaddr; // Debug received address let _proper_address = address as *const GuestSockaddrIn; @@ -611,7 +611,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let socket = socket_varargs.get(&ctx); let address: u32 = socket_varargs.get(&ctx); let address_len = socket_varargs.get(&ctx); - let address = emscripten_memory_pointer!(ctx, &memory, address) as *mut sockaddr; + let address = emscripten_memory_pointer!(&memory, address) as *mut sockaddr; unsafe { connect(socket, address, address_len) } } 4 => { @@ -636,10 +636,10 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var debug!( "=> socket: {}, address: {:?}, address_len: {}", socket, - address.deref(&ctx, &memory).read().unwrap(), - address_len.deref(&ctx, &memory).read().unwrap() + address.deref(&memory).read().unwrap(), + address_len.deref(&memory).read().unwrap() ); - let mut address_len_addr = address_len.deref(&ctx, &memory).read().unwrap(); + let mut address_len_addr = address_len.deref(&memory).read().unwrap(); // let mut address_len_addr: socklen_t = 0; let mut host_address: sockaddr = sockaddr { @@ -649,7 +649,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var sa_len: Default::default(), }; let fd = unsafe { accept(socket, &mut host_address, &mut address_len_addr) }; - let mut address_addr = address.deref(&ctx, &memory).read().unwrap(); + let mut address_addr = address.deref(&memory).read().unwrap(); address_addr.sa_family = host_address.sa_family as _; address_addr.sa_data = host_address.sa_data; @@ -673,7 +673,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let socket: i32 = socket_varargs.get(&ctx); let address: WasmPtr = socket_varargs.get(&ctx); let address_len: WasmPtr = socket_varargs.get(&ctx); - let address_len_addr = address_len.deref(&ctx, &memory).read().unwrap(); + let address_len_addr = address_len.deref(&memory).read().unwrap(); let mut sock_addr_host: sockaddr = sockaddr { sa_family: Default::default(), @@ -689,7 +689,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var ) }; // translate from host data into emscripten data - let mut address_mut = address.deref(&ctx, &memory).read().unwrap(); + let mut address_mut = address.deref(&memory).read().unwrap(); address_mut.sa_family = sock_addr_host.sa_family as _; address_mut.sa_data = sock_addr_host.sa_data; @@ -706,9 +706,9 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let socket = socket_varargs.get(&ctx); let address: u32 = socket_varargs.get(&ctx); let address_len: u32 = socket_varargs.get(&ctx); - let address = emscripten_memory_pointer!(ctx, memory, address) as *mut sockaddr; + let address = emscripten_memory_pointer!(memory, address) as *mut sockaddr; let address_len_addr = - emscripten_memory_pointer!(ctx, memory, address_len) as *mut socklen_t; + emscripten_memory_pointer!(memory, address_len) as *mut socklen_t; unsafe { getpeername(socket, address, address_len_addr) } } 11 => { @@ -720,8 +720,8 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let len: i32 = socket_varargs.get(&ctx); let address: u32 = socket_varargs.get(&ctx); let address_len = socket_varargs.get(&ctx); - let buf_addr = emscripten_memory_pointer!(ctx, memory, buf) as _; - let address = emscripten_memory_pointer!(ctx, memory, address) as *mut sockaddr; + let buf_addr = emscripten_memory_pointer!(memory, buf) as _; + let address = emscripten_memory_pointer!(memory, address) as *mut sockaddr; unsafe { sendto(socket, buf_addr, flags, len, address, address_len) as i32 } } 12 => { @@ -733,10 +733,10 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let flags: i32 = socket_varargs.get(&ctx); let address: u32 = socket_varargs.get(&ctx); let address_len: u32 = socket_varargs.get(&ctx); - let buf_addr = emscripten_memory_pointer!(ctx, memory, buf) as _; - let address = emscripten_memory_pointer!(ctx, memory, address) as *mut sockaddr; + let buf_addr = emscripten_memory_pointer!(memory, buf) as _; + let address = emscripten_memory_pointer!(memory, address) as *mut sockaddr; let address_len_addr = - emscripten_memory_pointer!(ctx, memory, address_len) as *mut socklen_t; + emscripten_memory_pointer!(memory, address_len) as *mut socklen_t; unsafe { recvfrom( socket, @@ -760,7 +760,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let untranslated_name: i32 = socket_varargs.get(&ctx); let value: u32 = socket_varargs.get(&ctx); let option_len: u32 = socket_varargs.get(&ctx); - let value_addr = emscripten_memory_pointer!(ctx, memory, value) as *const libc::c_void; + let value_addr = emscripten_memory_pointer!(memory, value) as *const libc::c_void; let name: i32 = translate_socket_name_flag(untranslated_name); let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) }; @@ -778,9 +778,9 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let name: i32 = translate_socket_name_flag(untranslated_name); let value: u32 = socket_varargs.get(&ctx); let option_len: u32 = socket_varargs.get(&ctx); - let value_addr = emscripten_memory_pointer!(ctx, memory, value) as _; + let value_addr = emscripten_memory_pointer!(memory, value) as _; let option_len_addr = - emscripten_memory_pointer!(ctx, memory, option_len) as *mut socklen_t; + emscripten_memory_pointer!(memory, option_len) as *mut socklen_t; unsafe { getsockopt(socket, level, name, value_addr, option_len_addr) } } 16 => { @@ -789,7 +789,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let socket: i32 = socket_varargs.get(&ctx); let msg: u32 = socket_varargs.get(&ctx); let flags: i32 = socket_varargs.get(&ctx); - let msg_addr = emscripten_memory_pointer!(ctx, memory, msg) as *const msghdr; + let msg_addr = emscripten_memory_pointer!(memory, msg) as *const msghdr; unsafe { sendmsg(socket, msg_addr, flags) as i32 } } 17 => { @@ -798,7 +798,7 @@ pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let socket: i32 = socket_varargs.get(&ctx); let msg: u32 = socket_varargs.get(&ctx); let flags: i32 = socket_varargs.get(&ctx); - let msg_addr = emscripten_memory_pointer!(ctx, memory, msg) as *mut msghdr; + let msg_addr = emscripten_memory_pointer!(memory, msg) as *mut msghdr; unsafe { recvmsg(socket, msg_addr, flags) as i32 } } _ => { @@ -860,9 +860,9 @@ pub fn ___syscall168(ctx: FunctionEnvMut, _which: i32, mut varargs: VarAr let fds: WasmPtr = varargs.get(&ctx); let nfds: u32 = varargs.get(&ctx); let timeout: i32 = varargs.get(&ctx); - let memory = ctx.data().memory(0); + let memory = ctx.data().memory_view(0, &ctx); - let mut fds_mut = fds.deref(&ctx, &memory).read().unwrap(); + let mut fds_mut = fds.deref(&memory).read().unwrap(); unsafe { libc::poll( @@ -885,7 +885,7 @@ pub fn ___syscall180(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var } let offset: i64 = varargs.get(&ctx); - let buf_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as _; + let buf_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as _; unsafe { pread(fd, buf_ptr, count as _, offset) as _ } } @@ -902,7 +902,7 @@ pub fn ___syscall181(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var } let offset: i64 = varargs.get(&ctx); - let buf_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as _; + let buf_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as _; let status = unsafe { pwrite(fd, buf_ptr, count as _, offset) as _ }; debug!( "=> fd: {}, buf: {}, count: {}, offset: {} = status:{}", @@ -927,9 +927,9 @@ pub fn ___syscall114(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var let status: u32 = varargs.get(&ctx); let options: c_int = varargs.get(&ctx); let rusage: u32 = varargs.get(&ctx); - let status_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), status) as *mut c_int; + let status_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), status) as *mut c_int; - let rusage_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), rusage) as *mut rusage; + let rusage_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), rusage) as *mut rusage; let res = unsafe { wait4(pid, status_addr, options, rusage_addr) }; debug!( "=> pid: {}, status: {:?}, options: {}, rusage: {:?} = pid: {}", @@ -962,8 +962,8 @@ pub fn ___syscall142(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var } assert!(exceptfds == 0, "`exceptfds` is not supporrted"); - let readfds_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), readfds) as _; - let writefds_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), writefds) as _; + let readfds_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), readfds) as _; + let writefds_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), writefds) as _; unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) } } @@ -998,7 +998,7 @@ pub fn ___syscall122(ctx: FunctionEnvMut, _which: c_int, mut varargs: Var debug!("emscripten::___syscall122 (uname) {}", _which); let buf: u32 = varargs.get(&ctx); debug!("=> buf: {}", buf); - let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut utsname; + let buf_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as *mut utsname; unsafe { uname(buf_addr) } } @@ -1057,7 +1057,7 @@ pub fn ___syscall220(ctx: FunctionEnvMut, _which: i32, mut varargs: VarAr fd, dirp_addr, count ); - let dirp = emscripten_memory_pointer!(ctx, ctx.data().memory(0), dirp_addr) as *mut u8; + let dirp = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), dirp_addr) as *mut u8; let data = &mut get_emscripten_data(&ctx); let opened_dirs = &mut data.as_mut().unwrap().opened_dirs; diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index 705dd19905c..f6601d4286b 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -28,8 +28,7 @@ pub fn ___syscall5(mut ctx: FunctionEnvMut, which: c_int, mut varargs: Va let flags: i32 = varargs.get(&ctx); let mode: u32 = varargs.get(&ctx); let path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }; - let memory = ctx.data().memory(0); - + match path_str { "/dev/urandom" => { // create a fake urandom file for windows, super hacky @@ -46,8 +45,9 @@ pub fn ___syscall5(mut ctx: FunctionEnvMut, which: c_int, mut varargs: Va let _ = urandom_file.write_all(&random_bytes).unwrap(); // put the file path string into wasm memory let urandom_file_offset = unsafe { copy_cstr_into_wasm(&mut ctx, ptr) }; + let memory = ctx.data().memory_view(0, &ctx); let raw_pointer_to_urandom_file = - emscripten_memory_pointer!(ctx, memory, urandom_file_offset) as *const i8; + emscripten_memory_pointer!(&memory, urandom_file_offset) as *const i8; let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}", diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index 63c90b13fc3..0b77ceec686 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -68,7 +68,7 @@ pub fn _gettimeofday(ctx: FunctionEnvMut, tp: c_int, tz: c_int) -> c_int let now = SystemTime::now(); let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); let timeval_struct_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), tp) as *mut GuestTimeVal; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), tp) as *mut GuestTimeVal; (*timeval_struct_ptr).tv_sec = since_epoch.as_secs() as _; (*timeval_struct_ptr).tv_usec = since_epoch.subsec_nanos() as _; @@ -109,7 +109,7 @@ pub fn _clock_gettime(ctx: FunctionEnvMut, clk_id: clockid_t, tp: c_int) unsafe { let timespec_struct_ptr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), tp) as *mut GuestTimeSpec; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), tp) as *mut GuestTimeSpec; (*timespec_struct_ptr).tv_sec = (duration / 1_000_000_000) as _; (*timespec_struct_ptr).tv_nsec = (duration % 1_000_000_000) as _; } @@ -178,7 +178,7 @@ pub fn _tvset(mut _ctx: FunctionEnvMut) { /// formats time as a C string #[allow(clippy::cast_ptr_alignment)] unsafe fn fmt_time(ctx: FunctionEnvMut, time: u32) -> *const c_char { - let date = &*(emscripten_memory_pointer!(ctx, ctx.data().memory(0), time) as *mut guest_tm); + let date = &*(emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), time) as *mut guest_tm); let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; let months = vec![ @@ -241,14 +241,14 @@ pub fn _localtime(mut ctx: FunctionEnvMut, time_p: u32) -> c_int { // https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r let timespec = unsafe { - let time_p_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_p) as *mut i64; + let time_p_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), time_p) as *mut i64; let seconds = *time_p_addr; time::OffsetDateTime::from_unix_timestamp(seconds) }; unsafe { let tm_struct_offset = env::call_malloc(&mut ctx, mem::size_of::() as _); - let tm_struct_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), tm_struct_offset) + let tm_struct_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), tm_struct_offset) as *mut guest_tm; // debug!( // ">>>>>>> time = {}, {}, {}, {}, {}, {}, {}, {}", @@ -279,7 +279,7 @@ pub fn _localtime_r(ctx: FunctionEnvMut, time_p: u32, result: u32) -> c_i // https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r unsafe { - let seconds = emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_p) as *const i32; + let seconds = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), time_p) as *const i32; let timespec = time::OffsetDateTime::from_unix_timestamp_nanos(*seconds as _); // debug!( @@ -289,7 +289,7 @@ pub fn _localtime_r(ctx: FunctionEnvMut, time_p: u32, result: u32) -> c_i // ); let result_addr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), result) as *mut guest_tm; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), result) as *mut guest_tm; (*result_addr).tm_sec = timespec.second() as _; (*result_addr).tm_min = timespec.minute() as _; @@ -313,7 +313,7 @@ pub fn _time(ctx: FunctionEnvMut, time_p: u32) -> i32 { debug!("emscripten::_time {}", time_p); unsafe { - let time_p_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_p) as *mut i64; + let time_p_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), time_p) as *mut i64; libc_time(time_p_addr) as i32 // TODO review i64 } } @@ -343,7 +343,7 @@ pub fn _timegm(ctx: FunctionEnvMut, time_ptr: u32) -> i32 { unsafe { let time_p_addr = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_ptr) as *mut guest_tm; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), time_ptr) as *mut guest_tm; let x: *mut c_char = CString::new("").expect("CString::new failed").into_raw(); let mut rust_tm = libc_tm { @@ -401,11 +401,11 @@ pub fn _strftime( ); #[allow(clippy::cast_ptr_alignment)] - let s = emscripten_memory_pointer!(ctx, ctx.data().memory(0), s_ptr) as *mut c_char; + let s = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), s_ptr) as *mut c_char; #[allow(clippy::cast_ptr_alignment)] - let format = emscripten_memory_pointer!(ctx, ctx.data().memory(0), format_ptr) as *const c_char; + let format = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), format_ptr) as *const c_char; #[allow(clippy::cast_ptr_alignment)] - let tm = emscripten_memory_pointer!(ctx, ctx.data().memory(0), tm_ptr) as *const guest_tm; + let tm = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), tm_ptr) as *const guest_tm; let format_string = unsafe { std::ffi::CStr::from_ptr(format).to_str().unwrap() }; diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index b645ae00ea8..376653a6b8a 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -8,7 +8,7 @@ use std::mem::size_of; use std::os::raw::c_char; use std::path::PathBuf; use std::slice; -use wasmer::{FunctionEnvMut, GlobalInit, Memory, Module, Pages, WasmPtr}; +use wasmer::{FunctionEnvMut, GlobalInit, Module, Pages, WasmPtr, MemoryView}; /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { @@ -99,7 +99,7 @@ pub unsafe fn write_to_buf( buf: u32, max: u32, ) -> u32 { - let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut c_char; + let buf_addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as *mut c_char; for i in 0..max { *buf_addr.add(i as _) = *string.add(i as _); @@ -114,7 +114,7 @@ pub unsafe fn copy_cstr_into_wasm(ctx: &mut FunctionEnvMut, cstr: *const let cstr_len = s.len(); let space_offset = env::call_malloc(ctx, (cstr_len as u32) + 1); let raw_memory = - emscripten_memory_pointer!(ctx, ctx.data().memory(0), space_offset) as *mut c_char; + emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), space_offset) as *mut c_char; let slice = slice::from_raw_parts_mut(raw_memory, cstr_len); for (byte, loc) in s.bytes().zip(slice.iter_mut()) { @@ -139,7 +139,7 @@ pub unsafe fn allocate_on_stack<'a, T: Copy>( .call(&mut ctx, count * (size_of::() as u32)) .unwrap(); - let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), offset) as *mut T; + let addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), offset) as *mut T; let slice = slice::from_raw_parts_mut(addr, count as usize); (offset, slice) @@ -204,7 +204,7 @@ pub struct GuestStat { #[allow(clippy::cast_ptr_alignment)] pub unsafe fn copy_stat_into_wasm(ctx: FunctionEnvMut, buf: u32, stat: &stat) { - let stat_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut GuestStat; + let stat_ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), buf) as *mut GuestStat; (*stat_ptr).st_dev = stat.st_dev as _; (*stat_ptr).__st_dev_padding = 0; (*stat_ptr).__st_ino_truncated = stat.st_ino as _; @@ -231,9 +231,9 @@ pub unsafe fn copy_stat_into_wasm(ctx: FunctionEnvMut, buf: u32, stat: &s } #[allow(dead_code)] // it's used in `env/windows/mod.rs`. -pub fn read_string_from_wasm(ctx: FunctionEnvMut, memory: &Memory, offset: u32) -> String { +pub fn read_string_from_wasm(memory: &MemoryView, offset: u32) -> String { WasmPtr::::new(offset) - .read_utf8_string_with_nul(&ctx, memory) + .read_utf8_string_with_nul(&memory) .unwrap() } diff --git a/lib/emscripten/src/varargs.rs b/lib/emscripten/src/varargs.rs index ab5dcf453b2..b9ce34c6a57 100644 --- a/lib/emscripten/src/varargs.rs +++ b/lib/emscripten/src/varargs.rs @@ -13,7 +13,7 @@ pub struct VarArgs { impl VarArgs { pub fn get(&mut self, ctx: &FunctionEnvMut) -> T { - let ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), self.pointer); + let ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), self.pointer); self.pointer += mem::size_of::() as u32; unsafe { (ptr as *const T).read() } } @@ -21,7 +21,7 @@ impl VarArgs { // pub fn getStr<'a>(&mut self, ctx: &mut Ctx) -> &'a CStr { pub fn get_str(&mut self, ctx: &FunctionEnvMut) -> *const c_char { let ptr_addr: u32 = self.get(ctx); - let ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), ptr_addr) as *const c_char; + let ptr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), ptr_addr) as *const c_char; ptr // unsafe { CStr::from_ptr(ptr) } } diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index abc96368fc2..74a7ff15530 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -64,7 +64,7 @@ use std::ops::Deref; use thiserror::Error; use wasmer::{ imports, namespace, AsStoreMut, Exports, Function, FunctionEnv, Imports, Memory, Memory32, - MemoryAccessError, MemorySize, Module, TypedFunction, + MemoryAccessError, MemorySize, Module, TypedFunction, MemoryView, AsStoreRef }; pub use runtime::{ @@ -330,11 +330,6 @@ impl WasiEnv { pub fn bus(&self) -> &(dyn VirtualBus) { self.runtime.bus() } - pub(crate) fn get_memory_and_wasi_state(&self, _mem_index: u32) -> (&Memory, &WasiState) { - let memory = self.memory(); - let state = self.state.deref(); - (memory, state) - } /// Set the memory of the WasiEnv (can only be done once) pub fn set_memory(&mut self, memory: Memory) { @@ -343,6 +338,12 @@ impl WasiEnv { } self.memory = Some(memory); } + + /// Providers safe access to the memory + /// (it must be initialized before it can be used) + pub fn memory_view<'a>(&'a self, store: &'a impl AsStoreRef) -> MemoryView<'a> { + self.memory().view(store) + } /// Get memory, that needs to have been set fist pub fn memory(&self) -> &Memory { @@ -353,22 +354,30 @@ impl WasiEnv { pub fn state(&self) -> &WasiState { &self.state } + + pub(crate) fn get_memory_and_wasi_state<'a>(&'a self, store: &'a impl AsStoreRef, _mem_index: u32) -> (MemoryView<'a>, &WasiState) { + let memory = self.memory_view(store); + let state = self.state.deref(); + (memory, state) + } - pub fn get_memory_and_wasi_state_and_inodes( - &self, + pub(crate) fn get_memory_and_wasi_state_and_inodes<'a>( + &'a self, + store: &'a impl AsStoreRef, _mem_index: u32, - ) -> (&Memory, &WasiState, RwLockReadGuard) { - let memory = self.memory(); + ) -> (MemoryView<'a>, &WasiState, RwLockReadGuard) { + let memory = self.memory_view(store); let state = self.state.deref(); let inodes = state.inodes.read().unwrap(); (memory, state, inodes) } - pub(crate) fn get_memory_and_wasi_state_and_inodes_mut( - &self, + pub(crate) fn get_memory_and_wasi_state_and_inodes_mut<'a>( + &'a self, + store: &'a impl AsStoreRef, _mem_index: u32, - ) -> (&Memory, &WasiState, RwLockWriteGuard) { - let memory = self.memory(); + ) -> (MemoryView<'a>, &WasiState, RwLockWriteGuard) { + let memory = self.memory_view(store); let state = self.state.deref(); let inodes = state.inodes.write().unwrap(); (memory, state, inodes) diff --git a/lib/wasi/src/macros.rs b/lib/wasi/src/macros.rs index bd6e6566d41..b9ec4245597 100644 --- a/lib/wasi/src/macros.rs +++ b/lib/wasi/src/macros.rs @@ -98,13 +98,13 @@ macro_rules! wasi_try_mem_ok { /// Reads a string from Wasm memory. macro_rules! get_input_str { - ($ctx:expr, $memory:expr, $data:expr, $len:expr) => {{ - wasi_try_mem!($data.read_utf8_string($ctx, $memory, $len)) + ($memory:expr, $data:expr, $len:expr) => {{ + wasi_try_mem!($data.read_utf8_string($memory, $len)) }}; } macro_rules! get_input_str_bus { - ($ctx:expr, $memory:expr, $data:expr, $len:expr) => {{ - wasi_try_mem_bus!($data.read_utf8_string($ctx, $memory, $len)) + ($memory:expr, $data:expr, $len:expr) => {{ + wasi_try_mem_bus!($data.read_utf8_string($memory, $len)) }}; } diff --git a/lib/wasi/src/state/pipe.rs b/lib/wasi/src/state/pipe.rs index 2f419214537..b2bab5ff4dc 100644 --- a/lib/wasi/src/state/pipe.rs +++ b/lib/wasi/src/state/pipe.rs @@ -1,14 +1,13 @@ use crate::syscalls::types::*; use crate::syscalls::{read_bytes, write_bytes}; -use crate::WasiEnv; use bytes::{Buf, Bytes}; use std::convert::TryInto; use std::io::{self, Read}; use std::ops::DerefMut; use std::sync::mpsc; use std::sync::Mutex; -use wasmer::MemorySize; -use wasmer::{FunctionEnvMut, Memory, WasmSlice}; +use wasmer::{MemorySize, MemoryView}; +use wasmer::WasmSlice; #[derive(Debug)] pub struct WasiPipe { @@ -42,8 +41,7 @@ impl WasiPipe { pub fn recv( &mut self, - ctx: &FunctionEnvMut<'_, WasiEnv>, - memory: &Memory, + memory: &MemoryView, iov: WasmSlice<__wasi_iovec_t>, ) -> Result { loop { @@ -51,7 +49,7 @@ impl WasiPipe { let buf_len = buf.len(); if buf_len > 0 { let reader = buf.as_ref(); - let read = read_bytes(ctx, reader, memory, iov).map(|_| buf_len as usize)?; + let read = read_bytes(reader, memory, iov).map(|_| buf_len as usize)?; buf.advance(read); return Ok(read); } @@ -64,8 +62,7 @@ impl WasiPipe { pub fn send( &mut self, - ctx: &FunctionEnvMut<'_, WasiEnv>, - memory: &Memory, + memory: &MemoryView, iov: WasmSlice<__wasi_ciovec_t>, ) -> Result { let buf_len: M::Offset = iov @@ -75,7 +72,7 @@ impl WasiPipe { .sum(); let buf_len: usize = buf_len.try_into().map_err(|_| __WASI_EINVAL)?; let mut buf = Vec::with_capacity(buf_len); - write_bytes(ctx, &mut buf, memory, iov)?; + write_bytes(&mut buf, memory, iov)?; let tx = self.tx.lock().unwrap(); tx.send(buf).map_err(|_| __WASI_EIO)?; Ok(buf_len) diff --git a/lib/wasi/src/state/socket.rs b/lib/wasi/src/state/socket.rs index ff4e92eca45..2914a1d94d4 100644 --- a/lib/wasi/src/state/socket.rs +++ b/lib/wasi/src/state/socket.rs @@ -1,7 +1,6 @@ use super::types::net_error_into_wasi_err; use crate::syscalls::types::*; use crate::syscalls::{read_bytes, write_bytes}; -use crate::WasiEnv; use bytes::{Buf, Bytes}; use std::convert::TryInto; use std::io::{self, Read}; @@ -11,7 +10,7 @@ use std::sync::Mutex; use std::time::Duration; #[allow(unused_imports)] use tracing::{debug, error, info, warn}; -use wasmer::{FunctionEnvMut, Memory, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{MemorySize, WasmPtr, WasmSlice, MemoryView}; use wasmer_vnet::{net_error_into_io_err, TimeType}; use wasmer_vnet::{ IpCidr, IpRoute, SocketHttpRequest, VirtualIcmpSocket, VirtualNetworking, VirtualRawSocket, @@ -769,8 +768,7 @@ impl InodeSocket { pub fn send( &mut self, - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, iov: WasmSlice<__wasi_ciovec_t>, ) -> Result { let buf_len: M::Offset = iov @@ -780,7 +778,7 @@ impl InodeSocket { .sum(); let buf_len: usize = buf_len.try_into().map_err(|_| __WASI_EINVAL)?; let mut buf = Vec::with_capacity(buf_len); - write_bytes(ctx, &mut buf, memory, iov)?; + write_bytes(&mut buf, memory, iov)?; match &mut self.kind { InodeSocketKind::HttpRequest(sock, ty) => { let sock = sock.get_mut().unwrap(); @@ -854,12 +852,11 @@ impl InodeSocket { pub fn send_to( &mut self, - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, iov: WasmSlice<__wasi_ciovec_t>, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> Result { - let (addr_ip, addr_port) = read_ip_port(ctx, memory, addr)?; + let (addr_ip, addr_port) = read_ip_port(memory, addr)?; let addr = SocketAddr::new(addr_ip, addr_port); let buf_len: M::Offset = iov .iter() @@ -868,7 +865,7 @@ impl InodeSocket { .sum(); let buf_len: usize = buf_len.try_into().map_err(|_| __WASI_EINVAL)?; let mut buf = Vec::with_capacity(buf_len); - write_bytes(ctx, &mut buf, memory, iov)?; + write_bytes(&mut buf, memory, iov)?; match &mut self.kind { InodeSocketKind::Icmp(sock) => sock .send_to(Bytes::from(buf), addr) @@ -885,8 +882,7 @@ impl InodeSocket { pub fn recv( &mut self, - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, iov: WasmSlice<__wasi_iovec_t>, ) -> Result { loop { @@ -894,7 +890,7 @@ impl InodeSocket { let buf_len = buf.len(); if buf_len > 0 { let reader = buf.as_ref(); - let read = read_bytes(ctx, reader, memory, iov).map(|_| buf_len)?; + let read = read_bytes(reader, memory, iov).map(|_| buf_len)?; if let InodeSocketKind::TcpStream(..) = &self.kind { buf.advance(read); } else { @@ -955,8 +951,7 @@ impl InodeSocket { pub fn recv_from( &mut self, - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, iov: WasmSlice<__wasi_iovec_t>, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> Result { @@ -964,11 +959,11 @@ impl InodeSocket { if let Some(buf) = self.read_buffer.as_mut() { if !buf.is_empty() { let reader = buf.as_ref(); - let ret = read_bytes(ctx, reader, memory, iov)?; + let ret = read_bytes(reader, memory, iov)?; let peer = self .read_addr .unwrap_or_else(|| SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)); - write_ip_port(ctx, memory, addr, peer.ip(), peer.port())?; + write_ip_port(memory, addr, peer.ip(), peer.port())?; return Ok(ret); } } @@ -1135,11 +1130,10 @@ impl Drop for InodeSocket { #[allow(dead_code)] pub(crate) fn read_ip( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_addr_t, M>, ) -> Result { - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.u.octs; @@ -1154,11 +1148,10 @@ pub(crate) fn read_ip( } pub(crate) fn read_ip_v4( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_addr_ip4_t, M>, ) -> Result { - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.octs; @@ -1166,11 +1159,10 @@ pub(crate) fn read_ip_v4( } pub(crate) fn read_ip_v6( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_addr_ip6_t, M>, ) -> Result { - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(addr.segs) }; @@ -1178,8 +1170,7 @@ pub(crate) fn read_ip_v6( } pub(crate) fn write_ip( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_addr_t, M>, ip: IpAddr, ) -> Result<(), __wasi_errno_t> { @@ -1202,18 +1193,17 @@ pub(crate) fn write_ip( } }; - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); addr_ptr.write(ip).map_err(crate::mem_error_to_wasi)?; Ok(()) } #[allow(dead_code)] pub(crate) fn read_cidr( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_cidr_t, M>, ) -> Result { - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.u.octs; @@ -1241,8 +1231,7 @@ pub(crate) fn read_cidr( #[allow(dead_code)] pub(crate) fn write_cidr( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_cidr_t, M>, cidr: IpCidr, ) -> Result<(), __wasi_errno_t> { @@ -1273,17 +1262,16 @@ pub(crate) fn write_cidr( } }; - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); addr_ptr.write(cidr).map_err(crate::mem_error_to_wasi)?; Ok(()) } pub(crate) fn read_ip_port( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_addr_port_t, M>, ) -> Result<(IpAddr, u16), __wasi_errno_t> { - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.u.octs; @@ -1311,8 +1299,7 @@ pub(crate) fn read_ip_port( #[allow(dead_code)] pub(crate) fn write_ip_port( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_addr_port_t, M>, ip: IpAddr, port: u16, @@ -1344,18 +1331,17 @@ pub(crate) fn write_ip_port( } }; - let addr_ptr = ptr.deref(ctx, memory); + let addr_ptr = ptr.deref(memory); addr_ptr.write(ipport).map_err(crate::mem_error_to_wasi)?; Ok(()) } #[allow(dead_code)] pub(crate) fn read_route( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_route_t, M>, ) -> Result { - let route_ptr = ptr.deref(ctx, memory); + let route_ptr = ptr.deref(memory); let route = route_ptr.read().map_err(crate::mem_error_to_wasi)?; Ok(IpRoute { @@ -1407,8 +1393,7 @@ pub(crate) fn read_route( } pub(crate) fn write_route( - ctx: &FunctionEnvMut, - memory: &Memory, + memory: &MemoryView, ptr: WasmPtr<__wasi_route_t, M>, route: IpRoute, ) -> Result<(), __wasi_errno_t> { @@ -1486,7 +1471,7 @@ pub(crate) fn write_route( expires_at, }; - let route_ptr = ptr.deref(ctx, memory); + let route_ptr = ptr.deref(memory); route_ptr.write(route).map_err(crate::mem_error_to_wasi)?; Ok(()) } diff --git a/lib/wasi/src/syscalls/legacy/snapshot0.rs b/lib/wasi/src/syscalls/legacy/snapshot0.rs index 33c2f1f6427..033abe11e04 100644 --- a/lib/wasi/src/syscalls/legacy/snapshot0.rs +++ b/lib/wasi/src/syscalls/legacy/snapshot0.rs @@ -15,7 +15,7 @@ pub fn fd_filestat_get( buf: WasmPtr, ) -> types::__wasi_errno_t { let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); // transmute the WasmPtr into a WasmPtr where T2 > T1, this will read extra memory. // The edge case of this cenv.mausing an OOB is not handled, if the new field is OOB, then the entire @@ -23,7 +23,7 @@ pub fn fd_filestat_get( let new_buf: WasmPtr = buf.cast(); // Copy the data including the extra data - let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&ctx, memory)); + let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&memory)); // Set up complete, make the call with the pointer that will write to the // struct and some unrelated memory after the struct. @@ -31,10 +31,10 @@ pub fn fd_filestat_get( // reborrow memory let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); // get the values written to memory - let new_filestat = wasi_try_mem!(new_buf.deref(&ctx, memory).read()); + let new_filestat = wasi_try_mem!(new_buf.deref(&memory).read()); // translate the new struct into the old struct in host memory let old_stat = snapshot0::__wasi_filestat_t { st_dev: new_filestat.st_dev, @@ -49,11 +49,11 @@ pub fn fd_filestat_get( // write back the original values at the pointer's memory locations // (including the memory unrelated to the pointer) - wasi_try_mem!(new_buf.deref(&ctx, memory).write(new_filestat_setup)); + wasi_try_mem!(new_buf.deref(&memory).write(new_filestat_setup)); // Now that this memory is back as it was, write the translated filestat // into memory leaving it as it should be - wasi_try_mem!(buf.deref(&ctx, memory).write(old_stat)); + wasi_try_mem!(buf.deref(&memory).write(old_stat)); result } @@ -70,18 +70,18 @@ pub fn path_filestat_get( ) -> types::__wasi_errno_t { // see `fd_filestat_get` in this file for an explanation of this strange behavior let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let new_buf: WasmPtr = buf.cast(); - let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&ctx, memory)); + let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&memory)); let result = syscalls::path_filestat_get::(ctx.as_mut(), fd, flags, path, path_len, new_buf); // need to re-borrow let env = ctx.data(); - let memory = env.memory(); - let new_filestat = wasi_try_mem!(new_buf.deref(&ctx, memory).read()); + let memory = env.memory_view(&ctx); + let new_filestat = wasi_try_mem!(new_buf.deref(&memory).read()); let old_stat = snapshot0::__wasi_filestat_t { st_dev: new_filestat.st_dev, st_ino: new_filestat.st_ino, @@ -93,8 +93,8 @@ pub fn path_filestat_get( st_ctim: new_filestat.st_ctim, }; - wasi_try_mem!(new_buf.deref(&ctx, memory).write(new_filestat_setup)); - wasi_try_mem!(buf.deref(&ctx, memory).write(old_stat)); + wasi_try_mem!(new_buf.deref(&memory).write(new_filestat_setup)); + wasi_try_mem!(buf.deref(&memory).write(old_stat)); result } @@ -132,16 +132,16 @@ pub fn poll_oneoff( // we start by adjusting `in_` into a format that the new code can understand let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let nsubscriptions_offset: u32 = nsubscriptions; - let in_origs = wasi_try_mem_ok!(in_.slice(&ctx, memory, nsubscriptions_offset)); + let in_origs = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions_offset)); let in_origs = wasi_try_mem_ok!(in_origs.read_to_vec()); // get a pointer to the smaller new type let in_new_type_ptr: WasmPtr = in_.cast(); for (in_sub_new, orig) in - wasi_try_mem_ok!(in_new_type_ptr.slice(&ctx, memory, nsubscriptions_offset)) + wasi_try_mem_ok!(in_new_type_ptr.slice(&memory, nsubscriptions_offset)) .iter() .zip(in_origs.iter()) { @@ -176,9 +176,9 @@ pub fn poll_oneoff( // replace the old values of in, in case the calling code reuses the memory let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); - for (in_sub, orig) in wasi_try_mem_ok!(in_.slice(&ctx, memory, nsubscriptions_offset)) + for (in_sub, orig) in wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions_offset)) .iter() .zip(in_origs.into_iter()) { diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 4d0c563a6f4..aa0f910741a 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -48,7 +48,7 @@ use std::time::Duration; use tracing::{debug, error, trace, warn}; use wasmer::{ AsStoreMut, FunctionEnvMut, Memory, Memory32, Memory64, MemorySize, RuntimeError, Value, - WasmPtr, WasmSlice, + WasmPtr, WasmSlice, FunctionEnv, Instance, Module, Extern, MemoryView, }; use wasmer_vbus::{FileDescriptor, StdioMode}; use wasmer_vfs::{FsError, VirtualFile}; @@ -79,16 +79,15 @@ fn from_offset(offset: M::Offset) -> Result( - ctx: &FunctionEnvMut<'_, WasiEnv>, mut write_loc: T, - memory: &Memory, + memory: &MemoryView, iovs_arr_cell: WasmSlice<__wasi_ciovec_t>, ) -> Result { let mut bytes_written = 0usize; for iov in iovs_arr_cell.iter() { let iov_inner = iov.read().map_err(mem_error_to_wasi)?; let bytes = WasmPtr::::new(iov_inner.buf) - .slice(ctx, memory, iov_inner.buf_len) + .slice(memory, iov_inner.buf_len) .map_err(mem_error_to_wasi)?; let bytes = bytes.read_to_vec().map_err(mem_error_to_wasi)?; write_loc.write_all(&bytes).map_err(map_io_err)?; @@ -99,20 +98,18 @@ fn write_bytes_inner( } pub(crate) fn write_bytes( - ctx: &FunctionEnvMut<'_, WasiEnv>, mut write_loc: T, - memory: &Memory, + memory: &MemoryView, iovs_arr: WasmSlice<__wasi_ciovec_t>, ) -> Result { - let result = write_bytes_inner::<_, M>(ctx, &mut write_loc, memory, iovs_arr); + let result = write_bytes_inner::<_, M>(&mut write_loc, memory, iovs_arr); write_loc.flush(); result } pub(crate) fn read_bytes( - ctx: &FunctionEnvMut<'_, WasiEnv>, mut reader: T, - memory: &Memory, + memory: &MemoryView, iovs_arr: WasmSlice<__wasi_iovec_t>, ) -> Result { let mut bytes_read = 0usize; @@ -129,7 +126,7 @@ pub(crate) fn read_bytes( let has_read = reader.read(&mut raw_bytes).map_err(map_io_err)?; let buf = WasmPtr::::new(iov_inner.buf) - .slice(ctx, memory, iov_inner.buf_len) + .slice(memory, iov_inner.buf_len) .map_err(mem_error_to_wasi)?; buf.write_slice(&raw_bytes).map_err(mem_error_to_wasi)?; bytes_read += has_read; @@ -155,7 +152,7 @@ where F: FnOnce(&crate::state::InodeSocket) -> Result, { let env = ctx.data(); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = state.fs.get_fd(sock)?; let ret = { @@ -188,7 +185,7 @@ where F: FnOnce(&mut crate::state::InodeSocket) -> Result, { let env = ctx.data(); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = state.fs.get_fd(sock)?; let ret = { @@ -223,7 +220,7 @@ where ) -> Result, __wasi_errno_t>, { let env = ctx.data(); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = state.fs.get_fd(sock)?; if rights != 0 && !has_rights(fd_entry.rights, rights) { @@ -252,15 +249,12 @@ where #[must_use] fn write_buffer_array( - ctx: &FunctionEnvMut<'_, WasiEnv>, - memory: &Memory, + memory: &MemoryView, from: &[Vec], ptr_buffer: WasmPtr, M>, buffer: WasmPtr, ) -> __wasi_errno_t { - let env = ctx.data(); - let memory = env.memory(); - let ptrs = wasi_try_mem!(ptr_buffer.slice(ctx, memory, wasi_try!(to_offset::(from.len())))); + let ptrs = wasi_try_mem!(ptr_buffer.slice(memory, wasi_try!(to_offset::(from.len())))); let mut current_buffer_offset = 0usize; for ((i, sub_buffer), ptr) in from.iter().enumerate().zip(ptrs.iter()) { @@ -271,12 +265,12 @@ fn write_buffer_array( wasi_try_mem!(ptr.write(new_ptr)); let data = - wasi_try_mem!(new_ptr.slice(ctx, memory, wasi_try!(to_offset::(sub_buffer.len())))); + wasi_try_mem!(new_ptr.slice(memory, wasi_try!(to_offset::(sub_buffer.len())))); wasi_try_mem!(data.write_slice(sub_buffer)); wasi_try_mem!(wasi_try_mem!( new_ptr.add_offset(wasi_try!(to_offset::(sub_buffer.len()))) ) - .write(ctx, memory, 0)); + .write(memory, 0)); current_buffer_offset += sub_buffer.len() + 1; } @@ -308,9 +302,9 @@ pub fn args_get( ) -> __wasi_errno_t { debug!("wasi::args_get"); let env = ctx.data(); - let (memory, mut state) = env.get_memory_and_wasi_state(0); + let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); - let result = write_buffer_array(&ctx, memory, &*state.args, argv, argv_buf); + let result = write_buffer_array(&memory, &*state.args, argv, argv_buf); debug!( "=> args:\n{}", @@ -340,10 +334,10 @@ pub fn args_sizes_get( ) -> __wasi_errno_t { debug!("wasi::args_sizes_get"); let env = ctx.data(); - let (memory, mut state) = env.get_memory_and_wasi_state(0); + let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); - let argc = argc.deref(&ctx, memory); - let argv_buf_size = argv_buf_size.deref(&ctx, memory); + let argc = argc.deref(&memory); + let argv_buf_size = argv_buf_size.deref(&memory); let argc_val: M::Offset = wasi_try!(state.args.len().try_into().map_err(|_| __WASI_EOVERFLOW)); let argv_buf_size_val: usize = state.args.iter().map(|v| v.len() + 1).sum(); @@ -372,11 +366,11 @@ pub fn clock_res_get( ) -> __wasi_errno_t { trace!("wasi::clock_res_get"); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); - let out_addr = resolution.deref(&ctx, memory); + let out_addr = resolution.deref(&memory); let t_out = wasi_try!(platform_clock_res_get(clock_id, out_addr)); - wasi_try_mem!(resolution.write(&ctx, memory, t_out as __wasi_timestamp_t)); + wasi_try_mem!(resolution.write(&memory, t_out as __wasi_timestamp_t)); __WASI_ESUCCESS } @@ -401,15 +395,15 @@ pub fn clock_time_get( clock_id, precision ); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let t_out = wasi_try!(platform_clock_time_get(clock_id, precision)); - wasi_try_mem!(time.write(&ctx, memory, t_out as __wasi_timestamp_t)); + wasi_try_mem!(time.write(&memory, t_out as __wasi_timestamp_t)); let result = __WASI_ESUCCESS; trace!( "time: {} => {}", - wasi_try_mem!(time.deref(&ctx, memory).read()), + wasi_try_mem!(time.deref(&memory).read()), result ); result @@ -433,10 +427,10 @@ pub fn environ_get( environ, environ_buf ); let env = ctx.data(); - let (memory, mut state) = env.get_memory_and_wasi_state(0); + let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); trace!(" -> State envs: {:?}", state.envs); - write_buffer_array(&ctx, memory, &*state.envs, environ, environ_buf) + write_buffer_array(&memory, &*state.envs, environ, environ_buf) } /// ### `environ_sizes_get()` @@ -453,10 +447,10 @@ pub fn environ_sizes_get( ) -> __wasi_errno_t { trace!("wasi::environ_sizes_get"); let env = ctx.data(); - let (memory, mut state) = env.get_memory_and_wasi_state(0); + let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); - let environ_count = environ_count.deref(&ctx, memory); - let environ_buf_size = environ_buf_size.deref(&ctx, memory); + let environ_count = environ_count.deref(&memory); + let environ_buf_size = environ_buf_size.deref(&memory); let env_var_count: M::Offset = wasi_try!(state.envs.len().try_into().map_err(|_| __WASI_EOVERFLOW)); @@ -516,7 +510,7 @@ pub fn fd_allocate( ) -> __wasi_errno_t { debug!("wasi::fd_allocate"); let env = ctx.data(); - let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); let inode = fd_entry.inode; @@ -563,7 +557,7 @@ pub fn fd_allocate( pub fn fd_close(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_close: fd={}", fd); let env = ctx.data(); - let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); @@ -580,7 +574,7 @@ pub fn fd_close(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_err pub fn fd_datasync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_datasync"); let env = ctx.data(); - let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_DATASYNC) { return __WASI_EACCES; @@ -612,10 +606,10 @@ pub fn fd_fdstat_get( buf_ptr.offset() ); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let stat = wasi_try!(state.fs.fdstat(inodes.deref(), fd)); - let buf = buf_ptr.deref(&ctx, memory); + let buf = buf_ptr.deref(&memory); wasi_try_mem!(buf.write(stat)); @@ -636,7 +630,7 @@ pub fn fd_fdstat_set_flags( ) -> __wasi_errno_t { debug!("wasi::fd_fdstat_set_flags"); let env = ctx.data(); - let (_, mut state) = env.get_memory_and_wasi_state(0); + let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -665,7 +659,7 @@ pub fn fd_fdstat_set_rights( ) -> __wasi_errno_t { debug!("wasi::fd_fdstat_set_rights"); let env = ctx.data(); - let (_, mut state) = env.get_memory_and_wasi_state(0); + let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -697,7 +691,7 @@ pub fn fd_filestat_get( ) -> __wasi_errno_t { debug!("wasi::fd_filestat_get"); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_FILESTAT_GET) { return __WASI_EACCES; @@ -705,7 +699,7 @@ pub fn fd_filestat_get( let stat = wasi_try!(state.fs.filestat_fd(inodes.deref(), fd)); - let buf = buf.deref(&ctx, memory); + let buf = buf.deref(&memory); wasi_try_mem!(buf.write(stat)); __WASI_ESUCCESS @@ -725,7 +719,7 @@ pub fn fd_filestat_set_size( ) -> __wasi_errno_t { debug!("wasi::fd_filestat_set_size"); let env = ctx.data(); - let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); let inode = fd_entry.inode; @@ -776,7 +770,7 @@ pub fn fd_filestat_set_times( ) -> __wasi_errno_t { debug!("wasi::fd_filestat_set_times"); let env = ctx.data(); - let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_FILESTAT_SET_TIMES) { @@ -839,10 +833,10 @@ pub fn fd_pread( ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_pread: fd={}, offset={}", fd, offset); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); - let iovs = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); - let nread_ref = nread.deref(&ctx, memory); + let iovs = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); + let nread_ref = nread.deref(&memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_read = match fd { @@ -854,7 +848,7 @@ pub fn fd_pread( env ); if let Some(ref mut stdin) = guard.deref_mut() { - wasi_try_ok!(read_bytes(&ctx, stdin, memory, iovs), env) + wasi_try_ok!(read_bytes(stdin, &memory, iovs), env) } else { return Ok(__WASI_EBADF); } @@ -882,23 +876,23 @@ pub fn fd_pread( .map_err(map_io_err), env ); - wasi_try_ok!(read_bytes(&ctx, h, memory, iovs), env) + wasi_try_ok!(read_bytes(h, &memory, iovs), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.recv(&ctx, memory, iovs), env) + wasi_try_ok!(socket.recv(&memory, iovs), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.recv(&ctx, memory, iovs), env) + wasi_try_ok!(pipe.recv(&memory, iovs), env) } Kind::EventNotifications { .. } => return Ok(__WASI_EINVAL), Kind::Dir { .. } | Kind::Root { .. } => return Ok(__WASI_EISDIR), Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pread"), Kind::Buffer { buffer } => { wasi_try_ok!( - read_bytes(&ctx, &buffer[(offset as usize)..], memory, iovs), + read_bytes(&buffer[(offset as usize)..], &memory, iovs), env ) } @@ -927,10 +921,16 @@ pub fn fd_prestat_get( ) -> __wasi_errno_t { trace!("wasi::fd_prestat_get: fd={}", fd); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); - let prestat_ptr = buf.deref(&ctx, memory); - wasi_try_mem!(prestat_ptr.write(wasi_try!(state.fs.prestat_fd(inodes.deref(), fd)))); + let prestat_ptr = buf.deref(&memory); + wasi_try_mem!(prestat_ptr.write(wasi_try!( + state.fs.prestat_fd(inodes.deref(), fd) + .map_err(|code| { + debug!("fd_prestat_get failed (fd={}) - errno={}", fd, code); + code + }) + ))); __WASI_ESUCCESS } @@ -947,8 +947,8 @@ pub fn fd_prestat_dir_name( path_len ); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let path_chars = wasi_try_mem!(path.slice(&ctx, memory, path_len)); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); + let path_chars = wasi_try_mem!(path.slice(&memory, path_len)); let real_inode = wasi_try!(state.fs.get_fd_inode(fd)); let inode_val = &inodes.arena[real_inode]; @@ -1008,9 +1008,9 @@ pub fn fd_pwrite( trace!("wasi::fd_pwrite"); // TODO: refactor, this is just copied from `fd_write`... let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let iovs_arr = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); - let nwritten_ref = nwritten.deref(&ctx, memory); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); + let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); + let nwritten_ref = nwritten.deref(&memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_written = match fd { @@ -1023,7 +1023,7 @@ pub fn fd_pwrite( env ); if let Some(ref mut stdout) = guard.deref_mut() { - wasi_try_ok!(write_bytes(&ctx, stdout, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(stdout, &memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1036,7 +1036,7 @@ pub fn fd_pwrite( env ); if let Some(ref mut stderr) = guard.deref_mut() { - wasi_try_ok!(write_bytes(&ctx, stderr, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(stderr, &memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1061,16 +1061,16 @@ pub fn fd_pwrite( .map_err(map_io_err), env ); - wasi_try_ok!(write_bytes(&ctx, handle, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(handle, &memory, iovs_arr), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.send(&ctx, memory, iovs_arr), env) + wasi_try_ok!(socket.send(&memory, iovs_arr), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.send(&ctx, memory, iovs_arr), env) + wasi_try_ok!(pipe.send(&memory, iovs_arr), env) } Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify @@ -1080,7 +1080,7 @@ pub fn fd_pwrite( Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pwrite"), Kind::Buffer { buffer } => { wasi_try_ok!( - write_bytes(&ctx, &mut buffer[(offset as usize)..], memory, iovs_arr), + write_bytes(&mut buffer[(offset as usize)..], &memory, iovs_arr), env ) } @@ -1117,10 +1117,10 @@ pub fn fd_read( ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_read: fd={}", fd); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); //let iovs_len = if iovs_len > M::Offset::from(1u32) { M::Offset::from(1u32) } else { iovs_len }; - let iovs_arr = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); - let nread_ref = nread.deref(&ctx, memory); + let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); + let nread_ref = nread.deref(&memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_read = match fd { @@ -1132,7 +1132,7 @@ pub fn fd_read( env ); if let Some(ref mut stdin) = guard.deref_mut() { - wasi_try_ok!(read_bytes(&ctx, stdin, memory, iovs_arr), env) + wasi_try_ok!(read_bytes(stdin, &memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1160,16 +1160,16 @@ pub fn fd_read( .map_err(map_io_err), env ); - wasi_try_ok!(read_bytes(&ctx, handle, memory, iovs_arr), env) + wasi_try_ok!(read_bytes(handle, &memory, iovs_arr), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.recv(&ctx, memory, iovs_arr), env) + wasi_try_ok!(socket.recv(&memory, iovs_arr), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.recv(&ctx, memory, iovs_arr), env) + wasi_try_ok!(pipe.recv(&memory, iovs_arr), env) } Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify @@ -1208,7 +1208,7 @@ pub fn fd_read( { let reader = val.to_ne_bytes(); ret = wasi_try_ok!( - read_bytes(&ctx, &reader[..], memory, iovs_arr), + read_bytes(&reader[..], &memory, iovs_arr), env ); break; @@ -1232,7 +1232,7 @@ pub fn fd_read( } Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"), Kind::Buffer { buffer } => { - wasi_try_ok!(read_bytes(&ctx, &buffer[offset..], memory, iovs_arr), env) + wasi_try_ok!(read_bytes(&buffer[offset..], &memory, iovs_arr), env) } } }; @@ -1276,12 +1276,12 @@ pub fn fd_readdir( ) -> __wasi_errno_t { trace!("wasi::fd_readdir"); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); // TODO: figure out how this is supposed to work; // is it supposed to pack the buffer full every time until it can't? or do one at a time? - let buf_arr = wasi_try_mem!(buf.slice(&ctx, memory, buf_len)); - let bufused_ref = bufused.deref(&ctx, memory); + let buf_arr = wasi_try_mem!(buf.slice(&memory, buf_len)); + let bufused_ref = bufused.deref(&memory); let working_dir = wasi_try!(state.fs.get_fd(fd)); let mut cur_cookie = cookie; let mut buf_idx = 0usize; @@ -1402,7 +1402,7 @@ pub fn fd_renumber( ) -> __wasi_errno_t { debug!("wasi::fd_renumber: from={}, to={}", from, to); let env = ctx.data(); - let (_, mut state) = env.get_memory_and_wasi_state(0); + let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&from).ok_or(__WASI_EBADF)); @@ -1434,10 +1434,10 @@ pub fn fd_dup( debug!("wasi::fd_dup"); let env = ctx.data(); - let (memory, state) = env.get_memory_and_wasi_state(0); + let (memory, state) = env.get_memory_and_wasi_state(&ctx, 0); let fd = wasi_try!(state.fs.clone_fd(fd)); - wasi_try_mem!(ret_fd.write(&ctx, memory, fd)); + wasi_try_mem!(ret_fd.write(&memory, fd)); __WASI_ESUCCESS } @@ -1453,7 +1453,7 @@ pub fn fd_event( debug!("wasi::fd_event"); let env = ctx.data(); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let kind = Kind::EventNotifications { counter: Arc::new(AtomicU64::new(initial_val)), @@ -1470,7 +1470,7 @@ pub fn fd_event( let rights = __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_POLL_FD_READWRITE; let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem!(ret_fd.write(&ctx, memory, fd)); + wasi_try_mem!(ret_fd.write(&memory, fd)); __WASI_ESUCCESS } @@ -1496,8 +1496,8 @@ pub fn fd_seek( ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_seek: fd={}, offset={}", fd, offset); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let new_offset_ref = newoffset.deref(&ctx, memory); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); + let new_offset_ref = newoffset.deref(&memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_SEEK) { @@ -1575,7 +1575,7 @@ pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errn debug!("wasi::fd_sync"); debug!("=> fd={}", fd); let env = ctx.data(); - let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_SYNC) { return __WASI_EACCES; @@ -1620,8 +1620,8 @@ pub fn fd_tell( ) -> __wasi_errno_t { debug!("wasi::fd_tell"); let env = ctx.data(); - let (memory, mut state) = env.get_memory_and_wasi_state(0); - let offset_ref = offset.deref(&ctx, memory); + let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); + let offset_ref = offset.deref(&memory); let fd_entry = wasi_try!(state.fs.get_fd(fd)); @@ -1657,9 +1657,9 @@ pub fn fd_write( ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_write: fd={}", fd); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let iovs_arr = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); - let nwritten_ref = nwritten.deref(&ctx, memory); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); + let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len)); + let nwritten_ref = nwritten.deref(&memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_written = match fd { @@ -1672,7 +1672,7 @@ pub fn fd_write( env ); if let Some(ref mut stdout) = guard.deref_mut() { - wasi_try_ok!(write_bytes(&ctx, stdout, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(stdout, &memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1685,7 +1685,7 @@ pub fn fd_write( env ); if let Some(ref mut stderr) = guard.deref_mut() { - wasi_try_ok!(write_bytes(&ctx, stderr, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(stderr, &memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1710,16 +1710,16 @@ pub fn fd_write( .map_err(map_io_err), env ); - wasi_try_ok!(write_bytes(&ctx, handle, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(handle, &memory, iovs_arr), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.send(&ctx, memory, iovs_arr), env) + wasi_try_ok!(socket.send(&memory, iovs_arr), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.send(&ctx, memory, iovs_arr), env) + wasi_try_ok!(pipe.send(&memory, iovs_arr), env) } Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify @@ -1730,7 +1730,7 @@ pub fn fd_write( } => { let mut val = 0u64.to_ne_bytes(); let written = - wasi_try_ok!(write_bytes(&ctx, &mut val[..], memory, iovs_arr)); + wasi_try_ok!(write_bytes(&mut val[..], &memory, iovs_arr)); if written != val.len() { return Ok(__WASI_EINVAL); } @@ -1751,7 +1751,7 @@ pub fn fd_write( Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_write"), Kind::Buffer { buffer } => { wasi_try_ok!( - write_bytes(&ctx, &mut buffer[offset..], memory, iovs_arr), + write_bytes(&mut buffer[offset..], &memory, iovs_arr), env ) } @@ -1792,7 +1792,7 @@ pub fn fd_pipe( trace!("wasi::fd_pipe"); let env = ctx.data(); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let (pipe1, pipe2) = WasiPipe::new(); @@ -1813,8 +1813,8 @@ pub fn fd_pipe( let fd1 = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode1)); let fd2 = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode2)); - wasi_try_mem!(ro_fd1.write(&ctx, memory, fd1)); - wasi_try_mem!(ro_fd2.write(&ctx, memory, fd2)); + wasi_try_mem!(ro_fd1.write(&memory, fd1)); + wasi_try_mem!(ro_fd2.write(&memory, fd2)); __WASI_ESUCCESS } @@ -1840,7 +1840,7 @@ pub fn path_create_directory( ) -> __wasi_errno_t { debug!("wasi::path_create_directory"); let env = ctx.data(); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let working_dir = wasi_try!(state.fs.get_fd(fd)); { @@ -1852,7 +1852,7 @@ pub fn path_create_directory( if !has_rights(working_dir.rights, __WASI_RIGHT_PATH_CREATE_DIRECTORY) { return __WASI_EACCES; } - let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&memory, path, path_len) }; debug!("=> fd: {}, path: {}", fd, &path_string); let path = std::path::PathBuf::from(&path_string); @@ -1900,7 +1900,7 @@ pub fn path_create_directory( // TODO: double check this doesn't risk breaking the sandbox adjusted_path.push(comp); if let Ok(adjusted_path_stat) = path_filestat_get_internal( - memory, + &memory, state, inodes.deref_mut(), fd, @@ -1970,12 +1970,12 @@ pub fn path_filestat_get( ) -> __wasi_errno_t { debug!("wasi::path_filestat_get (fd={})", fd); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); - let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&memory, path, path_len) }; let stat = wasi_try!(path_filestat_get_internal( - memory, + &memory, state, inodes.deref_mut(), fd, @@ -1983,7 +1983,7 @@ pub fn path_filestat_get( &path_string )); - wasi_try_mem!(buf.deref(&ctx, memory).write(stat)); + wasi_try_mem!(buf.deref(&memory).write(stat)); __WASI_ESUCCESS } @@ -2003,7 +2003,7 @@ pub fn path_filestat_get( /// - `__wasi_file_stat_t *buf` /// The location where the metadata will be stored pub fn path_filestat_get_internal( - memory: &Memory, + memory: &MemoryView, state: &WasiState, inodes: &mut crate::WasiInodes, fd: __wasi_fd_t, @@ -2060,7 +2060,7 @@ pub fn path_filestat_set_times( ) -> __wasi_errno_t { debug!("wasi::path_filestat_set_times"); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); let fd_inode = fd_entry.inode; if !has_rights(fd_entry.rights, __WASI_RIGHT_PATH_FILESTAT_SET_TIMES) { @@ -2073,7 +2073,7 @@ pub fn path_filestat_set_times( return __WASI_EINVAL; } - let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&memory, path, path_len) }; debug!("=> base_fd: {}, path: {}", fd, &path_string); let file_inode = wasi_try!(state.fs.get_inode_at_path( @@ -2141,9 +2141,9 @@ pub fn path_link( debug!(" - will follow symlinks when opening path"); } let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let old_path_str = unsafe { get_input_str!(&ctx, memory, old_path, old_path_len) }; - let new_path_str = unsafe { get_input_str!(&ctx, memory, new_path, new_path_len) }; + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); + let old_path_str = unsafe { get_input_str!(&memory, old_path, old_path_len) }; + let new_path_str = unsafe { get_input_str!(&memory, new_path, new_path_len) }; let source_fd = wasi_try!(state.fs.get_fd(old_fd)); let target_fd = wasi_try!(state.fs.get_fd(new_fd)); debug!( @@ -2239,14 +2239,14 @@ pub fn path_open( debug!(" - will follow symlinks when opening path"); } let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); /* TODO: find actual upper bound on name size (also this is a path, not a name :think-fish:) */ let path_len64: u64 = path_len.into(); if path_len64 > 1024u64 * 1024u64 { return __WASI_ENAMETOOLONG; } - let fd_ref = fd.deref(&ctx, memory); + let fd_ref = fd.deref(&memory); // o_flags: // - __WASI_O_CREAT (create if it does not exist) @@ -2261,7 +2261,7 @@ pub fn path_open( if !has_rights(working_dir.rights, __WASI_RIGHT_PATH_OPEN) { return __WASI_EACCES; } - let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&memory, path, path_len) }; debug!("=> fd: {}, path: {}", dirfd, &path_string); @@ -2476,13 +2476,13 @@ pub fn path_readlink( ) -> __wasi_errno_t { debug!("wasi::path_readlink"); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let base_dir = wasi_try!(state.fs.get_fd(dir_fd)); if !has_rights(base_dir.rights, __WASI_RIGHT_PATH_READLINK) { return __WASI_EACCES; } - let path_str = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_str = unsafe { get_input_str!(&memory, path, path_len) }; let inode = wasi_try!(state .fs .get_inode_at_path(inodes.deref_mut(), dir_fd, &path_str, false)); @@ -2500,13 +2500,13 @@ pub fn path_readlink( let bytes: Vec<_> = bytes.collect(); let out = - wasi_try_mem!(buf.slice(&ctx, memory, wasi_try!(to_offset::(bytes.len())))); + wasi_try_mem!(buf.slice(&memory, wasi_try!(to_offset::(bytes.len())))); wasi_try_mem!(out.write_slice(&bytes)); // should we null terminate this? let bytes_len: M::Offset = wasi_try!(bytes.len().try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(buf_used.deref(&ctx, memory).write(bytes_len)); + wasi_try_mem!(buf_used.deref(&memory).write(bytes_len)); } else { return __WASI_EINVAL; } @@ -2525,10 +2525,10 @@ pub fn path_remove_directory( // TODO check if fd is a dir, ensure it's within sandbox, etc. debug!("wasi::path_remove_directory"); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let base_dir = wasi_try!(state.fs.get_fd(fd)); - let path_str = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_str = unsafe { get_input_str!(&memory, path, path_len) }; let inode = wasi_try!(state .fs @@ -2615,10 +2615,10 @@ pub fn path_rename( old_fd, new_fd ); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let source_str = unsafe { get_input_str!(&ctx, memory, old_path, old_path_len) }; + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); + let source_str = unsafe { get_input_str!(&memory, old_path, old_path_len) }; let source_path = std::path::Path::new(&source_str); - let target_str = unsafe { get_input_str!(&ctx, memory, new_path, new_path_len) }; + let target_str = unsafe { get_input_str!(&memory, new_path, new_path_len) }; let target_path = std::path::Path::new(&target_str); debug!("=> rename from {} to {}", &source_str, &target_str); @@ -2775,9 +2775,9 @@ pub fn path_symlink( ) -> __wasi_errno_t { debug!("wasi::path_symlink"); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let old_path_str = unsafe { get_input_str!(&ctx, memory, old_path, old_path_len) }; - let new_path_str = unsafe { get_input_str!(&ctx, memory, new_path, new_path_len) }; + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); + let old_path_str = unsafe { get_input_str!(&memory, old_path, old_path_len) }; + let new_path_str = unsafe { get_input_str!(&memory, new_path, new_path_len) }; let base_fd = wasi_try!(state.fs.get_fd(fd)); if !has_rights(base_fd.rights, __WASI_RIGHT_PATH_SYMLINK) { return __WASI_EACCES; @@ -2873,13 +2873,13 @@ pub fn path_unlink_file( ) -> __wasi_errno_t { debug!("wasi::path_unlink_file"); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let base_dir = wasi_try!(state.fs.get_fd(fd)); if !has_rights(base_dir.rights, __WASI_RIGHT_PATH_UNLINK_FILE) { return __WASI_EACCES; } - let path_str = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let path_str = unsafe { get_input_str!(&memory, path, path_len) }; debug!("Requested file: {}", path_str); let inode = wasi_try!(state @@ -2986,12 +2986,12 @@ pub fn poll_oneoff( trace!("wasi::poll_oneoff"); trace!(" => nsubscriptions = {}", nsubscriptions); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); - let subscription_array = wasi_try_mem_ok!(in_.slice(&ctx, memory, nsubscriptions)); - let event_array = wasi_try_mem_ok!(out_.slice(&ctx, memory, nsubscriptions)); + let subscription_array = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions)); + let event_array = wasi_try_mem_ok!(out_.slice(&memory, nsubscriptions)); let mut events_seen: u32 = 0; - let out_ptr = nevents.deref(&ctx, memory); + let out_ptr = nevents.deref(&memory); let mut fd_guards = vec![]; let mut clock_subs = vec![]; @@ -3269,13 +3269,13 @@ pub fn random_get( ) -> __wasi_errno_t { trace!("wasi::random_get buf_len: {}", buf_len); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let buf_len64: u64 = buf_len.into(); let mut u8_buffer = vec![0; buf_len64 as usize]; let res = getrandom::getrandom(&mut u8_buffer); match res { Ok(()) => { - let buf = wasi_try_mem!(buf.slice(&ctx, memory, buf_len)); + let buf = wasi_try_mem!(buf.slice(&memory, buf_len)); wasi_try_mem!(buf.write_slice(&u8_buffer)); __WASI_ESUCCESS } @@ -3320,8 +3320,8 @@ pub fn tty_get( }, }; - let memory = env.memory(); - wasi_try_mem!(tty_state.write(&ctx, memory, state)); + let memory = env.memory_view(&ctx); + wasi_try_mem!(tty_state.write(&memory, state)); __WASI_ESUCCESS } @@ -3335,8 +3335,8 @@ pub fn tty_set( debug!("wasi::tty_set"); let env = ctx.data(); - let memory = env.memory(); - let state = wasi_try_mem!(tty_state.read(&ctx, memory)); + let memory = env.memory_view(&ctx); + let state = wasi_try_mem!(tty_state.read(&memory)); let state = super::runtime::WasiTtyState { cols: state.cols, rows: state.rows, @@ -3385,18 +3385,18 @@ pub fn getcwd( ) -> __wasi_errno_t { debug!("wasi::getcwd"); let env = ctx.data(); - let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let (_, cur_dir) = wasi_try!(state .fs .get_current_dir(inodes.deref_mut(), crate::VIRTUAL_ROOT_FD,)); - let max_path_len = wasi_try_mem!(path_len.read(&ctx, memory)); - let path_slice = wasi_try_mem!(path.slice(&ctx, memory, max_path_len)); + let max_path_len = wasi_try_mem!(path_len.read(&memory)); + let path_slice = wasi_try_mem!(path.slice(&memory, max_path_len)); let max_path_len: u64 = max_path_len.into(); let cur_dir = cur_dir.as_bytes(); - wasi_try_mem!(path_len.write(&ctx, memory, wasi_try!(to_offset::(cur_dir.len())))); + wasi_try_mem!(path_len.write(&memory, wasi_try!(to_offset::(cur_dir.len())))); if cur_dir.len() as u64 >= max_path_len { return __WASI_EOVERFLOW; } @@ -3426,8 +3426,8 @@ pub fn chdir( ) -> __wasi_errno_t { debug!("wasi::chdir"); let env = ctx.data(); - let (memory, mut state) = env.get_memory_and_wasi_state(0); - let path = unsafe { get_input_str!(&ctx, memory, path, path_len) }; + let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0); + let path = unsafe { get_input_str!(&memory, path, path_len) }; state.fs.set_current_dir(path.as_str()); __WASI_ESUCCESS @@ -3461,8 +3461,8 @@ pub fn thread_spawn( ) -> __wasi_errno_t { debug!("wasi::thread_spawn"); let env = ctx.data(); - let memory = env.memory(); - let method = unsafe { get_input_str!(&ctx, memory, method, method_len) }; + let memory = env.memory_view(&ctx); + let method = unsafe { get_input_str!(&memory, method, method_len) }; // Load the callback function if method.as_str() != "_thread_start" { @@ -3528,7 +3528,7 @@ pub fn thread_spawn( }; let child: __wasi_tid_t = child.into(); - wasi_try_mem!(ret_tid.write(&ctx, memory, child)); + wasi_try_mem!(ret_tid.write(&memory, child)); __WASI_ESUCCESS } @@ -3561,7 +3561,8 @@ pub fn thread_id( let env = ctx.data(); let tid: __wasi_tid_t = env.id.into(); - wasi_try_mem!(ret_tid.write(&ctx, env.memory(), tid)); + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_tid.write(&memory, tid)); __WASI_ESUCCESS } @@ -3612,7 +3613,8 @@ pub fn thread_parallelism( err })); let parallelism: M::Offset = wasi_try!(parallelism.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(ret_parallelism.write(&ctx, env.memory(), parallelism)); + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_parallelism.write(&memory, parallelism)); __WASI_ESUCCESS } @@ -3627,7 +3629,8 @@ pub fn getpid( let env = ctx.data(); let pid = env.runtime().getpid(); if let Some(pid) = pid { - wasi_try_mem!(ret_pid.write(&ctx, env.memory(), pid as __wasi_pid_t)); + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_pid.write(&memory, pid as __wasi_pid_t)); __WASI_ESUCCESS } else { __WASI_ENOTSUP @@ -3688,11 +3691,11 @@ pub fn process_spawn( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); - let name = unsafe { get_input_str_bus!(&ctx, memory, name, name_len) }; - let args = unsafe { get_input_str_bus!(&ctx, memory, args, args_len) }; - let preopen = unsafe { get_input_str_bus!(&ctx, memory, preopen, preopen_len) }; - let working_dir = unsafe { get_input_str_bus!(&ctx, memory, working_dir, working_dir_len) }; + let memory = env.memory_view(&ctx); + let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; + let args = unsafe { get_input_str_bus!(&memory, args, args_len) }; + let preopen = unsafe { get_input_str_bus!(&memory, preopen, preopen_len) }; + let working_dir = unsafe { get_input_str_bus!(&memory, working_dir, working_dir_len) }; let chroot = chroot == __WASI_BOOL_TRUE; debug!("wasi::process_spawn (name={})", name); @@ -3754,7 +3757,7 @@ pub fn process_spawn( stderr, }; - wasi_try_mem_bus!(ret_handles.write(&ctx, memory, handles)); + wasi_try_mem_bus!(ret_handles.write(&memory, handles)); __BUS_ESUCCESS } @@ -3780,8 +3783,8 @@ pub fn bus_open_local( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); - let name = unsafe { get_input_str_bus!(&ctx, memory, name, name_len) }; + let memory = env.memory_view(&ctx); + let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; let reuse = reuse == __WASI_BOOL_TRUE; debug!("wasi::bus_open_local (name={}, reuse={})", name, reuse); @@ -3815,10 +3818,10 @@ pub fn bus_open_remote( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); - let name = unsafe { get_input_str_bus!(&ctx, memory, name, name_len) }; - let instance = unsafe { get_input_str_bus!(&ctx, memory, instance, instance_len) }; - let token = unsafe { get_input_str_bus!(&ctx, memory, token, token_len) }; + let memory = env.memory_view(&ctx); + let name = unsafe { get_input_str_bus!(&memory, name, name_len) }; + let instance = unsafe { get_input_str_bus!(&memory, instance, instance_len) }; + let token = unsafe { get_input_str_bus!(&memory, token, token_len) }; let reuse = reuse == __WASI_BOOL_TRUE; debug!( "wasi::bus_open_remote (name={}, reuse={}, instance={})", @@ -3838,7 +3841,7 @@ fn bus_open_local_internal( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let name: Cow<'static, str> = name.into(); // Check if it already exists @@ -3846,7 +3849,7 @@ fn bus_open_local_internal( let guard = env.state.threading.lock().unwrap(); if let Some(bid) = guard.process_reuse.get(&name) { if guard.processes.contains_key(bid) { - wasi_try_mem_bus!(ret_bid.write(&ctx, memory, (*bid).into())); + wasi_try_mem_bus!(ret_bid.write(&memory, (*bid).into())); return __BUS_ESUCCESS; } } @@ -3881,7 +3884,7 @@ fn bus_open_local_internal( bid }; - wasi_try_mem_bus!(ret_bid.write(&ctx, memory, bid.into())); + wasi_try_mem_bus!(ret_bid.write(&memory, bid.into())); __BUS_ESUCCESS } @@ -3926,8 +3929,8 @@ pub fn bus_call( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); - let topic = unsafe { get_input_str_bus!(&ctx, memory, topic, topic_len) }; + let memory = env.memory_view(&ctx); + let topic = unsafe { get_input_str_bus!(&memory, topic, topic_len) }; let keep_alive = keep_alive == __WASI_BOOL_TRUE; trace!( "wasi::bus_call (bid={}, topic={}, buf_len={})", @@ -3963,8 +3966,8 @@ pub fn bus_subcall( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); - let topic = unsafe { get_input_str_bus!(&ctx, memory, topic, topic_len) }; + let memory = env.memory_view(&ctx); + let topic = unsafe { get_input_str_bus!(&memory, topic, topic_len) }; let keep_alive = keep_alive == __WASI_BOOL_TRUE; trace!( "wasi::bus_subcall (parent={}, topic={}, buf_len={})", @@ -4001,8 +4004,8 @@ pub fn bus_poll( ) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); - let memory = env.memory(); - let malloc = unsafe { get_input_str_bus!(&ctx, memory, malloc, malloc_len) }; + let memory = env.memory_view(&ctx); + let malloc = unsafe { get_input_str_bus!(&memory, malloc, malloc_len) }; trace!("wasi::bus_poll (timeout={}, malloc={})", timeout, malloc); __BUS_EUNSUPPORTED @@ -4088,15 +4091,15 @@ pub fn ws_connect( ) -> __wasi_errno_t { debug!("wasi::ws_connect"); let env = ctx.data(); - let memory = env.memory(); - let url = unsafe { get_input_str!(&ctx, memory, url, url_len) }; + let memory = env.memory_view(&ctx); + let url = unsafe { get_input_str!(&memory, url, url_len) }; let socket = wasi_try!(env .net() .ws_connect(url.as_str()) .map_err(net_error_into_wasi_err)); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let kind = Kind::Socket { socket: InodeSocket::new(InodeSocketKind::WebSocket(socket)), @@ -4111,7 +4114,7 @@ pub fn ws_connect( let rights = super::state::all_socket_rights(); let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem!(ret_sock.write(&ctx, memory, fd)); + wasi_try_mem!(ret_sock.write(&memory, fd)); __WASI_ESUCCESS } @@ -4145,10 +4148,10 @@ pub fn http_request( ) -> __wasi_errno_t { debug!("wasi::http_request"); let env = ctx.data(); - let memory = env.memory(); - let url = unsafe { get_input_str!(&ctx, memory, url, url_len) }; - let method = unsafe { get_input_str!(&ctx, memory, method, method_len) }; - let headers = unsafe { get_input_str!(&ctx, memory, headers, headers_len) }; + let memory = env.memory_view(&ctx); + let url = unsafe { get_input_str!(&memory, url, url_len) }; + let method = unsafe { get_input_str!(&memory, method, method_len) }; + let headers = unsafe { get_input_str!(&memory, headers, headers_len) }; let gzip = match gzip { __WASI_BOOL_FALSE => false, @@ -4179,7 +4182,7 @@ pub fn http_request( status: socket.status, }; - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let kind_req = Kind::Socket { socket: InodeSocket::new(InodeSocketKind::HttpRequest( @@ -4226,7 +4229,7 @@ pub fn http_request( hdr: wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode_hdr)), }; - wasi_try_mem!(ret_handles.write(&ctx, memory, handles)); + wasi_try_mem!(ret_handles.write(&memory, handles)); __WASI_ESUCCESS } @@ -4247,8 +4250,8 @@ pub fn http_status( debug!("wasi::http_status"); let env = ctx.data(); - let memory = env.memory(); - let ref_status = status.deref(&ctx, memory); + let memory = env.memory_view(&ctx); + let ref_status = status.deref(&memory); let http_status = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.http_status() @@ -4288,9 +4291,9 @@ pub fn port_bridge( ) -> __wasi_errno_t { debug!("wasi::port_bridge"); let env = ctx.data(); - let memory = env.memory(); - let network = unsafe { get_input_str!(&ctx, memory, network, network_len) }; - let token = unsafe { get_input_str!(&ctx, memory, token, token_len) }; + let memory = env.memory_view(&ctx); + let network = unsafe { get_input_str!(&memory, network, network_len) }; + let token = unsafe { get_input_str!(&memory, token, token_len) }; let security = match security { __WASI_STREAM_SECURITY_UNENCRYPTED => StreamSecurity::Unencrypted, __WASI_STREAM_SECURITY_ANY_ENCRYPTION => StreamSecurity::AnyEncyption, @@ -4336,8 +4339,8 @@ pub fn port_addr_add( ) -> __wasi_errno_t { debug!("wasi::port_addr_add"); let env = ctx.data(); - let memory = env.memory(); - let cidr = wasi_try!(super::state::read_cidr(&ctx, memory, ip)); + let memory = env.memory_view(&ctx); + let cidr = wasi_try!(super::state::read_cidr(&memory, ip)); wasi_try!(env .net() .ip_add(cidr.ip, cidr.prefix) @@ -4357,8 +4360,8 @@ pub fn port_addr_remove( ) -> __wasi_errno_t { debug!("wasi::port_addr_remove"); let env = ctx.data(); - let memory = env.memory(); - let ip = wasi_try!(super::state::read_ip(&ctx, memory, ip)); + let memory = env.memory_view(&ctx); + let ip = wasi_try!(super::state::read_ip(&memory, ip)); wasi_try!(env.net().ip_remove(ip).map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } @@ -4380,10 +4383,10 @@ pub fn port_mac( ) -> __wasi_errno_t { debug!("wasi::port_mac"); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let mac = wasi_try!(env.net().mac().map_err(net_error_into_wasi_err)); let mac = __wasi_hardwareaddress_t { octs: mac }; - wasi_try_mem!(ret_mac.write(&ctx, memory, mac)); + wasi_try_mem!(ret_mac.write(&memory, mac)); __WASI_ESUCCESS } @@ -4407,23 +4410,23 @@ pub fn port_addr_list( ) -> __wasi_errno_t { debug!("wasi::port_addr_list"); let env = ctx.data(); - let memory = env.memory(); - let max_addrs = wasi_try_mem!(naddrs.read(&ctx, memory)); + let memory = env.memory_view(&ctx); + let max_addrs = wasi_try_mem!(naddrs.read(&memory)); let max_addrs: u64 = wasi_try!(max_addrs.try_into().map_err(|_| __WASI_EOVERFLOW)); let ref_addrs = - wasi_try_mem!(addrs.slice(&ctx, memory, wasi_try!(to_offset::(max_addrs as usize)))); + wasi_try_mem!(addrs.slice(&memory, wasi_try!(to_offset::(max_addrs as usize)))); let addrs = wasi_try!(env.net().ip_list().map_err(net_error_into_wasi_err)); let addrs_len: M::Offset = wasi_try!(addrs.len().try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(naddrs.write(&ctx, memory, addrs_len)); + wasi_try_mem!(naddrs.write(&memory, addrs_len)); if addrs.len() as u64 > max_addrs { return __WASI_EOVERFLOW; } for n in 0..addrs.len() { let nip = ref_addrs.index(n as u64); - super::state::write_cidr(&ctx, memory, nip.as_ptr::(), *addrs.get(n).unwrap()); + super::state::write_cidr(&memory, nip.as_ptr::(), *addrs.get(n).unwrap()); } __WASI_ESUCCESS @@ -4441,8 +4444,8 @@ pub fn port_gateway_set( ) -> __wasi_errno_t { debug!("wasi::port_gateway_set"); let env = ctx.data(); - let memory = env.memory(); - let ip = wasi_try!(super::state::read_ip(&ctx, memory, ip)); + let memory = env.memory_view(&ctx); + let ip = wasi_try!(super::state::read_ip(&memory, ip)); wasi_try!(env.net().gateway_set(ip).map_err(net_error_into_wasi_err)); __WASI_ESUCCESS @@ -4459,16 +4462,16 @@ pub fn port_route_add( ) -> __wasi_errno_t { debug!("wasi::port_route_add"); let env = ctx.data(); - let memory = env.memory(); - let cidr = wasi_try!(super::state::read_cidr(&ctx, memory, cidr)); - let via_router = wasi_try!(super::state::read_ip(&ctx, memory, via_router)); - let preferred_until = wasi_try_mem!(preferred_until.read(&ctx, memory)); + let memory = env.memory_view(&ctx); + let cidr = wasi_try!(super::state::read_cidr(&memory, cidr)); + let via_router = wasi_try!(super::state::read_ip(&memory, via_router)); + let preferred_until = wasi_try_mem!(preferred_until.read(&memory)); let preferred_until = match preferred_until.tag { __WASI_OPTION_NONE => None, __WASI_OPTION_SOME => Some(Duration::from_nanos(preferred_until.u)), _ => return __WASI_EINVAL, }; - let expires_at = wasi_try_mem!(expires_at.read(&ctx, memory)); + let expires_at = wasi_try_mem!(expires_at.read(&memory)); let expires_at = match expires_at.tag { __WASI_OPTION_NONE => None, __WASI_OPTION_SOME => Some(Duration::from_nanos(expires_at.u)), @@ -4490,8 +4493,8 @@ pub fn port_route_remove( ) -> __wasi_errno_t { debug!("wasi::port_route_remove"); let env = ctx.data(); - let memory = env.memory(); - let ip = wasi_try!(super::state::read_ip(&ctx, memory, ip)); + let memory = env.memory_view(&ctx); + let ip = wasi_try!(super::state::read_ip(&memory, ip)); wasi_try!(env.net().route_remove(ip).map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } @@ -4521,13 +4524,13 @@ pub fn port_route_list( ) -> __wasi_errno_t { debug!("wasi::port_route_list"); let env = ctx.data(); - let memory = env.memory(); - let nroutes = nroutes.deref(&ctx, memory); + let memory = env.memory_view(&ctx); + let nroutes = nroutes.deref(&memory); let max_routes: usize = wasi_try!(wasi_try_mem!(nroutes.read()) .try_into() .map_err(|_| __WASI_EINVAL)); let ref_routes = - wasi_try_mem!(routes.slice(&ctx, memory, wasi_try!(to_offset::(max_routes)))); + wasi_try_mem!(routes.slice(&memory, wasi_try!(to_offset::(max_routes)))); let routes = wasi_try!(env.net().route_list().map_err(net_error_into_wasi_err)); @@ -4540,8 +4543,7 @@ pub fn port_route_list( for n in 0..routes.len() { let nroute = ref_routes.index(n as u64); super::state::write_route( - &ctx, - memory, + &memory, nroute.as_ptr::(), routes.get(n).unwrap().clone(), ); @@ -4602,7 +4604,8 @@ pub fn sock_status( }; let env = ctx.data(); - wasi_try_mem!(ret_status.write(&ctx, env.memory(), status)); + let memory = env.memory_view(&ctx); + wasi_try_mem!(ret_status.write(&memory, status)); __WASI_ESUCCESS } @@ -4628,10 +4631,9 @@ pub fn sock_addr_local( let addr = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.addr_local() })); - let memory = ctx.data().memory(); + let memory = ctx.data().memory_view(&ctx); wasi_try!(super::state::write_ip_port( - &ctx, - memory, + &memory, ret_addr, addr.ip(), addr.port() @@ -4659,9 +4661,9 @@ pub fn sock_addr_peer( let env = ctx.data(); let addr = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.addr_peer() })); + let memory = env.memory_view(&ctx); wasi_try!(super::state::write_ip_port( - &ctx, - env.memory(), + &memory, ro_addr, addr.ip(), addr.port() @@ -4698,7 +4700,7 @@ pub fn sock_open( debug!("wasi::sock_open"); let env = ctx.data(); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let kind = match ty { __WASI_SOCK_TYPE_STREAM | __WASI_SOCK_TYPE_DGRAM => Kind::Socket { @@ -4730,7 +4732,7 @@ pub fn sock_open( let rights = super::state::all_socket_rights(); let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem!(ro_sock.write(&ctx, memory, fd)); + wasi_try_mem!(ro_sock.write(&memory, fd)); __WASI_ESUCCESS } @@ -4781,7 +4783,7 @@ pub fn sock_get_opt_flag( ) -> __wasi_errno_t { debug!("wasi::sock_get_opt_flag(ty={})", opt); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let option: super::state::WasiSocketOption = opt.into(); let flag = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { @@ -4792,7 +4794,7 @@ pub fn sock_get_opt_flag( true => __WASI_BOOL_TRUE, }; - wasi_try_mem!(ret_flag.write(&ctx, memory, flag)); + wasi_try_mem!(ret_flag.write(&memory, flag)); __WASI_ESUCCESS } @@ -4814,8 +4816,8 @@ pub fn sock_set_opt_time( debug!("wasi::sock_set_opt_time(ty={})", opt); let env = ctx.data(); - let memory = env.memory(); - let time = wasi_try_mem!(time.read(&ctx, memory)); + let memory = env.memory_view(&ctx); + let time = wasi_try_mem!(time.read(&memory)); let time = match time.tag { __WASI_OPTION_NONE => None, __WASI_OPTION_SOME => Some(Duration::from_nanos(time.u)), @@ -4853,7 +4855,7 @@ pub fn sock_get_opt_time( ) -> __wasi_errno_t { debug!("wasi::sock_get_opt_time(ty={})", opt); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let ty = match opt { __WASI_SOCK_OPTION_RECV_TIMEOUT => wasmer_vnet::TimeType::ReadTimeout, @@ -4878,7 +4880,7 @@ pub fn sock_get_opt_time( }, }; - wasi_try_mem!(ret_time.write(&ctx, memory, time)); + wasi_try_mem!(ret_time.write(&memory, time)); __WASI_ESUCCESS } @@ -4938,7 +4940,7 @@ pub fn sock_get_opt_size( ) -> __wasi_errno_t { debug!("wasi::sock_get_opt_size(ty={})", opt); let env = ctx.data(); - let memory = env.memory(); + let memory = env.memory_view(&ctx); let size = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { match opt { @@ -4955,7 +4957,7 @@ pub fn sock_get_opt_size( _ => Err(__WASI_EINVAL), } })); - wasi_try_mem!(ret_size.write(&ctx, memory, size)); + wasi_try_mem!(ret_size.write(&memory, size)); __WASI_ESUCCESS } @@ -4977,9 +4979,9 @@ pub fn sock_join_multicast_v4( debug!("wasi::sock_join_multicast_v4"); let env = ctx.data(); - let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v4(&ctx, memory, multiaddr)); - let iface = wasi_try!(super::state::read_ip_v4(&ctx, memory, iface)); + let memory = env.memory_view(&ctx); + let multiaddr = wasi_try!(super::state::read_ip_v4(&memory, multiaddr)); + let iface = wasi_try!(super::state::read_ip_v4(&memory, iface)); wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.join_multicast_v4(multiaddr, iface) })); @@ -5003,9 +5005,9 @@ pub fn sock_leave_multicast_v4( debug!("wasi::sock_leave_multicast_v4"); let env = ctx.data(); - let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v4(&ctx, memory, multiaddr)); - let iface = wasi_try!(super::state::read_ip_v4(&ctx, memory, iface)); + let memory = env.memory_view(&ctx); + let multiaddr = wasi_try!(super::state::read_ip_v4(&memory, multiaddr)); + let iface = wasi_try!(super::state::read_ip_v4(&memory, iface)); wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.leave_multicast_v4(multiaddr, iface) })); @@ -5029,8 +5031,8 @@ pub fn sock_join_multicast_v6( debug!("wasi::sock_join_multicast_v6"); let env = ctx.data(); - let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v6(&ctx, memory, multiaddr)); + let memory = env.memory_view(&ctx); + let multiaddr = wasi_try!(super::state::read_ip_v6(&memory, multiaddr)); wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.join_multicast_v6(multiaddr, iface) })); @@ -5054,8 +5056,8 @@ pub fn sock_leave_multicast_v6( debug!("wasi::sock_leave_multicast_v6"); let env = ctx.data(); - let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v6(&ctx, memory, multiaddr)); + let memory = env.memory_view(&ctx); + let multiaddr = wasi_try!(super::state::read_ip_v6(&memory, multiaddr)); wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.leave_multicast_v6(multiaddr, iface) })); @@ -5078,7 +5080,8 @@ pub fn sock_bind( debug!("wasi::sock_bind"); let env = ctx.data(); - let addr = wasi_try!(super::state::read_ip_port(&ctx, env.memory(), addr)); + let memory = env.memory_view(&ctx); + let addr = wasi_try!(super::state::read_ip_port(&memory, addr)); let addr = SocketAddr::new(addr.0, addr.1); wasi_try!(__sock_upgrade( &ctx, @@ -5143,7 +5146,7 @@ pub fn sock_accept( let env = ctx.data(); let (child, addr) = { let mut ret; - let (_, state) = env.get_memory_and_wasi_state(0); + let (_, state) = env.get_memory_and_wasi_state(&ctx, 0); loop { wasi_try_ok!( match __sock_actor(&ctx, sock, __WASI_RIGHT_SOCK_ACCEPT, |socket| socket @@ -5168,7 +5171,7 @@ pub fn sock_accept( ret }; - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0); let kind = Kind::Socket { socket: InodeSocket::new(InodeSocketKind::TcpStream(child)), @@ -5183,10 +5186,9 @@ pub fn sock_accept( let rights = super::state::all_socket_rights(); let fd = wasi_try_ok!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem_ok!(ro_fd.write(&ctx, memory, fd)); + wasi_try_mem_ok!(ro_fd.write(&memory, fd)); wasi_try_ok!(super::state::write_ip_port( - &ctx, - memory, + &memory, ro_addr, addr.ip(), addr.port() @@ -5215,7 +5217,8 @@ pub fn sock_connect( debug!("wasi::sock_connect"); let env = ctx.data(); - let addr = wasi_try!(super::state::read_ip_port(&ctx, env.memory(), addr)); + let memory = env.memory_view(&ctx); + let addr = wasi_try!(super::state::read_ip_port(&memory, addr)); let addr = SocketAddr::new(addr.0, addr.1); wasi_try!(__sock_upgrade( &ctx, @@ -5251,19 +5254,19 @@ pub fn sock_recv( debug!("wasi::sock_recv"); let env = ctx.data(); - let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&ctx, memory, ri_data_len)); + let memory = env.memory_view(&ctx); + let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&memory, ri_data_len)); let bytes_read = wasi_try_ok!(__sock_actor_mut( &ctx, sock, __WASI_RIGHT_SOCK_RECV, - |socket| { socket.recv(&ctx, memory, iovs_arr) } + |socket| { socket.recv(& memory, iovs_arr) } )); let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ro_flags.write(&ctx, memory, 0)); - wasi_try_mem_ok!(ro_data_len.write(&ctx, memory, bytes_read)); + wasi_try_mem_ok!(ro_flags.write(&memory, 0)); + wasi_try_mem_ok!(ro_data_len.write(&memory, bytes_read)); Ok(__WASI_ESUCCESS) } @@ -5294,19 +5297,19 @@ pub fn sock_recv_from( debug!("wasi::sock_recv_from"); let env = ctx.data(); - let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&ctx, memory, ri_data_len)); + let memory = env.memory_view(&ctx); + let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&memory, ri_data_len)); let bytes_read = wasi_try_ok!(__sock_actor_mut( &ctx, sock, __WASI_RIGHT_SOCK_RECV_FROM, - |socket| { socket.recv_from(&ctx, memory, iovs_arr, ro_addr) } + |socket| { socket.recv_from(&memory, iovs_arr, ro_addr) } )); let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ro_flags.write(&ctx, memory, 0)); - wasi_try_mem_ok!(ro_data_len.write(&ctx, memory, bytes_read)); + wasi_try_mem_ok!(ro_flags.write(&memory, 0)); + wasi_try_mem_ok!(ro_data_len.write(&memory, bytes_read)); Ok(__WASI_ESUCCESS) } @@ -5335,19 +5338,19 @@ pub fn sock_send( debug!("wasi::sock_send"); let env = ctx.data(); - let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(si_data.slice(&ctx, memory, si_data_len)); + let memory = env.memory_view(&ctx); + let iovs_arr = wasi_try_mem_ok!(si_data.slice(&memory, si_data_len)); let bytes_written = wasi_try_ok!(__sock_actor_mut( &ctx, sock, __WASI_RIGHT_SOCK_SEND, - |socket| { socket.send(&ctx, memory, iovs_arr) } + |socket| { socket.send(&memory, iovs_arr) } )); let bytes_written: M::Offset = wasi_try_ok!(bytes_written.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ret_data_len.write(&ctx, memory, bytes_written)); + wasi_try_mem_ok!(ret_data_len.write(&memory, bytes_written)); Ok(__WASI_ESUCCESS) } @@ -5378,19 +5381,19 @@ pub fn sock_send_to( debug!("wasi::sock_send_to"); let env = ctx.data(); - let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(si_data.slice(&ctx, memory, si_data_len)); + let memory = env.memory_view(&ctx); + let iovs_arr = wasi_try_mem_ok!(si_data.slice(&memory, si_data_len)); let bytes_written = wasi_try_ok!(__sock_actor_mut( &ctx, sock, __WASI_RIGHT_SOCK_SEND_TO, - |socket| { socket.send_to::(&ctx, memory, iovs_arr, addr) } + |socket| { socket.send_to::(&memory, iovs_arr, addr) } )); let bytes_written: M::Offset = wasi_try_ok!(bytes_written.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ret_data_len.write(&ctx, memory, bytes_written as M::Offset)); + wasi_try_mem_ok!(ret_data_len.write(&memory, bytes_written as M::Offset)); Ok(__WASI_ESUCCESS) } @@ -5417,7 +5420,7 @@ pub unsafe fn sock_send_file( ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::send_file"); let env = ctx.data(); - let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0); // Set the offset of the file { @@ -5517,7 +5520,7 @@ pub unsafe fn sock_send_file( total_written += bytes_written as u64; } - wasi_try_mem_ok!(ret_sent.write(&ctx, memory, total_written as __wasi_filesize_t)); + wasi_try_mem_ok!(ret_sent.write(&memory, total_written as __wasi_filesize_t)); Ok(__WASI_ESUCCESS) } @@ -5553,9 +5556,9 @@ pub fn resolve( let naddrs: usize = wasi_try!(naddrs.try_into().map_err(|_| __WASI_EINVAL)); let env = ctx.data(); - let memory = env.memory(); - let host_str = unsafe { get_input_str!(&ctx, memory, host, host_len) }; - let addrs = wasi_try_mem!(addrs.slice(&ctx, memory, wasi_try!(to_offset::(naddrs)))); + let memory = env.memory_view(&ctx); + let host_str = unsafe { get_input_str!(&memory, host, host_len) }; + let addrs = wasi_try_mem!(addrs.slice(&memory, wasi_try!(to_offset::(naddrs)))); let port = if port > 0 { Some(port) } else { None }; @@ -5566,12 +5569,12 @@ pub fn resolve( let mut idx = 0; for found_ip in found_ips.iter().take(naddrs) { - super::state::write_ip(&ctx, memory, addrs.index(idx).as_ptr::(), *found_ip); + super::state::write_ip(&memory, addrs.index(idx).as_ptr::(), *found_ip); idx += 1; } let idx: M::Offset = wasi_try!(idx.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(ret_naddrs.write(&ctx, memory, idx)); + wasi_try_mem!(ret_naddrs.write(&memory, idx)); __WASI_ESUCCESS } diff --git a/tests/compilers/issues.rs b/tests/compilers/issues.rs index 03a301e8690..6fed2c724c7 100644 --- a/tests/compilers/issues.rs +++ b/tests/compilers/issues.rs @@ -102,7 +102,7 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { println!("{:?}", (a, b, c, d, e, f, g, h)); let mut buf = vec![0; d as usize]; let memory = ctx.data_mut().memory.as_ref().unwrap().clone(); - memory.read(&mut ctx, e, &mut buf).unwrap(); + memory.view(&ctx).read(e, &mut buf).unwrap(); let input_string = std::str::from_utf8(&buf).unwrap(); assert_eq!(input_string, "bananapeach"); 0 From 8ff164036d44ba4d5958a9a4784475fd0491eb23 Mon Sep 17 00:00:00 2001 From: John Sharratt's Shared Account Date: Tue, 2 Aug 2022 10:50:34 +1000 Subject: [PATCH 2/2] Removed uint8view() from the memory API and redundant FunctionEnv in tests --- examples/engine_headless.rs | 1 - examples/errors.rs | 1 - examples/exports_function.rs | 1 - examples/exports_global.rs | 1 - examples/exports_memory.rs | 1 - examples/features.rs | 1 - examples/imports_global.rs | 1 - examples/instance.rs | 1 - examples/memory.rs | 1 - examples/metering.rs | 1 - examples/tunables_limit_memory.rs | 1 - lib/api/Cargo.toml | 2 +- lib/api/src/js/externals/memory.rs | 5 ++- lib/api/src/js/externals/memory_view.rs | 48 +++++++++++++++++++++--- lib/api/src/sys/externals/memory.rs | 4 ++ lib/api/src/sys/externals/memory_view.rs | 27 +++++++++++++ lib/api/tests/js_externals.rs | 6 --- lib/api/tests/js_instance.rs | 24 +++++------- 18 files changed, 88 insertions(+), 39 deletions(-) diff --git a/examples/engine_headless.rs b/examples/engine_headless.rs index e11731f49e0..6ff9c95d2a0 100644 --- a/examples/engine_headless.rs +++ b/examples/engine_headless.rs @@ -96,7 +96,6 @@ fn main() -> Result<(), Box> { // We create a headless Universal engine. let engine = EngineBuilder::headless(); let mut store = Store::new(engine); - let _env = FunctionEnv::new(&mut store, ()); println!("Deserializing module..."); // Here we go. diff --git a/examples/errors.rs b/examples/errors.rs index 46fa0c05b28..d2bedfbf69a 100644 --- a/examples/errors.rs +++ b/examples/errors.rs @@ -39,7 +39,6 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/exports_function.rs b/examples/exports_function.rs index 7722e95c2dd..958a86d094f 100644 --- a/examples/exports_function.rs +++ b/examples/exports_function.rs @@ -40,7 +40,6 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/exports_global.rs b/examples/exports_global.rs index f880e8b7a94..06921b0d846 100644 --- a/examples/exports_global.rs +++ b/examples/exports_global.rs @@ -40,7 +40,6 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/exports_memory.rs b/examples/exports_memory.rs index 2eb1fb196ed..c6c3d058ea0 100644 --- a/examples/exports_memory.rs +++ b/examples/exports_memory.rs @@ -37,7 +37,6 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/features.rs b/examples/features.rs index 1469f47b0de..4f8a800386b 100644 --- a/examples/features.rs +++ b/examples/features.rs @@ -41,7 +41,6 @@ fn main() -> anyhow::Result<()> { // Now, let's define the store, and compile the module. let mut store = Store::new(engine); - let _env = FunctionEnv::new(&mut store, ()); let module = Module::new(&store, wasm_bytes)?; // Finally, let's instantiate the module, and execute something diff --git a/examples/imports_global.rs b/examples/imports_global.rs index 2609161716a..a00c9756431 100644 --- a/examples/imports_global.rs +++ b/examples/imports_global.rs @@ -40,7 +40,6 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/instance.rs b/examples/instance.rs index faff810ebeb..e563af07e73 100644 --- a/examples/instance.rs +++ b/examples/instance.rs @@ -39,7 +39,6 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/memory.rs b/examples/memory.rs index c90fbdd91aa..3cd1815a181 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -59,7 +59,6 @@ fn main() -> anyhow::Result<()> { // the default provided by Wasmer. // You can use `Store::default()` for that. let mut store = Store::new(Cranelift::default()); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/metering.rs b/examples/metering.rs index 39dadf9d358..0d37491e0a9 100644 --- a/examples/metering.rs +++ b/examples/metering.rs @@ -72,7 +72,6 @@ fn main() -> anyhow::Result<()> { // We use our previously create compiler configuration // with the Universal engine. let mut store = Store::new(EngineBuilder::new(compiler_config)); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/tunables_limit_memory.rs b/examples/tunables_limit_memory.rs index b31b4b74d37..2b2f36900ac 100644 --- a/examples/tunables_limit_memory.rs +++ b/examples/tunables_limit_memory.rs @@ -143,7 +143,6 @@ fn main() -> Result<(), Box> { // Create a store, that holds the engine and our custom tunables let mut store = Store::new_with_tunables(compiler, tunables); - let _env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); let module = Module::new(&store, wasm_bytes)?; diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 16a518fa9b8..7cac69aa1f5 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -26,9 +26,9 @@ indexmap = { version = "1.6", features = ["serde-1"] } cfg-if = "1.0" thiserror = "1.0" more-asserts = "0.2" -tracing = "0.1" # - Optional shared dependencies. wat = { version = "1.0", optional = true } +tracing = { version = "0.1", optional = true } # Dependencies and Development Dependencies for `sys`. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/lib/api/src/js/externals/memory.rs b/lib/api/src/js/externals/memory.rs index 65e657b2bdd..d181e6c6d89 100644 --- a/lib/api/src/js/externals/memory.rs +++ b/lib/api/src/js/externals/memory.rs @@ -7,6 +7,7 @@ use std::marker::PhantomData; use std::mem::MaybeUninit; use std::slice; use thiserror::Error; +#[cfg(feature = "tracing")] use tracing::warn; use wasm_bindgen::prelude::*; @@ -177,7 +178,6 @@ impl Memory { IntoPages: Into, { let pages = delta.into(); - warn!("memory grow {}", pages.0); let js_memory = &self.handle.get_mut(store.objects_mut()).memory; let our_js_memory: &JSMemory = JsCast::unchecked_from_js_ref(js_memory); let new_pages = our_js_memory.grow(pages.0).map_err(|err| { @@ -239,6 +239,7 @@ impl<'a> MemoryBuffer<'a> { .ok_or(MemoryAccessError::Overflow)?; let view = unsafe { &*(self.base) }; if end > view.length().into() { + #[cfg(feature = "tracing")] warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, view.length()); return Err(MemoryAccessError::HeapOutOfBounds); } @@ -257,6 +258,7 @@ impl<'a> MemoryBuffer<'a> { .ok_or(MemoryAccessError::Overflow)?; let view = unsafe { &*(self.base) }; if end > view.length().into() { + #[cfg(feature = "tracing")] warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, view.length()); return Err(MemoryAccessError::HeapOutOfBounds); } @@ -273,6 +275,7 @@ impl<'a> MemoryBuffer<'a> { .ok_or(MemoryAccessError::Overflow)?; let view = unsafe { &mut *(self.base) }; if end > view.length().into() { + #[cfg(feature = "tracing")] warn!("attempted to write ({} bytes) beyond the bounds of the memory view ({} > {})", data.len(), end, view.length()); return Err(MemoryAccessError::HeapOutOfBounds); } diff --git a/lib/api/src/js/externals/memory_view.rs b/lib/api/src/js/externals/memory_view.rs index 34fbb5f26be..bf2b63e0c99 100644 --- a/lib/api/src/js/externals/memory_view.rs +++ b/lib/api/src/js/externals/memory_view.rs @@ -4,6 +4,7 @@ use std::convert::TryInto; use std::marker::PhantomData; use std::mem::MaybeUninit; use std::slice; +#[cfg(feature = "tracing")] use tracing::warn; use wasmer_types::{Bytes, Pages}; @@ -79,12 +80,6 @@ impl<'a> MemoryView<'a> Bytes(self.size as usize).try_into().unwrap() } - /// Used by tests - #[doc(hidden)] - pub fn uint8view(&self) -> js_sys::Uint8Array { - self.view.clone() - } - pub(crate) fn buffer(&self) -> MemoryBuffer<'a> { MemoryBuffer { base: &self.view as *const _ as *mut _, @@ -112,6 +107,7 @@ impl<'a> MemoryView<'a> .map_err(|_| MemoryAccessError::Overflow)?; let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; if end > view.length() { + #[cfg(feature = "tracing")] warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", len, end, view.length()); Err(MemoryAccessError::HeapOutOfBounds)?; } @@ -119,6 +115,24 @@ impl<'a> MemoryView<'a> Ok(()) } + /// Safely reads a single byte from memory at the given offset + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn read_u8( + &self, + offset: u64 + ) -> Result { + let view = &self.view; + let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; + if offset >= view.length() { + #[cfg(feature = "tracing")] + warn!("attempted to read beyond the bounds of the memory view ({} >= {})", offset, view.length()); + Err(MemoryAccessError::HeapOutOfBounds)?; + } + Ok(view.get_index(offset)) + } + /// Safely reads bytes from the memory at the given offset. /// /// This method is similar to `read` but allows reading into an @@ -142,6 +156,7 @@ impl<'a> MemoryView<'a> .map_err(|_| MemoryAccessError::Overflow)?; let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; if end > view.length() { + #[cfg(feature = "tracing")] warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", len, end, view.length()); Err(MemoryAccessError::HeapOutOfBounds)?; } @@ -177,10 +192,31 @@ impl<'a> MemoryView<'a> let view = &self.view; let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; if end > view.length() { + #[cfg(feature = "tracing")] warn!("attempted to write ({} bytes) beyond the bounds of the memory view ({} > {})", len, end, view.length()); Err(MemoryAccessError::HeapOutOfBounds)?; } view.subarray(offset, end).copy_from(data); Ok(()) } + + /// Safely reads a single byte from memory at the given offset + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn write_u8( + &self, + offset: u64, + val: u8 + ) -> Result<(), MemoryAccessError> { + let view = &self.view; + let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; + if offset >= view.length() { + #[cfg(feature = "tracing")] + warn!("attempted to write beyond the bounds of the memory view ({} >= {})", offset, view.length()); + Err(MemoryAccessError::HeapOutOfBounds)?; + } + view.set_index(offset, val); + Ok(()) + } } diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 7ed86e8d851..f01a5dafdf7 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -8,6 +8,7 @@ use std::marker::PhantomData; use std::mem; use std::mem::MaybeUninit; use std::slice; +#[cfg(feature = "tracing")] use tracing::warn; use wasmer_types::Pages; use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, StoreObjects, VMExtern, VMMemory}; @@ -177,6 +178,7 @@ impl<'a> MemoryBuffer<'a> { .checked_add(buf.len() as u64) .ok_or(MemoryAccessError::Overflow)?; if end > self.len.try_into().unwrap() { + #[cfg(feature = "tracing")] warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, self.len); return Err(MemoryAccessError::HeapOutOfBounds); } @@ -195,6 +197,7 @@ impl<'a> MemoryBuffer<'a> { .checked_add(buf.len() as u64) .ok_or(MemoryAccessError::Overflow)?; if end > self.len.try_into().unwrap() { + #[cfg(feature = "tracing")] warn!("attempted to read ({} bytes) beyond the bounds of the memory view ({} > {})", buf.len(), end, self.len); return Err(MemoryAccessError::HeapOutOfBounds); } @@ -211,6 +214,7 @@ impl<'a> MemoryBuffer<'a> { .checked_add(data.len() as u64) .ok_or(MemoryAccessError::Overflow)?; if end > self.len.try_into().unwrap() { + #[cfg(feature = "tracing")] warn!("attempted to write ({} bytes) beyond the bounds of the memory view ({} > {})", data.len(), end, self.len); return Err(MemoryAccessError::HeapOutOfBounds); } diff --git a/lib/api/src/sys/externals/memory_view.rs b/lib/api/src/sys/externals/memory_view.rs index 5e1eb247703..dcbfad6dcd5 100644 --- a/lib/api/src/sys/externals/memory_view.rs +++ b/lib/api/src/sys/externals/memory_view.rs @@ -115,6 +115,19 @@ impl<'a> MemoryView<'a> self.buffer.read(offset, buf) } + /// Safely reads a single byte from memory at the given offset + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn read_u8( + &self, + offset: u64 + ) -> Result { + let mut buf = [0u8; 1]; + self.read(offset, &mut buf)?; + Ok(buf[0]) + } + /// Safely reads bytes from the memory at the given offset. /// /// This method is similar to `read` but allows reading into an @@ -147,4 +160,18 @@ impl<'a> MemoryView<'a> ) -> Result<(), MemoryAccessError> { self.buffer.write(offset, data) } + + /// Safely reads a single byte from memory at the given offset + /// + /// This method is guaranteed to be safe (from the host side) in the face of + /// concurrent writes. + pub fn write_u8( + &self, + offset: u64, + val: u8 + ) -> Result<(), MemoryAccessError> { + let buf = [ val ]; + self.write(offset, &buf)?; + Ok(()) + } } diff --git a/lib/api/tests/js_externals.rs b/lib/api/tests/js_externals.rs index 41dacdabda1..4f8401232f3 100644 --- a/lib/api/tests/js_externals.rs +++ b/lib/api/tests/js_externals.rs @@ -6,7 +6,6 @@ mod js { #[wasm_bindgen_test] fn global_new() { let mut store = Store::default(); - let _env = FunctionEnv::new(&mut store, ()); let global = Global::new(&mut store, Value::I32(10)); assert_eq!( global.ty(&store), @@ -29,7 +28,6 @@ mod js { #[wasm_bindgen_test] fn global_get() { let mut store = Store::default(); - let _env = FunctionEnv::new(&mut store, ()); let global_i32 = Global::new(&mut store, Value::I32(10)); assert_eq!(global_i32.get(&store), Value::I32(10)); // 64-bit values are not yet fully supported in some versions of Node @@ -46,7 +44,6 @@ mod js { #[wasm_bindgen_test] fn global_set() { let mut store = Store::default(); - let _env = FunctionEnv::new(&mut store, ()); let global_i32 = Global::new(&mut store, Value::I32(10)); // Set on a constant should error assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); @@ -144,7 +141,6 @@ mod js { #[wasm_bindgen_test] fn memory_new() { let mut store = Store::default(); - let _env = FunctionEnv::new(&mut store, ()); let memory_type = MemoryType { shared: false, minimum: Pages(0), @@ -158,7 +154,6 @@ mod js { #[wasm_bindgen_test] fn memory_grow() { let mut store = Store::default(); - let _env = FunctionEnv::new(&mut store, ()); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); let memory = Memory::new(&mut store, desc).unwrap(); @@ -444,7 +439,6 @@ mod js { #[wasm_bindgen_test] fn function_outlives_instance() { let mut store = Store::default(); - let _env = FunctionEnv::new(&mut store, ()); let wat = r#"(module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs index 6a1912037b6..18e185dfca3 100644 --- a/lib/api/tests/js_instance.rs +++ b/lib/api/tests/js_instance.rs @@ -41,7 +41,6 @@ mod js { .unwrap(); let import_object = imports! {}; - let _env = FunctionEnv::new(&mut store, ()); let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("mem").unwrap(); @@ -81,7 +80,6 @@ mod js { .unwrap(); let import_object = imports! {}; - let _env = FunctionEnv::new(&mut store, ()); let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let get_magic = instance.exports.get_function("get_magic").unwrap(); @@ -403,7 +401,7 @@ mod js { fn imported_fn(env: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.view(&env).uint8view().get_index(0); + let memory_val = memory.view(&env).read_u8(0).unwrap(); return (memory_val as u32) * env.data().multiplier * arg; } @@ -425,11 +423,11 @@ mod js { let memory = instance.exports.get_memory("memory").unwrap(); assert_eq!(memory.view(&store).data_size(), 65536); - let memory_val = memory.view(&store).uint8view() .get_index(0); + let memory_val = memory.view(&store).read_u8(0).unwrap(); assert_eq!(memory_val, 0); - memory.view(&store).uint8view().set_index(0, 2); - let memory_val = memory.view(&store).uint8view().get_index(0); + memory.view(&store).write_u8(0, 2).unwrap(); + let memory_val = memory.view(&store).read_u8(0).unwrap(); assert_eq!(memory_val, 2); env.as_mut(&mut store).memory = Some(memory.clone()); @@ -441,7 +439,7 @@ mod js { assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.view(&store).uint8view().set_index(0, 3); + memory.view(&store).write_u8(0, 3).unwrap(); let expected = vec![Val::I32(36)].into_boxed_slice(); assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } @@ -511,7 +509,7 @@ mod js { args: &[Val], ) -> Result, RuntimeError> { let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.view(&env).uint8view().get_index(0); + let memory_val = memory.view(&env).read_u8(0).unwrap(); let value = (memory_val as u32) * env.data().multiplier * args[0].unwrap_i32() as u32; return Ok(vec![Val::I32(value as _)]); } @@ -536,11 +534,11 @@ mod js { let memory = instance.exports.get_memory("memory").unwrap(); assert_eq!(memory.view(&store).data_size(), 65536); - let memory_val = memory.view(&store).uint8view().get_index(0); + let memory_val = memory.view(&store).read_u8(0).unwrap(); assert_eq!(memory_val, 0); - memory.view(&store).uint8view().set_index(0, 2); - let memory_val = memory.view(&store).uint8view().get_index(0); + memory.view(&store).write_u8(0, 2).unwrap(); + let memory_val = memory.view(&store).read_u8(0).unwrap(); assert_eq!(memory_val, 2); env.as_mut(&mut store).memory = Some(memory.clone()); @@ -552,7 +550,7 @@ mod js { assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.view(&store).uint8view().set_index(0, 3); + memory.view(&store).write_u8(0, 3).unwrap(); let expected = vec![Val::I32(36)].into_boxed_slice(); assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } @@ -585,7 +583,6 @@ mod js { ], }) .unwrap(); - let _env = FunctionEnv::new(&mut store, ()); let global = Global::new_mut(&mut store, Value::I32(0)); let import_object = imports! { "" => { @@ -802,7 +799,6 @@ mod js { .unwrap(); let import_object = imports! {}; - let _env = FunctionEnv::new(&mut store, ()); let result = Instance::new(&mut store, &module, &import_object); let err = result.unwrap_err(); assert!(format!("{:?}", err).contains("zero"))