63
63
) ]
64
64
#![ allow( missing_docs) ]
65
65
66
- use safety:: requires;
66
+ use safety:: { ensures , requires} ;
67
67
use crate :: marker:: DiscriminantKind ;
68
68
use crate :: marker:: Tuple ;
69
69
use crate :: ptr;
@@ -2728,6 +2728,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2728
2728
#[ requires( ub_checks:: can_dereference( y) && ub_checks:: can_write( y) ) ]
2729
2729
#[ requires( x. addr( ) != y. addr( ) || core:: mem:: size_of:: <T >( ) == 0 ) ]
2730
2730
#[ requires( ub_checks:: is_nonoverlapping( x as * const ( ) , x as * const ( ) , size_of:: <T >( ) , 1 ) ) ]
2731
+ #[ ensures( |_| ub_checks:: can_dereference( x) && ub_checks:: can_dereference( y) ) ]
2731
2732
pub const unsafe fn typed_swap < T > ( x : * mut T , y : * mut T ) {
2732
2733
// SAFETY: The caller provided single non-overlapping items behind
2733
2734
// pointers, so swapping them with `count: 1` is fine.
@@ -2957,13 +2958,23 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
2957
2958
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
2958
2959
#[ rustc_diagnostic_item = "ptr_copy_nonoverlapping" ]
2959
2960
// Copy is "untyped".
2961
+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
2960
2962
#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
2961
2963
&& ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
2962
2964
&& ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
2963
2965
#[ requires( ub_checks:: is_nonoverlapping( src as * const ( ) , dst as * const ( ) , size_of:: <T >( ) , count) ) ]
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)))]
2966
+ // TODO: Use quantifiers once it's available.
2967
+ // Ensures the initialization state is preserved.
2968
+ #[ ensures( |_| {
2969
+ if count > 0 {
2970
+ let byte = kani:: any_where( | sz: & usize | * sz < size_of:: < T >) ;
2971
+ let elem = kani:: any_where( | val: & usize | * val < count) ;
2972
+ let src_data = src as * const u8 ;
2973
+ let dst_data = unsafe { dst. offset( elem) } as * const u8 ;
2974
+ ub_checks:: can_dereference( unsafe { src_data. offset( byte) } )
2975
+ == ub_checks:: can_dereference( unsafe { dst_data. offset( byte) } )
2976
+ }
2977
+ } ) ]
2967
2978
pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
2968
2979
extern "rust-intrinsic" {
2969
2980
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3066,13 +3077,20 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
3066
3077
#[ inline( always) ]
3067
3078
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3068
3079
#[ rustc_diagnostic_item = "ptr_copy" ]
3069
- // FIXME: How to verify safety for types that do not implement Copy and count > 1??
3080
+ // FIXME(kani) : How to verify safety for types that do not implement Copy and count > 1??
3070
3081
#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3071
3082
&& ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
3072
3083
&& 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)))]
3084
+ #[ ensures( |_| {
3085
+ if count > 0 {
3086
+ let byte = kani:: any_where( | sz: & usize | * sz < size_of:: < T >) ;
3087
+ let elem = kani:: any_where( | val: & usize | * val < count) ;
3088
+ let src_data = src as * const u8 ;
3089
+ let dst_data = unsafe { dst. offset( elem) } as * const u8 ;
3090
+ ub_checks:: can_dereference( unsafe { src_data. offset( byte) } )
3091
+ == ub_checks:: can_dereference( unsafe { dst_data. offset( byte) } )
3092
+ }
3093
+ } ) ]
3076
3094
pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
3077
3095
extern "rust-intrinsic" {
3078
3096
#[ rustc_const_unstable( feature = "const_intrinsic_copy" , issue = "80697" ) ]
@@ -3156,11 +3174,14 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
3156
3174
#[ inline( always) ]
3157
3175
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
3158
3176
#[ rustc_diagnostic_item = "ptr_write_bytes" ]
3177
+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
3159
3178
#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
3160
3179
&& 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)))]
3180
+ // TODO: Change this to quantifiers when available.
3181
+ #[ ensures( |_| {
3182
+ let idx = kani:: any_where( |idx: & usize | * idx < count) ;
3183
+ ub_checks:: can_dereference( dst. offset( idx) as * const u8 )
3184
+ } ) ]
3164
3185
pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
3165
3186
extern "rust-intrinsic" {
3166
3187
#[ rustc_const_unstable( feature = "const_ptr_write" , issue = "86302" ) ]
@@ -3208,6 +3229,7 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
3208
3229
#[ unstable( feature="kani" , issue="none" ) ]
3209
3230
mod verify {
3210
3231
use core:: { cmp, fmt} ;
3232
+ use core:: ptr:: addr_of_mut;
3211
3233
use super :: * ;
3212
3234
use crate :: kani;
3213
3235
@@ -3270,16 +3292,18 @@ mod verify {
3270
3292
bytes : u64 ,
3271
3293
}
3272
3294
let mut single = kani:: any :: < u32 > ( ) ;
3273
- let ptr1 = crate :: ptr :: addr_of_mut!( single) ;
3295
+ let ptr1 = addr_of_mut ! ( single) ;
3274
3296
3275
- let mut array = [ kani:: any :: < u32 > ( ) ; 100 ] ;
3276
- let ptr2 = crate :: ptr:: addr_of_mut!( array) as * mut u32 ;
3297
+ // FIXME(kani) this should be but this is not available in `kani_core` yet:
3298
+ // let mut array: [u8; 100] = kani::any();
3299
+ let mut array = [ kani:: any :: < u32 > ( ) , 100 ] ;
3300
+ let ptr2 = addr_of_mut ! ( array) as * mut u32 ;
3277
3301
3278
- let mut buffer = [ 0u8 , 6 ] ;
3279
- let unaligned = unsafe { crate :: ptr :: addr_of_mut!( buffer) . byte_offset ( 1 ) } as * mut u32 ;
3302
+ let mut buffer = [ 0u8 ; 6 ] ;
3303
+ let unaligned = unsafe { addr_of_mut ! ( buffer) . byte_offset ( 1 ) } as * mut u32 ;
3280
3304
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 ;
3305
+ let mut padding = WithPadding { byte : kani :: any ( ) , bytes : kani :: any ( ) } ;
3306
+ let uninit = unsafe { addr_of_mut ! ( padding. byte) . byte_offset ( 4 ) } as * mut u32 ;
3283
3307
3284
3308
let arbitrary = ArbitraryPointers :: from ( ptr1, ptr2, unaligned, uninit) ;
3285
3309
harness ( arbitrary) ;
@@ -3348,7 +3372,7 @@ mod verify {
3348
3372
} ) ;
3349
3373
}
3350
3374
3351
- /// This harness currently fails because we cannot define the modifies clause for slices.
3375
+ /// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
3352
3376
#[ kani:: proof_for_contract( copy_nonoverlapping) ]
3353
3377
fn check_copy_nonoverlapping ( ) {
3354
3378
ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
@@ -3360,7 +3384,7 @@ mod verify {
3360
3384
} ) ;
3361
3385
}
3362
3386
3363
- /// This harness currently fails because we cannot define the modifies clause for slices.
3387
+ /// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
3364
3388
#[ kani:: proof_for_contract( write_bytes) ]
3365
3389
fn check_write_bytes ( ) {
3366
3390
ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
0 commit comments