Skip to content
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

Kani does not flag out-of-bounds dereference with kani::vec::any_vec #2759

Closed
zhassan-aws opened this issue Sep 12, 2023 · 4 comments · Fixed by #2765
Closed

Kani does not flag out-of-bounds dereference with kani::vec::any_vec #2759

zhassan-aws opened this issue Sep 12, 2023 · 4 comments · Fixed by #2765
Assignees
Labels
[C] Bug This is a bug. Something isn't working. [F] Soundness Kani failed to detect an issue

Comments

@zhassan-aws
Copy link
Contributor

I tried this code:

#[kani::proof]
fn main() {
    let v = kani::vec::any_vec::<u8, 2>();
    if v.len() == 1 {
        let x = unsafe { *v.as_slice().as_ptr().add(1) };
        println!("{x}");
    }
}

using the following command line invocation:

kani test.rs

with Kani version: 7136495

I expected to see this happen: Kani flags the out-of-bounds pointer dereference.

Instead, this happened: Verification is successful.

@zhassan-aws zhassan-aws added [C] Bug This is a bug. Something isn't working. [F] Soundness Kani failed to detect an issue labels Sep 12, 2023
@zhassan-aws
Copy link
Contributor Author

zhassan-aws commented Sep 12, 2023

This unsoundness is similar to the one reported in #1009.

@arctic-alpaca
Copy link

Adding v.shrink_to(real_length); at https://github.com/model-checking/kani/blob/main/library/kani/src/vec.rs#L15 seems to fix this in my limited testing. I can't run the regression tests locally so I'm not sure whether this affects anything else.

@arctic-alpaca
Copy link

arctic-alpaca commented Sep 13, 2023

It should actually be possible to remove the unsafe part of any_vec() by replacing set_len() with truncate() :

Current impl:

pub fn any_vec<T, const MAX_LENGTH: usize>() -> Vec<T>
where
    T: Arbitrary,
    [(); std::mem::size_of::<[T; MAX_LENGTH]>()]:,
{
    let mut v = exact_vec::<T, MAX_LENGTH>();
    let real_length: usize = any();
    assume(real_length <= MAX_LENGTH);
    unsafe { v.set_len(real_length) };

    v
}

Proposed impl:

pub fn any_vec<T, const MAX_LENGTH: usize>() -> Vec<T>
where
    T: Arbitrary,
    [(); std::mem::size_of::<[T; MAX_LENGTH]>()]:,
{
    let mut v = exact_vec::<T, MAX_LENGTH>();
    let real_length: usize = any();
    assume(real_length <= MAX_LENGTH);
    v.truncate(real_length);
    v.shrink_to(real_length)

    v
}

Again only tested with the code from the first post in this issue.

@zhassan-aws
Copy link
Contributor Author

Thanks @arctic-alpaca. The diff that I was going to propose is doing exactly that:

$ git diff
diff --git a/library/kani/src/vec.rs b/library/kani/src/vec.rs
index 5deb90d0ec1..4df6fafe457 100644
--- a/library/kani/src/vec.rs
+++ b/library/kani/src/vec.rs
@@ -11,7 +11,8 @@ pub fn any_vec<T, const MAX_LENGTH: usize>() -> Vec<T>
     let mut v = exact_vec::<T, MAX_LENGTH>();
     let real_length: usize = any();
     assume(real_length <= MAX_LENGTH);
-    unsafe { v.set_len(real_length) };
+    v.truncate(real_length);
+    v.shrink_to_fit();
 
     v
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C] Bug This is a bug. Something isn't working. [F] Soundness Kani failed to detect an issue
Projects
No open projects
Status: No status
Development

Successfully merging a pull request may close this issue.

3 participants