diff options
Diffstat (limited to 'scripts/src/libs/buffer.rs')
| -rw-r--r-- | scripts/src/libs/buffer.rs | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/scripts/src/libs/buffer.rs b/scripts/src/libs/buffer.rs new file mode 100644 index 0000000..b4cee77 --- /dev/null +++ b/scripts/src/libs/buffer.rs @@ -0,0 +1,182 @@ +use wasmtime::Caller; + +use crate::{ScriptManager, WasmScriptState}; + +use super::{system::_get_memory, LIBRARY_NAME}; + +fn memory_search(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 { + let (_, mem_ptr) = _get_memory(&mut caller); + let len = len as usize; + let ptr = ptr as usize; + let ch = ch as u8; + if (len + ptr) > mem_ptr.len() { + return 4; + } + + for i in 0..len { + if mem_ptr[ptr + i] == ch { + return (ptr + i) as u32; + } + } + + 0 +} + +fn memory_search_last(mut caller: Caller<'_, WasmScriptState>, ptr: u32, ch: u32, len: u32) -> u32 { + let (_, mem_ptr) = _get_memory(&mut caller); + let len = len as usize; + let ptr = ptr as usize; + let ch = ch as u8; + if (len + ptr) > mem_ptr.len() { + return 4; + } + + for i in 0..len { + let index = ptr + len - i - 1; + if mem_ptr[index] == ch { + return index as u32; + } + } + + 0 +} + +fn memory_compare( + mut caller: Caller<'_, WasmScriptState>, + lhs: u32, + rhs: u32, + len: u32, +) -> (u32, u32) { + let (_, mem_ptr) = _get_memory(&mut caller); + let len = len as usize; + let lhs = lhs as usize; + let rhs = rhs as usize; + if (len + lhs) > mem_ptr.len() || (len + rhs) > mem_ptr.len() { + return (4, 0); + } + + for i in 0..len { + let diff = mem_ptr[lhs + i] - mem_ptr[rhs + i]; + if diff != 0 { + return (0, diff as u32); + } + } + + (0, 0) +} + +fn memory_fill(mut caller: Caller<'_, WasmScriptState>, dest: u32, ch: u32, len: u32) -> u32 { + let (_, mem_ptr) = _get_memory(&mut caller); + let len = len as usize; + let dest = dest as usize; + let ch = ch as u8; + + if (len + dest) > mem_ptr.len() { + return 4; + } + + for i in 0..len { + mem_ptr[dest + i] = ch; + } + + 0 +} + +fn memory_copy(mut caller: Caller<'_, WasmScriptState>, dest: u32, src: u32, len: u32) -> u32 { + let (_, mem_ptr) = _get_memory(&mut caller); + let len = len as usize; + let dest = dest as usize; + let src = src as usize; + if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() { + return 4; + } + + // check for overlap + if (dest < src && dest + len > src) || (src < dest && src + len > dest) { + let src = mem_ptr[src..src + len].to_vec(); + let dest = &mut mem_ptr[dest..dest + len]; + dest.clone_from_slice(&src); + } else { + for i in 0..len { + mem_ptr[dest + i] = mem_ptr[src + i]; + } + } + + 0 +} + +fn memory_copy_until( + mut caller: Caller<'_, WasmScriptState>, + dest: u32, + src: u32, + len: u32, + delimiter: u32, +) -> u32 { + let (_, mem_ptr) = _get_memory(&mut caller); + let len = len as usize; + let dest = dest as usize; + let src = src as usize; + let delimiter = delimiter as u8; + if (len + dest) > mem_ptr.len() || (len + src) > mem_ptr.len() { + return 4; + } + + // check for overlap + if (dest < src && dest + len > src) || (src < dest && src + len > dest) { + let cloned_src = mem_ptr[src..src + len].to_vec(); + let dest = &mut mem_ptr[dest..dest + len]; + for i in 0..len { + let ch = cloned_src[i]; + dest[i] = ch; + if ch == delimiter { + return (src + i + 1) as u32; + } + } + } else { + for i in 0..len { + let ch = mem_ptr[src + i]; + mem_ptr[dest + i] = ch; + if ch == delimiter { + return (src + i + 1) as u32; + } + } + } + + 0 +} + +fn memory_concatenate( + mut caller: Caller<'_, WasmScriptState>, + dest: u32, + src: u32, + dest_len: u32, + src_len: u32, +) -> u32 { + let (_, mem_ptr) = _get_memory(&mut caller); + let dest = dest as usize; + let src = src as usize; + let dest_len = dest_len as usize; + let src_len = src_len as usize; + if (dest_len + src_len + dest) > mem_ptr.len() || (src_len + src) > mem_ptr.len() { + return 4; + } + + let src = mem_ptr[src..src + src_len].to_vec(); + let dest_offset = dest + dest_len; + let dest = &mut mem_ptr[dest_offset..dest_offset + src_len]; + dest.clone_from_slice(&src); + + 0 +} + +pub fn library(manager: &mut ScriptManager) -> Option<()> { + manager.add_library_function(LIBRARY_NAME, "memchr", memory_search)?; + manager.add_library_function(LIBRARY_NAME, "memrchr", memory_search_last)?; + manager.add_library_function(LIBRARY_NAME, "memcmp", memory_compare)?; + manager.add_library_function(LIBRARY_NAME, "memset", memory_fill)?; + manager.add_library_function(LIBRARY_NAME, "memcpy", memory_copy)?; + manager.add_library_function(LIBRARY_NAME, "memccpy", memory_copy_until)?; + manager.add_library_function(LIBRARY_NAME, "memcat", memory_concatenate)?; + + Some(()) +} |
