Skip to content

Commit 0ed4f75

Browse files
SahithiMVaa-lunaMooniniteErrcarolynzechzhassan-aws
authored
NonZero (new_unchecked) Proof for Contract (Init) (#109)
Working on #71 (Safety of NonZero) We are looking for feedback on our proof_for_contract. We have implemented it for all the data types. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: aaluna <[email protected]> Co-authored-by: aaluna <[email protected]> Co-authored-by: Carolyn Zech <[email protected]> Co-authored-by: Zyad Hassan <[email protected]>
1 parent 576fbe4 commit 0ed4f75

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

library/core/src/num/nonzero.rs

+57-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
88
use crate::panic::{RefUnwindSafe, UnwindSafe};
99
use crate::str::FromStr;
1010
use crate::{fmt, intrinsics, ptr, ub_checks};
11-
11+
use safety::{ensures, requires};
12+
#[cfg(kani)]
13+
use crate::kani;
1214
/// A marker trait for primitive types which can be zero.
1315
///
1416
/// This is an implementation detail for <code>[NonZero]\<T></code> which may disappear or be replaced at any time.
@@ -364,6 +366,27 @@ where
364366
#[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
365367
#[must_use]
366368
#[inline]
369+
// #[rustc_allow_const_fn_unstable(const_refs_to_cell)] enables byte-level
370+
// comparisons within const functions. This is needed here to validate the
371+
// contents of `T` by converting a pointer to a `u8` slice for our `requires`
372+
// and `ensures` checks.
373+
#[rustc_allow_const_fn_unstable(const_refs_to_cell)]
374+
#[requires({
375+
let size = core::mem::size_of::<T>();
376+
let ptr = &n as *const T as *const u8;
377+
let slice = unsafe { core::slice::from_raw_parts(ptr, size) };
378+
!slice.iter().all(|&byte| byte == 0)
379+
})]
380+
#[ensures(|result: &Self|{
381+
let size = core::mem::size_of::<T>();
382+
let n_ptr: *const T = &n;
383+
let result_inner: T = result.get();
384+
let result_ptr: *const T = &result_inner;
385+
let n_slice = unsafe { core::slice::from_raw_parts(n_ptr as *const u8, size) };
386+
let result_slice = unsafe { core::slice::from_raw_parts(result_ptr as *const u8, size) };
387+
388+
n_slice == result_slice
389+
})]
367390
pub const unsafe fn new_unchecked(n: T) -> Self {
368391
match Self::new(n) {
369392
Some(n) => n,
@@ -2159,3 +2182,36 @@ nonzero_integer! {
21592182
swapped = "0x5634129078563412",
21602183
reversed = "0x6a2c48091e6a2c48",
21612184
}
2185+
2186+
#[unstable(feature="kani", issue="none")]
2187+
#[cfg(kani)]
2188+
mod verify {
2189+
use super::*;
2190+
2191+
macro_rules! nonzero_check {
2192+
($t:ty, $nonzero_type:ty, $nonzero_check_new_unchecked_for:ident) => {
2193+
#[kani::proof_for_contract(NonZero::new_unchecked)]
2194+
pub fn $nonzero_check_new_unchecked_for() {
2195+
let x: $t = kani::any(); // Generates a symbolic value of the provided type
2196+
2197+
unsafe {
2198+
<$nonzero_type>::new_unchecked(x); // Calls NonZero::new_unchecked for the specified NonZero type
2199+
}
2200+
}
2201+
};
2202+
}
2203+
2204+
// Use the macro to generate different versions of the function for multiple types
2205+
nonzero_check!(i8, core::num::NonZeroI8, nonzero_check_new_unchecked_for_i8);
2206+
nonzero_check!(i16, core::num::NonZeroI16, nonzero_check_new_unchecked_for_16);
2207+
nonzero_check!(i32, core::num::NonZeroI32, nonzero_check_new_unchecked_for_32);
2208+
nonzero_check!(i64, core::num::NonZeroI64, nonzero_check_new_unchecked_for_64);
2209+
nonzero_check!(i128, core::num::NonZeroI128, nonzero_check_new_unchecked_for_128);
2210+
nonzero_check!(isize, core::num::NonZeroIsize, nonzero_check_new_unchecked_for_isize);
2211+
nonzero_check!(u8, core::num::NonZeroU8, nonzero_check_new_unchecked_for_u8);
2212+
nonzero_check!(u16, core::num::NonZeroU16, nonzero_check_new_unchecked_for_u16);
2213+
nonzero_check!(u32, core::num::NonZeroU32, nonzero_check_new_unchecked_for_u32);
2214+
nonzero_check!(u64, core::num::NonZeroU64, nonzero_check_new_unchecked_for_u64);
2215+
nonzero_check!(u128, core::num::NonZeroU128, nonzero_check_new_unchecked_for_u128);
2216+
nonzero_check!(usize, core::num::NonZeroUsize, nonzero_check_new_unchecked_for_usize);
2217+
}

0 commit comments

Comments
 (0)