@@ -1064,7 +1064,17 @@ extern "rust-intrinsic" {
10641064 /// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
10651065 #[ rustc_const_unstable( feature = "const_size_of_val" , issue = "46571" ) ]
10661066 #[ 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 ;
10681078 /// The required alignment of the referenced value.
10691079 ///
10701080 /// 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)
27902800#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
27912801#[ rustc_intrinsic]
27922802#[ 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 >) ) ]
27932806pub unsafe fn vtable_size ( _ptr : * const ( ) ) -> usize {
27942807 unreachable ! ( )
27952808}
@@ -2800,6 +2813,9 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
28002813#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
28012814#[ rustc_intrinsic]
28022815#[ 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 >) ) ]
28032819pub unsafe fn vtable_align ( _ptr : * const ( ) ) -> usize {
28042820 unreachable ! ( )
28052821}
@@ -2927,6 +2943,14 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
29272943#[ inline( always) ]
29282944#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
29292945#[ 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)))]
29302954pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
29312955 extern "rust-intrinsic" {
29322956 #[ 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
30293053#[ inline( always) ]
30303054#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
30313055#[ 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)))]
30323063pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
30333064 extern "rust-intrinsic" {
30343065 #[ 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) {
30483079 align: usize = align_of:: <T >( ) ,
30493080 ) =>
30503081 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)
30523086 ) ;
30533087 copy ( src, dst, count)
30543088 }
@@ -3110,6 +3144,11 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
31103144#[ inline( always) ]
31113145#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
31123146#[ 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)))]
31133152pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
31143153 extern "rust-intrinsic" {
31153154 #[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3185,4 +3224,138 @@ mod verify {
31853224 assert_eq ! ( y, old_x) ;
31863225 assert_eq ! ( x, old_y) ;
31873226 }
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+ }
31883361}
0 commit comments