6363) ]
6464#![ allow( missing_docs) ]
6565
66- use safety:: requires;
66+ use safety:: { ensures , requires} ;
6767use crate :: marker:: DiscriminantKind ;
6868use crate :: marker:: Tuple ;
6969use crate :: ptr;
@@ -2728,6 +2728,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
27282728#[ requires( ub_checks:: can_dereference( y) && ub_checks:: can_write( y) ) ]
27292729#[ requires( x. addr( ) != y. addr( ) || core:: mem:: size_of:: <T >( ) == 0 ) ]
27302730#[ 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) ) ]
27312732pub const unsafe fn typed_swap < T > ( x : * mut T , y : * mut T ) {
27322733 // SAFETY: The caller provided single non-overlapping items behind
27332734 // 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
29572958#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
29582959#[ rustc_diagnostic_item = "ptr_copy_nonoverlapping" ]
29592960// Copy is "untyped".
2961+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
29602962#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
29612963 && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
29622964 && ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( dst, count) ) ) ]
29632965#[ 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+ } ) ]
29672978pub const unsafe fn copy_nonoverlapping < T > ( src : * const T , dst : * mut T , count : usize ) {
29682979 extern "rust-intrinsic" {
29692980 #[ 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
30663077#[ inline( always) ]
30673078#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
30683079#[ 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??
30703081#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
30713082 && ub_checks:: can_dereference( core:: ptr:: slice_from_raw_parts( src as * const crate :: mem:: MaybeUninit <T >, count) )
30723083 && 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+ } ) ]
30763094pub const unsafe fn copy < T > ( src : * const T , dst : * mut T , count : usize ) {
30773095 extern "rust-intrinsic" {
30783096 #[ 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) {
31563174#[ inline( always) ]
31573175#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
31583176#[ rustc_diagnostic_item = "ptr_write_bytes" ]
3177+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( dst, count) ) ) ]
31593178#[ requires( !count. overflowing_mul( size_of:: <T >( ) ) . 1
31603179 && 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+ } ) ]
31643185pub const unsafe fn write_bytes < T > ( dst : * mut T , val : u8 , count : usize ) {
31653186 extern "rust-intrinsic" {
31663187 #[ 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
32083229#[ unstable( feature="kani" , issue="none" ) ]
32093230mod verify {
32103231 use core:: { cmp, fmt} ;
3232+ use core:: ptr:: addr_of_mut;
32113233 use super :: * ;
32123234 use crate :: kani;
32133235
@@ -3270,16 +3292,18 @@ mod verify {
32703292 bytes : u64 ,
32713293 }
32723294 let mut single = kani:: any :: < u32 > ( ) ;
3273- let ptr1 = crate :: ptr :: addr_of_mut!( single) ;
3295+ let ptr1 = addr_of_mut ! ( single) ;
32743296
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 ;
32773301
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 ;
32803304
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 ;
32833307
32843308 let arbitrary = ArbitraryPointers :: from ( ptr1, ptr2, unaligned, uninit) ;
32853309 harness ( arbitrary) ;
@@ -3348,7 +3372,7 @@ mod verify {
33483372 } ) ;
33493373 }
33503374
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.
33523376 #[ kani:: proof_for_contract( copy_nonoverlapping) ]
33533377 fn check_copy_nonoverlapping ( ) {
33543378 ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
@@ -3360,7 +3384,7 @@ mod verify {
33603384 } ) ;
33613385 }
33623386
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.
33643388 #[ kani:: proof_for_contract( write_bytes) ]
33653389 fn check_write_bytes ( ) {
33663390 ArbitraryPointers :: < u32 > :: with_arbitrary ( |arbitrary| {
0 commit comments