Skip to content

Commit a52b65a

Browse files
MayureshJoshi25stogarucarolynzechfeliperodri
authored
Contracts and harnesses for <*mut T>::offset_from (#168)
- Added contracts for offset_from (mut type); - Accomplished using a macro which generates harnesses; - Verifies: int types, unit, tuples (composite types). Towards #76 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: stogaru <[email protected]> Co-authored-by: Carolyn Zech <[email protected]> Co-authored-by: Felipe R. Monteiro <[email protected]>
1 parent dd75225 commit a52b65a

File tree

1 file changed

+77
-130
lines changed

1 file changed

+77
-130
lines changed

library/core/src/ptr/mut_ptr.rs

+77-130
Original file line numberDiff line numberDiff line change
@@ -857,11 +857,22 @@ impl<T: ?Sized> *mut T {
857857
/// unsafe {
858858
/// let one = ptr2_other.offset_from(ptr2); // Undefined Behavior! ⚠️
859859
/// }
860+
///
861+
///
860862
/// ```
861863
#[stable(feature = "ptr_offset_from", since = "1.47.0")]
862864
#[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")]
863865
#[inline(always)]
864866
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
867+
#[requires(
868+
// Ensuring that subtracting 'origin' from 'self' doesn't result in an overflow
869+
(self as isize).checked_sub(origin as isize).is_some() &&
870+
// Ensuring that the distance between 'self' and 'origin' is aligned to `T`
871+
(self as isize - origin as isize) % (mem::size_of::<T>() as isize) == 0 &&
872+
// Ensuring that both pointers point to the same address or are in the same allocation
873+
(self as isize == origin as isize || core::ub_checks::same_allocation(self, origin))
874+
)]
875+
#[ensures(|result| *result == (self as isize - origin as isize) / (mem::size_of::<T>() as isize))]
865876
pub const unsafe fn offset_from(self, origin: *const T) -> isize
866877
where
867878
T: Sized,
@@ -2472,143 +2483,79 @@ mod verify {
24722483
gen_mut_byte_arith_harness_for_slice!(u128, byte_offset, check_mut_byte_offset_u128_slice);
24732484
gen_mut_byte_arith_harness_for_slice!(usize, byte_offset, check_mut_byte_offset_usize_slice);
24742485

2475-
/// This macro generates a single verification harness for the `offset`, `add`, or `sub`
2476-
/// pointer operations, supporting integer, composite, or unit types.
2477-
/// - `$ty`: The type of the slice's elements (e.g., `i32`, `u32`, tuples).
2478-
/// - `$fn_name`: The name of the function being checked (`add`, `sub`, or `offset`).
2479-
/// - `$proof_name`: The name assigned to the generated proof for the contract.
2480-
/// - `$count_ty:ty`: The type of the input variable passed to the method being invoked.
2481-
///
2482-
/// Note: This macro is intended for internal use only and should be invoked exclusively
2483-
/// by the `generate_arithmetic_harnesses` macro. Its purpose is to reduce code duplication,
2484-
/// and it is not meant to be used directly elsewhere in the codebase.
2485-
macro_rules! generate_single_arithmetic_harness {
2486-
($ty:ty, $proof_name:ident, $fn_name:ident, $count_ty:ty) => {
2487-
#[kani::proof_for_contract(<*mut $ty>::$fn_name)]
2488-
pub fn $proof_name() {
2489-
// 200 bytes are large enough to cover all pointee types used for testing
2490-
const BUF_SIZE: usize = 200;
2491-
let mut generator = kani::PointerGenerator::<BUF_SIZE>::new();
2492-
let test_ptr: *mut $ty = generator.any_in_bounds().ptr;
2493-
let count: $count_ty = kani::any();
2486+
// The proof for a unit type panics as offset_from needs the pointee size > 0
2487+
#[kani::proof_for_contract(<*mut ()>::offset_from)]
2488+
#[kani::should_panic]
2489+
pub fn check_mut_offset_from_unit() {
2490+
let mut val: () = ();
2491+
let src_ptr: *mut () = &mut val;
2492+
let dest_ptr: *mut () = &mut val;
2493+
unsafe {
2494+
dest_ptr.offset_from(src_ptr);
2495+
}
2496+
}
2497+
2498+
macro_rules! generate_offset_from_harness {
2499+
($type: ty, $proof_name1: ident, $proof_name2: ident) => {
2500+
#[kani::proof_for_contract(<*mut $type>::offset_from)]
2501+
// Below function is for a single element
2502+
pub fn $proof_name1() {
2503+
const gen_size: usize = mem::size_of::<$type>();
2504+
let mut generator1 = PointerGenerator::<gen_size>::new();
2505+
let mut generator2 = PointerGenerator::<gen_size>::new();
2506+
let ptr1: *mut $type = generator1.any_in_bounds().ptr;
2507+
let ptr2: *mut $type = if kani::any() {
2508+
generator1.any_alloc_status().ptr
2509+
} else {
2510+
generator2.any_alloc_status().ptr
2511+
};
2512+
24942513
unsafe {
2495-
test_ptr.$fn_name(count);
2514+
ptr1.offset_from(ptr2);
2515+
}
2516+
}
2517+
2518+
// Below function is for large arrays
2519+
pub fn $proof_name2() {
2520+
const gen_size: usize = mem::size_of::<$type>();
2521+
let mut generator1 = PointerGenerator::<{ gen_size * ARRAY_LEN }>::new();
2522+
let mut generator2 = PointerGenerator::<{ gen_size * ARRAY_LEN }>::new();
2523+
let ptr1: *mut $type = generator1.any_in_bounds().ptr;
2524+
let ptr2: *mut $type = if kani::any() {
2525+
generator1.any_alloc_status().ptr
2526+
} else {
2527+
generator2.any_alloc_status().ptr
2528+
};
2529+
2530+
unsafe {
2531+
ptr1.offset_from(ptr2);
24962532
}
24972533
}
2498-
};
2499-
}
25002534

2501-
/// This macro generates verification harnesses for the `offset`, `add`, and `sub`
2502-
/// pointer operations, supporting integer, composite, and unit types.
2503-
/// - `$ty`: The pointee type (e.g., i32, u32, tuples).
2504-
/// - `$offset_fn_name`: The name for the `offset` proof for contract.
2505-
/// - `$add_fn_name`: The name for the `add` proof for contract.
2506-
/// - `$sub_fn_name`: The name for the `sub` proof for contract.
2507-
macro_rules! generate_arithmetic_harnesses {
2508-
($ty:ty, $add_fn_name:ident, $sub_fn_name:ident, $offset_fn_name:ident) => {
2509-
generate_single_arithmetic_harness!($ty, $add_fn_name, add, usize);
2510-
generate_single_arithmetic_harness!($ty, $sub_fn_name, sub, usize);
2511-
generate_single_arithmetic_harness!($ty, $offset_fn_name, offset, isize);
25122535
};
25132536
}
25142537

2515-
// Generate harnesses for unit type (add, sub, offset)
2516-
generate_arithmetic_harnesses!(
2517-
(),
2518-
check_mut_add_unit,
2519-
check_mut_sub_unit,
2520-
check_mut_offset_unit
2521-
);
2522-
2523-
// Generate harnesses for integer types (add, sub, offset)
2524-
generate_arithmetic_harnesses!(i8, check_mut_add_i8, check_mut_sub_i8, check_mut_offset_i8);
2525-
generate_arithmetic_harnesses!(
2526-
i16,
2527-
check_mut_add_i16,
2528-
check_mut_sub_i16,
2529-
check_mut_offset_i16
2530-
);
2531-
generate_arithmetic_harnesses!(
2532-
i32,
2533-
check_mut_add_i32,
2534-
check_mut_sub_i32,
2535-
check_mut_offset_i32
2536-
);
2537-
generate_arithmetic_harnesses!(
2538-
i64,
2539-
check_mut_add_i64,
2540-
check_mut_sub_i64,
2541-
check_mut_offset_i64
2542-
);
2543-
generate_arithmetic_harnesses!(
2544-
i128,
2545-
check_mut_add_i128,
2546-
check_mut_sub_i128,
2547-
check_mut_offset_i128
2548-
);
2549-
generate_arithmetic_harnesses!(
2550-
isize,
2551-
check_mut_add_isize,
2552-
check_mut_sub_isize,
2553-
check_mut_offset_isize
2554-
);
2555-
// Due to a bug of kani the test `check_mut_add_u8` is malfunctioning for now.
2556-
// Tracking issue: https://github.com/model-checking/kani/issues/3743
2557-
// generate_arithmetic_harnesses!(u8, check_mut_add_u8, check_mut_sub_u8, check_mut_offset_u8);
2558-
generate_arithmetic_harnesses!(
2559-
u16,
2560-
check_mut_add_u16,
2561-
check_mut_sub_u16,
2562-
check_mut_offset_u16
2563-
);
2564-
generate_arithmetic_harnesses!(
2565-
u32,
2566-
check_mut_add_u32,
2567-
check_mut_sub_u32,
2568-
check_mut_offset_u32
2569-
);
2570-
generate_arithmetic_harnesses!(
2571-
u64,
2572-
check_mut_add_u64,
2573-
check_mut_sub_u64,
2574-
check_mut_offset_u64
2575-
);
2576-
generate_arithmetic_harnesses!(
2577-
u128,
2578-
check_mut_add_u128,
2579-
check_mut_sub_u128,
2580-
check_mut_offset_u128
2581-
);
2582-
generate_arithmetic_harnesses!(
2583-
usize,
2584-
check_mut_add_usize,
2585-
check_mut_sub_usize,
2586-
check_mut_offset_usize
2538+
generate_offset_from_harness!(u8, check_mut_offset_from_u8, check_mut_offset_from_u8_array);
2539+
generate_offset_from_harness!(u16, check_mut_offset_from_u16, check_mut_offset_from_u16_array);
2540+
generate_offset_from_harness!(u32, check_mut_offset_from_u32, check_mut_offset_from_u32_array);
2541+
generate_offset_from_harness!(u64, check_mut_offset_from_u64, check_mut_offset_from_u64_array);
2542+
generate_offset_from_harness!(u128, check_mut_offset_from_u128, check_mut_offset_from_u128_array);
2543+
generate_offset_from_harness!(usize, check_mut_offset_from_usize, check_mut_offset_from_usize_array);
2544+
2545+
generate_offset_from_harness!(i8, check_mut_offset_from_i8, check_mut_offset_from_i8_array);
2546+
generate_offset_from_harness!(i16, check_mut_offset_from_i16, check_mut_offset_from_i16_array);
2547+
generate_offset_from_harness!(i32, check_mut_offset_from_i32, check_mut_offset_from_i32_array);
2548+
generate_offset_from_harness!(i64, check_mut_offset_from_i64, check_mut_offset_from_i64_array);
2549+
generate_offset_from_harness!(i128, check_mut_offset_from_i128, check_mut_offset_from_i128_array);
2550+
generate_offset_from_harness!(isize, check_mut_offset_from_isize, check_mut_offset_from_isize_array);
2551+
2552+
generate_offset_from_harness!((i8, i8), check_mut_offset_from_tuple_1, check_mut_offset_from_tuple_1_array);
2553+
generate_offset_from_harness!((f64, bool), check_mut_offset_from_tuple_2, check_mut_offset_from_tuple_2_array);
2554+
generate_offset_from_harness!((u32, i16, f32), check_mut_offset_from_tuple_3, check_mut_offset_from_tuple_3_array);
2555+
generate_offset_from_harness!(
2556+
((), bool, u8, u16, i32, f64, i128, usize),
2557+
check_mut_offset_from_tuple_4,
2558+
check_mut_offset_from_tuple_4_array
25872559
);
25882560

2589-
// Generte harnesses for composite types (add, sub, offset)
2590-
generate_arithmetic_harnesses!(
2591-
(i8, i8),
2592-
check_mut_add_tuple_1,
2593-
check_mut_sub_tuple_1,
2594-
check_mut_offset_tuple_1
2595-
);
2596-
generate_arithmetic_harnesses!(
2597-
(f64, bool),
2598-
check_mut_add_tuple_2,
2599-
check_mut_sub_tuple_2,
2600-
check_mut_offset_tuple_2
2601-
);
2602-
generate_arithmetic_harnesses!(
2603-
(i32, f64, bool),
2604-
check_mut_add_tuple_3,
2605-
check_mut_sub_tuple_3,
2606-
check_mut_offset_tuple_3
2607-
);
2608-
generate_arithmetic_harnesses!(
2609-
(i8, u16, i32, u64, isize),
2610-
check_mut_add_tuple_4,
2611-
check_mut_sub_tuple_4,
2612-
check_mut_offset_tuple_4
2613-
);
26142561
}

0 commit comments

Comments
 (0)