@@ -405,10 +405,11 @@ impl<T: ?Sized> *mut T {
405405 // Note: It is the caller's responsibility to ensure that `self` is non-null and properly aligned.
406406 // These conditions are not verified as part of the preconditions.
407407 #[ requires(
408- // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`
409- count. checked_mul( core:: mem:: size_of:: <T >( ) as isize ) . is_some( ) &&
410- // Precondition 2: adding the computed offset to `self` does not cause overflow
411- ( self as isize ) . checked_add( ( count * core:: mem:: size_of:: <T >( ) as isize ) ) . is_some( ) &&
408+ // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`.
409+ // Precondition 2: adding the computed offset to `self` does not cause overflow.
410+ // These two preconditions are combined for performance reason, as multiplication is computationally expensive in Kani.
411+ count. checked_mul( core:: mem:: size_of:: <T >( ) as isize )
412+ . map_or( false , |computed_offset| ( self as isize ) . checked_add( computed_offset) . is_some( ) ) &&
412413 // Precondition 3: If `T` is a unit type (`size_of::<T>() == 0`), this check is unnecessary as it has no allocated memory.
413414 // Otherwise, for non-unit types, `self` and `self.wrapping_offset(count)` should point to the same allocated object,
414415 // restricting `count` to prevent crossing allocation boundaries.
@@ -1016,11 +1017,13 @@ impl<T: ?Sized> *mut T {
10161017 // Note: It is the caller's responsibility to ensure that `self` is non-null and properly aligned.
10171018 // These conditions are not verified as part of the preconditions.
10181019 #[ requires(
1019- // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`
1020- count. checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) &&
1021- count * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize &&
1022- // Precondition 2: adding the computed offset to `self` does not cause overflow
1023- ( self as isize ) . checked_add( ( count * core:: mem:: size_of:: <T >( ) ) as isize ) . is_some( ) &&
1020+ // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`.
1021+ // Precondition 2: adding the computed offset to `self` does not cause overflow.
1022+ // These two preconditions are combined for performance reason, as multiplication is computationally expensive in Kani.
1023+ count. checked_mul( core:: mem:: size_of:: <T >( ) )
1024+ . map_or( false , |computed_offset| {
1025+ computed_offset <= isize :: MAX as usize && ( self as isize ) . checked_add( computed_offset as isize ) . is_some( )
1026+ } ) &&
10241027 // Precondition 3: If `T` is a unit type (`size_of::<T>() == 0`), this check is unnecessary as it has no allocated memory.
10251028 // Otherwise, for non-unit types, `self` and `self.wrapping_add(count)` should point to the same allocated object,
10261029 // restricting `count` to prevent crossing allocation boundaries.
@@ -1140,11 +1143,13 @@ impl<T: ?Sized> *mut T {
11401143 // Note: It is the caller's responsibility to ensure that `self` is non-null and properly aligned.
11411144 // These conditions are not verified as part of the preconditions.
11421145 #[ requires(
1143- // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`
1144- count. checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) &&
1145- count * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize &&
1146- // Precondition 2: subtracting the computed offset from `self` does not cause overflow
1147- ( self as isize ) . checked_sub( ( count * core:: mem:: size_of:: <T >( ) ) as isize ) . is_some( ) &&
1146+ // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`.
1147+ // Precondition 2: substracting the computed offset from `self` does not cause overflow.
1148+ // These two preconditions are combined for performance reason, as multiplication is computationally expensive in Kani.
1149+ count. checked_mul( core:: mem:: size_of:: <T >( ) )
1150+ . map_or( false , |computed_offset| {
1151+ computed_offset <= isize :: MAX as usize && ( self as isize ) . checked_sub( computed_offset as isize ) . is_some( )
1152+ } ) &&
11481153 // Precondition 3: If `T` is a unit type (`size_of::<T>() == 0`), this check is unnecessary as it has no allocated memory.
11491154 // Otherwise, for non-unit types, `self` and `self.wrapping_sub(count)` should point to the same allocated object,
11501155 // restricting `count` to prevent crossing allocation boundaries.
@@ -2173,120 +2178,143 @@ impl<T: ?Sized> PartialOrd for *mut T {
21732178mod verify {
21742179 use crate :: kani;
21752180
2176- /// This macro generates proofs for contracts on `add`, `sub`, and `offset`
2177- /// operations for pointers to integer, composite, and unit types.
2178- /// - `$type`: Specifies the pointee type.
2179- /// - `$proof_name`: Specifies the name of the generated proof for contract.
2180- macro_rules! generate_mut_arithmetic_harness {
2181- ( $type: ty, $proof_name: ident, add) => {
2182- #[ kani:: proof_for_contract( <* mut $type>:: add) ]
2181+ /// This macro generates a single verification harness for the `offset`, `add`, or `sub`
2182+ /// pointer operations, supporting integer, composite, or unit types.
2183+ /// - `$ty`: The type of the slice's elements (e.g., `i32`, `u32`, tuples).
2184+ /// - `$fn_name`: The name of the function being checked (`add`, `sub`, or `offset`).
2185+ /// - `$proof_name`: The name assigned to the generated proof for the contract.
2186+ /// - `$count_ty:ty`: The type of the input variable passed to the method being invoked.
2187+ ///
2188+ /// Note: This macro is intended for internal use only and should be invoked exclusively
2189+ /// by the `generate_arithmetic_harnesses` macro. Its purpose is to reduce code duplication,
2190+ /// and it is not meant to be used directly elsewhere in the codebase.
2191+ macro_rules! generate_single_arithmetic_harness {
2192+ ( $ty: ty, $proof_name: ident, $fn_name: ident, $count_ty: ty) => {
2193+ #[ kani:: proof_for_contract( <* mut $ty>:: $fn_name) ]
21832194 pub fn $proof_name( ) {
21842195 // 200 bytes are large enough to cover all pointee types used for testing
21852196 const BUF_SIZE : usize = 200 ;
21862197 let mut generator = kani:: PointerGenerator :: <BUF_SIZE >:: new( ) ;
2187- let test_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2188- let count: usize = kani:: any( ) ;
2198+ let test_ptr: * mut $ty = generator. any_in_bounds( ) . ptr;
2199+ let count: $count_ty = kani:: any( ) ;
21892200 unsafe {
2190- test_ptr. add ( count) ;
2201+ test_ptr. $fn_name ( count) ;
21912202 }
21922203 }
21932204 } ;
2194- ( $type: ty, $proof_name: ident, sub) => {
2195- #[ kani:: proof_for_contract( <* mut $type>:: sub) ]
2196- pub fn $proof_name( ) {
2197- // 200 bytes are large enough to cover all pointee types used for testing
2198- const BUF_SIZE : usize = 200 ;
2199- let mut generator = kani:: PointerGenerator :: <BUF_SIZE >:: new( ) ;
2200- let test_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2201- let count: usize = kani:: any( ) ;
2202- unsafe {
2203- test_ptr. sub( count) ;
2204- }
2205- }
2206- } ;
2207- ( $type: ty, $proof_name: ident, offset) => {
2208- #[ kani:: proof_for_contract( <* mut $type>:: offset) ]
2209- pub fn $proof_name( ) {
2210- // 200 bytes are large enough to cover all pointee types used for testing
2211- const BUF_SIZE : usize = 200 ;
2212- let mut generator = kani:: PointerGenerator :: <BUF_SIZE >:: new( ) ;
2213- let test_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2214- let count: isize = kani:: any( ) ;
2215- unsafe {
2216- test_ptr. offset( count) ;
2217- }
2218- }
2205+ }
2206+
2207+ /// This macro generates verification harnesses for the `offset`, `add`, and `sub`
2208+ /// pointer operations, supporting integer, composite, and unit types.
2209+ /// - `$ty`: The pointee type (e.g., i32, u32, tuples).
2210+ /// - `$offset_fn_name`: The name for the `offset` proof for contract.
2211+ /// - `$add_fn_name`: The name for the `add` proof for contract.
2212+ /// - `$sub_fn_name`: The name for the `sub` proof for contract.
2213+ macro_rules! generate_arithmetic_harnesses {
2214+ ( $ty: ty, $add_fn_name: ident, $sub_fn_name: ident, $offset_fn_name: ident) => {
2215+ generate_single_arithmetic_harness!( $ty, $add_fn_name, add, usize ) ;
2216+ generate_single_arithmetic_harness!( $ty, $sub_fn_name, sub, usize ) ;
2217+ generate_single_arithmetic_harness!( $ty, $offset_fn_name, offset, isize ) ;
22192218 } ;
22202219 }
22212220
2222- // <*mut T>:: add() integer types verification
2223- generate_mut_arithmetic_harness ! ( i8 , check_mut_add_i8, add) ;
2224- generate_mut_arithmetic_harness ! ( i16 , check_mut_add_i16, add) ;
2225- generate_mut_arithmetic_harness ! ( i32 , check_mut_add_i32, add) ;
2226- generate_mut_arithmetic_harness ! ( i64 , check_mut_add_i64, add) ;
2227- generate_mut_arithmetic_harness ! ( i128 , check_mut_add_i128, add) ;
2228- generate_mut_arithmetic_harness ! ( isize , check_mut_add_isize, add) ;
2229- // Due to a bug of kani this test case is malfunctioning for now.
2221+ // Generate harnesses for unit type (add, sub, offset)
2222+ generate_arithmetic_harnesses ! (
2223+ ( ) ,
2224+ check_mut_add_unit,
2225+ check_mut_sub_unit,
2226+ check_mut_offset_unit
2227+ ) ;
2228+
2229+ // Generate harnesses for integer types (add, sub, offset)
2230+ generate_arithmetic_harnesses ! ( i8 , check_mut_add_i8, check_mut_sub_i8, check_mut_offset_i8) ;
2231+ generate_arithmetic_harnesses ! (
2232+ i16 ,
2233+ check_mut_add_i16,
2234+ check_mut_sub_i16,
2235+ check_mut_offset_i16
2236+ ) ;
2237+ generate_arithmetic_harnesses ! (
2238+ i32 ,
2239+ check_mut_add_i32,
2240+ check_mut_sub_i32,
2241+ check_mut_offset_i32
2242+ ) ;
2243+ generate_arithmetic_harnesses ! (
2244+ i64 ,
2245+ check_mut_add_i64,
2246+ check_mut_sub_i64,
2247+ check_mut_offset_i64
2248+ ) ;
2249+ generate_arithmetic_harnesses ! (
2250+ i128 ,
2251+ check_mut_add_i128,
2252+ check_mut_sub_i128,
2253+ check_mut_offset_i128
2254+ ) ;
2255+ generate_arithmetic_harnesses ! (
2256+ isize ,
2257+ check_mut_add_isize,
2258+ check_mut_sub_isize,
2259+ check_mut_offset_isize
2260+ ) ;
2261+ // Due to a bug of kani the test `check_mut_add_u8` is malfunctioning for now.
22302262 // Tracking issue: https://github.com/model-checking/kani/issues/3743
2231- // generate_mut_arithmetic_harness!(u8, check_mut_add_u8, add);
2232- generate_mut_arithmetic_harness ! ( u16 , check_mut_add_u16, add) ;
2233- generate_mut_arithmetic_harness ! ( u32 , check_mut_add_u32, add) ;
2234- generate_mut_arithmetic_harness ! ( u64 , check_mut_add_u64, add) ;
2235- generate_mut_arithmetic_harness ! ( u128 , check_mut_add_u128, add) ;
2236- generate_mut_arithmetic_harness ! ( usize , check_mut_add_usize, add) ;
2237-
2238- // <*mut T>:: add() unit type verification
2239- generate_mut_arithmetic_harness ! ( ( ) , check_mut_add_unit, add) ;
2240-
2241- // <*mut T>:: add() composite types verification
2242- generate_mut_arithmetic_harness ! ( ( i8 , i8 ) , check_mut_add_tuple_1, add) ;
2243- generate_mut_arithmetic_harness ! ( ( f64 , bool ) , check_mut_add_tuple_2, add) ;
2244- generate_mut_arithmetic_harness ! ( ( i32 , f64 , bool ) , check_mut_add_tuple_3, add) ;
2245- generate_mut_arithmetic_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_add_tuple_4, add) ;
2246-
2247- // <*mut T>:: sub() integer types verification
2248- generate_mut_arithmetic_harness ! ( i8 , check_mut_sub_i8, sub) ;
2249- generate_mut_arithmetic_harness ! ( i16 , check_mut_sub_i16, sub) ;
2250- generate_mut_arithmetic_harness ! ( i32 , check_mut_sub_i32, sub) ;
2251- generate_mut_arithmetic_harness ! ( i64 , check_mut_sub_i64, sub) ;
2252- generate_mut_arithmetic_harness ! ( i128 , check_mut_sub_i128, sub) ;
2253- generate_mut_arithmetic_harness ! ( isize , check_mut_sub_isize, sub) ;
2254- generate_mut_arithmetic_harness ! ( u8 , check_mut_sub_u8, sub) ;
2255- generate_mut_arithmetic_harness ! ( u16 , check_mut_sub_u16, sub) ;
2256- generate_mut_arithmetic_harness ! ( u32 , check_mut_sub_u32, sub) ;
2257- generate_mut_arithmetic_harness ! ( u64 , check_mut_sub_u64, sub) ;
2258- generate_mut_arithmetic_harness ! ( u128 , check_mut_sub_u128, sub) ;
2259- generate_mut_arithmetic_harness ! ( usize , check_mut_sub_usize, sub) ;
2260-
2261- // <*mut T>:: sub() unit type verification
2262- generate_mut_arithmetic_harness ! ( ( ) , check_mut_sub_unit, sub) ;
2263-
2264- // <*mut T>:: sub() composite types verification
2265- generate_mut_arithmetic_harness ! ( ( i8 , i8 ) , check_mut_sub_tuple_1, sub) ;
2266- generate_mut_arithmetic_harness ! ( ( f64 , bool ) , check_mut_sub_tuple_2, sub) ;
2267- generate_mut_arithmetic_harness ! ( ( i32 , f64 , bool ) , check_mut_sub_tuple_3, sub) ;
2268- generate_mut_arithmetic_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_sub_tuple_4, sub) ;
2269-
2270- // fn <*mut T>::offset() integer types verification
2271- generate_mut_arithmetic_harness ! ( i8 , check_mut_offset_i8, offset) ;
2272- generate_mut_arithmetic_harness ! ( i16 , check_mut_offset_i16, offset) ;
2273- generate_mut_arithmetic_harness ! ( i32 , check_mut_offset_i32, offset) ;
2274- generate_mut_arithmetic_harness ! ( i64 , check_mut_offset_i64, offset) ;
2275- generate_mut_arithmetic_harness ! ( i128 , check_mut_offset_i128, offset) ;
2276- generate_mut_arithmetic_harness ! ( isize , check_mut_offset_isize, offset) ;
2277- generate_mut_arithmetic_harness ! ( u8 , check_mut_offset_u8, offset) ;
2278- generate_mut_arithmetic_harness ! ( u16 , check_mut_offset_u16, offset) ;
2279- generate_mut_arithmetic_harness ! ( u32 , check_mut_offset_u32, offset) ;
2280- generate_mut_arithmetic_harness ! ( u64 , check_mut_offset_u64, offset) ;
2281- generate_mut_arithmetic_harness ! ( u128 , check_mut_offset_u128, offset) ;
2282- generate_mut_arithmetic_harness ! ( usize , check_mut_offset_usize, offset) ;
2283-
2284- // fn <*mut T>::offset() unit type verification
2285- generate_mut_arithmetic_harness ! ( ( ) , check_mut_offset_unit, offset) ;
2286-
2287- // fn <*mut T>::offset() composite type verification
2288- generate_mut_arithmetic_harness ! ( ( i8 , i8 ) , check_mut_offset_tuple_1, offset) ;
2289- generate_mut_arithmetic_harness ! ( ( f64 , bool ) , check_mut_offset_tuple_2, offset) ;
2290- generate_mut_arithmetic_harness ! ( ( i32 , f64 , bool ) , check_mut_offset_tuple_3, offset) ;
2291- generate_mut_arithmetic_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_offset_tuple_4, offset) ;
2263+ // generate_arithmetic_harnesses!(u8, check_mut_add_u8, check_mut_sub_u8, check_mut_offset_u8);
2264+ generate_arithmetic_harnesses ! (
2265+ u16 ,
2266+ check_mut_add_u16,
2267+ check_mut_sub_u16,
2268+ check_mut_offset_u16
2269+ ) ;
2270+ generate_arithmetic_harnesses ! (
2271+ u32 ,
2272+ check_mut_add_u32,
2273+ check_mut_sub_u32,
2274+ check_mut_offset_u32
2275+ ) ;
2276+ generate_arithmetic_harnesses ! (
2277+ u64 ,
2278+ check_mut_add_u64,
2279+ check_mut_sub_u64,
2280+ check_mut_offset_u64
2281+ ) ;
2282+ generate_arithmetic_harnesses ! (
2283+ u128 ,
2284+ check_mut_add_u128,
2285+ check_mut_sub_u128,
2286+ check_mut_offset_u128
2287+ ) ;
2288+ generate_arithmetic_harnesses ! (
2289+ usize ,
2290+ check_mut_add_usize,
2291+ check_mut_sub_usize,
2292+ check_mut_offset_usize
2293+ ) ;
2294+
2295+ // Generte harnesses for composite types (add, sub, offset)
2296+ generate_arithmetic_harnesses ! (
2297+ ( i8 , i8 ) ,
2298+ check_mut_add_tuple_1,
2299+ check_mut_sub_tuple_1,
2300+ check_mut_offset_tuple_1
2301+ ) ;
2302+ generate_arithmetic_harnesses ! (
2303+ ( f64 , bool ) ,
2304+ check_mut_add_tuple_2,
2305+ check_mut_sub_tuple_2,
2306+ check_mut_offset_tuple_2
2307+ ) ;
2308+ generate_arithmetic_harnesses ! (
2309+ ( i32 , f64 , bool ) ,
2310+ check_mut_add_tuple_3,
2311+ check_mut_sub_tuple_3,
2312+ check_mut_offset_tuple_3
2313+ ) ;
2314+ generate_arithmetic_harnesses ! (
2315+ ( i8 , u16 , i32 , u64 , isize ) ,
2316+ check_mut_add_tuple_4,
2317+ check_mut_sub_tuple_4,
2318+ check_mut_offset_tuple_4
2319+ ) ;
22922320}
0 commit comments