@@ -1210,6 +1210,8 @@ impl<T: ?Sized> NonNull<T> {
12101210 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
12111211 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
12121212 #[ rustc_const_stable( feature = "const_ptr_write" , since = "1.83.0" ) ]
1213+ #[ cfg_attr( kani, kani:: modifies( self . as_ptr( ) ) ) ]
1214+ #[ requires( ub_checks:: can_write( self . as_ptr( ) ) ) ]
12131215 pub const unsafe fn write ( self , val : T )
12141216 where
12151217 T : Sized ,
@@ -1229,6 +1231,13 @@ impl<T: ?Sized> NonNull<T> {
12291231 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
12301232 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
12311233 #[ rustc_const_stable( feature = "const_ptr_write" , since = "1.83.0" ) ]
1234+ #[ cfg_attr( kani, kani:: modifies( crate :: ptr:: slice_from_raw_parts( self . as_ptr( ) , count) ) ) ]
1235+ #[ requires(
1236+ count. checked_mul( core:: mem:: size_of:: <T >( ) as usize ) . is_some_and( |byte_count| byte_count. wrapping_add( self . as_ptr( ) as usize ) <= isize :: MAX as usize ) &&
1237+ ub_checks:: can_write( core:: ptr:: slice_from_raw_parts_mut( self . as_ptr( ) , count) )
1238+ ) ]
1239+ #[ ensures( |_|
1240+ ub_checks:: can_dereference( crate :: ptr:: slice_from_raw_parts( self . as_ptr( ) as * const u8 , count * size_of:: <T >( ) ) ) ) ]
12321241 pub const unsafe fn write_bytes ( self , val : u8 , count : usize )
12331242 where
12341243 T : Sized ,
@@ -1272,6 +1281,8 @@ impl<T: ?Sized> NonNull<T> {
12721281 #[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
12731282 #[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
12741283 #[ rustc_const_stable( feature = "const_ptr_write" , since = "1.83.0" ) ]
1284+ #[ cfg_attr( kani, kani:: modifies( self . as_ptr( ) ) ) ]
1285+ #[ requires( ub_checks:: can_write_unaligned( self . as_ptr( ) ) ) ]
12751286 pub const unsafe fn write_unaligned ( self , val : T )
12761287 where
12771288 T : Sized ,
@@ -2531,12 +2542,143 @@ mod verify {
25312542 }
25322543 }
25332544
2545+ macro_rules! generate_write_harness {
2546+ ( $type: ty, $harness_name: ident) => {
2547+ #[ kani:: proof_for_contract( NonNull :: write) ]
2548+ pub fn $harness_name( ) {
2549+ // Create a pointer generator for the given type with appropriate byte size
2550+ const ARR_SIZE : usize = mem:: size_of:: <$type>( ) * 100 ;
2551+ let mut generator = kani:: PointerGenerator :: <ARR_SIZE >:: new( ) ;
2552+
2553+ // Get a raw pointer from the generator
2554+ let raw_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2555+
2556+ // Create a non-null pointer from the raw pointer
2557+ let ptr = NonNull :: new( raw_ptr) . unwrap( ) ;
2558+
2559+ // Create a non-deterministic value to write
2560+ let new_value: $type = kani:: any( ) ;
2561+
2562+ unsafe {
2563+ // Perform the volatile write operation
2564+ ptr. write( new_value) ;
2565+
2566+ // Read back the value and assert it's correct
2567+ assert_eq!( ptr. as_ptr( ) . read( ) , new_value) ;
2568+ }
2569+ }
2570+ } ;
2571+ }
2572+
2573+ #[ kani:: proof_for_contract( NonNull :: write) ]
2574+ pub fn non_null_check_write_unit ( ) {
2575+ // Create a pointer generator for the given type with appropriate byte size
2576+ let mut generator = kani:: PointerGenerator :: < 1 > :: new ( ) ;
2577+
2578+ // Get a raw pointer from the generator
2579+ let raw_ptr: * mut ( ) = generator. any_in_bounds ( ) . ptr ;
2580+
2581+ // Create a non-null pointer from the raw pointer
2582+ let ptr = NonNull :: new ( raw_ptr) . unwrap ( ) ;
2583+
2584+ // Create a non-deterministic value to write
2585+ let new_value: ( ) = kani:: any ( ) ;
2586+
2587+ unsafe {
2588+ // Perform the volatile write operation
2589+ ptr. write ( new_value) ;
2590+
2591+ // Read back the value and assert it's correct
2592+ assert_eq ! ( ptr. as_ptr( ) . read( ) , new_value) ;
2593+ }
2594+ }
2595+
2596+ // Generate proof harnesses for multiple types with appropriate byte sizes
2597+ generate_write_harness ! ( i8 , non_null_check_write_i8) ;
2598+ generate_write_harness ! ( i16 , non_null_check_write_i16) ;
2599+ generate_write_harness ! ( i32 , non_null_check_write_i32) ;
2600+ generate_write_harness ! ( i64 , non_null_check_write_i64) ;
2601+ generate_write_harness ! ( i128 , non_null_check_write_i128) ;
2602+ generate_write_harness ! ( isize , non_null_check_write_isize) ;
2603+ generate_write_harness ! ( u8 , non_null_check_write_u8) ;
2604+ generate_write_harness ! ( u16 , non_null_check_write_u16) ;
2605+ generate_write_harness ! ( u32 , non_null_check_write_u32) ;
2606+ generate_write_harness ! ( u64 , non_null_check_write_u64) ;
2607+ generate_write_harness ! ( u128 , non_null_check_write_u128) ;
2608+ generate_write_harness ! ( usize , non_null_check_write_usize) ;
2609+
2610+ macro_rules! generate_write_unaligned_harness {
2611+ ( $type: ty, $harness_name: ident) => {
2612+ #[ kani:: proof_for_contract( NonNull :: write_unaligned) ]
2613+ pub fn $harness_name( ) {
2614+ // Create a pointer generator for the given type with appropriate byte size
2615+ const ARR_SIZE : usize = mem:: size_of:: <$type>( ) * 100 ;
2616+ let mut generator = kani:: PointerGenerator :: <ARR_SIZE >:: new( ) ;
2617+
2618+ // Get a raw pointer from the generator
2619+ let raw_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2620+
2621+ // Create a non-null pointer from the raw pointer
2622+ let ptr = NonNull :: new( raw_ptr) . unwrap( ) ;
2623+
2624+ // Create a non-deterministic value to write
2625+ let new_value: $type = kani:: any( ) ;
2626+
2627+ unsafe {
2628+ // Perform the volatile write operation
2629+ ptr. write_unaligned( new_value) ;
2630+
2631+ // Read back the value and assert it's correct
2632+ assert_eq!( ptr. as_ptr( ) . read_unaligned( ) , new_value) ;
2633+ }
2634+ }
2635+ } ;
2636+ }
2637+
2638+ #[ kani:: proof_for_contract( NonNull :: write_unaligned) ]
2639+ pub fn non_null_check_write_unaligned_unit ( ) {
2640+ // Create a pointer generator for the given type with appropriate byte size
2641+ let mut generator = kani:: PointerGenerator :: < 1 > :: new ( ) ;
2642+
2643+ // Get a raw pointer from the generator
2644+ let raw_ptr: * mut ( ) = generator. any_in_bounds ( ) . ptr ;
2645+
2646+ // Create a non-null pointer from the raw pointer
2647+ let ptr = NonNull :: new ( raw_ptr) . unwrap ( ) ;
2648+
2649+ // Create a non-deterministic value to write
2650+ let new_value: ( ) = kani:: any ( ) ;
2651+
2652+ unsafe {
2653+ // Perform the volatile write operation
2654+ ptr. write_unaligned ( new_value) ;
2655+
2656+ // Read back the value and assert it's correct
2657+ assert_eq ! ( ptr. as_ptr( ) . read_unaligned( ) , new_value) ;
2658+ }
2659+ }
2660+
2661+ // Generate proof harnesses for multiple types with appropriate byte sizes
2662+ generate_write_unaligned_harness ! ( i8 , non_null_check_write_unaligned_i8) ;
2663+ generate_write_unaligned_harness ! ( i16 , non_null_check_write_unaligned_i16) ;
2664+ generate_write_unaligned_harness ! ( i32 , non_null_check_write_unaligned_i32) ;
2665+ generate_write_unaligned_harness ! ( i64 , non_null_check_write_unaligned_i64) ;
2666+ generate_write_unaligned_harness ! ( i128 , non_null_check_write_unaligned_i128) ;
2667+ generate_write_unaligned_harness ! ( isize , non_null_check_write_unaligned_isize) ;
2668+ generate_write_unaligned_harness ! ( u8 , non_null_check_write_unaligned_u8) ;
2669+ generate_write_unaligned_harness ! ( u16 , non_null_check_write_unaligned_u16) ;
2670+ generate_write_unaligned_harness ! ( u32 , non_null_check_write_unaligned_u32) ;
2671+ generate_write_unaligned_harness ! ( u64 , non_null_check_write_unaligned_u64) ;
2672+ generate_write_unaligned_harness ! ( u128 , non_null_check_write_unaligned_u128) ;
2673+ generate_write_unaligned_harness ! ( usize , non_null_check_write_unaligned_usize) ;
2674+
25342675 macro_rules! generate_write_volatile_harness {
2535- ( $type: ty, $byte_size : expr , $ harness_name: ident) => {
2676+ ( $type: ty, $harness_name: ident) => {
25362677 #[ kani:: proof_for_contract( NonNull :: write_volatile) ]
25372678 pub fn $harness_name( ) {
25382679 // Create a pointer generator for the given type with appropriate byte size
2539- let mut generator = kani:: PointerGenerator :: <$byte_size>:: new( ) ;
2680+ const ARR_SIZE : usize = mem:: size_of:: <$type>( ) * 100 ;
2681+ let mut generator = kani:: PointerGenerator :: <ARR_SIZE >:: new( ) ;
25402682
25412683 // Get a raw pointer from the generator
25422684 let raw_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
@@ -2558,28 +2700,114 @@ mod verify {
25582700 } ;
25592701 }
25602702
2703+ #[ kani:: proof_for_contract( NonNull :: write_volatile) ]
2704+ pub fn non_null_check_write_volatile_unit ( ) {
2705+ // Create a pointer generator for the given type with appropriate byte size
2706+ let mut generator = kani:: PointerGenerator :: < 1 > :: new ( ) ;
2707+
2708+ // Get a raw pointer from the generator
2709+ let raw_ptr: * mut ( ) = generator. any_in_bounds ( ) . ptr ;
2710+
2711+ // Create a non-null pointer from the raw pointer
2712+ let ptr = NonNull :: new ( raw_ptr) . unwrap ( ) ;
2713+
2714+ // Create a non-deterministic value to write
2715+ let new_value: ( ) = kani:: any ( ) ;
2716+
2717+ unsafe {
2718+ // Perform the volatile write operation
2719+ ptr. write_volatile ( new_value) ;
2720+
2721+ // Read back the value and assert it's correct
2722+ assert_eq ! ( ptr. as_ptr( ) . read_volatile( ) , new_value) ;
2723+ }
2724+ }
2725+
2726+ // Generate proof harnesses for multiple types with appropriate byte sizes
2727+ generate_write_volatile_harness ! ( i8 , non_null_check_write_volatile_i8) ;
2728+ generate_write_volatile_harness ! ( i16 , non_null_check_write_volatile_i16) ;
2729+ generate_write_volatile_harness ! ( i32 , non_null_check_write_volatile_i32) ;
2730+ generate_write_volatile_harness ! ( i64 , non_null_check_write_volatile_i64) ;
2731+ generate_write_volatile_harness ! ( i128 , non_null_check_write_volatile_i128) ;
2732+ generate_write_volatile_harness ! ( isize , non_null_check_write_volatile_isize) ;
2733+ generate_write_volatile_harness ! ( u8 , non_null_check_write_volatile_u8) ;
2734+ generate_write_volatile_harness ! ( u16 , non_null_check_write_volatile_u16) ;
2735+ generate_write_volatile_harness ! ( u32 , non_null_check_write_volatile_u32) ;
2736+ generate_write_volatile_harness ! ( u64 , non_null_check_write_volatile_u64) ;
2737+ generate_write_volatile_harness ! ( u128 , non_null_check_write_volatile_u128) ;
2738+ generate_write_volatile_harness ! ( usize , non_null_check_write_volatile_usize) ;
2739+
2740+ macro_rules! generate_write_bytes_harness {
2741+ ( $type: ty, $harness_name: ident) => {
2742+ #[ kani:: proof_for_contract( NonNull :: write_bytes) ]
2743+ pub fn $harness_name( ) {
2744+ // Create a pointer generator for the given type with appropriate byte size
2745+ const ARR_SIZE : usize = mem:: size_of:: <$type>( ) * 10 ;
2746+ let mut generator = kani:: PointerGenerator :: <ARR_SIZE >:: new( ) ;
2747+
2748+ // Get a raw pointer from the generator
2749+ let raw_ptr: * mut $type = generator. any_in_bounds( ) . ptr;
2750+
2751+ // Create a non-null pointer from the raw pointer
2752+ let ptr = NonNull :: new( raw_ptr) . unwrap( ) ;
2753+
2754+ // Create a non-deterministic value to write
2755+ let val: u8 = kani:: any( ) ;
2756+
2757+ // Create a non-deterministic count
2758+ let count: usize = kani:: any( ) ;
2759+
2760+ unsafe {
2761+ // Perform the volatile write operation
2762+ ptr. write_bytes( val, count) ;
2763+
2764+ // Create a non-deterministic count
2765+ let i: usize = kani:: any_where( |& x| x < count * mem:: size_of:: <$type>( ) ) ;
2766+ let ptr_byte = ptr. as_ptr( ) as * const u8 ;
2767+
2768+ // Read back the value and assert it's correct
2769+ assert_eq!( * ptr_byte. add( i) , val) ;
2770+ }
2771+ }
2772+ } ;
2773+ }
2774+
2775+ #[ kani:: proof_for_contract( NonNull :: write_bytes) ]
2776+ pub fn non_null_check_write_bytes_unit ( ) {
2777+ // Create a pointer generator for the given type with appropriate byte size
2778+ let mut generator = kani:: PointerGenerator :: < 1 > :: new ( ) ;
2779+
2780+ // Get a raw pointer from the generator
2781+ let raw_ptr: * mut ( ) = generator. any_in_bounds ( ) . ptr ;
2782+
2783+ // Create a non-null pointer from the raw pointer
2784+ let ptr = NonNull :: new ( raw_ptr) . unwrap ( ) ;
2785+
2786+ // Create a non-deterministic value to write
2787+ let val: u8 = kani:: any ( ) ;
2788+
2789+ // Create a non-deterministic count
2790+ let count: usize = kani:: any ( ) ;
2791+
2792+ unsafe {
2793+ // Perform the volatile write operation
2794+ ptr. write_bytes ( val, count) ;
2795+ }
2796+ }
2797+
25612798 // Generate proof harnesses for multiple types with appropriate byte sizes
2562- generate_write_volatile_harness ! ( i8 , 1 , non_null_check_write_volatile_i8) ;
2563- generate_write_volatile_harness ! ( i16 , 2 , non_null_check_write_volatile_i16) ;
2564- generate_write_volatile_harness ! ( i32 , 4 , non_null_check_write_volatile_i32) ;
2565- generate_write_volatile_harness ! ( i64 , 8 , non_null_check_write_volatile_i64) ;
2566- generate_write_volatile_harness ! ( i128 , 16 , non_null_check_write_volatile_i128) ;
2567- generate_write_volatile_harness ! (
2568- isize ,
2569- { core:: mem:: size_of:: <isize >( ) } ,
2570- non_null_check_write_volatile_isize
2571- ) ;
2572- generate_write_volatile_harness ! ( u8 , 1 , non_null_check_write_volatile_u8) ;
2573- generate_write_volatile_harness ! ( u16 , 2 , non_null_check_write_volatile_u16) ;
2574- generate_write_volatile_harness ! ( u32 , 4 , non_null_check_write_volatile_u32) ;
2575- generate_write_volatile_harness ! ( u64 , 8 , non_null_check_write_volatile_u64) ;
2576- generate_write_volatile_harness ! ( u128 , 16 , non_null_check_write_volatile_u128) ;
2577- generate_write_volatile_harness ! (
2578- usize ,
2579- { core:: mem:: size_of:: <usize >( ) } ,
2580- non_null_check_write_volatile_usize
2581- ) ;
2582- generate_write_volatile_harness ! ( ( ) , 1 , non_null_check_write_volatile_unit) ;
2799+ generate_write_bytes_harness ! ( i8 , non_null_check_write_bytes_i8) ;
2800+ generate_write_bytes_harness ! ( i16 , non_null_check_write_bytes_i16) ;
2801+ generate_write_bytes_harness ! ( i32 , non_null_check_write_bytes_i32) ;
2802+ generate_write_bytes_harness ! ( i64 , non_null_check_write_bytes_i64) ;
2803+ generate_write_bytes_harness ! ( i128 , non_null_check_write_bytes_i128) ;
2804+ generate_write_bytes_harness ! ( isize , non_null_check_write_bytes_isize) ;
2805+ generate_write_bytes_harness ! ( u8 , non_null_check_write_bytes_u8) ;
2806+ generate_write_bytes_harness ! ( u16 , non_null_check_write_bytes_u16) ;
2807+ generate_write_bytes_harness ! ( u32 , non_null_check_write_bytes_u32) ;
2808+ generate_write_bytes_harness ! ( u64 , non_null_check_write_bytes_u64) ;
2809+ generate_write_bytes_harness ! ( u128 , non_null_check_write_bytes_u128) ;
2810+ generate_write_bytes_harness ! ( usize , non_null_check_write_bytes_usize) ;
25832811
25842812 #[ kani:: proof_for_contract( NonNull :: byte_add) ]
25852813 pub fn non_null_byte_add_proof ( ) {
0 commit comments