@@ -1064,7 +1064,17 @@ extern "rust-intrinsic" {
1064
1064
/// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
1065
1065
#[ rustc_const_unstable( feature = "const_size_of_val" , issue = "46571" ) ]
1066
1066
#[ rustc_nounwind]
1067
- pub fn size_of_val < T : ?Sized > ( _: * const T ) -> usize ;
1067
+ // FIXME: Kani currently does not support annotating intrinsics.
1068
+ // See https://github.com/model-checking/kani/issues/3325
1069
+ #[ cfg_attr( not( kani) , requires( matches!(
1070
+ <T as Pointee >:: Metadata :: map_dyn( crate :: ptr:: metadata( _val) :: metadata( ) ,
1071
+ |dyn_meta| { ub_checks:: can_dereference( dyn_meta) } ) ,
1072
+ None | Some ( true ) ) ) ) ]
1073
+ #[ cfg_attr( not( kani) , requires( matches!(
1074
+ <T as Pointee >:: Metadata :: map_len( crate :: ptr:: metadata( _val) :: metadata( ) ,
1075
+ |_| { ub_checks:: can_dereference( _val) } ) ,
1076
+ None | Some ( true ) ) ) ) ]
1077
+ pub fn size_of_val < T : ?Sized > ( _val : * const T ) -> usize ;
1068
1078
/// The required alignment of the referenced value.
1069
1079
///
1070
1080
/// The stabilized version of this intrinsic is [`core::mem::align_of_val`].
@@ -2790,6 +2800,9 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize)
2790
2800
#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
2791
2801
#[ rustc_intrinsic]
2792
2802
#[ rustc_intrinsic_must_be_overridden]
2803
+ // FIXME(kani): Cannot verify intrinsics contract yet.
2804
+ // <https://github.com/model-checking/kani/issues/3345>
2805
+ #[ requires( ub_checks:: can_dereference( _ptr as * const crate :: ptr:: DynMetadata <dyn crate :: any:: Any >) ) ]
2793
2806
pub unsafe fn vtable_size ( _ptr : * const ( ) ) -> usize {
2794
2807
unreachable ! ( )
2795
2808
}
@@ -2800,6 +2813,9 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
2800
2813
#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
2801
2814
#[ rustc_intrinsic]
2802
2815
#[ rustc_intrinsic_must_be_overridden]
2816
+ // FIXME(kani): Cannot verify intrinsics contract yet.
2817
+ // <https://github.com/model-checking/kani/issues/3345>
2818
+ #[ requires( ub_checks:: can_dereference( _ptr as * const crate :: ptr:: DynMetadata <dyn crate :: any:: Any >) ) ]
2803
2819
pub unsafe fn vtable_align ( _ptr : * const ( ) ) -> usize {
2804
2820
unreachable ! ( )
2805
2821
}
@@ -2927,6 +2943,14 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
2927
2943
#[ inline( always) ]
2928
2944
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
2929
2945
#[ rustc_diagnostic_item = "ptr_copy_nonoverlapping" ]
2946
+ #[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
2947
+ && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src, count) )
2948
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
2949
+ #[ requires( src. addr( ) != dst. addr( ) || core:: mem:: size_of:: <T >( ) == 0 ) ]
2950
+ #[ requires( ( src. addr( ) >= dst. addr( ) + core:: mem:: size_of:: <T >( ) ) || ( dst. addr( ) >= src. addr( ) + core:: mem:: size_of:: <T >( ) ) ) ]
2951
+ // TODO: Modifies doesn't work with slices today.
2952
+ // https://github.com/model-checking/kani/pull/3295
2953
+ // #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
2930
2954
pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
2931
2955
extern "rust-intrinsic" {
2932
2956
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3029,6 +3053,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
3029
3053
#[ inline( always) ]
3030
3054
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3031
3055
#[ rustc_diagnostic_item = "ptr_copy" ]
3056
+ // FIXME: How to verify safety for types that do not implement Copy and count > 1??
3057
+ #[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3058
+ && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src, count) )
3059
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
3060
+ // TODO: Modifies doesn't work with slices today.
3061
+ // https://github.com/model-checking/kani/pull/3295
3062
+ // #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
3032
3063
pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
3033
3064
extern "rust-intrinsic" {
3034
3065
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3048,7 +3079,10 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
3048
3079
align: usize = align_of:: <T >( ) ,
3049
3080
) =>
3050
3081
ub_checks:: is_aligned_and_not_null( src, align)
3051
- && ub_checks:: is_aligned_and_not_null( dst, align)
3082
+
3083
+
3084
+
3085
+ && ub_checks:: is_aligned_and_not_null( dst, align)
3052
3086
) ;
3053
3087
copy ( src, dst, count)
3054
3088
}
@@ -3110,6 +3144,11 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
3110
3144
#[ inline( always) ]
3111
3145
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3112
3146
#[ rustc_diagnostic_item = "ptr_write_bytes" ]
3147
+ #[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3148
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst as * mut u8 , count) ) ) ]
3149
+ // TODO: Modifies doesn't work with slices today.
3150
+ // https://github.com/model-checking/kani/pull/3295
3151
+ // #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
3113
3152
pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
3114
3153
extern "rust-intrinsic" {
3115
3154
#[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3185,4 +3224,138 @@ mod verify {
3185
3224
assert_eq ! ( y, old_x) ;
3186
3225
assert_eq ! ( x, old_y) ;
3187
3226
}
3227
+
3228
+ /// Note that in `core` we cannot check allocated pointers.
3229
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , kani:: Arbitrary ) ]
3230
+ enum PtrKind {
3231
+ /// Dangling pointers
3232
+ Dangling ,
3233
+ /// Null pointers
3234
+ Null ,
3235
+ /// Stack pointers
3236
+ Stack ,
3237
+ /// Overlapping pointers
3238
+ Overlap ,
3239
+ /// Unaligned pointers
3240
+ Unaligned ,
3241
+ /// Pointer to uninitialized memory
3242
+ Uninitialized ,
3243
+ }
3244
+
3245
+ struct ArbitraryPointers < T > {
3246
+ src : * const T ,
3247
+ dst : * mut T ,
3248
+ dst_kind : PtrKind ,
3249
+ src_kind : PtrKind ,
3250
+ }
3251
+
3252
+ impl < T : kani:: Arbitrary > ArbitraryPointers < T > {
3253
+ fn with_arbitrary < F > ( harness : F ) where F : FnOnce ( ArbitraryPointers < u32 > ) {
3254
+ #[ repr( C ) ]
3255
+ struct WithPadding {
3256
+ byte : u8 ,
3257
+ // padding in the middle.
3258
+ bytes : u64 ,
3259
+ }
3260
+ let mut single = kani:: any :: < u32 > ( ) ;
3261
+ let ptr1 = crate :: ptr:: addr_of_mut!( single) ;
3262
+
3263
+ let mut array = [ kani:: any :: < u32 > ( ) ; 100 ] ;
3264
+ let ptr2 = crate :: ptr:: addr_of_mut!( array) as * mut u32 ;
3265
+
3266
+ let mut buffer = [ 0u8 , 6 ] ;
3267
+ let unaligned = unsafe { crate :: ptr:: addr_of_mut!( buffer) . byte_offset ( 1 ) } as * mut u32 ;
3268
+
3269
+ let mut padding = WithPadding { byte : 0 , bytes : 0 } ;
3270
+ let uninit = unsafe { crate :: ptr:: addr_of_mut!( padding. byte) . byte_offset ( 4 ) } as * mut u32 ;
3271
+
3272
+ let arbitrary = ArbitraryPointers :: from ( ptr1, ptr2, unaligned, uninit) ;
3273
+ harness ( arbitrary) ;
3274
+ }
3275
+
3276
+ fn from ( ptr1 : * mut T , ptr2 : * mut T , unaligned : * mut T , uninit : * mut T ) -> Self {
3277
+ let ( src_kind, src) = ArbitraryPointers :: any ( ptr1, ptr2, unaligned, uninit) ;
3278
+ let ( dst_kind, dst) = ArbitraryPointers :: any ( ptr2, ptr1, unaligned, uninit) ;
3279
+ ArbitraryPointers {
3280
+ src_kind,
3281
+ src,
3282
+ dst_kind,
3283
+ dst,
3284
+ }
3285
+ }
3286
+
3287
+ fn any ( unique : * mut T , overlap : * mut T , unaligned : * mut T , uninit : * mut T ) -> ( PtrKind , * mut T ) {
3288
+ let kind = kani:: any :: < PtrKind > ( ) ;
3289
+ let ptr = match kind {
3290
+ PtrKind :: Dangling => {
3291
+ crate :: ptr:: dangling_mut :: < T > ( )
3292
+ }
3293
+ PtrKind :: Null => {
3294
+ crate :: ptr:: null_mut :: < T > ( )
3295
+ }
3296
+ PtrKind :: Stack => {
3297
+ unique
3298
+ }
3299
+ PtrKind :: Overlap => {
3300
+ if kani:: any ( ) { unique } else { overlap }
3301
+ }
3302
+ PtrKind :: Unaligned => {
3303
+ unaligned
3304
+ }
3305
+ PtrKind :: Uninitialized => {
3306
+ uninit
3307
+ }
3308
+ } ;
3309
+ ( kind, ptr)
3310
+ }
3311
+ }
3312
+
3313
+ /// This harness currently fails because we cannot define the modifies clause for slices.
3314
+ #[ kani:: proof_for_contract( copy) ]
3315
+ fn check_copy ( ) {
3316
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3317
+ // Skip dangling for now since it makes Kani contract panic.
3318
+ // Verify this case in a separate harness.
3319
+ kani:: assume ( arbitrary. dst_kind != PtrKind :: Dangling ) ;
3320
+ kani:: assume ( arbitrary. src_kind != PtrKind :: Dangling ) ;
3321
+ unsafe { copy ( arbitrary. src , arbitrary. dst , kani:: any ( ) ) }
3322
+ } ) ;
3323
+ }
3324
+
3325
+ /// This harness fails because Kani cannot assume a pointer is valid.
3326
+ ///
3327
+ /// The specification should ensure the pointers passed are allocated, and this harness should
3328
+ /// succeed since `copy` ensures would reject dangling pointers.
3329
+ #[ cfg( ignore) ]
3330
+ #[ kani:: proof_for_contract( copy) ]
3331
+ fn check_copy_dangling ( ) {
3332
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3333
+ // Verify the dangling case.
3334
+ kani:: assume ( arbitrary. dst_kind == PtrKind :: Dangling || arbitrary. src_kind == PtrKind :: Dangling ) ;
3335
+ unsafe { copy ( arbitrary. src , arbitrary. dst , kani:: any ( ) ) }
3336
+ } ) ;
3337
+ }
3338
+
3339
+ /// This harness currently fails because we cannot define the modifies clause for slices.
3340
+ #[ kani:: proof_for_contract( copy_nonoverlapping) ]
3341
+ fn check_copy_nonoverlapping ( ) {
3342
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3343
+ // Skip dangling for now since it makes Kani contract panic.
3344
+ // Verify this case in a separate harness.
3345
+ kani:: assume ( arbitrary. dst_kind != PtrKind :: Dangling ) ;
3346
+ kani:: assume ( arbitrary. src_kind != PtrKind :: Dangling ) ;
3347
+ unsafe { copy_nonoverlapping ( arbitrary. src , arbitrary. dst , kani:: any ( ) ) }
3348
+ } ) ;
3349
+ }
3350
+
3351
+ /// This harness currently fails because we cannot define the modifies clause for slices.
3352
+ #[ kani:: proof_for_contract( write_bytes) ]
3353
+ fn check_write_bytes ( ) {
3354
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3355
+ // Skip dangling for now since it makes Kani contract panic.
3356
+ // Verify this case in a separate harness.
3357
+ kani:: assume ( arbitrary. dst_kind != PtrKind :: Dangling ) ;
3358
+ unsafe { write_bytes ( arbitrary. dst , kani:: any ( ) , kani:: any ( ) ) }
3359
+ } ) ;
3360
+ }
3188
3361
}
0 commit comments