Skip to content

Commit bb44f4b

Browse files
committed
Add safety preconditions to alloc/src/boxed/thin.rs
Note that I've added `#[requires]` attributes to represent the safety conditions as code contracts. These are based on the "SAFETY:" comments in the original code. The conditions are: 1. For `with_header`, we require that the pointer is aligned. 2. For `drop`, we require that the value pointer is either null or aligned. 3. For `header`, we require that the pointer is aligned. These contracts ensure that the safety conditions mentioned in the comments are checked at compile-time or runtime, depending on the contract system used.
1 parent 3a967e3 commit bb44f4b

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

library/alloc/src/boxed/thin.rs

+32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
//! <https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs>
33
//! by matthieu-m
44
5+
use safety::requires;
6+
#[cfg(kani)]
7+
#[unstable(feature="kani", issue="none")]
8+
use core::kani;
9+
510
use core::error::Error;
611
use core::fmt::{self, Debug, Display, Formatter};
712
#[cfg(not(no_global_oom_handling))]
@@ -185,6 +190,7 @@ impl<T: ?Sized> ThinBox<T> {
185190
}
186191

187192
fn with_header(&self) -> &WithHeader<<T as Pointee>::Metadata> {
193+
#[requires(self.ptr.0.is_aligned())]
188194
// SAFETY: both types are transparent to `NonNull<u8>`
189195
unsafe { &*(core::ptr::addr_of!(self.ptr) as *const WithHeader<_>) }
190196
}
@@ -361,6 +367,7 @@ impl<H> WithHeader<H> {
361367
}
362368

363369
// Safety:
370+
#[requires(value.is_null() || value.is_aligned())]
364371
// - Assumes that either `value` can be dereferenced, or is the
365372
// `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
366373
unsafe fn drop<T: ?Sized>(&self, value: *mut T) {
@@ -404,6 +411,7 @@ impl<H> WithHeader<H> {
404411
}
405412

406413
fn header(&self) -> *mut H {
414+
#[requires(self.0.as_ptr().is_aligned())]
407415
// Safety:
408416
// - At least `size_of::<H>()` bytes are allocated ahead of the pointer.
409417
// - We know that H will be aligned because the middle pointer is aligned to the greater
@@ -435,3 +443,27 @@ impl<T: ?Sized + Error> Error for ThinBox<T> {
435443
self.deref().source()
436444
}
437445
}
446+
447+
#[cfg(kani)]
448+
#[unstable(feature="kani", issue="none")]
449+
mod verify {
450+
use super::*;
451+
452+
// fn with_header(&self) -> &WithHeader<<T as Pointee>::Metadata>
453+
#[kani::proof_for_contract(impl<T::with_header)]
454+
pub fn check_with_header() {
455+
let _ = with_header(kani::any());
456+
}
457+
458+
// fn drop(&mut self)
459+
#[kani::proof_for_contract(impl<T::drop)]
460+
pub fn check_drop() {
461+
let _ = drop(kani::any());
462+
}
463+
464+
// fn header(&self) -> *mut H
465+
#[kani::proof_for_contract(::header)]
466+
pub fn check_header() {
467+
let _ = header(kani::any());
468+
}
469+
}

0 commit comments

Comments
 (0)