@@ -295,6 +295,7 @@ impl<T: ?Sized> NonNull<T> {
295
295
#[ must_use]
296
296
#[ inline]
297
297
#[ stable( feature = "strict_provenance" , since = "CURRENT_RUSTC_VERSION" ) ]
298
+ #[ ensures( |result| result. get( ) == self . as_ptr( ) as * const ( ) as usize ) ]
298
299
pub fn addr ( self ) -> NonZero < usize > {
299
300
// SAFETY: The pointer is guaranteed by the type to be non-null,
300
301
// meaning that the address will be non-zero.
@@ -573,6 +574,11 @@ impl<T: ?Sized> NonNull<T> {
573
574
#[ must_use = "returns a new pointer rather than modifying its argument" ]
574
575
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
575
576
#[ rustc_const_stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
577
+ #[ requires( count. checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( )
578
+ && count * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize
579
+ && ( self . pointer as isize ) . checked_add( count as isize * core:: mem:: size_of:: <T >( ) as isize ) . is_some( ) // check wrapping add
580
+ && kani:: mem:: same_allocation( self . pointer, self . pointer. wrapping_offset( count as isize ) ) ) ]
581
+ #[ ensures( |result: & NonNull <T >| result. as_ptr( ) == self . as_ptr( ) . offset( count as isize ) ) ]
576
582
pub const unsafe fn add ( self , count : usize ) -> Self
577
583
where
578
584
T : Sized ,
@@ -1214,6 +1220,36 @@ impl<T: ?Sized> NonNull<T> {
1214
1220
#[ must_use]
1215
1221
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
1216
1222
#[ rustc_const_unstable( feature = "const_align_offset" , issue = "90962" ) ]
1223
+ #[ ensures( |result| {
1224
+ // Post-condition reference: https://github.com/model-checking/verify-rust-std/pull/69/files
1225
+ let stride = crate :: mem:: size_of:: <T >( ) ;
1226
+ // ZSTs
1227
+ if stride == 0 {
1228
+ if self . pointer. addr( ) % align == 0 {
1229
+ return * result == 0 ;
1230
+ } else {
1231
+ return * result == usize :: MAX ;
1232
+ }
1233
+ }
1234
+ // In this case, the pointer cannot be aligned
1235
+ if ( align % stride == 0 ) && ( self . pointer. addr( ) % stride != 0 ) {
1236
+ return * result == usize :: MAX ;
1237
+ }
1238
+ // Checking if the answer should indeed be usize::MAX when align % stride != 0
1239
+ // requires computing gcd(a, stride), which is too expensive without
1240
+ // quantifiers (https://model-checking.github.io/kani/rfc/rfcs/0010-quantifiers.html).
1241
+ // This should be updated once quantifiers are available.
1242
+ if ( align % stride != 0 && * result == usize :: MAX ) {
1243
+ return true ;
1244
+ }
1245
+ // If we reach this case, either:
1246
+ // - align % stride == 0 and self.pointer.addr() % stride == 0, so it is definitely possible to align the pointer
1247
+ // - align % stride != 0 and result != usize::MAX, so align_offset is claiming that it's possible to align the pointer
1248
+ // Check that applying the returned result does indeed produce an aligned address
1249
+ let product = usize :: wrapping_mul( * result, stride) ;
1250
+ let new_addr = usize :: wrapping_add( product, self . pointer. addr( ) ) ;
1251
+ * result != usize :: MAX && new_addr % align == 0
1252
+ } ) ]
1217
1253
pub const fn align_offset ( self , align : usize ) -> usize
1218
1254
where
1219
1255
T : Sized ,
@@ -1818,6 +1854,7 @@ impl<T: ?Sized> From<&T> for NonNull<T> {
1818
1854
mod verify {
1819
1855
use super :: * ;
1820
1856
use crate :: ptr:: null_mut;
1857
+ use kani:: PointerGenerator ;
1821
1858
1822
1859
// pub const unsafe fn new_unchecked(ptr: *mut T) -> Self
1823
1860
#[ kani:: proof_for_contract( NonNull :: new_unchecked) ]
@@ -1828,7 +1865,7 @@ mod verify {
1828
1865
}
1829
1866
}
1830
1867
1831
- // pub const unsafe fn new(ptr: *mut T) -> Option<Self>
1868
+ // pub const fn new(ptr: *mut T) -> Option<Self>
1832
1869
#[ kani:: proof_for_contract( NonNull :: new) ]
1833
1870
pub fn non_null_check_new ( ) {
1834
1871
let mut x: i32 = kani:: any ( ) ;
@@ -1936,4 +1973,56 @@ mod verify {
1936
1973
let _ = ptr. get_unchecked_mut ( lower..upper) ;
1937
1974
}
1938
1975
}
1976
+
1977
+ // pub const unsafe fn add(self, count: usize) -> Self
1978
+ #[ kani:: proof_for_contract( NonNull :: add) ]
1979
+ pub fn non_null_check_add ( ) {
1980
+ const SIZE : usize = 100000 ;
1981
+ let mut generator = PointerGenerator :: < 100000 > :: new ( ) ;
1982
+ let raw_ptr: * mut i8 = generator. any_in_bounds ( ) . ptr ;
1983
+ let ptr = unsafe { NonNull :: new ( raw_ptr) . unwrap ( ) } ;
1984
+ // Create a non-deterministic count value
1985
+ let count: usize = kani:: any ( ) ;
1986
+
1987
+ unsafe {
1988
+ let result = ptr. add ( count) ;
1989
+ }
1990
+ }
1991
+
1992
+ // pub fn addr(self) -> NonZero<usize>
1993
+ #[ kani:: proof_for_contract( NonNull :: addr) ]
1994
+ pub fn non_null_check_addr ( ) {
1995
+ // Create NonNull pointer & get pointer address
1996
+ let x = kani:: any :: < usize > ( ) as * mut i32 ;
1997
+ let Some ( nonnull_xptr) = NonNull :: new ( x) else { return ; } ;
1998
+ let address = nonnull_xptr. addr ( ) ;
1999
+ }
2000
+
2001
+ // pub fn align_offset(self, align: usize) -> usize
2002
+ #[ kani:: proof_for_contract( NonNull :: align_offset) ]
2003
+ pub fn non_null_check_align_offset ( ) {
2004
+ // Create NonNull pointer
2005
+ let x = kani:: any :: < usize > ( ) as * mut i32 ;
2006
+ let Some ( nonnull_xptr) = NonNull :: new ( x) else { return ; } ;
2007
+
2008
+ // Call align_offset with valid align value
2009
+ let align: usize = kani:: any ( ) ;
2010
+ kani:: assume ( align. is_power_of_two ( ) ) ;
2011
+ nonnull_xptr. align_offset ( align) ;
2012
+ }
2013
+
2014
+ // pub fn align_offset(self, align: usize) -> usize
2015
+ #[ kani:: should_panic]
2016
+ #[ kani:: proof_for_contract( NonNull :: align_offset) ]
2017
+ pub fn non_null_check_align_offset_negative ( ) {
2018
+ // Create NonNull pointer
2019
+ let x = kani:: any :: < usize > ( ) as * mut i8 ;
2020
+ let Some ( nonnull_xptr) = NonNull :: new ( x) else { return ; } ;
2021
+
2022
+ // Generate align value that is not necessarily a power of two
2023
+ let invalid_align: usize = kani:: any ( ) ;
2024
+
2025
+ // Trigger panic
2026
+ let offset = nonnull_xptr. align_offset ( invalid_align) ;
2027
+ }
1939
2028
}
0 commit comments