memory.rs (3204B)
1 use anyhow::Result; 2 use wasmer::{Array, Memory, WasmPtr}; 3 4 use crate::error::RuntimeError; 5 6 pub trait MemoryManipulation { 7 fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()>; 8 fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]>; 9 } 10 11 impl MemoryManipulation for Memory { 12 fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()> { 13 // Prepare WasmPtr 14 let target_ptr: WasmPtr<u8, Array> = WasmPtr::new(mem_offset); 15 16 // Allocate necessary memory space on guest 17 let guest_value_slice = match target_ptr.deref(self, 0, value_slice.len() as u32) { 18 Some(slice) => slice, 19 None => [].to_vec(), 20 }; 21 22 if guest_value_slice.is_empty() { 23 return Err(RuntimeError::OutOfMemory.into()) 24 } 25 26 // Copy bytes to guest 27 for i in 0..value_slice.len() { 28 guest_value_slice[i].set(value_slice[i]); 29 } 30 31 Ok(()) 32 } 33 34 fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]> { 35 let memory_size = self.size().bytes().0; 36 37 if mem_offset as usize + value_len > memory_size || mem_offset as usize >= memory_size { 38 return None 39 } 40 41 let ptr = unsafe { self.view::<u8>().as_ptr().add(mem_offset as usize) as *const u8 }; 42 unsafe { Some(std::slice::from_raw_parts(ptr, value_len)) } 43 } 44 } 45 46 #[cfg(test)] 47 mod tests { 48 use super::*; 49 use wasmer::{imports, wat2wasm, Instance, Module, Store}; 50 51 fn wasmer_instance() -> Instance { 52 let wasm_bytes = wat2wasm( 53 br#" 54 (module 55 (type $add_one_t (func (param i32) (result i32))) 56 (func $add_one_f (type $add_one_t) (param $value i32) (result i32) 57 local.get $value 58 i32.const 1 59 i32.add) 60 (export "add_one" (func $add_one_f)) 61 (memory $memory (export "memory") 17)) 62 "#, 63 ) 64 .unwrap(); 65 66 let store = Store::default(); 67 let module = Module::new(&store, wasm_bytes).unwrap(); 68 69 let import_object = imports! {}; 70 Instance::new(&module, &import_object).unwrap() 71 } 72 73 #[test] 74 fn can_write_on_memory() { 75 let wasmer_instance = wasmer_instance(); 76 77 let memory = wasmer_instance.exports.get_memory("memory").unwrap(); 78 let data = String::from("data_test"); 79 80 let mem_addr = 0x2220; 81 82 memory.write(mem_addr as u32, data.as_bytes()).unwrap(); 83 84 let ptr = unsafe { memory.view::<u8>().as_ptr().add(mem_addr as usize) as *const u8 }; 85 let slice_raw = unsafe { std::slice::from_raw_parts(ptr, data.len()) }; 86 87 assert_eq!(data.as_bytes(), slice_raw); 88 } 89 90 #[test] 91 fn can_read_from_memory() { 92 let wasmer_instance = wasmer_instance(); 93 94 let memory = wasmer_instance.exports.get_memory("memory").unwrap(); 95 let data = String::from("data_test"); 96 97 let mem_addr = 0x2220; 98 99 memory.write(mem_addr as u32, data.as_bytes()).unwrap(); 100 101 let slice_raw = memory.read(mem_addr as u32, data.as_bytes().len()).unwrap(); 102 103 assert_eq!(data.as_bytes(), slice_raw); 104 } 105 }