wasm-runtime

A wasm runtime
git clone https://git.parazyd.org/wasm-runtime
Log | Files | Refs | README | LICENSE

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 }