@@ -407,10 +407,20 @@ impl<T: ?Sized> *mut T {
407407 #[ rustc_const_stable( feature = "const_ptr_offset" , since = "1.61.0" ) ]
408408 #[ inline( always) ]
409409 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
410- #[ requires( kani:: mem:: can_dereference( self ) ) ]
411- // TODO: Determine the valid value range for 'count' and update the precondition accordingly.
412- #[ requires( count == 0 ) ] // This precondition is currently a placeholder.
413- #[ ensures( |result| kani:: mem:: can_dereference( result) ) ]
410+ #[ requires(
411+ // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`
412+ count. checked_mul( core:: mem:: size_of:: <T >( ) as isize ) . is_some( ) &&
413+ // Precondition 2: adding the computed offset to `self` does not cause overflow
414+ ( self as isize ) . checked_add( ( count * core:: mem:: size_of:: <T >( ) as isize ) ) . is_some( ) &&
415+ // Precondition 3: If `T` is a unit type (`size_of::<T>() == 0`), this check is unnecessary as it has no allocated memory.
416+ // Otherwise, for non-unit types, `self` and `self.wrapping_offset(count)` should point to the same allocated object,
417+ // restricting `count` to prevent crossing allocation boundaries.
418+ ( ( core:: mem:: size_of:: <T >( ) == 0 ) || ( kani:: mem:: same_allocation( self , self . wrapping_offset( count) ) ) )
419+ ) ]
420+ // Postcondition: If `T` is a unit type (`size_of::<T>() == 0`), no allocation check is needed.
421+ // Otherwise, for non-unit types, ensure that `self` and `result` point to the same allocated object,
422+ // verifying that the result remains within the same allocation as `self`.
423+ #[ ensures( |result| ( core:: mem:: size_of:: <T >( ) == 0 ) || kani:: mem:: same_allocation( self as * const T , * result as * const T ) ) ]
414424 pub const unsafe fn offset ( self , count : isize ) -> * mut T
415425 where
416426 T : Sized ,
@@ -955,10 +965,21 @@ impl<T: ?Sized> *mut T {
955965 #[ rustc_const_stable( feature = "const_ptr_offset" , since = "1.61.0" ) ]
956966 #[ inline( always) ]
957967 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
958- #[ requires( kani:: mem:: can_dereference( self ) ) ]
959- // TODO: Determine the valid value range for 'count' and update the precondition accordingly.
960- #[ requires( count == 0 ) ] // This precondition is currently a placeholder.
961- #[ ensures( |result| kani:: mem:: can_dereference( result) ) ]
968+ #[ requires(
969+ // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`
970+ count. checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) &&
971+ count * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize &&
972+ // Precondition 2: adding the computed offset to `self` does not cause overflow
973+ ( self as isize ) . checked_add( ( count * core:: mem:: size_of:: <T >( ) ) as isize ) . is_some( ) &&
974+ // Precondition 3: If `T` is a unit type (`size_of::<T>() == 0`), this check is unnecessary as it has no allocated memory.
975+ // Otherwise, for non-unit types, `self` and `self.wrapping_add(count)` should point to the same allocated object,
976+ // restricting `count` to prevent crossing allocation boundaries.
977+ ( ( core:: mem:: size_of:: <T >( ) == 0 ) || ( kani:: mem:: same_allocation( self , self . wrapping_add( count) ) ) )
978+ ) ]
979+ // Postcondition: If `T` is a unit type (`size_of::<T>() == 0`), no allocation check is needed.
980+ // Otherwise, for non-unit types, ensure that `self` and `result` point to the same allocated object,
981+ // verifying that the result remains within the same allocation as `self`.
982+ #[ ensures( |result| ( core:: mem:: size_of:: <T >( ) == 0 ) || kani:: mem:: same_allocation( self as * const T , * result as * const T ) ) ]
962983 pub const unsafe fn add ( self , count : usize ) -> Self
963984 where
964985 T : Sized ,
@@ -1034,10 +1055,21 @@ impl<T: ?Sized> *mut T {
10341055 #[ rustc_allow_const_fn_unstable( unchecked_neg) ]
10351056 #[ inline( always) ]
10361057 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1037- #[ requires( kani:: mem:: can_dereference( self ) ) ]
1038- // TODO: Determine the valid value range for 'count' and update the precondition accordingly.
1039- #[ requires( count == 0 ) ] // This precondition is currently a placeholder.
1040- #[ ensures( |result| kani:: mem:: can_dereference( result) ) ]
1058+ #[ requires(
1059+ // Precondition 1: the computed offset `count * size_of::<T>()` does not overflow `isize`
1060+ count. checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) &&
1061+ count * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize &&
1062+ // Precondition 2: subtracting the computed offset from `self` does not cause overflow
1063+ ( self as isize ) . checked_sub( ( count * core:: mem:: size_of:: <T >( ) ) as isize ) . is_some( ) &&
1064+ // Precondition 3: If `T` is a unit type (`size_of::<T>() == 0`), this check is unnecessary as it has no allocated memory.
1065+ // Otherwise, for non-unit types, `self` and `self.wrapping_sub(count)` should point to the same allocated object,
1066+ // restricting `count` to prevent crossing allocation boundaries.
1067+ ( ( core:: mem:: size_of:: <T >( ) == 0 ) || ( kani:: mem:: same_allocation( self , self . wrapping_sub( count) ) ) )
1068+ ) ]
1069+ // Postcondition: If `T` is a unit type (`size_of::<T>() == 0`), no allocation check is needed.
1070+ // Otherwise, for non-unit types, ensure that `self` and `result` point to the same allocated object,
1071+ // verifying that the result remains within the same allocation as `self`.
1072+ #[ ensures( |result| ( core:: mem:: size_of:: <T >( ) == 0 ) || kani:: mem:: same_allocation( self as * const T , * result as * const T ) ) ]
10411073 pub const unsafe fn sub ( self , count : usize ) -> Self
10421074 where
10431075 T : Sized ,
@@ -2219,102 +2251,120 @@ impl<T: ?Sized> PartialOrd for *mut T {
22192251mod verify {
22202252 use crate :: kani;
22212253
2222- macro_rules! generate_mut_add_and_sub_harness {
2223- ( $type: ty, $proof_name: ident, $func_name : ident ) => {
2224- #[ kani:: proof_for_contract( <* mut $type>:: $func_name ) ]
2254+ macro_rules! generate_mut_arithmetic_harness {
2255+ ( $type: ty, $proof_name: ident, add ) => {
2256+ #[ kani:: proof_for_contract( <* mut $type>:: add ) ]
22252257 pub fn $proof_name( ) {
22262258 let mut test_val: $type = kani:: any:: <$type>( ) ;
2259+ let offset: usize = kani:: any( ) ;
2260+ let count: usize = kani:: any( ) ;
2261+ kani:: assume( offset <= 1 ) ;
2262+
22272263 let test_ptr: * mut $type = & mut test_val;
2264+ let ptr_with_offset: * mut $type = test_ptr. wrapping_add( offset) ;
2265+ unsafe {
2266+ ptr_with_offset. add( count) ;
2267+ }
2268+ }
2269+ } ;
2270+ ( $type: ty, $proof_name: ident, sub) => {
2271+ #[ kani:: proof_for_contract( <* mut $type>:: sub) ]
2272+ pub fn $proof_name( ) {
2273+ let mut test_val: $type = kani:: any:: <$type>( ) ;
2274+ let offset: usize = kani:: any( ) ;
22282275 let count: usize = kani:: any( ) ;
2276+ kani:: assume( offset <= 1 ) ;
2277+
2278+ let test_ptr: * mut $type = & mut test_val;
2279+ let ptr_with_offset: * mut $type = test_ptr. wrapping_add( offset) ;
2280+ unsafe {
2281+ ptr_with_offset. sub( count) ;
2282+ }
2283+ }
2284+ } ;
2285+ ( $type: ty, $proof_name: ident, offset) => {
2286+ #[ kani:: proof_for_contract( <* mut $type>:: offset) ]
2287+ pub fn $proof_name( ) {
2288+ let mut test_val: $type = kani:: any:: <$type>( ) ;
2289+ let offset: usize = kani:: any( ) ;
2290+ let count: isize = kani:: any( ) ;
2291+ kani:: assume( offset <= 1 ) ;
2292+
2293+ let test_ptr: * mut $type = & mut test_val;
2294+ let ptr_with_offset: * mut $type = test_ptr. wrapping_add( offset) ;
22292295 unsafe {
2230- test_ptr . $func_name ( count) ;
2296+ ptr_with_offset . offset ( count) ;
22312297 }
22322298 }
22332299 } ;
22342300 }
22352301
22362302 // <*mut T>:: add() integer types verification
2237- generate_mut_add_and_sub_harness ! ( i8 , check_mut_add_i8, add) ;
2238- generate_mut_add_and_sub_harness ! ( i16 , check_mut_add_i16, add) ;
2239- generate_mut_add_and_sub_harness ! ( i32 , check_mut_add_i32, add) ;
2240- generate_mut_add_and_sub_harness ! ( i64 , check_mut_add_i64, add) ;
2241- generate_mut_add_and_sub_harness ! ( i128 , check_mut_add_i128, add) ;
2242- generate_mut_add_and_sub_harness ! ( isize , check_mut_add_isize, add) ;
2243- generate_mut_add_and_sub_harness ! ( u8 , check_mut_add_u8, add) ;
2244- generate_mut_add_and_sub_harness ! ( u16 , check_mut_add_u16, add) ;
2245- generate_mut_add_and_sub_harness ! ( u32 , check_mut_add_u32, add) ;
2246- generate_mut_add_and_sub_harness ! ( u64 , check_mut_add_u64, add) ;
2247- generate_mut_add_and_sub_harness ! ( u128 , check_mut_add_u128, add) ;
2248- generate_mut_add_and_sub_harness ! ( usize , check_mut_add_usize, add) ;
2303+ generate_mut_arithmetic_harness ! ( i8 , check_mut_add_i8, add) ;
2304+ generate_mut_arithmetic_harness ! ( i16 , check_mut_add_i16, add) ;
2305+ generate_mut_arithmetic_harness ! ( i32 , check_mut_add_i32, add) ;
2306+ generate_mut_arithmetic_harness ! ( i64 , check_mut_add_i64, add) ;
2307+ generate_mut_arithmetic_harness ! ( i128 , check_mut_add_i128, add) ;
2308+ generate_mut_arithmetic_harness ! ( isize , check_mut_add_isize, add) ;
2309+ generate_mut_arithmetic_harness ! ( u8 , check_mut_add_u8, add) ;
2310+ generate_mut_arithmetic_harness ! ( u16 , check_mut_add_u16, add) ;
2311+ generate_mut_arithmetic_harness ! ( u32 , check_mut_add_u32, add) ;
2312+ generate_mut_arithmetic_harness ! ( u64 , check_mut_add_u64, add) ;
2313+ generate_mut_arithmetic_harness ! ( u128 , check_mut_add_u128, add) ;
2314+ generate_mut_arithmetic_harness ! ( usize , check_mut_add_usize, add) ;
22492315
22502316 // <*mut T>:: add() unit type verification
2251- generate_mut_add_and_sub_harness ! ( ( ) , check_mut_add_unit, add) ;
2317+ generate_mut_arithmetic_harness ! ( ( ) , check_mut_add_unit, add) ;
22522318
22532319 // <*mut T>:: add() composite types verification
2254- generate_mut_add_and_sub_harness ! ( ( i8 , i8 ) , check_mut_add_tuple_1, add) ;
2255- generate_mut_add_and_sub_harness ! ( ( f64 , bool ) , check_mut_add_tuple_2, add) ;
2256- generate_mut_add_and_sub_harness ! ( ( i32 , f64 , bool ) , check_mut_add_tuple_3, add) ;
2257- generate_mut_add_and_sub_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_add_tuple_4, add) ;
2320+ generate_mut_arithmetic_harness ! ( ( i8 , i8 ) , check_mut_add_tuple_1, add) ;
2321+ generate_mut_arithmetic_harness ! ( ( f64 , bool ) , check_mut_add_tuple_2, add) ;
2322+ generate_mut_arithmetic_harness ! ( ( i32 , f64 , bool ) , check_mut_add_tuple_3, add) ;
2323+ generate_mut_arithmetic_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_add_tuple_4, add) ;
22582324
22592325 // <*mut T>:: sub() integer types verification
2260- generate_mut_add_and_sub_harness ! ( i8 , check_mut_sub_i8, sub) ;
2261- generate_mut_add_and_sub_harness ! ( i16 , check_mut_sub_i16, sub) ;
2262- generate_mut_add_and_sub_harness ! ( i32 , check_mut_sub_i32, sub) ;
2263- generate_mut_add_and_sub_harness ! ( i64 , check_mut_sub_i64, sub) ;
2264- generate_mut_add_and_sub_harness ! ( i128 , check_mut_sub_i128, sub) ;
2265- generate_mut_add_and_sub_harness ! ( isize , check_mut_sub_isize, sub) ;
2266- generate_mut_add_and_sub_harness ! ( u8 , check_mut_sub_u8, sub) ;
2267- generate_mut_add_and_sub_harness ! ( u16 , check_mut_sub_u16, sub) ;
2268- generate_mut_add_and_sub_harness ! ( u32 , check_mut_sub_u32, sub) ;
2269- generate_mut_add_and_sub_harness ! ( u64 , check_mut_sub_u64, sub) ;
2270- generate_mut_add_and_sub_harness ! ( u128 , check_mut_sub_u128, sub) ;
2271- generate_mut_add_and_sub_harness ! ( usize , check_mut_sub_usize, sub) ;
2326+ generate_mut_arithmetic_harness ! ( i8 , check_mut_sub_i8, sub) ;
2327+ generate_mut_arithmetic_harness ! ( i16 , check_mut_sub_i16, sub) ;
2328+ generate_mut_arithmetic_harness ! ( i32 , check_mut_sub_i32, sub) ;
2329+ generate_mut_arithmetic_harness ! ( i64 , check_mut_sub_i64, sub) ;
2330+ generate_mut_arithmetic_harness ! ( i128 , check_mut_sub_i128, sub) ;
2331+ generate_mut_arithmetic_harness ! ( isize , check_mut_sub_isize, sub) ;
2332+ generate_mut_arithmetic_harness ! ( u8 , check_mut_sub_u8, sub) ;
2333+ generate_mut_arithmetic_harness ! ( u16 , check_mut_sub_u16, sub) ;
2334+ generate_mut_arithmetic_harness ! ( u32 , check_mut_sub_u32, sub) ;
2335+ generate_mut_arithmetic_harness ! ( u64 , check_mut_sub_u64, sub) ;
2336+ generate_mut_arithmetic_harness ! ( u128 , check_mut_sub_u128, sub) ;
2337+ generate_mut_arithmetic_harness ! ( usize , check_mut_sub_usize, sub) ;
22722338
22732339 // <*mut T>:: sub() unit type verification
2274- generate_mut_add_and_sub_harness ! ( ( ) , check_mut_sub_unit, sub) ;
2340+ generate_mut_arithmetic_harness ! ( ( ) , check_mut_sub_unit, sub) ;
22752341
22762342 // <*mut T>:: sub() composite types verification
2277- generate_mut_add_and_sub_harness ! ( ( i8 , i8 ) , check_mut_sub_tuple_1, sub) ;
2278- generate_mut_add_and_sub_harness ! ( ( f64 , bool ) , check_mut_sub_tuple_2, sub) ;
2279- generate_mut_add_and_sub_harness ! ( ( i32 , f64 , bool ) , check_mut_sub_tuple_3, sub) ;
2280- generate_mut_add_and_sub_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_sub_tuple_4, sub) ;
2281-
2282-
2283- // fn <*mut T>::offset verification begin
2284- macro_rules! generate_mut_offset_harness {
2285- ( $type: ty, $proof_name: ident) => {
2286- #[ kani:: proof_for_contract( <* mut $type>:: offset) ]
2287- pub fn $proof_name( ) {
2288- let mut test_val: $type = kani:: any:: <$type>( ) ;
2289- let test_ptr: * mut $type = & mut test_val;
2290- let count: isize = kani:: any( ) ;
2291- unsafe {
2292- test_ptr. offset( count) ;
2293- }
2294- }
2295- } ;
2296- }
2297-
2298- // fn <*mut T>::offset integer types verification
2299- generate_mut_offset_harness ! ( i8 , check_mut_offset_i8) ;
2300- generate_mut_offset_harness ! ( i16 , check_mut_offset_i16) ;
2301- generate_mut_offset_harness ! ( i32 , check_mut_offset_i32) ;
2302- generate_mut_offset_harness ! ( i64 , check_mut_offset_i64) ;
2303- generate_mut_offset_harness ! ( i128 , check_mut_offset_i128) ;
2304- generate_mut_offset_harness ! ( isize , check_mut_offset_isize) ;
2305- generate_mut_offset_harness ! ( u8 , check_mut_offset_u8) ;
2306- generate_mut_offset_harness ! ( u16 , check_mut_offset_u16) ;
2307- generate_mut_offset_harness ! ( u32 , check_mut_offset_u32) ;
2308- generate_mut_offset_harness ! ( u64 , check_mut_offset_u64) ;
2309- generate_mut_offset_harness ! ( u128 , check_mut_offset_u128) ;
2310- generate_mut_offset_harness ! ( usize , check_mut_offset_usize) ;
2311-
2312- // fn <*mut T>::offset unit type verification
2313- generate_mut_offset_harness ! ( ( ) , check_mut_offset_unit) ;
2314-
2315- // fn <*mut T>::offset composite type verification
2316- generate_mut_offset_harness ! ( ( i8 , i8 ) , check_mut_offset_tuple_1) ;
2317- generate_mut_offset_harness ! ( ( f64 , bool ) , check_mut_offset_tuple_2) ;
2318- generate_mut_offset_harness ! ( ( i32 , f64 , bool ) , check_mut_offset_tuple_3) ;
2319- generate_mut_offset_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_offset_tuple_4) ;
2343+ generate_mut_arithmetic_harness ! ( ( i8 , i8 ) , check_mut_sub_tuple_1, sub) ;
2344+ generate_mut_arithmetic_harness ! ( ( f64 , bool ) , check_mut_sub_tuple_2, sub) ;
2345+ generate_mut_arithmetic_harness ! ( ( i32 , f64 , bool ) , check_mut_sub_tuple_3, sub) ;
2346+ generate_mut_arithmetic_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_sub_tuple_4, sub) ;
2347+
2348+ // fn <*mut T>::offset() integer types verification
2349+ generate_mut_arithmetic_harness ! ( i8 , check_mut_offset_i8, offset) ;
2350+ generate_mut_arithmetic_harness ! ( i16 , check_mut_offset_i16, offset) ;
2351+ generate_mut_arithmetic_harness ! ( i32 , check_mut_offset_i32, offset) ;
2352+ generate_mut_arithmetic_harness ! ( i64 , check_mut_offset_i64, offset) ;
2353+ generate_mut_arithmetic_harness ! ( i128 , check_mut_offset_i128, offset) ;
2354+ generate_mut_arithmetic_harness ! ( isize , check_mut_offset_isize, offset) ;
2355+ generate_mut_arithmetic_harness ! ( u8 , check_mut_offset_u8, offset) ;
2356+ generate_mut_arithmetic_harness ! ( u16 , check_mut_offset_u16, offset) ;
2357+ generate_mut_arithmetic_harness ! ( u32 , check_mut_offset_u32, offset) ;
2358+ generate_mut_arithmetic_harness ! ( u64 , check_mut_offset_u64, offset) ;
2359+ generate_mut_arithmetic_harness ! ( u128 , check_mut_offset_u128, offset) ;
2360+ generate_mut_arithmetic_harness ! ( usize , check_mut_offset_usize, offset) ;
2361+
2362+ // fn <*mut T>::offset() unit type verification
2363+ generate_mut_arithmetic_harness ! ( ( ) , check_mut_offset_unit, offset) ;
2364+
2365+ // fn <*mut T>::offset() composite type verification
2366+ generate_mut_arithmetic_harness ! ( ( i8 , i8 ) , check_mut_offset_tuple_1, offset) ;
2367+ generate_mut_arithmetic_harness ! ( ( f64 , bool ) , check_mut_offset_tuple_2, offset) ;
2368+ generate_mut_arithmetic_harness ! ( ( i32 , f64 , bool ) , check_mut_offset_tuple_3, offset) ;
2369+ generate_mut_arithmetic_harness ! ( ( i8 , u16 , i32 , u64 , isize ) , check_mut_offset_tuple_4, offset) ;
23202370}
0 commit comments