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(()) }