-
Notifications
You must be signed in to change notification settings - Fork 115
Semantics of ZST dangling pointers: Kani differs from Miri #1574
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
Comments
They must also not be OOB, if they do have the provenance of some allocation. I wonder, how do you model Rust's |
However, I should also note that these are just the current rules in Miri, not some final decision about Rust semantics. There are several threads in the UCG related to this question, e.g. rust-lang/unsafe-code-guidelines#93. |
Our modeling of the
As the doc comment says, we currently don't check that the resulting pointer stays within bounds of the object. |
Right, indeed it is okay for it to leave the bounds of the object. But when the pointer is actually used, then it must be in-bounds of the offset it started out from. So this is an interesting test for provenance. |
Kani supposedly handles the out-of-bounds pointer dereference correctly, e.g.: #[cfg_attr(kani, kani::proof)]
fn main() {
let arr = [1u8, 2, 3, 4, 5];
let ptr1: *const u8 = arr.as_ptr();
let ptr2 = ptr1.wrapping_offset(5);
//let _v = unsafe { *ptr2 };
}
And uncommenting the
|
Yes Kani handles wrapping offset very well, but it fails at detecting overflow for non-wrapping offset operators. #[kani::proof]
fn main() {
let x: [u32; 4] = [0, 1, 2, 3];
let p = &x as *const [u32; 4] as *const u32;
let _pp = unsafe { p.offset(1000) };
} |
Actually, it's maybe not that expensive, Kanillian supports it and will correctly fail on that example |
For CBMC to detect that case, we probably just need to explicitly add the boundary check after the offset call. |
I believe this issue is related to #763. We used to enable CBMC's offset checks, but we decided to disable them. |
Correct: running @giltho's example with:
correctly reports the issue:
|
Interesting, but then you indeed end up doing oob checks on dangling pointers which causes spurious errors. In Kanillian, I model ZST pointers as "any non-0 usize with the right alignment". However, that means I'm not tracking pointer provenance, which is unsound |
FWIW there are some arguments that might make us change MiniRust to allow UAF and OOB pointers for zero-sized accesses. |
Reading threads and issues about ZST pointer arithmetics is such a rabbit hole, I've been reading these for the last 2 hours hahahaha |
Only in the sense that if we weren't based on LLVM I would advocate even more strongly in favor of making Also see this discussion. |
I believe this can be closed since we have updated Kani to always accept ZST access as decided in this issue: rust-lang/unsafe-code-guidelines#472 |
Dangling pointers in Rust are considered valid by Miri as long as they are not null, aligned, not deallocated, not out of bounds (if they have the provenance of some allocation) and we don't read or write more than zero bytes from/to the memory location they point to. By contrast, CBMC considers reading and writing from/to such dangling pointers to be UB, for example in
memcmp(..., ..., 0)
.This was originally discovered in #1489 but the same problem could occur with other functions than
memcmp
, so we should probably figure out a better way to deal with it. Previous discussion:memcmp
: Mitigate issue with dangling pointers andmemcmp
#1526memcmp
#1526 (comment)--pointer-primitive-check
fails on__CPROVER_r_ok(ptr, 0)
whenptr = malloc(0)
diffblue/cbmc#7064.--pointer-primitive-check
fails on__CPROVER_r_ok(ptr, 0)
whenptr = malloc(0)
diffblue/cbmc#7064 (comment)). So the interpretation of the C standard seems to differ here.The text was updated successfully, but these errors were encountered: