-
For the #[requires(count.checked_mul(core::mem::size_of::<T>()).is_some())] // Prevent offset overflow
#[requires(count * core::mem::size_of::<T>() <= isize::MAX as usize)] // SAFETY: count * size_of::<T>() does not overflow isize
#[requires(ub_checks::can_write(self.as_ptr().offset(count as isize)))]// Check operation is within allocated memory
#[ensures(|result: &NonNull<T>| result.as_ptr() == self.as_ptr().offset(count as isize))]
pub const unsafe fn add(self, count: usize) -> Self
where
T: Sized,
{
// SAFETY: the caller must uphold the safety contract for `offset`.
// Additionally safety contract of `offset` guarantees that the resulting pointer is
// pointing to an allocation, there can't be an allocation at null, thus it's safe to
// construct `NonNull`.
unsafe { NonNull { pointer: intrinsics::offset(self.pointer, count) } }
} The third
I have the following harness: #[kani::proof_for_contract(NonNull::add)]
pub fn non_null_check_add() {
const SIZE: usize = 100000;
// Randomiz pointer offset within array bound
let offset = kani::any_where(|x| *x < SIZE);
// Create a non-deterministic array of size SIZE
let arr: [i8; SIZE] = kani::any();
// Get a raw pointer to the array
let raw_ptr: *mut i8 = arr.as_ptr() as *mut i8;
// NonNUll pointer to the random offset
let ptr = unsafe { NonNull::new(raw_ptr.add(offset)).unwrap()};
// Create a non-deterministic count value
let count: usize = kani::any();
unsafe {
// Add a positive offset to pointer
let result = ptr.add(count);
} Am I using |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Hi @QinyuanWu. This is an issue with the order of the The workaround is to combine dependent requires clauses into a single one, e.g. if you have
where
In your case, the following
relies on this other one:
to prevent an overflow in |
Beta Was this translation helpful? Give feedback.
-
After discussion with @zhassan-aws we will hold off from using |
Beta Was this translation helpful? Give feedback.
After discussion with @zhassan-aws we will hold off from using
ub_checks::can_write
in the contract to check the pointer boundary as the kani team is working on a new API that does this job(given a pointer, check whether it is pointing to an address within the allocated memory). The current workaround is to useassume
inside the harness to constraincount
to avoid pointer out of bound.