Skip to content

Commit 79c6536

Browse files
committed
Add a few ensure clauses
1 parent 898f08f commit 79c6536

File tree

1 file changed

+44
-20
lines changed

1 file changed

+44
-20
lines changed

library/core/src/intrinsics.rs

+44-20
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
)]
6464
#![allow(missing_docs)]
6565

66-
use safety::requires;
66+
use safety::{ensures, requires};
6767
use crate::marker::DiscriminantKind;
6868
use crate::marker::Tuple;
6969
use crate::ptr;
@@ -2728,6 +2728,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
27282728
#[requires(ub_checks::can_dereference(y) && ub_checks::can_write(y))]
27292729
#[requires(x.addr() != y.addr() || core::mem::size_of::<T>() == 0)]
27302730
#[requires(ub_checks::is_nonoverlapping(x as *const (), x as *const (), size_of::<T>(), 1))]
2731+
#[ensures(|_| ub_checks::can_dereference(x) && ub_checks::can_dereference(y))]
27312732
pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
27322733
// SAFETY: The caller provided single non-overlapping items behind
27332734
// pointers, so swapping them with `count: 1` is fine.
@@ -2957,13 +2958,23 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
29572958
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
29582959
#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
29592960
// Copy is "untyped".
2961+
#[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
29602962
#[requires(!count.overflowing_mul(size_of::<T>()).1
29612963
&& ub_checks::can_dereference(core::ptr::slice_from_raw_parts(src as *const crate::mem::MaybeUninit<T>, count))
29622964
&& ub_checks::can_write(core::ptr::slice_from_raw_parts_mut(dst, count)))]
29632965
#[requires(ub_checks::is_nonoverlapping(src as *const (), dst as *const (), size_of::<T>(), count))]
2964-
// TODO: Modifies doesn't work with slices today.
2965-
// https://github.com/model-checking/kani/pull/3295
2966-
// #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
2966+
// TODO: Use quantifiers once it's available.
2967+
// Ensures the initialization state is preserved.
2968+
#[ensures(|_| {
2969+
if count > 0 {
2970+
let byte = kani::any_where(| sz: &usize | *sz < size_of::< T >);
2971+
let elem = kani::any_where(| val: &usize | *val < count);
2972+
let src_data = src as * const u8;
2973+
let dst_data = unsafe { dst.offset(elem) } as * const u8;
2974+
ub_checks::can_dereference(unsafe { src_data.offset(byte) })
2975+
== ub_checks::can_dereference(unsafe { dst_data.offset(byte) })
2976+
}
2977+
})]
29672978
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
29682979
extern "rust-intrinsic" {
29692980
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
@@ -3066,13 +3077,20 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
30663077
#[inline(always)]
30673078
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
30683079
#[rustc_diagnostic_item = "ptr_copy"]
3069-
// FIXME: How to verify safety for types that do not implement Copy and count > 1??
3080+
// FIXME(kani): How to verify safety for types that do not implement Copy and count > 1??
30703081
#[requires(!count.overflowing_mul(size_of::<T>()).1
30713082
&& ub_checks::can_dereference(core::ptr::slice_from_raw_parts(src as *const crate::mem::MaybeUninit<T>, count))
30723083
&& ub_checks::can_write(core::ptr::slice_from_raw_parts_mut(dst, count)))]
3073-
// TODO: Modifies doesn't work with slices today.
3074-
// https://github.com/model-checking/kani/pull/3295
3075-
// #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
3084+
#[ensures(|_| {
3085+
if count > 0 {
3086+
let byte = kani::any_where(| sz: &usize | *sz < size_of::< T >);
3087+
let elem = kani::any_where(| val: &usize | *val < count);
3088+
let src_data = src as * const u8;
3089+
let dst_data = unsafe { dst.offset(elem) } as * const u8;
3090+
ub_checks::can_dereference(unsafe { src_data.offset(byte) })
3091+
== ub_checks::can_dereference(unsafe { dst_data.offset(byte) })
3092+
}
3093+
})]
30763094
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
30773095
extern "rust-intrinsic" {
30783096
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
@@ -3156,11 +3174,14 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
31563174
#[inline(always)]
31573175
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
31583176
#[rustc_diagnostic_item = "ptr_write_bytes"]
3177+
#[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
31593178
#[requires(!count.overflowing_mul(size_of::<T>()).1
31603179
&& ub_checks::can_write(core::ptr::slice_from_raw_parts_mut(dst as *mut u8, count)))]
3161-
// TODO: Modifies doesn't work with slices today.
3162-
// https://github.com/model-checking/kani/pull/3295
3163-
// #[cfg_attr(kani, kani::modifies(crate::ptr::slice_from_raw_parts(dst, count)))]
3180+
// TODO: Change this to quantifiers when available.
3181+
#[ensures(|_| {
3182+
let idx = kani::any_where(|idx: &usize| *idx < count);
3183+
ub_checks::can_dereference(dst.offset(idx) as * const u8)
3184+
})]
31643185
pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
31653186
extern "rust-intrinsic" {
31663187
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
@@ -3208,6 +3229,7 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
32083229
#[unstable(feature="kani", issue="none")]
32093230
mod verify {
32103231
use core::{cmp, fmt};
3232+
use core::ptr::addr_of_mut;
32113233
use super::*;
32123234
use crate::kani;
32133235

@@ -3270,16 +3292,18 @@ mod verify {
32703292
bytes: u64,
32713293
}
32723294
let mut single = kani::any::<u32>();
3273-
let ptr1 = crate::ptr::addr_of_mut!(single);
3295+
let ptr1 = addr_of_mut!(single);
32743296

3275-
let mut array = [kani::any::<u32>(); 100];
3276-
let ptr2 = crate::ptr::addr_of_mut!(array) as *mut u32;
3297+
// FIXME(kani) this should be but this is not available in `kani_core` yet:
3298+
// let mut array: [u8; 100] = kani::any();
3299+
let mut array = [kani::any::<u32>(), 100];
3300+
let ptr2 = addr_of_mut!(array) as *mut u32;
32773301

3278-
let mut buffer = [0u8, 6];
3279-
let unaligned = unsafe { crate::ptr::addr_of_mut!(buffer).byte_offset(1) } as *mut u32;
3302+
let mut buffer = [0u8; 6];
3303+
let unaligned = unsafe { addr_of_mut!(buffer).byte_offset(1) } as *mut u32;
32803304

3281-
let mut padding = WithPadding { byte: 0, bytes: 0};
3282-
let uninit = unsafe { crate::ptr::addr_of_mut!(padding.byte).byte_offset(4)} as *mut u32;
3305+
let mut padding = WithPadding { byte: kani::any(), bytes: kani::any()};
3306+
let uninit = unsafe { addr_of_mut!(padding.byte).byte_offset(4)} as *mut u32;
32833307

32843308
let arbitrary = ArbitraryPointers::from(ptr1, ptr2, unaligned, uninit);
32853309
harness(arbitrary);
@@ -3348,7 +3372,7 @@ mod verify {
33483372
});
33493373
}
33503374

3351-
/// This harness currently fails because we cannot define the modifies clause for slices.
3375+
/// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
33523376
#[kani::proof_for_contract(copy_nonoverlapping)]
33533377
fn check_copy_nonoverlapping() {
33543378
ArbitraryPointers::<u32>::with_arbitrary(|arbitrary| {
@@ -3360,7 +3384,7 @@ mod verify {
33603384
});
33613385
}
33623386

3363-
/// This harness currently fails because we cannot define the modifies clause for slices.
3387+
/// FIXME(kani): This harness currently fails because we cannot define the modifies clause for slices.
33643388
#[kani::proof_for_contract(write_bytes)]
33653389
fn check_write_bytes() {
33663390
ArbitraryPointers::<u32>::with_arbitrary(|arbitrary| {

0 commit comments

Comments
 (0)