Skip to content

Contracts & Harnesses for byte_add, byte_offset, and byte_offset_from #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Dec 3, 2024
Merged
Changes from 12 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
bcdedb8
verification for byte_add, byte_offset, and byte_offset_from
danielhumanmod Oct 5, 2024
009c561
remove redundant requires and add TODO
danielhumanmod Oct 23, 2024
a8974ed
Merge branch 'main' into daniel/byte_operation
danielhumanmod Oct 23, 2024
3a986c5
fix error for byte_offset()
danielhumanmod Oct 24, 2024
fff0e6a
add contracts with same_allocation
danielhumanmod Nov 1, 2024
7ce2d89
simplify contract for byte_offset
danielhumanmod Nov 5, 2024
459a692
refactor proof harness with pointer generator for byte_offset_from
danielhumanmod Nov 5, 2024
d95ad3e
Merge branch 'main' into daniel/byte_operation
danielhumanmod Nov 5, 2024
670adef
update code based on comments
danielhumanmod Nov 8, 2024
505f90b
Merge branch 'daniel/byte_operation' of https://github.com/danielhuma…
danielhumanmod Nov 8, 2024
e6c6795
update contracts
danielhumanmod Nov 13, 2024
293d9c8
remove unnecessary preconditions
danielhumanmod Nov 13, 2024
40b3833
fix comment issues
danielhumanmod Nov 14, 2024
42cb421
Merge remote-tracking branch 'origin' into daniel/byte_operation
danielhumanmod Nov 15, 2024
16bf419
adjust the usage of pointer generator
danielhumanmod Nov 15, 2024
8451bcb
unify contracts
danielhumanmod Nov 15, 2024
98a196a
fix overflow fail case
danielhumanmod Nov 16, 2024
fbccaa2
Merge branch 'main' of https://github.com/danielhumanmod/verify-rust-…
danielhumanmod Nov 27, 2024
c1b4488
Merge branch 'main' of https://github.com/danielhumanmod/verify-rust-…
danielhumanmod Nov 27, 2024
48b30e5
Merge branch 'main' into daniel/byte_operation
danielhumanmod Nov 28, 2024
0e11499
Merge branch 'main' into daniel/byte_operation
danielhumanmod Nov 28, 2024
7c7ae14
dangling pointer verification
danielhumanmod Dec 2, 2024
e383340
Merge branch 'daniel/byte_operation' of https://github.com/danielhuma…
danielhumanmod Dec 2, 2024
bed291b
Merge branch 'main' into daniel/byte_operation
danielhumanmod Dec 2, 2024
0f1c6d3
comment
danielhumanmod Dec 3, 2024
2c68cf4
Merge branch 'main' of https://github.com/danielhumanmod/verify-rust-…
danielhumanmod Dec 3, 2024
18188e6
Merge branch 'main' into daniel/byte_operation
tautschnig Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,11 @@ impl<T: ?Sized> NonNull<T> {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[stable(feature = "non_null_convenience", since = "1.80.0")]
#[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
#[kani::requires(
(self.as_ptr().addr() as isize).checked_add(count).is_some() &&
kani::mem::same_allocation(self.as_ptr() as *const(), self.as_ptr().byte_offset(count) as *const())
)]
#[kani::ensures(|result: &Self| result.as_ptr() == self.as_ptr().byte_offset(count))]
pub const unsafe fn byte_offset(self, count: isize) -> Self {
// SAFETY: the caller must uphold the safety contract for `offset` and `byte_offset` has
// the same safety contract.
Expand Down Expand Up @@ -579,6 +584,14 @@ impl<T: ?Sized> NonNull<T> {
#[rustc_allow_const_fn_unstable(set_ptr_value)]
#[stable(feature = "non_null_convenience", since = "1.80.0")]
#[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
#[kani::requires(
self.as_ptr().addr().checked_add(count).is_some() &&
kani::mem::same_allocation(self.as_ptr() as *const(),((self.as_ptr().addr()) + count) as *const())
)]
#[kani::ensures(
|result: &NonNull<T>|
result.as_ptr().addr() == (self.as_ptr().addr() + count)
)]
pub const unsafe fn byte_add(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `add` and `byte_add` has the same
// safety contract.
Expand Down Expand Up @@ -783,6 +796,11 @@ impl<T: ?Sized> NonNull<T> {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[stable(feature = "non_null_convenience", since = "1.80.0")]
#[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")]
#[kani::requires(kani::mem::same_allocation(self.as_ptr() as *const(), origin.as_ptr() as *const()))]
#[kani::ensures(
|result: &isize|
*result == (self.as_ptr() as *const u8).offset_from(origin.as_ptr() as *const u8)
)]
pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: NonNull<U>) -> isize {
// SAFETY: the caller must uphold the safety contract for `byte_offset_from`.
unsafe { self.pointer.byte_offset_from(origin.pointer) }
Expand Down Expand Up @@ -1785,6 +1803,8 @@ impl<T: ?Sized> From<&T> for NonNull<T> {
mod verify {
use super::*;
use crate::ptr::null_mut;
use crate::mem;
use kani::PointerGenerator;

// pub const unsafe fn new_unchecked(ptr: *mut T) -> Self
#[kani::proof_for_contract(NonNull::new_unchecked)]
Expand All @@ -1803,4 +1823,58 @@ mod verify {
let maybe_null_ptr = if kani::any() { xptr as *mut i32 } else { null_mut() };
let _ = NonNull::new(maybe_null_ptr);
}

#[kani::proof_for_contract(NonNull::byte_add)]
pub fn non_null_byte_add_proof() {
const ARR_SIZE: usize = 100000;
let arr: [i32; ARR_SIZE] = kani::any();
let offset = kani::any_where(|x| *x <= ARR_SIZE);
let raw_ptr: *mut i32 = arr.as_ptr() as *mut i32;
let ptr = unsafe { NonNull::new(raw_ptr.add(offset)).unwrap() };
let count: usize = kani::any();

unsafe {
let result = ptr.byte_add(count);
}
}

#[kani::proof_for_contract(NonNull::byte_offset)]
pub fn non_null_byte_offset_proof() {
const ARR_SIZE: usize = 100000;
let arr: [i32; ARR_SIZE] = kani::any();
let offset = kani::any_where(|x| *x <= ARR_SIZE);
let raw_ptr: *mut i32 = arr.as_ptr() as *mut i32;
let ptr = unsafe { NonNull::new(raw_ptr.add(offset)).unwrap() };
let count: isize = kani::any();

unsafe {
let result = ptr.byte_offset(count);
}
}

#[kani::proof_for_contract(NonNull::byte_offset_from)]
pub fn non_null_byte_offset_from_proof() {
const SIZE: usize = mem::size_of::<i32>() * 10;
let mut generator1 = PointerGenerator::<SIZE>::new();
let mut generator2 = PointerGenerator::<SIZE>::new();

let ptr: *mut i32 = if kani::any() {
generator1.any_in_bounds().ptr as *mut i32
} else {
generator2.any_in_bounds().ptr as *mut i32
};

let origin: *mut i32 = if kani::any() {
generator1.any_in_bounds().ptr as *mut i32
} else {
generator2.any_in_bounds().ptr as *mut i32
};

let ptr_nonnull = unsafe { NonNull::new(ptr).unwrap() };
let origin_nonnull = unsafe { NonNull::new(origin).unwrap() };

unsafe {
let result = ptr_nonnull.byte_offset_from(origin_nonnull);
}
}
}
Loading