Skip to content

Instantly share code, notes, and snippets.

@thomcc
Created July 5, 2023 21:16
Show Gist options
  • Save thomcc/b2730e3b1a56c4d8cdebf29814ea2351 to your computer and use it in GitHub Desktop.
Save thomcc/b2730e3b1a56c4d8cdebf29814ea2351 to your computer and use it in GitHub Desktop.
impl RawArray {
/// Returns if the pointer is within our bounds.
///
/// If you intend to read a number of bytes, optionally you may providing a
/// size for the read. That said, if you provide a non-zero size, then `p`
/// needs to be strictly in-bounds -- it may not be the one-past-the-end
/// pointer when `size` is non-zero.
///
/// Similar to computing `start_ptr <= P && P <= end_ptr` where `P` is both
/// `p` and `p.wrapping_add(size)`, but handles all the weird edge cases
/// correctly (in particular address aritmetic leading to wraparound).
///
/// This is usally overkill, so it should probably only be used in asserts,
/// error checking, etc (ideally just asserts). Returning true does *not*
/// mean the read is legal (provenance may be invalid).
#[inline]
pub(crate) fn is_in_bounds(&self, p: *const u8, size: usize) -> bool {
if size >= isize::MAX as usize {
return false;
}
let base = self.ptr.as_ptr().cast::<u8>();
let mem_size = unsafe { crate::varlena::varsize_any(base.cast()) };
if size > mem_size {
return false;
}
let Ok(start_offset) = usize::try_from(ptr_diff_bytes(p, base)) else {
return false;
};
if start_offset > mem_size {
return false;
}
if size == 0 {
return true;
}
let Ok(end_offset) = usize::try_from(ptr_diff_bytes(p.wrapping_add(size), base)) else {
return false;
}
end_offset <= mem_size && start_offset <= end_offset
}
}
#[inline]
fn wrapping_byte_offset_from(ptr: *const u8, base: *const u8) -> isize {
(ptr as usize).wrapping_sub(base as usize) as isize
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment