@@ -1063,7 +1063,17 @@ extern "rust-intrinsic" {
10631063 /// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
10641064 #[ rustc_const_unstable( feature = "const_size_of_val" , issue = "46571" ) ]
10651065 #[ 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 ;
10671077 /// The required alignment of the referenced value.
10681078 ///
10691079 /// 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)
27892799#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
27902800#[ rustc_intrinsic]
27912801#[ 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 >) ) ]
27922805pub unsafe fn vtable_size ( _ptr : * const ( ) ) -> usize {
27932806 unreachable ! ( )
27942807}
@@ -2799,6 +2812,9 @@ pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
27992812#[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
28002813#[ rustc_intrinsic]
28012814#[ 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 >) ) ]
28022818pub unsafe fn vtable_align ( _ptr : * const ( ) ) -> usize {
28032819 unreachable ! ( )
28042820}
@@ -2940,6 +2956,14 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
29402956#[ inline( always) ]
29412957#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
29422958#[ 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)))]
29432967pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
29442968 extern "rust-intrinsic" {
29452969 #[ 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
30423066#[ inline( always) ]
30433067#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
30443068#[ 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)))]
30453076pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
30463077 extern "rust-intrinsic" {
30473078 #[ 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) {
30603091 align: usize = align_of:: <T >( ) ,
30613092 ) =>
30623093 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)
30643098 ) ;
30653099 copy ( src, dst, count)
30663100 }
@@ -3122,6 +3156,11 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
31223156#[ inline( always) ]
31233157#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
31243158#[ 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)))]
31253164pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
31263165 extern "rust-intrinsic" {
31273166 #[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3197,4 +3236,138 @@ mod verify {
31973236 assert_eq ! ( y, old_x) ;
31983237 assert_eq ! ( x, old_y) ;
31993238 }
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+ }
32003373}
0 commit comments