@@ -1132,6 +1132,8 @@ impl<T: ?Sized> NonNull<T> {
1132
1132
#[ inline( always) ]
1133
1133
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
1134
1134
#[ 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( ) ) ) ]
1135
1137
pub unsafe fn write_volatile ( self , val : T )
1136
1138
where
1137
1139
T : Sized ,
@@ -1775,7 +1777,7 @@ mod verify {
1775
1777
let maybe_null_ptr = if kani:: any ( ) { xptr as * mut i32 } else { null_mut ( ) } ;
1776
1778
let _ = NonNull :: new ( maybe_null_ptr) ;
1777
1779
}
1778
-
1780
+
1779
1781
// pub const unsafe fn read(self) -> T where T: Sized
1780
1782
#[ kani:: proof_for_contract( NonNull :: read) ]
1781
1783
pub fn non_null_check_read ( ) {
@@ -2300,4 +2302,47 @@ mod verify {
2300
2302
let distance = ptr_nonnull. offset_from ( origin_nonnull) ;
2301
2303
}
2302
2304
}
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
+
2303
2348
}
0 commit comments