Skip to content

Commit 0a2913f

Browse files
contract and harness for byte_sub and offset
1 parent 0bb80ab commit 0a2913f

File tree

2 files changed

+39
-37
lines changed

2 files changed

+39
-37
lines changed

library/core/src/num/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
use crate::str::FromStr;
66
use crate::ub_checks::assert_unsafe_precondition;
77
use crate::{ascii, intrinsics, mem};
8-
use safety::requires;
8+
/*use safety::requires;
99
1010
#[cfg(kani)]
1111
use crate::kani;
12-
12+
*/
1313
// Used because the `?` operator is not allowed in a const context.
1414
macro_rules! try_opt {
1515
($e:expr) => {
@@ -1585,7 +1585,6 @@ from_str_radix_size_impl! { i16 isize, u16 usize }
15851585
from_str_radix_size_impl! { i32 isize, u32 usize }
15861586
#[cfg(target_pointer_width = "64")]
15871587
from_str_radix_size_impl! { i64 isize, u64 usize }
1588-
15891588
#[cfg(kani)]
15901589
#[unstable(feature = "kani", issue = "none")]
15911590
mod verify {

library/core/src/ptr/non_null.rs

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::cmp::Ordering;
22
use crate::marker::Unsize;
3+
//use crate::num::NonZeroUsize;
34
use crate::mem::{MaybeUninit, SizedTypeProperties};
45
use crate::num::NonZero;
56
use crate::ops::{CoerceUnsized, DispatchFromDyn};
@@ -476,11 +477,12 @@ impl<T: ?Sized> NonNull<T> {
476477
#[must_use = "returns a new pointer rather than modifying its argument"]
477478
#[stable(feature = "non_null_convenience", since = "1.80.0")]
478479
#[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
479-
#[kani::requires(!self.as_ptr().is_null())]// Ensures that the input pointer is not null, which is a requirement for NonNull
480-
#[kani::requires(count.checked_mul(std::mem::size_of::<T>() as isize).is_some())]// Checks that multiplying count by the size of T doesn't overflow isize
481-
#[kani::ensures(|result: &NonNull<T>| !result.as_ptr().is_null())] // Guarantees that the resulting pointer is also not null
482-
#[kani::ensures(|result: &NonNull<T>| (result.as_ptr() as isize) == (self.as_ptr() as isize) + count * (std::mem::size_of::<T>() as isize))]
483-
// It checks that the resulting pointer address is equal to the original address plus the offset
480+
// Requires that the input pointer is not null
481+
#[kani::requires(!self.as_ptr().is_null())]
482+
// Requires that multiplying count by the size of T doesn't overflow isize
483+
#[kani::requires(count.checked_mul(core::mem::size_of::<T>() as isize).is_some())]
484+
//Two conditions for postconditions: 1.Resulting pointer is not null 2.Safe operation of pointer arithmetic
485+
#[kani::ensures(|result: &NonNull<T>| !result.as_ptr().is_null() && (result.as_ptr() as isize) == (self.as_ptr() as isize).wrapping_add(count.wrapping_mul(core::mem::size_of::<T>() as isize)))]
484486
pub const unsafe fn offset(self, count: isize) -> Self
485487
where
486488
T: Sized,
@@ -668,11 +670,12 @@ impl<T: ?Sized> NonNull<T> {
668670
#[rustc_allow_const_fn_unstable(set_ptr_value)]
669671
#[stable(feature = "non_null_convenience", since = "1.80.0")]
670672
#[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
671-
#[kani::requires(!self.as_ptr().is_null())] //precondition to ensures that pointer is not null
672-
#[kani::requires(count <= isize::MAX as usize)] //precondition to ensure count doesn't exceed max
673-
#[kani::ensures(|result: &NonNull<T>| !result.as_ptr().is_null())] //postcondition that result is not null
674-
#[kani::ensures(|result: &NonNull<T>| result.as_ptr() as usize == self.as_ptr() as usize - count)] //postcondition that verifies correctness of pointer arithmetic
675-
673+
//Requires that the input pointer is not null
674+
#[kani::requires(!self.as_ptr().is_null())]
675+
// Requires that count doesnt exceed Max
676+
#[kani::requires(count <= isize::MAX as usize)]
677+
//Ensures that result is not null
678+
#[kani::ensures(|result: &NonNull<T>| !result.as_ptr().is_null())]
676679
pub const unsafe fn byte_sub(self, count: usize) -> Self {
677680
// SAFETY: the caller must uphold the safety contract for `sub` and `byte_sub` has the same
678681
// safety contract.
@@ -1814,43 +1817,43 @@ mod verify {
18141817
let _ = NonNull::new(maybe_null_ptr);
18151818
}
18161819
#[kani::proof_for_contract(NonNull::byte_sub)]
1817-
pub fn non_null_byte_sub() {
1818-
// Create an array to work with
1820+
pub fn non_null_check_byte_sub() {
1821+
// Initializing array of size 10000
18191822
const ARR_SIZE: usize = 100000;
18201823
let arr: [i32; ARR_SIZE] = kani::any();
1821-
//Randomizing the start
1824+
//Randomizing start pointer within array
18221825
let offset = kani::any_where(|x| *x <= ARR_SIZE);
18231826
// Create a NonNull pointer to the end of the array
18241827
let raw_ptr: *mut i32 = unsafe { arr.as_ptr().add(offset) as *mut i32 };
18251828
let ptr = unsafe { NonNull::new(raw_ptr).unwrap() };
18261829
// Choose an arbitrary count to subtract
18271830
let count: usize = kani::any();
1828-
// Assume preconditions
1829-
kani::assume(!ptr.as_ptr().is_null());
1830-
kani::assume(count <= isize::MAX as usize);
1831-
kani::assume(count <= offset);
1832-
// Ensure that the subtraction doesnt go out of bounds of array
1833-
kani::assume(count < ARR_SIZE - offset);
1831+
// Ensure that the subtraction doesnt go out of bounds of array
1832+
kani::assume(count < ARR_SIZE - offset);
18341833
unsafe {
18351834
// Perform the byte_sub operation
18361835
let result = ptr.byte_sub(count);
18371836
}}
18381837

18391838
#[kani::proof_for_contract(NonNull::offset)]
1840-
pub fun non_null_offset(){
1841-
const ARR_SIZE: usize = 10000;
1842-
let arr: [i32; ARR_SIZE] = kani::any();
1843-
// Randomizing start pointer within array
1844-
let start_offset = kani::any_where(|x| *x < ARR_SIZE);
1845-
let ptr = unsafe { NonNull::new(arr.as_ptr().add(start_offset) as *mut i32).unwrap() };
1846-
1847-
// Choose an arbitrary count to offset
1848-
let count: isize = kani::any();
1849-
kani::assume(!ptr.as_ptr().is_null()); // NonNull guarantee
1850-
kani::assume(count.checked_mul(std::mem::size_of::<i32>() as isize).is_some()); // Prevent overflow
1851-
unsafe {
1852-
let result = ptr.offset(count);
1839+
pub fn non_null_check_offset(){
1840+
//Initializing array of size 10000
1841+
const ARR_SIZE: usize = 10000;
1842+
let arr: [i32; ARR_SIZE] = kani::any();
1843+
// Randomizing start pointer within array
1844+
let start_offset = kani::any_where(|x| *x < ARR_SIZE);
1845+
// Creating a NonNull pointer to a random position within the array
1846+
let ptr = unsafe { NonNull::new(arr.as_ptr().add(start_offset) as *mut i32).unwrap() };
1847+
// Choose an arbitrary count to offset
1848+
let count: isize = kani::any();
1849+
// Constraining the count to ensure it doesn't go out of bounds
1850+
kani::assume(
1851+
(count >= 0 && (count as usize) < ARR_SIZE - start_offset) ||
1852+
(count < 0 && count.unsigned_abs() <= start_offset)
1853+
);
1854+
unsafe {
1855+
// Perform the offset operation
1856+
let result = ptr.offset(count);
1857+
}
18531858
}
1854-
1855-
}
18561859
}

0 commit comments

Comments
 (0)