Skip to content

Commit 467bb49

Browse files
authored
ptr_offset_from: Replace arithmetic over pointers by offset arithmetic (#4180)
Makes `pointer_offset` crate-available just like `pointer_object` is. This enables its use in `ptr_offset_from`, whereby we create expressions that CBMC's simplifier can more readily deal with. Resolves: #2235 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent 173594b commit 467bb49

File tree

5 files changed

+27
-8
lines changed

5 files changed

+27
-8
lines changed

library/kani_core/src/mem.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,9 @@ macro_rules! kani_mem {
287287

288288
/// Get the object offset of the given pointer.
289289
#[doc(hidden)]
290-
#[crate::kani::unstable_feature(
291-
feature = "ghost-state",
292-
issue = 3184,
293-
reason = "experimental ghost state/shadow memory API"
294-
)]
295290
#[kanitool::fn_marker = "PointerOffsetHook"]
296291
#[inline(never)]
297-
pub fn pointer_offset<T: PointeeSized>(_ptr: *const T) -> usize {
292+
pub(crate) fn pointer_offset<T: PointeeSized>(_ptr: *const T) -> usize {
298293
kani_intrinsic()
299294
}
300295
};

library/kani_core/src/models.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ macro_rules! generate_models {
8585
"Offset result and original pointer should point to the same allocation",
8686
);
8787
// The offset must fit in isize since this represents the same allocation.
88-
let offset_bytes = ptr1.addr().wrapping_sub(ptr2.addr()) as isize;
88+
let offset_bytes = kani::mem::pointer_offset(ptr1)
89+
.wrapping_sub(kani::mem::pointer_offset(ptr2))
90+
as isize;
8991
let t_size = size_of::<T>() as isize;
9092
kani::safety_check(
9193
offset_bytes % t_size == 0,

tests/expected/shadow/unsupported_object_size/test.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
// This test checks the maximum object size supported by Kani's shadow
66
// memory model (currently 64)
77

8+
#![feature(core_intrinsics)]
9+
use std::intrinsics::ptr_offset_from_unsigned;
10+
811
static mut SM: kani::shadow::ShadowMem<bool> = kani::shadow::ShadowMem::new(false);
912

1013
fn check_max_objects<const N: usize>() {
1114
let arr: [u8; N] = [0; N];
1215
let last = &arr[N - 1];
13-
assert_eq!(kani::mem::pointer_offset(last as *const u8), N - 1);
16+
unsafe {
17+
assert_eq!(ptr_offset_from_unsigned(last as *const u8, &arr[0] as *const u8), N - 1);
18+
}
1419
// the following call to `set_init` would fail if the object offset for
1520
// `last` exceeds the maximum allowed by Kani's shadow memory model
1621
unsafe {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Failed Checks: called `Option::unwrap()` on a `None` value
2+
Verification failed for - repeat_panic
3+
Complete - 1 successfully verified harnesses, 1 failures, 2 total.

tests/expected/string-repeat/2235.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
#[kani::proof]
5+
fn repeat_const() {
6+
let s = String::from("a").repeat(1);
7+
assert_eq!(s.chars().nth(0).unwrap(), 'a');
8+
}
9+
10+
#[kani::proof]
11+
fn repeat_panic() {
12+
let x = String::new().repeat(1);
13+
let z = x.chars().nth(1).unwrap();
14+
}

0 commit comments

Comments
 (0)