Skip to content

Commit 4c86400

Browse files
stogarucarolynzech
andauthored
Contract and Harnesses for <*const T>::offset_from (#154)
Towards #76 ### Changes * Adds contracts for `<*const T>::offset_from`. * Adds harnesses for the function verifying: * All integer types * Tuples (composite types) * Unit Type * Accomplishes this using a macro. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: Carolyn Zech <[email protected]>
1 parent e2db435 commit 4c86400

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

library/core/src/ptr/const_ptr.rs

+160
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ use crate::cmp::Ordering::{Equal, Greater, Less};
33
use crate::intrinsics::const_eval_select;
44
use crate::mem::SizedTypeProperties;
55
use crate::slice::{self, SliceIndex};
6+
use safety::{ensures, requires};
7+
8+
#[cfg(kani)]
9+
use crate::kani;
610

711
impl<T: ?Sized> *const T {
812
/// Returns `true` if the pointer is null.
@@ -667,6 +671,16 @@ impl<T: ?Sized> *const T {
667671
#[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")]
668672
#[inline]
669673
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
674+
#[requires(
675+
// Ensures subtracting `origin` from `self` doesn't overflow
676+
(self as isize).checked_sub(origin as isize).is_some() &&
677+
// Ensure the distance between `self` and `origin` is aligned to `T`
678+
(self as isize - origin as isize) % (mem::size_of::<T>() as isize) == 0 &&
679+
// Ensure both pointers are in the same allocation or are pointing to the same address
680+
(self as isize == origin as isize || kani::mem::same_allocation(self, origin))
681+
)]
682+
// The result should equal the distance in terms of elements of type `T` as per the documentation above
683+
#[ensures(|result| *result == (self as isize - origin as isize) / (mem::size_of::<T>() as isize))]
670684
pub const unsafe fn offset_from(self, origin: *const T) -> isize
671685
where
672686
T: Sized,
@@ -1899,3 +1913,149 @@ impl<T: ?Sized> PartialOrd for *const T {
18991913
*self >= *other
19001914
}
19011915
}
1916+
1917+
#[cfg(kani)]
1918+
#[unstable(feature = "kani", issue = "none")]
1919+
mod verify {
1920+
use crate::kani;
1921+
use core::mem;
1922+
use kani::PointerGenerator;
1923+
1924+
// Proof for unit size will panic as offset_from needs the pointee size to be greater then 0
1925+
#[kani::proof_for_contract(<*const ()>::offset_from)]
1926+
#[kani::should_panic]
1927+
pub fn check_const_offset_from_unit() {
1928+
let val: () = ();
1929+
let src_ptr: *const () = &val;
1930+
let dest_ptr: *const () = &val;
1931+
unsafe {
1932+
dest_ptr.offset_from(src_ptr);
1933+
}
1934+
}
1935+
1936+
// Array size bound for kani::any_array
1937+
const ARRAY_LEN: usize = 40;
1938+
1939+
macro_rules! generate_offset_from_harness {
1940+
($type: ty, $proof_name1: ident, $proof_name2: ident) => {
1941+
// Proof for a single element
1942+
#[kani::proof_for_contract(<*const $type>::offset_from)]
1943+
pub fn $proof_name1() {
1944+
const gen_size: usize = mem::size_of::<$type>();
1945+
let mut generator1 = PointerGenerator::<gen_size>::new();
1946+
let mut generator2 = PointerGenerator::<gen_size>::new();
1947+
let ptr1: *const $type = generator1.any_in_bounds().ptr;
1948+
let ptr2: *const $type = if kani::any() {
1949+
generator1.any_alloc_status().ptr
1950+
} else {
1951+
generator2.any_alloc_status().ptr
1952+
};
1953+
1954+
unsafe {
1955+
ptr1.offset_from(ptr2);
1956+
}
1957+
}
1958+
1959+
// Proof for large arrays
1960+
#[kani::proof_for_contract(<*const $type>::offset_from)]
1961+
pub fn $proof_name2() {
1962+
const gen_size: usize = mem::size_of::<$type>();
1963+
let mut generator1 = PointerGenerator::<{ gen_size * ARRAY_LEN }>::new();
1964+
let mut generator2 = PointerGenerator::<{ gen_size * ARRAY_LEN }>::new();
1965+
let ptr1: *const $type = generator1.any_in_bounds().ptr;
1966+
let ptr2: *const $type = if kani::any() {
1967+
generator1.any_alloc_status().ptr
1968+
} else {
1969+
generator2.any_alloc_status().ptr
1970+
};
1971+
1972+
unsafe {
1973+
ptr1.offset_from(ptr2);
1974+
}
1975+
}
1976+
};
1977+
}
1978+
1979+
generate_offset_from_harness!(
1980+
u8,
1981+
check_const_offset_from_u8,
1982+
check_const_offset_from_u8_arr
1983+
);
1984+
generate_offset_from_harness!(
1985+
u16,
1986+
check_const_offset_from_u16,
1987+
check_const_offset_from_u16_arr
1988+
);
1989+
generate_offset_from_harness!(
1990+
u32,
1991+
check_const_offset_from_u32,
1992+
check_const_offset_from_u32_arr
1993+
);
1994+
generate_offset_from_harness!(
1995+
u64,
1996+
check_const_offset_from_u64,
1997+
check_const_offset_from_u64_arr
1998+
);
1999+
generate_offset_from_harness!(
2000+
u128,
2001+
check_const_offset_from_u128,
2002+
check_const_offset_from_u128_arr
2003+
);
2004+
generate_offset_from_harness!(
2005+
usize,
2006+
check_const_offset_from_usize,
2007+
check_const_offset_from_usize_arr
2008+
);
2009+
2010+
generate_offset_from_harness!(
2011+
i8,
2012+
check_const_offset_from_i8,
2013+
check_const_offset_from_i8_arr
2014+
);
2015+
generate_offset_from_harness!(
2016+
i16,
2017+
check_const_offset_from_i16,
2018+
check_const_offset_from_i16_arr
2019+
);
2020+
generate_offset_from_harness!(
2021+
i32,
2022+
check_const_offset_from_i32,
2023+
check_const_offset_from_i32_arr
2024+
);
2025+
generate_offset_from_harness!(
2026+
i64,
2027+
check_const_offset_from_i64,
2028+
check_const_offset_from_i64_arr
2029+
);
2030+
generate_offset_from_harness!(
2031+
i128,
2032+
check_const_offset_from_i128,
2033+
check_const_offset_from_i128_arr
2034+
);
2035+
generate_offset_from_harness!(
2036+
isize,
2037+
check_const_offset_from_isize,
2038+
check_const_offset_from_isize_arr
2039+
);
2040+
2041+
generate_offset_from_harness!(
2042+
(i8, i8),
2043+
check_const_offset_from_tuple_1,
2044+
check_const_offset_from_tuple_1_arr
2045+
);
2046+
generate_offset_from_harness!(
2047+
(f64, bool),
2048+
check_const_offset_from_tuple_2,
2049+
check_const_offset_from_tuple_2_arr
2050+
);
2051+
generate_offset_from_harness!(
2052+
(u32, i16, f32),
2053+
check_const_offset_from_tuple_3,
2054+
check_const_offset_from_tuple_3_arr
2055+
);
2056+
generate_offset_from_harness!(
2057+
((), bool, u8, u16, i32, f64, i128, usize),
2058+
check_const_offset_from_tuple_4,
2059+
check_const_offset_from_tuple_4_arr
2060+
);
2061+
}

0 commit comments

Comments
 (0)