-
Notifications
You must be signed in to change notification settings - Fork 18
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
Challenge 6: Safety of NonNull
#53
Comments
NonNull
Continuing the discussion from #84.
This sounds like a bug. Can you:
?
Can you post the harness name printed in the Kani output? The name is included in a line of the form:
|
Correct. When verifying a contract (using |
@zhassan-aws I realized I didn't find these proofs being run was because kani has not finished running proofs in the other modules yet, I will let it run for longer to get the complete result for all proofs in the library.
I found the correct full name to be
|
@zhassan-aws Following up on our meeting just now, would you please give us a rundown on Kani's capability to verify the four undefined behaviors for challenge 6? You mentioned that Kani can verify property 1,2, and 4(partially) and we also want to know which flags are verifying these properties. For property 3 is there a timeline on when the check would be released?
|
@feliperodri Hi Felipe, this is Grace from CMU III, I'm the project manager of Team 4. Could you please assign me to the issue as well? |
Correct. No flags are needed for 1 and 2 (the checks are ON by default). For 4, the
For 3, the timeline is not clear at the moment. There is experimental support added in a branch of the Kani repository (i.e. it's not included in the Kani releases): https://github.com/model-checking/kani/tree/features/aliasing-checks. We can perhaps experiment with the current support and see if it's sufficient. |
@zhassan-aws How should we interpret
What does this mean? Is this normal or does that indicate we need to modify the harness? Thanks! |
Hi @QinyuanWu. This indicates that some code that should be unreachable (as indicated by the check name) was indeed proven to be unreachable (as indicated by the |
Thank you @zhassan-aws. Is it possible to view the source coverage as well? I added |
For instance, this program: #[kani::proof]
fn foo() {
let x: i8 = kani::any();
let y: i8 = kani::any();
let z = (x as i16).checked_add(y as i16);
// unwrap the result using a match
let z = match z {
Some(z) => z,
None => unreachable!(),
};
} calls
and thus it proved the |
@zhassan-aws Opened PR for |
@zhassan-aws would appreciate any guidance on the coverage. Thank you! |
If you type in the PR description "Towards #53" the PR will be linked to this issue. |
You also need to pass |
Hi this is Jimmy from team 4. Currently I am working on the harness for sub function in the non null challenge. When I tried to run the harness for sub, I encountered something below: It looks like there is something wrong with kani. My kani version is 0.55.0. Rustc version: 1.83.0-nightly Cargo : 1.83.0-nightly. Any suggestion for this problem? Thanks in advance The command I used
|
Hi @Jimmycreative. I believe this is the same crash in model-checking/kani#3467. Can you post the harness/contract to confirm? @carolynzech did you find a workaround for this crash? |
Depends on what's causing the crash -- @Jimmycreative I would make sure that your harness is actually invoking |
@carolynzech After investigating we found that not invoking the target function was the issue. Thank you! |
Hi @carolynzech and @feliperodri. I am Dhvani Kapadia from AWS Team 4, working on this challenge. Could you please assign me to the issue as well? |
Clarifying Questions Regarding the
|
Hi @Jimmycreative.
That's correct.
If the harness creates a block of memory with an arbitrary size, then it would subsume the case of a single int, char, etc. since these have a block of memory of size 1. So, the short answer is yes.
Since we can't prove things for all possible types with Kani, it would be good to have a sample number of types. A good list of types is mentioned in Challenge 3: https://model-checking.github.io/verify-rust-std/challenges/0003-pointer-arithmentic.html#assumptions.
It should. Note that a subtraction would not be possible for the first element in the vector since the subtraction operation would take the pointer out of the block of allocated memory.
I would guess that this is due to violating this requirement for /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. i.e. even though the multiplication did not overflow for a |
@zhassan-aws Thanks for your reply! It's really helpful! The proof works now only handle the array with a fixed size and uses the last element for subtraction. The element is i32 type. Is this ok for the current stage? Or maybe we need to consider more scenarios you mentioned above? Any suggestion? Thanks in advance. #[kani::requires(!self.as_ptr().is_null())]
#[kani::requires(count <= isize::MAX as usize)] // Ensure count fits within isize range
#[kani::requires(count.checked_mul(core::mem::size_of::<T>()).is_some())] // Prevent offset overflow
#[kani::requires(count * core::mem::size_of::<T>() <= isize::MAX as usize)]
#[kani::ensures(|result: &NonNull<T>| result.as_ptr() == self.as_ptr().offset(-(count as isize)))]
pub const unsafe fn sub(self, count: usize) -> Self
where
T: Sized,
{
if T::IS_ZST {
// Pointer arithmetic does nothing when the pointee is a ZST.
self
} else {
// SAFETY: the caller must uphold the safety contract for `offset`.
// Because the pointee is *not* a ZST, that means that `count` is
// at most `isize::MAX`, and thus the negation cannot overflow.
unsafe { self.offset((count as isize).unchecked_neg()) }
}
} #[kani::proof_for_contract(NonNull::sub)]
pub fn non_null_check_sub() {
const SIZE: usize = 10;
kani::assume(SIZE > 0);
let arr: [i32; SIZE] = kani::any(); // Create a non-deterministic array of size SIZE
let raw_ptr: *mut i32 = arr.as_ptr() as *mut i32; // Get a raw pointer to the array
// Point to the last element of the array
let last_ptr = unsafe { NonNull::new(raw_ptr.add(SIZE - 1)).unwrap() }; // Pointer to the last element
let count: usize = kani::any(); // Create a non-deterministic count value
// Ensure that the subtraction does not go out of the bounds of the array
kani::assume(count < SIZE); // Ensure count is less than SIZE to stay within bounds
unsafe {
// Perform the pointer subtraction from the last element
let result = last_ptr.sub(count);
}
} |
Hi AWS Team, I have a question regarding how to write function contracts using Current Code:
What I want to achieve is make this line works in
|
BTW can you assign this challenge issue to @danielhumanmod @Jimmycreative as well, thanks! |
@zhassan-aws Is |
@carolynzech Would you please point us to the
But encountered the following error:
|
Add an ampersand before let slice = &arr[..end]; |
They're both the same: for |
…d` (#88) Towards #53 ### Changes - added contract and harness for `non_null::new` - added contract and harness for `non_null::new_unchecked` The difference between the two APIs is that `non_null::new` can handle null pointers while `non_null::new_unchecked` does not. Therefore the contract for `non_null::new` does not require a `nonnull` pointer. ### Re-validation To re-validate the verification results, run `kani verify-std -Z unstable-options "path/to/library" -Z function-contracts -Z mem-predicates --harness ptr::non_null::verify::non_null_check_new`. This will run both harnesses. All default checks should pass. --------- Co-authored-by: OwO <[email protected]> Co-authored-by: Zyad Hassan <[email protected]>
@zhassan-aws and @carolynzech, could you please provide examples of using a mapping function in a harness? I'm writing a harness for the map_addr function, which takes a function f as an argument. I'm having trouble implementing this correctly in the harness |
Here's one example: let x: i32 = kani::any();
let ptr1 = &x as *const i32;
let ptr2 = ptr1.map_addr(|addr| addr + 4); Is that what you're looking for? |
Thanks, the issue got resolved |
…d` (model-checking#88) Towards model-checking#53 ### Changes - added contract and harness for `non_null::new` - added contract and harness for `non_null::new_unchecked` The difference between the two APIs is that `non_null::new` can handle null pointers while `non_null::new_unchecked` does not. Therefore the contract for `non_null::new` does not require a `nonnull` pointer. ### Re-validation To re-validate the verification results, run `kani verify-std -Z unstable-options "path/to/library" -Z function-contracts -Z mem-predicates --harness ptr::non_null::verify::non_null_check_new`. This will run both harnesses. All default checks should pass. --------- Co-authored-by: OwO <[email protected]> Co-authored-by: Zyad Hassan <[email protected]>
Challenge 6: Safety of
NonNull
The text was updated successfully, but these errors were encountered: