@@ -139,6 +139,8 @@ impl<T: Sized> NonNull<T> {
139
139
#[ must_use]
140
140
#[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
141
141
#[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
142
+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure the pointer is valid to create a reference.
143
+ #[ ensures( |result: &&MaybeUninit <T >| core:: ptr:: eq( * result, self . cast( ) . as_ptr( ) ) ) ] // Ensure returned reference points to the correct memory location.
142
144
pub const unsafe fn as_uninit_ref < ' a > ( self ) -> & ' a MaybeUninit < T > {
143
145
// SAFETY: the caller must guarantee that `self` meets all the
144
146
// requirements for a reference.
@@ -163,6 +165,8 @@ impl<T: Sized> NonNull<T> {
163
165
#[ must_use]
164
166
#[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
165
167
#[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
168
+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure pointer is valid to create a mutable reference.
169
+ #[ ensures( |result: &&mut MaybeUninit <T >| core:: ptr:: eq( * result, self . cast( ) . as_ptr( ) ) ) ] // Ensure the returned reference points to the correct memory.
166
170
pub const unsafe fn as_uninit_mut < ' a > ( self ) -> & ' a mut MaybeUninit < T > {
167
171
// SAFETY: the caller must guarantee that `self` meets all the
168
172
// requirements for a reference.
@@ -386,6 +390,8 @@ impl<T: ?Sized> NonNull<T> {
386
390
#[ rustc_const_stable( feature = "const_nonnull_as_ref" , since = "1.73.0" ) ]
387
391
#[ must_use]
388
392
#[ inline( always) ]
393
+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) as * const ( ) ) ) ] // Ensure input is convertible to a reference
394
+ #[ ensures( |result: &&T | core:: ptr:: eq( * result, self . as_ptr( ) ) ) ] // Ensure returned reference matches pointer
389
395
pub const unsafe fn as_ref < ' a > ( & self ) -> & ' a T {
390
396
// SAFETY: the caller must guarantee that `self` meets all the
391
397
// requirements for a reference.
@@ -424,6 +430,9 @@ impl<T: ?Sized> NonNull<T> {
424
430
#[ rustc_const_stable( feature = "const_ptr_as_ref" , since = "1.83.0" ) ]
425
431
#[ must_use]
426
432
#[ inline( always) ]
433
+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) as * const ( ) ) ) ]
434
+ // verify result (a mutable reference) is still associated with the same memory address as the raw pointer stored in self
435
+ #[ ensures( |result: &&mut T | core:: ptr:: eq( * result, self . as_ptr( ) ) ) ]
427
436
pub const unsafe fn as_mut < ' a > ( & mut self ) -> & ' a mut T {
428
437
// SAFETY: the caller must guarantee that `self` meets all the
429
438
// requirements for a mutable reference.
@@ -1642,6 +1651,11 @@ impl<T> NonNull<[T]> {
1642
1651
#[ must_use]
1643
1652
#[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1644
1653
#[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1654
+ #[ requires( self . as_ptr( ) . cast:: <T >( ) . align_offset( core:: mem:: align_of:: <T >( ) ) == 0 ) ] // Ensure the pointer is properly aligned
1655
+ #[ requires( self . len( ) . checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) && self . len( ) * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize ) ] // Ensure the slice size does not exceed isize::MAX
1656
+ #[ requires( kani:: mem:: same_allocation( self . as_ptr( ) as * const ( ) , self . as_ptr( ) . byte_add( self . len( ) * core:: mem:: size_of:: <T >( ) ) as * const ( ) ) ) ] // Ensure the slice is contained within a single allocation
1657
+ #[ ensures( |result: &&[ MaybeUninit <T >] | result. len( ) == self . len( ) ) ] // Length check
1658
+ #[ ensures( |result: &&[ MaybeUninit <T >] | core:: ptr:: eq( result. as_ptr( ) , self . cast( ) . as_ptr( ) ) ) ] // Ensure the memory addresses match.
1645
1659
pub const unsafe fn as_uninit_slice < ' a > ( self ) -> & ' a [ MaybeUninit < T > ] {
1646
1660
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
1647
1661
unsafe { slice:: from_raw_parts ( self . cast ( ) . as_ptr ( ) , self . len ( ) ) }
@@ -1707,6 +1721,11 @@ impl<T> NonNull<[T]> {
1707
1721
#[ must_use]
1708
1722
#[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1709
1723
#[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1724
+ #[ requires( self . as_ptr( ) . cast:: <T >( ) . align_offset( core:: mem:: align_of:: <T >( ) ) == 0 ) ] // Ensure the pointer is properly aligned
1725
+ #[ requires( self . len( ) . checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) && self . len( ) * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize ) ] // Ensure the slice size does not exceed isize::MAX
1726
+ #[ requires( kani:: mem:: same_allocation( self . as_ptr( ) as * const ( ) , self . as_ptr( ) . byte_add( self . len( ) * core:: mem:: size_of:: <T >( ) ) as * const ( ) ) ) ] // Ensure the slice is contained within a single allocation
1727
+ #[ ensures( |result: &&mut [ MaybeUninit <T >] | result. len( ) == self . len( ) ) ] // Length check
1728
+ #[ ensures( |result: &&mut [ MaybeUninit <T >] | core:: ptr:: eq( result. as_ptr( ) , self . cast( ) . as_ptr( ) ) ) ] // Address check
1710
1729
pub const unsafe fn as_uninit_slice_mut < ' a > ( self ) -> & ' a mut [ MaybeUninit < T > ] {
1711
1730
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
1712
1731
unsafe { slice:: from_raw_parts_mut ( self . cast ( ) . as_ptr ( ) , self . len ( ) ) }
@@ -1735,6 +1754,7 @@ impl<T> NonNull<[T]> {
1735
1754
/// ```
1736
1755
#[ unstable( feature = "slice_ptr_get" , issue = "74265" ) ]
1737
1756
#[ inline]
1757
+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure self can be dereferenced
1738
1758
pub unsafe fn get_unchecked_mut < I > ( self , index : I ) -> NonNull < I :: Output >
1739
1759
where
1740
1760
I : SliceIndex < [ T ] > ,
@@ -1871,7 +1891,7 @@ mod verify {
1871
1891
let maybe_null_ptr = if kani:: any ( ) { xptr as * mut i32 } else { null_mut ( ) } ;
1872
1892
let _ = NonNull :: new ( maybe_null_ptr) ;
1873
1893
}
1874
-
1894
+
1875
1895
// pub const unsafe fn read(self) -> T where T: Sized
1876
1896
#[ kani:: proof_for_contract( NonNull :: read) ]
1877
1897
pub fn non_null_check_read ( ) {
@@ -1996,4 +2016,106 @@ mod verify {
1996
2016
// Trigger panic
1997
2017
let offset = nonnull_xptr. align_offset ( invalid_align) ;
1998
2018
}
2019
+
2020
+ #[ kani:: proof_for_contract( NonNull :: as_mut) ]
2021
+ pub fn non_null_check_as_mut ( ) {
2022
+ let mut x: i32 = kani:: any ( ) ;
2023
+ if let Some ( mut ptr) = NonNull :: new ( & mut x as * mut i32 ) {
2024
+ unsafe {
2025
+ let result = ptr. as_mut ( ) ;
2026
+ }
2027
+ }
2028
+ }
2029
+
2030
+ #[ kani:: proof_for_contract( NonNull :: as_ref) ]
2031
+ pub fn non_null_check_as_ref ( ) {
2032
+ let mut x: i32 = kani:: any ( ) ;
2033
+ if let Some ( ptr) = NonNull :: new ( & mut x as * mut i32 ) {
2034
+ unsafe {
2035
+ let _ = ptr. as_ref ( ) ;
2036
+ }
2037
+ }
2038
+ }
2039
+
2040
+ #[ kani:: proof_for_contract( NonNull :: as_uninit_mut) ]
2041
+ pub fn non_null_check_as_uninit_mut ( ) {
2042
+ use core:: mem:: MaybeUninit ;
2043
+
2044
+ // Create an uninitialized MaybeUninit value
2045
+ let mut uninit: MaybeUninit < i32 > = MaybeUninit :: uninit ( ) ;
2046
+ let mut ptr = NonNull :: new ( uninit. as_mut_ptr ( ) ) . unwrap ( ) ;
2047
+
2048
+ unsafe {
2049
+ let _ = ptr. as_uninit_mut ( ) ;
2050
+ }
2051
+ }
2052
+
2053
+ #[ kani:: proof_for_contract( NonNull :: as_uninit_ref) ]
2054
+ pub fn non_null_check_as_uninit_ref ( ) {
2055
+ use core:: mem:: MaybeUninit ;
2056
+
2057
+ // Create an uninitialized MaybeUninit value
2058
+ let mut uninit: MaybeUninit < i32 > = MaybeUninit :: uninit ( ) ;
2059
+ let ptr = NonNull :: new ( uninit. as_mut_ptr ( ) ) . unwrap ( ) ;
2060
+
2061
+ unsafe {
2062
+ let uninit_ref = ptr. as_uninit_ref ( ) ;
2063
+ }
2064
+ }
2065
+
2066
+ #[ kani:: proof_for_contract( NonNull :: as_uninit_slice) ]
2067
+ pub fn non_null_check_as_uninit_slice ( ) {
2068
+ use core:: mem:: MaybeUninit ;
2069
+
2070
+ const SIZE : usize = 100000 ;
2071
+ let arr: [ MaybeUninit < i32 > ; SIZE ] = MaybeUninit :: uninit_array ( ) ;
2072
+ let slice: & [ MaybeUninit < i32 > ] = kani:: slice:: any_slice_of_array ( & arr) ;
2073
+ let ptr = NonNull :: slice_from_raw_parts (
2074
+ NonNull :: new ( slice. as_ptr ( ) as * mut MaybeUninit < i32 > ) . unwrap ( ) ,
2075
+ slice. len ( ) ,
2076
+ ) ;
2077
+
2078
+ unsafe {
2079
+ let _ = ptr. as_uninit_slice ( ) ;
2080
+ }
2081
+ }
2082
+
2083
+ #[ kani:: proof_for_contract( NonNull :: as_uninit_slice_mut) ]
2084
+ pub fn non_null_check_as_uninit_slice_mut ( ) {
2085
+ use core:: mem:: MaybeUninit ;
2086
+
2087
+ const SIZE : usize = 100000 ;
2088
+ let mut arr: [ MaybeUninit < i32 > ; SIZE ] = MaybeUninit :: uninit_array ( ) ;
2089
+ let slice: & [ MaybeUninit < i32 > ] = kani:: slice:: any_slice_of_array ( & mut arr) ;
2090
+ let ptr = NonNull :: slice_from_raw_parts (
2091
+ NonNull :: new ( slice. as_ptr ( ) as * mut MaybeUninit < i32 > ) . unwrap ( ) ,
2092
+ SIZE ,
2093
+ ) ;
2094
+
2095
+ unsafe {
2096
+ let _ = ptr. as_uninit_slice_mut ( ) ;
2097
+ }
2098
+ }
2099
+
2100
+ #[ kani:: proof_for_contract( NonNull :: get_unchecked_mut) ]
2101
+ pub fn non_null_check_get_unchecked_mut ( ) {
2102
+ const ARR_SIZE : usize = 100000 ;
2103
+ let mut arr: [ i32 ; ARR_SIZE ] = kani:: any ( ) ;
2104
+ let raw_ptr = arr. as_mut_ptr ( ) ;
2105
+ let ptr = NonNull :: slice_from_raw_parts (
2106
+ NonNull :: new ( raw_ptr) . unwrap ( ) ,
2107
+ ARR_SIZE ,
2108
+ ) ;
2109
+ let lower = kani:: any_where ( |x| * x < ARR_SIZE ) ;
2110
+ let upper = kani:: any_where ( |x| * x < ARR_SIZE && * x >= lower) ;
2111
+ unsafe {
2112
+ // NOTE: The `index` parameter cannot be used in the function contracts without being moved.
2113
+ // Since the `SliceIndex` trait does not guarantee that `index` implements `Clone` or `Copy`,
2114
+ // it cannot be reused after being consumed in the precondition. To comply with Rust's ownership
2115
+ // rules and ensure `index` is only used once, the in-bounds check is moved to the proof harness
2116
+ // as a workaround.
2117
+ kani:: assume ( ptr. as_ref ( ) . get ( lower..upper) . is_some ( ) ) ;
2118
+ let _ = ptr. get_unchecked_mut ( lower..upper) ;
2119
+ }
2120
+ }
1999
2121
}
0 commit comments