Skip to content

Commit

Permalink
Fix the computation of the number of bytes of a pointer offset
Browse files Browse the repository at this point in the history
  • Loading branch information
zhassan-aws committed Oct 9, 2024
1 parent f17cc4d commit fd39cfc
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 3 deletions.
2 changes: 1 addition & 1 deletion kani-compiler/src/codegen_cprover_gotoc/codegen/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ impl<'tcx> GotocCtx<'tcx> {
// Check that computing `offset` in bytes would not overflow
let (offset_bytes, bytes_overflow_check) = self.count_in_bytes(
ce2.clone().cast_to(Type::ssize_t()),
ty,
pointee_type_stable(ty).unwrap(),
Type::ssize_t(),
"offset",
loc,
Expand Down
2 changes: 1 addition & 1 deletion tests/expected/offset-from-bytes-overflow/expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
FAILURE\
attempt to compute offset which would overflow
attempt to compute number in bytes which would overflow
2 changes: 1 addition & 1 deletion tests/expected/offset-overflow/expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
FAILURE\
attempt to compute offset which would overflow
attempt to compute number in bytes which would overflow
5 changes: 5 additions & 0 deletions tests/expected/ptr-offset-overflow/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
std::ptr::const_ptr::<impl *const Foo>::offset.arithmetic_overflow\
Status: FAILURE\
Description: "offset: attempt to compute number in bytes which would overflow"

VERIFICATION:- FAILED
27 changes: 27 additions & 0 deletions tests/expected/ptr-offset-overflow/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT

//! This test checks that Kani detects the overflow in pointer offset

use std::convert::TryFrom;

struct Foo {
arr: [i32; 4096],
}

#[cfg_attr(kani, kani::proof)]
fn main() {
let f = Foo { arr: [0; 4096] };
assert_eq!(std::mem::size_of::<Foo>(), 16384);
// a large enough count that causes `count * size_of::<Foo>()` to overflow
// `isize` without overflowing `usize`
let count: usize = 562949953421320;
// the `unwrap` ensures that it indeed doesn't overflow `usize`
let bytes = count.checked_mul(std::mem::size_of::<Foo>()).unwrap();
// ensure that it overflows `isize`:
assert!(isize::try_from(bytes).is_err());

let ptr: *const Foo = &f as *const Foo;
// this should fail because `count * size_of::<Foo>` overflows `isize`
let _p = unsafe { ptr.offset(count as isize) };
}

0 comments on commit fd39cfc

Please sign in to comment.