@@ -1035,8 +1035,14 @@ impl<T: ?Sized> NonNull<T> {
1035
1035
/// [`ptr::copy`]: crate::ptr::copy()
1036
1036
#[ inline( always) ]
1037
1037
#[ 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( ) ) ) ]
1038
1039
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
1039
1040
#[ 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 ) ) ]
1040
1046
pub const unsafe fn copy_to ( self , dest : NonNull < T > , count : usize )
1041
1047
where
1042
1048
T : Sized ,
@@ -1055,8 +1061,15 @@ impl<T: ?Sized> NonNull<T> {
1055
1061
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
1056
1062
#[ inline( always) ]
1057
1063
#[ 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( ) ) ) ]
1058
1065
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
1059
1066
#[ 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 ) ) ]
1060
1073
pub const unsafe fn copy_to_nonoverlapping ( self , dest : NonNull < T > , count : usize )
1061
1074
where
1062
1075
T : Sized ,
@@ -1075,8 +1088,14 @@ impl<T: ?Sized> NonNull<T> {
1075
1088
/// [`ptr::copy`]: crate::ptr::copy()
1076
1089
#[ inline( always) ]
1077
1090
#[ 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( ) ) ) ]
1078
1092
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
1079
1093
#[ 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 ) ) ]
1080
1099
pub const unsafe fn copy_from ( self , src : NonNull < T > , count : usize )
1081
1100
where
1082
1101
T : Sized ,
@@ -1095,8 +1114,15 @@ impl<T: ?Sized> NonNull<T> {
1095
1114
/// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping()
1096
1115
#[ inline( always) ]
1097
1116
#[ 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( ) ) ) ]
1098
1118
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
1099
1119
#[ 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 ) ) ]
1100
1126
pub const unsafe fn copy_from_nonoverlapping ( self , src : NonNull < T > , count : usize )
1101
1127
where
1102
1128
T : Sized ,
@@ -2538,4 +2564,62 @@ mod verify {
2538
2564
let _ = ptr. byte_offset_from ( origin) ;
2539
2565
}
2540
2566
}
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
+ }
2541
2625
}
0 commit comments