diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 78e5aec09b18d..b2f6b2ef34dcd 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -2,6 +2,15 @@ //! //! by matthieu-m +use safety::requires; +#[cfg(kani)] +#[unstable(feature="kani", issue="none")] +use core::kani; +#[cfg(kani)] +use core::ub_checks; +#[cfg(kani)] +use crate::boxed::Box; + use core::error::Error; use core::fmt::{self, Debug, Display, Formatter}; #[cfg(not(no_global_oom_handling))] @@ -363,6 +372,8 @@ impl WithHeader { // Safety: // - Assumes that either `value` can be dereferenced, or is the // `NonNull::dangling()` we use when both `T` and `H` are ZSTs. + #[requires((mem::size_of_val_raw(value) == 0 && size_of::() == 0) || + ub_checks::can_dereference(value as *const u8))] unsafe fn drop(&self, value: *mut T) { struct DropGuard { ptr: NonNull, @@ -435,3 +446,22 @@ impl Error for ThinBox { self.deref().source() } } + +#[cfg(kani)] +#[unstable(feature="kani", issue="none")] +mod verify { + use super::*; + + // unsafe fn drop(&self, value: *mut T) + #[kani::proof_for_contract(WithHeader::drop)] + pub fn check_drop() { + let v = Box::::into_raw(Box::new(kani::any::())); + let w = WithHeader::new(kani::any::(), v); + // TODO: this harness is not the most generic possible as we are currently unable to + // express the precondition that the pointer is heap-allocated. + let xptr = Box::::into_raw(Box::new(kani::any::())); + unsafe { + let _ = w.drop(xptr); + } + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 088770facc4c8..cd42fde9ea6e9 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -92,6 +92,7 @@ // Library features: // tidy-alphabetical-start #![cfg_attr(kani, feature(kani))] +#![cfg_attr(kani, feature(ub_checks))] #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] #![cfg_attr(test, feature(str_as_str))]