diff --git a/hbvm/src/vm/mem/mod.rs b/hbvm/src/vm/mem/mod.rs index a10490d..bad822e 100644 --- a/hbvm/src/vm/mem/mod.rs +++ b/hbvm/src/vm/mem/mod.rs @@ -64,8 +64,25 @@ impl Memory { } let mut value = MaybeUninit::::zeroed(); + let overflow = (lookup.offset + S::BYTES).saturating_sub(lookup.size - 1); + let normal = S::BYTES - overflow; + unsafe { - core::ptr::copy_nonoverlapping::(lookup.ptr, value.as_mut_ptr().cast(), 1); + core::ptr::copy_nonoverlapping::(lookup.ptr, value.as_mut_ptr().cast(), normal); + if overflow != 0 { + let lookup = self.page_lookup(lookup.ptr as u64 + lookup.size as u64)?; + match lookup.perm { + Permission::Empty | Permission::Node => return None, + Permission::Readonly | Permission::Write | Permission::Exec => (), + } + + core::ptr::copy_nonoverlapping::( + lookup.ptr, + value.as_mut_ptr().cast::().add(normal), + overflow, + ); + } + Some(value.assume_init()) } } @@ -76,9 +93,27 @@ impl Memory { if lookup.perm != Permission::Write { return Err(()); } - + + let overflow = (lookup.offset + S::BYTES).saturating_sub(lookup.size - 1); + let normal = S::BYTES - overflow; unsafe { - core::ptr::copy_nonoverlapping::((&value as *const Value).cast(), lookup.ptr, 1) + core::ptr::copy_nonoverlapping::( + (&value as *const Value).cast(), + lookup.ptr, + normal, + ); + + if overflow != 0 { + let lookup = self + .page_lookup(lookup.ptr as u64 + lookup.size as u64) + .ok_or(())?; + + core::ptr::copy_nonoverlapping::( + (&value as *const Value).cast::().add(normal), + lookup.ptr, + overflow, + ); + } }; Ok(())