tmemory.rs - wasm-runtime - A wasm runtime
HTML git clone https://git.parazyd.org/wasm-runtime
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tmemory.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 }