kani icon indicating copy to clipboard operation
kani copied to clipboard

Kani failed to detect unaligned access to N-ZST pointers

Open giltho opened this issue 2 years ago • 0 comments

CBMC doesn't model pointer alignments, see #1168 . This leads to unsoundness in the kani proofs - although keep in mind that these are really corner cases.

Rust expects pointers to N-aligned ZSTs to have an alignment of N. Creating a misaligned reference, or dereferencing a misaligned pointer is undefined behaviour. That is also the case with pointers to ZSTs, even though dereferencing a pointer to a ZST is no-op.

For example, this code is invalid Rust, and triggers undefined behaviour:

use std::ptr::NonNull;

#[derive(Clone, Copy)]
#[repr(align(32))]
struct Zst32;

#[kani::proof]
pub fn main() {
    unsafe {
        let u: NonNull<Zst32> = NonNull::new_unchecked(8 as *mut Zst32);
        let v = *(u.as_ptr());
    }
}

You can try running it with MIRI in the playground, it is properly caught: the alignment check should fail. However, Kani does not catch it.


Similarly, Rust guarantees that creating references to ZSTs will yield properly-aligned pointers. For example, the following code is a test that is guaranteed to always pass

#[repr(align(32))]
struct Zst32;

#[kani::proof]
pub fn main() {
    let u: Zst32 = Zst32;
    let v = &u;

    assert_eq!((v as *const Zst32 as usize) % 32, 0, "pointers to a 32-ZST should be 32 aligned")
}

But, this test should not pass:

#[repr(align(32))]
struct Zst32;

#[kani::proof]
pub fn main() {
    let u: Zst32 = Zst32;
    let v = &u;

    assert_eq!((v as *const Zst32 as usize) % 4096, 0, "pointers to a 32-ZST should be 4096 aligned - that is incorrect")
}

You can try running it in the playground, with miri or not; it is a bit non-deterministic, but there is a very strong chance that it fails. In kani, it passes. I've tried a few things, and it seems that pointers will behave as if they were aligned on any power of 2 in CBMC.

giltho avatar Jul 06 '22 16:07 giltho