@@ -1035,8 +1035,14 @@ impl<T: ?Sized> NonNull<T> {
10351035 /// [`ptr::copy`]: crate::ptr::copy()
10361036 #[ inline( always) ]
10371037 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1038+ #[ cfg_attr( kani, kani:: modifies( NonNull :: slice_from_raw_parts( dest, count) . as_ptr( ) ) ) ]
10381039 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
10391040 #[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.83.0" ) ]
1041+ #[ requires( count. checked_mul( core:: mem:: size_of:: <T >( ) ) . map_or_else( || false , |size| size <= isize :: MAX as usize )
1042+ && ub_checks:: can_dereference( NonNull :: slice_from_raw_parts( self , count) . as_ptr( ) )
1043+ && ub_checks:: can_write( NonNull :: slice_from_raw_parts( dest, count) . as_ptr( ) ) ) ]
1044+ #[ ensures( |result: & ( ) | ub_checks:: can_dereference( self . as_ptr( ) as * const u8 )
1045+ && ub_checks:: can_dereference( dest. as_ptr( ) as * const u8 ) ) ]
10401046 pub const unsafe fn copy_to ( self , dest : NonNull < T > , count : usize )
10411047 where
10421048 T : Sized ,
@@ -1055,8 +1061,15 @@ impl<T: ?Sized> NonNull<T> {
10551061 /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
10561062 #[ inline( always) ]
10571063 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1064+ #[ cfg_attr( kani, kani:: modifies( NonNull :: slice_from_raw_parts( dest, count) . as_ptr( ) ) ) ]
10581065 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
10591066 #[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.83.0" ) ]
1067+ #[ requires( count. checked_mul( core:: mem:: size_of:: <T >( ) ) . map_or_else( || false , |size| size <= isize :: MAX as usize )
1068+ && ub_checks:: can_dereference( NonNull :: slice_from_raw_parts( self , count) . as_ptr( ) )
1069+ && ub_checks:: can_write( NonNull :: slice_from_raw_parts( dest, count) . as_ptr( ) )
1070+ && ub_checks:: maybe_is_nonoverlapping( self . as_ptr( ) as * const ( ) , dest. as_ptr( ) as * const ( ) , count, core:: mem:: size_of:: <T >( ) ) ) ]
1071+ #[ ensures( |result: & ( ) | ub_checks:: can_dereference( self . as_ptr( ) as * const u8 )
1072+ && ub_checks:: can_dereference( dest. as_ptr( ) as * const u8 ) ) ]
10601073 pub const unsafe fn copy_to_nonoverlapping ( self , dest : NonNull < T > , count : usize )
10611074 where
10621075 T : Sized ,
@@ -1075,8 +1088,14 @@ impl<T: ?Sized> NonNull<T> {
10751088 /// [`ptr::copy`]: crate::ptr::copy()
10761089 #[ inline( always) ]
10771090 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1091+ #[ cfg_attr( kani, kani:: modifies( NonNull :: slice_from_raw_parts( self , count) . as_ptr( ) ) ) ]
10781092 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
10791093 #[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.83.0" ) ]
1094+ #[ requires( count. checked_mul( core:: mem:: size_of:: <T >( ) ) . map_or_else( || false , |size| size <= isize :: MAX as usize )
1095+ && ub_checks:: can_dereference( NonNull :: slice_from_raw_parts( src, count) . as_ptr( ) )
1096+ && ub_checks:: can_write( NonNull :: slice_from_raw_parts( self , count) . as_ptr( ) ) ) ]
1097+ #[ ensures( |result: & ( ) | ub_checks:: can_dereference( src. as_ptr( ) as * const u8 )
1098+ && ub_checks:: can_dereference( self . as_ptr( ) as * const u8 ) ) ]
10801099 pub const unsafe fn copy_from ( self , src : NonNull < T > , count : usize )
10811100 where
10821101 T : Sized ,
@@ -1095,8 +1114,15 @@ impl<T: ?Sized> NonNull<T> {
10951114 /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
10961115 #[ inline( always) ]
10971116 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1117+ #[ cfg_attr( kani, kani:: modifies( NonNull :: slice_from_raw_parts( self , count) . as_ptr( ) ) ) ]
10981118 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
10991119 #[ rustc_const_stable( feature = "const_intrinsic_copy" , since = "1.83.0" ) ]
1120+ #[ requires( count. checked_mul( core:: mem:: size_of:: <T >( ) ) . map_or_else( || false , |size| size <= isize :: MAX as usize )
1121+ && ub_checks:: can_dereference( NonNull :: slice_from_raw_parts( src, count) . as_ptr( ) )
1122+ && ub_checks:: can_write( NonNull :: slice_from_raw_parts( self , count) . as_ptr( ) )
1123+ && ub_checks:: maybe_is_nonoverlapping( src. as_ptr( ) as * const ( ) , self . as_ptr( ) as * const ( ) , count, core:: mem:: size_of:: <T >( ) ) ) ]
1124+ #[ ensures( |result: & ( ) | ub_checks:: can_dereference( src. as_ptr( ) as * const u8 )
1125+ && ub_checks:: can_dereference( self . as_ptr( ) as * const u8 ) ) ]
11001126 pub const unsafe fn copy_from_nonoverlapping ( self , src : NonNull < T > , count : usize )
11011127 where
11021128 T : Sized ,
@@ -2538,4 +2564,62 @@ mod verify {
25382564 let _ = ptr. byte_offset_from ( origin) ;
25392565 }
25402566 }
2567+
2568+ #[ kani:: proof_for_contract( NonNull :: <T >:: copy_to) ]
2569+ pub fn non_null_check_copy_to ( ) {
2570+ // PointerGenerator instance
2571+ let mut generator = PointerGenerator :: < 16 > :: new ( ) ;
2572+ // Generate arbitrary pointers for src and dest
2573+ let src_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2574+ let dest_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2575+ // Wrap the raw pointers in NonNull
2576+ let src = NonNull :: new ( src_ptr) . unwrap ( ) ;
2577+ let dest = NonNull :: new ( dest_ptr) . unwrap ( ) ;
2578+ // Generate an arbitrary count using kani::any
2579+ let count: usize = kani:: any ( ) ;
2580+ unsafe { src. copy_to ( dest, count) ; }
2581+ }
2582+
2583+ #[ kani:: proof_for_contract( NonNull :: <T >:: copy_from) ]
2584+ pub fn non_null_check_copy_from ( ) {
2585+ // PointerGenerator instance
2586+ let mut generator = PointerGenerator :: < 16 > :: new ( ) ;
2587+ // Generate arbitrary pointers for src and dest
2588+ let src_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2589+ let dest_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2590+ // Wrap the raw pointers in NonNull
2591+ let src = NonNull :: new ( src_ptr) . unwrap ( ) ;
2592+ let dest = NonNull :: new ( dest_ptr) . unwrap ( ) ;
2593+ // Generate an arbitrary count using kani::any
2594+ let count: usize = kani:: any ( ) ;
2595+ unsafe { src. copy_from ( dest, count) ; }
2596+ }
2597+ #[ kani:: proof_for_contract( NonNull :: <T >:: copy_to_nonoverlapping) ]
2598+ pub fn non_null_check_copy_to_nonoverlapping ( ) {
2599+ // PointerGenerator instance
2600+ let mut generator = PointerGenerator :: < 16 > :: new ( ) ;
2601+ // Generate arbitrary pointers for src and dest
2602+ let src_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2603+ let dest_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2604+ // Wrap the raw pointers in NonNull
2605+ let src = NonNull :: new ( src_ptr) . unwrap ( ) ;
2606+ let dest = NonNull :: new ( dest_ptr) . unwrap ( ) ;
2607+ // Generate an arbitrary count using kani::any
2608+ let count: usize = kani:: any ( ) ;
2609+ unsafe { src. copy_to_nonoverlapping ( dest, count) ; }
2610+ }
2611+ #[ kani:: proof_for_contract( NonNull :: <T >:: copy_from_nonoverlapping) ]
2612+ pub fn non_null_check_copy_from_nonoverlapping ( ) {
2613+ // PointerGenerator instance
2614+ let mut generator = PointerGenerator :: < 16 > :: new ( ) ;
2615+ // Generate arbitrary pointers for src and dest
2616+ let src_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2617+ let dest_ptr = generator. any_in_bounds :: < i32 > ( ) . ptr ;
2618+ // Wrap the raw pointers in NonNull
2619+ let src = NonNull :: new ( src_ptr) . unwrap ( ) ;
2620+ let dest = NonNull :: new ( dest_ptr) . unwrap ( ) ;
2621+ // Generate an arbitrary count using kani::any
2622+ let count: usize = kani:: any ( ) ;
2623+ unsafe { src. copy_from_nonoverlapping ( dest, count) ; }
2624+ }
25412625}
0 commit comments