Skip to content

Commit b6552b8

Browse files
authoredDec 10, 2024··
Harnesses verifying slice types for add, sub and offset (#179)
Towards #76 ## Changes ### Contracts Added: - Added contracts for <*mut T>::add, <*mut T>::sub, and <*mut T>::offset operations for raw pointers to slices. ### Proofs Implemented: - Added proofs for the above contracts, verifying safety for the following slice pointee types using arrays: - All integer types (i8, i16, i32, etc.). - Tuples (composite types) (e.g., (i8, i8), (i32, f64, bool)). - Unit type (()). ### Macro Definitions: - Introduced macros to simplify and automate harness generation: - One macro for add and sub operations on slices. - Another macro for offset operations on slices. ### Array-Based Implementation for Slice Verification: - Arrays are used as a proxy for slices (as slices do not have a known length at compile time) to enable proper bounds checking and assumptions during verification.
1 parent 82893c5 commit b6552b8

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed
 

‎library/core/src/ptr/mut_ptr.rs

+76
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,82 @@ impl<T: ?Sized> PartialOrd for *mut T {
22422242
mod verify {
22432243
use crate::kani;
22442244
use core::mem;
2245+
2246+
// Chosen for simplicity and sufficient size to test edge cases effectively
2247+
// Represents the number of elements in the slice or array being tested.
2248+
// Doesn't need to be large because all possible values for the slice are explored,
2249+
// including edge cases like pointers at the start, middle, and end of the slice.
2250+
// Symbolic execution generalizes across all possible elements, regardless of the actual array size.
2251+
const ARRAY_SIZE: usize = 5;
2252+
2253+
/// This macro generates verification harnesses for the `offset`, `add`, and `sub`
2254+
/// pointer operations for a slice type and function name.
2255+
macro_rules! generate_mut_slice_harnesses {
2256+
($ty:ty, $offset_fn:ident, $add_fn:ident, $sub_fn:ident) => {
2257+
// Generates a harness for the `offset` operation
2258+
#[kani::proof_for_contract(<*mut $ty>::offset)]
2259+
fn $offset_fn() {
2260+
let mut arr: [$ty; ARRAY_SIZE] = kani::Arbitrary::any_array();
2261+
let test_ptr: *mut $ty = arr.as_mut_ptr();
2262+
let offset: usize = kani::any();
2263+
let count: isize = kani::any();
2264+
kani::assume(offset <= ARRAY_SIZE * mem::size_of::<$ty>());
2265+
let ptr_with_offset: *mut $ty = test_ptr.wrapping_byte_add(offset);
2266+
unsafe {
2267+
ptr_with_offset.offset(count);
2268+
}
2269+
}
2270+
2271+
// Generates a harness for the `add` operation
2272+
#[kani::proof_for_contract(<*mut $ty>::add)]
2273+
fn $add_fn() {
2274+
let mut arr: [$ty; ARRAY_SIZE] = kani::Arbitrary::any_array();
2275+
let test_ptr: *mut $ty = arr.as_mut_ptr();
2276+
let offset: usize = kani::any();
2277+
let count: usize = kani::any();
2278+
kani::assume(offset <= ARRAY_SIZE * mem::size_of::<$ty>());
2279+
let ptr_with_offset: *mut $ty = test_ptr.wrapping_byte_add(offset);
2280+
unsafe {
2281+
ptr_with_offset.add(count);
2282+
}
2283+
}
2284+
2285+
// Generates a harness for the `sub` operation
2286+
#[kani::proof_for_contract(<*mut $ty>::sub)]
2287+
fn $sub_fn() {
2288+
let mut arr: [$ty; ARRAY_SIZE] = kani::Arbitrary::any_array();
2289+
let test_ptr: *mut $ty = arr.as_mut_ptr();
2290+
let offset: usize = kani::any();
2291+
let count: usize = kani::any();
2292+
kani::assume(offset <= ARRAY_SIZE * mem::size_of::<$ty>());
2293+
let ptr_with_offset: *mut $ty = test_ptr.wrapping_byte_add(offset);
2294+
unsafe {
2295+
ptr_with_offset.sub(count);
2296+
}
2297+
}
2298+
};
2299+
}
2300+
2301+
// Generate pointer harnesses for various types (offset, add, sub)
2302+
generate_mut_slice_harnesses!(i8, check_mut_offset_slice_i8, check_mut_add_slice_i8, check_mut_sub_slice_i8);
2303+
generate_mut_slice_harnesses!(i16, check_mut_offset_slice_i16, check_mut_add_slice_i16, check_mut_sub_slice_i16);
2304+
generate_mut_slice_harnesses!(i32, check_mut_offset_slice_i32, check_mut_add_slice_i32, check_mut_sub_slice_i32);
2305+
generate_mut_slice_harnesses!(i64, check_mut_offset_slice_i64, check_mut_add_slice_i64, check_mut_sub_slice_i64);
2306+
generate_mut_slice_harnesses!(i128, check_mut_offset_slice_i128, check_mut_add_slice_i128, check_mut_sub_slice_i128);
2307+
generate_mut_slice_harnesses!(isize, check_mut_offset_slice_isize, check_mut_add_slice_isize, check_mut_sub_slice_isize);
2308+
generate_mut_slice_harnesses!(u8, check_mut_offset_slice_u8, check_mut_add_slice_u8, check_mut_sub_slice_u8);
2309+
generate_mut_slice_harnesses!(u16, check_mut_offset_slice_u16, check_mut_add_slice_u16, check_mut_sub_slice_u16);
2310+
generate_mut_slice_harnesses!(u32, check_mut_offset_slice_u32, check_mut_add_slice_u32, check_mut_sub_slice_u32);
2311+
generate_mut_slice_harnesses!(u64, check_mut_offset_slice_u64, check_mut_add_slice_u64, check_mut_sub_slice_u64);
2312+
generate_mut_slice_harnesses!(u128, check_mut_offset_slice_u128, check_mut_add_slice_u128, check_mut_sub_slice_u128);
2313+
generate_mut_slice_harnesses!(usize, check_mut_offset_slice_usize, check_mut_add_slice_usize, check_mut_sub_slice_usize);
2314+
2315+
// Generate pointer harnesses for tuples (offset, add, sub)
2316+
generate_mut_slice_harnesses!((i8, i8), check_mut_offset_slice_tuple_1, check_mut_add_slice_tuple_1, check_mut_sub_slice_tuple_1);
2317+
generate_mut_slice_harnesses!((f64, bool), check_mut_offset_slice_tuple_2, check_mut_add_slice_tuple_2, check_mut_sub_slice_tuple_2);
2318+
generate_mut_slice_harnesses!((i32, f64, bool), check_mut_offset_slice_tuple_3, check_mut_add_slice_tuple_3, check_mut_sub_slice_tuple_3);
2319+
generate_mut_slice_harnesses!((i8, u16, i32, u64, isize), check_mut_offset_slice_tuple_4, check_mut_add_slice_tuple_4, check_mut_sub_slice_tuple_4);
2320+
22452321
use kani::PointerGenerator;
22462322

22472323
/// This macro generates a single verification harness for the `offset`, `add`, or `sub`

0 commit comments

Comments
 (0)
Please sign in to comment.