@@ -1132,6 +1132,8 @@ impl<T: ?Sized> NonNull<T> {
11321132 #[ inline( always) ]
11331133 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
11341134 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
1135+ #[ cfg_attr( kani, kani:: modifies( self . as_ptr( ) ) ) ]
1136+ #[ requires( ub_checks:: can_write( self . as_ptr( ) ) ) ]
11351137 pub unsafe fn write_volatile ( self , val : T )
11361138 where
11371139 T : Sized ,
@@ -1775,7 +1777,7 @@ mod verify {
17751777 let maybe_null_ptr = if kani:: any ( ) { xptr as * mut i32 } else { null_mut ( ) } ;
17761778 let _ = NonNull :: new ( maybe_null_ptr) ;
17771779 }
1778-
1780+
17791781 // pub const unsafe fn read(self) -> T where T: Sized
17801782 #[ kani:: proof_for_contract( NonNull :: read) ]
17811783 pub fn non_null_check_read ( ) {
@@ -2300,4 +2302,47 @@ mod verify {
23002302 let distance = ptr_nonnull. offset_from ( origin_nonnull) ;
23012303 }
23022304 }
2305+
2306+ macro_rules! generate_write_volatile_harness {
2307+ ( $type: ty, $byte_size: expr, $harness_name: ident) => {
2308+ #[ kani:: proof_for_contract( NonNull :: write_volatile) ]
2309+ pub fn $harness_name( ) {
2310+ // Create a pointer generator for the given type with appropriate byte size
2311+ let mut generator = kani:: PointerGenerator :: <$byte_size>:: new( ) ;
2312+
2313+ // Get a raw pointer from the generator
2314+ let raw_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2315+
2316+ // Create a non-null pointer from the raw pointer
2317+ let ptr = NonNull :: new( raw_ptr) . unwrap( ) ;
2318+
2319+ // Create a non-deterministic value to write
2320+ let new_value: $type = kani:: any( ) ;
2321+
2322+ unsafe {
2323+ // Perform the volatile write operation
2324+ ptr. write_volatile( new_value) ;
2325+
2326+ // Read back the value and assert it's correct
2327+ assert_eq!( ptr. as_ptr( ) . read_volatile( ) , new_value) ;
2328+ }
2329+ }
2330+ } ;
2331+ }
2332+
2333+ // Generate proof harnesses for multiple types with appropriate byte sizes
2334+ generate_write_volatile_harness ! ( i8 , 1 , non_null_check_write_volatile_i8) ;
2335+ generate_write_volatile_harness ! ( i16 , 2 , non_null_check_write_volatile_i16) ;
2336+ generate_write_volatile_harness ! ( i32 , 4 , non_null_check_write_volatile_i32) ;
2337+ generate_write_volatile_harness ! ( i64 , 8 , non_null_check_write_volatile_i64) ;
2338+ generate_write_volatile_harness ! ( i128 , 16 , non_null_check_write_volatile_i128) ;
2339+ generate_write_volatile_harness ! ( isize , { core:: mem:: size_of:: <isize >( ) } , non_null_check_write_volatile_isize) ;
2340+ generate_write_volatile_harness ! ( u8 , 1 , non_null_check_write_volatile_u8) ;
2341+ generate_write_volatile_harness ! ( u16 , 2 , non_null_check_write_volatile_u16) ;
2342+ generate_write_volatile_harness ! ( u32 , 4 , non_null_check_write_volatile_u32) ;
2343+ generate_write_volatile_harness ! ( u64 , 8 , non_null_check_write_volatile_u64) ;
2344+ generate_write_volatile_harness ! ( u128 , 16 , non_null_check_write_volatile_u128) ;
2345+ generate_write_volatile_harness ! ( usize , { core:: mem:: size_of:: <usize >( ) } , non_null_check_write_volatile_usize) ;
2346+ generate_write_volatile_harness ! ( ( ) , 1 , non_null_check_write_volatile_unit) ;
2347+
23032348}
0 commit comments