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 misses out of bounds index for get_unchecked with raw pointer to slice #3707

Open
carolynzech opened this issue Nov 11, 2024 · 5 comments
Assignees
Labels
[C] Bug This is a bug. Something isn't working. [F] Soundness Kani failed to detect an issue

Comments

@carolynzech
Copy link
Contributor

I tried this code:

#![feature(slice_ptr_get)]
use core::ptr::NonNull;

#[kani::proof]
fn out_of_bounds_get_unchecked() {
    const ARR_SIZE: usize = 10;
    let mut arr: [i32; ARR_SIZE] = kani::any();
    let ptr = NonNull::slice_from_raw_parts(
        NonNull::new(arr.as_mut_ptr()).unwrap(),
        ARR_SIZE,
    );

    unsafe {
        let _ = ptr.get_unchecked_mut(100000000);
    }
}

with Kani version: 0.56.0

I expected to see this happen: Verification failed because the index is out of bounds

Instead, this happened: Verification succeeded

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

This can be reproduced without NonNull as well:

#[kani::proof]
fn out_of_bounds_get_unchecked() {
    const ARR_SIZE: usize = 10;
    let mut arr: [i32; ARR_SIZE] = kani::any();
    let ptr = std::ptr::slice_from_raw_parts_mut(
        arr.as_mut_ptr(),
        ARR_SIZE,
    );

    unsafe {
        let _ = ptr.get_unchecked_mut(100);
    }
}
$ cargo kani
...
SUMMARY:
 ** 0 of 5 failed

VERIFICATION:- SUCCESSFUL

@carolynzech carolynzech changed the title Kani misses out of bounds index for NonNull get_unchecked Kani misses out of bounds index for get_unchecked with slice_from_raw_parts pointer Nov 11, 2024
@celinval
Copy link
Contributor

celinval commented Nov 12, 2024

This doesn't seem related to slice_from_raw_parts though. This also succeeds See #3707 (comment) example instead.

#[kani::proof]
fn out_of_bounds_get_unchecked() {
    const ARR_SIZE: usize = 10;
    let mut arr: [i32; ARR_SIZE] = kani::any();
    let ptr = std::ptr::slice_from_raw_parts_mut(
        arr.as_mut_ptr(),
        ARR_SIZE,
    );

    unsafe {
        let _ = ptr.get_unchecked_mut(100);
    }
}

@carolynzech
Copy link
Contributor Author

carolynzech commented Nov 12, 2024

This doesn't seem related to slice_from_raw_parts though. This also succeeds

#[kani::proof]
fn out_of_bounds_get_unchecked() {
    const ARR_SIZE: usize = 10;
    let mut arr: [i32; ARR_SIZE] = kani::any();
    let ptr = std::ptr::slice_from_raw_parts_mut(
        arr.as_mut_ptr(),
        ARR_SIZE,
    );

    unsafe {
        let _ = ptr.get_unchecked_mut(100);
    }
}

@celinval I'm confused -- this example also calls slice_from_raw_parts (the mutable version, but presumably these issues have similar root causes). I can broaden the title to talk about slice_from_raw_parts_mut too.

@celinval
Copy link
Contributor

oops... wrong copy and paste.

#[kani::proof]
fn out_of_bounds_get_unchecked() {
    const ARR_SIZE: usize = 10;
    let mut arr: [i32; ARR_SIZE] = kani::any();
    let ptr = &mut arr as *mut _;

    unsafe {
        let i = ptr.get_unchecked_mut(100);
    }
}

@carolynzech carolynzech changed the title Kani misses out of bounds index for get_unchecked with slice_from_raw_parts pointer Kani misses out of bounds index for get_unchecked with raw pointer to slice Nov 12, 2024
@celinval celinval self-assigned this Nov 12, 2024
@celinval
Copy link
Contributor

I believe the issue here is similar to #1233. We had disabled bounds checks in some intrinsics a long time ago because the semantics were still up in the air when handling offset operations with count 0 and dangling pointers. However, the behavior is well defined, and we need enable those bounds checks again.

In the implementation of get_unchecked_mut, I believe the UB comes from invoking the pointer add, that will eventually invoke the offset intrinsic.

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
None yet
Development

No branches or pull requests

3 participants