@@ -1063,7 +1063,17 @@ extern "rust-intrinsic" {
1063
1063
/// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
1064
1064
#[ rustc_const_unstable( feature = "const_size_of_val" , issue = "46571" ) ]
1065
1065
#[ rustc_nounwind]
1066
- pub fn size_of_val < T : ?Sized > ( _: * const T ) -> usize ;
1066
+ // FIXME: Kani currently does not support annotating intrinsics.
1067
+ // See https://github.com/model-checking/kani/issues/3325
1068
+ #[ cfg_attr( not( kani) , requires( matches!(
1069
+ <T as Pointee >:: Metadata :: map_dyn( crate :: ptr:: metadata( _val) :: metadata( ) ,
1070
+ |dyn_meta| { ub_checks:: can_dereference( dyn_meta) } ) ,
1071
+ None | Some ( true ) ) ) ) ]
1072
+ #[ cfg_attr( not( kani) , requires( matches!(
1073
+ <T as Pointee >:: Metadata :: map_len( crate :: ptr:: metadata( _val) :: metadata( ) ,
1074
+ |_| { ub_checks:: can_dereference( _val) } ) ,
1075
+ None | Some ( true ) ) ) ) ]
1076
+ pub fn size_of_val < T : ?Sized > ( _val : * const T ) -> usize ;
1067
1077
/// The required alignment of the referenced value.
1068
1078
///
1069
1079
/// The stabilized version of this intrinsic is [`core::mem::align_of_val`].
@@ -2789,6 +2799,9 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize)
2789
2799
#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
2790
2800
#[ rustc_intrinsic]
2791
2801
#[ rustc_intrinsic_must_be_overridden]
2802
+ // FIXME(kani): Cannot verify intrinsics contract yet.
2803
+ // <https://github.com/model-checking/kani/issues/3345>
2804
+ #[ requires( ub_checks:: can_dereference( _ptr as * const crate :: ptr:: DynMetadata <dyn crate :: any:: Any >) ) ]
2792
2805
pub unsafe fn vtable_size ( _ptr : * const ( ) ) -> usize {
2793
2806
unreachable ! ( )
2794
2807
}
@@ -2799,6 +2812,9 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
2799
2812
#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
2800
2813
#[ rustc_intrinsic]
2801
2814
#[ rustc_intrinsic_must_be_overridden]
2815
+ // FIXME(kani): Cannot verify intrinsics contract yet.
2816
+ // <https://github.com/model-checking/kani/issues/3345>
2817
+ #[ requires( ub_checks:: can_dereference( _ptr as * const crate :: ptr:: DynMetadata <dyn crate :: any:: Any >) ) ]
2802
2818
pub unsafe fn vtable_align ( _ptr : * const ( ) ) -> usize {
2803
2819
unreachable ! ( )
2804
2820
}
@@ -2940,6 +2956,14 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
2940
2956
#[ inline( always) ]
2941
2957
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
2942
2958
#[ rustc_diagnostic_item = "ptr_copy_nonoverlapping" ]
2959
+ #[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
2960
+ && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src, count) )
2961
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
2962
+ #[ requires( src. addr( ) != dst. addr( ) || core:: mem:: size_of:: <T >( ) == 0 ) ]
2963
+ #[ requires( ( src. addr( ) >= dst. addr( ) + core:: mem:: size_of:: <T >( ) ) || ( dst. addr( ) >= src. addr( ) + core:: mem:: size_of:: <T >( ) ) ) ]
2964
+ // TODO: Modifies doesn't work with slices today.
2965
+ // https://github.com/model-checking/kani/pull/3295
2966
+ // #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
2943
2967
pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
2944
2968
extern "rust-intrinsic" {
2945
2969
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3042,6 +3066,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
3042
3066
#[ inline( always) ]
3043
3067
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3044
3068
#[ rustc_diagnostic_item = "ptr_copy" ]
3069
+ // FIXME: How to verify safety for types that do not implement Copy and count > 1??
3070
+ #[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3071
+ && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src, count) )
3072
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
3073
+ // TODO: Modifies doesn't work with slices today.
3074
+ // https://github.com/model-checking/kani/pull/3295
3075
+ // #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
3045
3076
pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
3046
3077
extern "rust-intrinsic" {
3047
3078
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3060,7 +3091,10 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
3060
3091
align: usize = align_of:: <T >( ) ,
3061
3092
) =>
3062
3093
ub_checks:: is_aligned_and_not_null( src, align)
3063
- && ub_checks:: is_aligned_and_not_null( dst, align)
3094
+
3095
+
3096
+
3097
+ && ub_checks:: is_aligned_and_not_null( dst, align)
3064
3098
) ;
3065
3099
copy ( src, dst, count)
3066
3100
}
@@ -3122,6 +3156,11 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
3122
3156
#[ inline( always) ]
3123
3157
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3124
3158
#[ rustc_diagnostic_item = "ptr_write_bytes" ]
3159
+ #[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3160
+ && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst as * mut u8 , count) ) ) ]
3161
+ // TODO: Modifies doesn't work with slices today.
3162
+ // https://github.com/model-checking/kani/pull/3295
3163
+ // #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
3125
3164
pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
3126
3165
extern "rust-intrinsic" {
3127
3166
#[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3197,4 +3236,138 @@ mod verify {
3197
3236
assert_eq ! ( y, old_x) ;
3198
3237
assert_eq ! ( x, old_y) ;
3199
3238
}
3239
+
3240
+ /// Note that in `core` we cannot check allocated pointers.
3241
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , kani:: Arbitrary ) ]
3242
+ enum PtrKind {
3243
+ /// Dangling pointers
3244
+ Dangling ,
3245
+ /// Null pointers
3246
+ Null ,
3247
+ /// Stack pointers
3248
+ Stack ,
3249
+ /// Overlapping pointers
3250
+ Overlap ,
3251
+ /// Unaligned pointers
3252
+ Unaligned ,
3253
+ /// Pointer to uninitialized memory
3254
+ Uninitialized ,
3255
+ }
3256
+
3257
+ struct ArbitraryPointers < T > {
3258
+ src : * const T ,
3259
+ dst : * mut T ,
3260
+ dst_kind : PtrKind ,
3261
+ src_kind : PtrKind ,
3262
+ }
3263
+
3264
+ impl < T : kani:: Arbitrary > ArbitraryPointers < T > {
3265
+ fn with_arbitrary < F > ( harness : F ) where F : FnOnce ( ArbitraryPointers < u32 > ) {
3266
+ #[ repr( C ) ]
3267
+ struct WithPadding {
3268
+ byte : u8 ,
3269
+ // padding in the middle.
3270
+ bytes : u64 ,
3271
+ }
3272
+ let mut single = kani:: any :: < u32 > ( ) ;
3273
+ let ptr1 = crate :: ptr:: addr_of_mut!( single) ;
3274
+
3275
+ let mut array = [ kani:: any :: < u32 > ( ) ; 100 ] ;
3276
+ let ptr2 = crate :: ptr:: addr_of_mut!( array) as * mut u32 ;
3277
+
3278
+ let mut buffer = [ 0u8 , 6 ] ;
3279
+ let unaligned = unsafe { crate :: ptr:: addr_of_mut!( buffer) . byte_offset ( 1 ) } as * mut u32 ;
3280
+
3281
+ let mut padding = WithPadding { byte : 0 , bytes : 0 } ;
3282
+ let uninit = unsafe { crate :: ptr:: addr_of_mut!( padding. byte) . byte_offset ( 4 ) } as * mut u32 ;
3283
+
3284
+ let arbitrary = ArbitraryPointers :: from ( ptr1, ptr2, unaligned, uninit) ;
3285
+ harness ( arbitrary) ;
3286
+ }
3287
+
3288
+ fn from ( ptr1 : * mut T , ptr2 : * mut T , unaligned : * mut T , uninit : * mut T ) -> Self {
3289
+ let ( src_kind, src) = ArbitraryPointers :: any ( ptr1, ptr2, unaligned, uninit) ;
3290
+ let ( dst_kind, dst) = ArbitraryPointers :: any ( ptr2, ptr1, unaligned, uninit) ;
3291
+ ArbitraryPointers {
3292
+ src_kind,
3293
+ src,
3294
+ dst_kind,
3295
+ dst,
3296
+ }
3297
+ }
3298
+
3299
+ fn any ( unique : * mut T , overlap : * mut T , unaligned : * mut T , uninit : * mut T ) -> ( PtrKind , * mut T ) {
3300
+ let kind = kani:: any :: < PtrKind > ( ) ;
3301
+ let ptr = match kind {
3302
+ PtrKind :: Dangling => {
3303
+ crate :: ptr:: dangling_mut :: < T > ( )
3304
+ }
3305
+ PtrKind :: Null => {
3306
+ crate :: ptr:: null_mut :: < T > ( )
3307
+ }
3308
+ PtrKind :: Stack => {
3309
+ unique
3310
+ }
3311
+ PtrKind :: Overlap => {
3312
+ if kani:: any ( ) { unique } else { overlap }
3313
+ }
3314
+ PtrKind :: Unaligned => {
3315
+ unaligned
3316
+ }
3317
+ PtrKind :: Uninitialized => {
3318
+ uninit
3319
+ }
3320
+ } ;
3321
+ ( kind, ptr)
3322
+ }
3323
+ }
3324
+
3325
+ /// This harness currently fails because we cannot define the modifies clause for slices.
3326
+ #[ kani:: proof_for_contract( copy) ]
3327
+ fn check_copy ( ) {
3328
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3329
+ // Skip dangling for now since it makes Kani contract panic.
3330
+ // Verify this case in a separate harness.
3331
+ kani:: assume ( arbitrary. dst_kind != PtrKind :: Dangling ) ;
3332
+ kani:: assume ( arbitrary. src_kind != PtrKind :: Dangling ) ;
3333
+ unsafe { copy ( arbitrary. src , arbitrary. dst , kani:: any ( ) ) }
3334
+ } ) ;
3335
+ }
3336
+
3337
+ /// This harness fails because Kani cannot assume a pointer is valid.
3338
+ ///
3339
+ /// The specification should ensure the pointers passed are allocated, and this harness should
3340
+ /// succeed since `copy` ensures would reject dangling pointers.
3341
+ #[ cfg( ignore) ]
3342
+ #[ kani:: proof_for_contract( copy) ]
3343
+ fn check_copy_dangling ( ) {
3344
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3345
+ // Verify the dangling case.
3346
+ kani:: assume ( arbitrary. dst_kind == PtrKind :: Dangling || arbitrary. src_kind == PtrKind :: Dangling ) ;
3347
+ unsafe { copy ( 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( copy_nonoverlapping) ]
3353
+ fn check_copy_nonoverlapping ( ) {
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
+ kani:: assume ( arbitrary. src_kind != PtrKind :: Dangling ) ;
3359
+ unsafe { copy_nonoverlapping ( arbitrary. src , arbitrary. dst , kani:: any ( ) ) }
3360
+ } ) ;
3361
+ }
3362
+
3363
+ /// This harness currently fails because we cannot define the modifies clause for slices.
3364
+ #[ kani:: proof_for_contract( write_bytes) ]
3365
+ fn check_write_bytes ( ) {
3366
+ ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
3367
+ // Skip dangling for now since it makes Kani contract panic.
3368
+ // Verify this case in a separate harness.
3369
+ kani:: assume ( arbitrary. dst_kind != PtrKind :: Dangling ) ;
3370
+ unsafe { write_bytes ( arbitrary. dst , kani:: any ( ) , kani:: any ( ) ) }
3371
+ } ) ;
3372
+ }
3200
3373
}
0 commit comments