Challenge 29: Verify Boxed safety in alloc::boxed, alloc::boxed::convert and alloc::boxed::thin with Kani#589
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Kani-based verification artifacts for Challenge 29 across alloc::boxed (including ThinBox) by introducing Kani harness modules and attaching Kani-only contracts (cfg_attr(kani, ...)) to selected unsafe APIs, without altering normal runtime behavior.
Changes:
- Adds Kani preconditions/postconditions to boxed raw-pointer reconstruction and unchecked downcast APIs.
- Introduces extensive
#[cfg(kani)]proof harness modules forBox,ThinBox, and header utilities across representative concrete instantiations. - Updates
library/Cargo.lockto include thesafetyproc-macro crate (and its transitive deps) in the lockfile dependency graph.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| library/alloc/src/boxed.rs | Adds Kani-only contracts for unsafe Box APIs and a large set of Kani proof harnesses/helpers for Challenge 29 coverage. |
| library/alloc/src/boxed/convert.rs | Adds Kani-only preconditions to downcast_unchecked variants and adds harnesses for boxed conversions/downcasts. |
| library/alloc/src/boxed/thin.rs | Adds Kani proof harnesses for ThinBox deref/drop/meta/header-related behavior. |
| library/Cargo.lock | Lockfile updates to reflect safety crate usage and its proc-macro dependencies. |
| #[cfg(kani)] | ||
| #[unstable(feature = "kani", issue = "none")] | ||
| mod verify_304 { | ||
| use super::super::kani_box_harness_helpers::*; |
There was a problem hiding this comment.
kani_box_harness_helpers is defined as a sibling module of convert under alloc::boxed (in boxed.rs), so super::super::kani_box_harness_helpers resolves to alloc::kani_box_harness_helpers and won’t compile. Use super::kani_box_harness_helpers (or crate::boxed::kani_box_harness_helpers) instead so the harness can see verifier_nondet_vec_box.
| use super::super::kani_box_harness_helpers::*; | |
| use super::kani_box_harness_helpers::*; |
| #[cfg(kani)] | ||
| #[unstable(feature = "kani", issue = "none")] | ||
| mod verify_336 { | ||
| use super::super::kani_box_harness_helpers::*; |
There was a problem hiding this comment.
Same issue here: super::super::kani_box_harness_helpers points at the alloc module, not the boxed module where kani_box_harness_helpers is declared. This will fail to compile under cfg(kani); refer to the helper module via super::kani_box_harness_helpers (or crate::boxed::kani_box_harness_helpers).
| use super::super::kani_box_harness_helpers::*; | |
| use super::kani_box_harness_helpers::*; |
| #[cfg(kani)] | ||
| #[unstable(feature = "kani", issue = "none")] | ||
| mod verify_170 { | ||
| use super::*; |
There was a problem hiding this comment.
The repository’s existing Kani harnesses are typically grouped under a single #[cfg(kani)] ... mod verify { ... } block (e.g. library/alloc/src/vec/mod.rs:4307-4353, library/alloc/src/collections/vec_deque/mod.rs:3274-3312). Using many numbered modules like verify_170, verify_251, etc. makes the verification surface harder to navigate and is inconsistent with that convention; consider consolidating into one mod verify (with submodules if needed).
|
|
||
| #[cfg(kani)] | ||
| #[unstable(feature = "kani", issue = "none")] | ||
| mod verify_146 { |
There was a problem hiding this comment.
The repository’s existing Kani harnesses are typically grouped under a single #[cfg(kani)] ... mod verify { ... } block (e.g. library/alloc/src/vec/mod.rs:4307-4353, library/alloc/src/collections/vec_deque/mod.rs:3274-3312). This file introduces multiple numbered modules like verify_146, verify_156, etc., which is inconsistent with that convention and makes it harder to find harnesses; consider consolidating into one mod verify (submodules/macros inside as needed).
| mod verify_146 { | |
| mod verify { |
| #[cfg(kani)] | ||
| #[unstable(feature = "kani", issue = "none")] | ||
| mod verify_944 { | ||
| use super::*; | ||
|
|
||
| // Kani limitation: proof_for_contract is not reliable for this | ||
| // MaybeUninit-based generic impl in boxed.rs, so these harnesses use |
There was a problem hiding this comment.
The repository’s existing Kani harnesses are typically grouped under a single #[cfg(kani)] ... mod verify { ... } block (e.g. library/alloc/src/vec/mod.rs:4307-4353, library/alloc/src/collections/vec_deque/mod.rs:3274-3312, and many library/core/src/** files). Adding dozens of separate numbered modules (verify_944, verify_1011, …) is inconsistent with that convention and makes the verification code harder to maintain; consider consolidating under one mod verify (with internal submodules for organization).
Summary
This PR adds Kani-based verification artifacts for
Box,ThinBox, and related boxed conversion APIs inlibrary/alloc/src/boxed.rs,library/alloc/src/boxed/convert.rs, andlibrary/alloc/src/boxed/thin.rsfor Challenge 29.The change introduces:
#[cfg(kani)]for the required unsafe functions and a broad safe-function subsetNo non-verification runtime behavior is changed in normal builds.
Notes on Challenge 29 Function Signatures
Several Challenge 29 entries do not exactly match the current repository source. This PR follows the actual checked-in API signatures rather than the likely stale or imprecise challenge text.
Notable mismatches include:
Box<T, A>::new_uninit_slice_in,Box<T, A>::new_zeroed_slice_in,Box<T, A>::try_new_uninit_slice_in, andBox<T, A>::try_new_zeroed_slice_in, but the current source implements them onBox<[T], A>and returns boxed[MaybeUninit<T>]slices.<Box<[T; N]> as TryFrom<Box<T>>>::try_fromdoes not match the source. The current implementation is<Box<[T; N]> as TryFrom<Vec<T>>>::try_from.<dyn Error>::downcast_uncheckedvariants in the challenge text, but the current source provides unchecked downcast APIs forBox<dyn Any, A>,Box<dyn Any + Send, A>, andBox<dyn Any + Send + Sync, A>.T: ?Sized,T: Clone, allocator bounds, or specialization-related constraints. The harnesses use the bounds from the actual source definitions.Verification Coverage Report
Unsafe functions
Coverage: 9 / 9 (100%)
Verified set includes:
Box<mem::MaybeUninit<T>, A>::assume_initBox<[mem::MaybeUninit<T>], A>::assume_initBox<T>::from_rawBox<T>::from_non_nullBox<T, A>::from_raw_inBox<T, A>::from_non_null_inBox<dyn Any, A>::downcast_uncheckedBox<dyn Any + Send, A>::downcast_uncheckedBox<dyn Any + Send + Sync, A>::downcast_uncheckedSafe functions
Coverage: 45 / 46 (97.8%)
This exceeds the Challenge 29 threshold of at least 75%.
Covered safe functions include APIs from the following groups:
Allocation and initialization
Box<[T], A>::new_uninit_slice_inBox<[T], A>::new_zeroed_slice_inBox<[T], A>::try_new_uninit_slice_inBox<[T], A>::try_new_zeroed_slice_inBox<mem::MaybeUninit<T>, A>::writeRaw pointer and ownership conversion
Box<T>::into_non_nullBox<T, A>::into_raw_with_allocatorBox<T, A>::into_non_null_with_allocatorBox<T, A>::into_uniqueBox<T, A>::leakBox<T, A>::into_pinTrait implementations for
Box<Box<T, A> as Drop>::drop<Box<T> as Default>::default<Box<str> as Default>::default<Box<T, A> as Clone>::clone<Box<str> as Clone>::clone<Box<str> as From<&str>>::from<Box<[u8], A> as From<Box<str, A>>>::from<Box<[T; N]> as TryFrom<Box<[T]>>>::try_from<Box<[T; N]> as TryFrom<Vec<T>>>::try_fromBox<dyn Any>andBox<dyn Error>conversionsBox<dyn Any, A>::downcastBox<dyn Any + Send, A>::downcastBox<dyn Any + Send + Sync, A>::downcast<dyn Error>::downcast<dyn Error + Send>::downcast<dyn Error + Send + Sync>::downcastThinBoxandWithHeader<ThinBox<T> as Deref>::deref<ThinBox<T> as DerefMut>::deref_mut<ThinBox<T> as Drop>::dropThinBox<T>::metaThinBox<T>::with_headerWithHeader<H>::newWithHeader<H>::try_newWithHeader<H>::new_unsize_zstWithHeader<H>::headerNot listed as a standalone harness target:
<Box<[T]> as BoxFromSlice<T>>::from_sliceApproach
The verification strategy combines contracts for unsafe entry points with executable proof harnesses:
kani::requirespreconditions for pointer non-nullness, layout compatibility, dereferenceability, and initialization where expressible.#[kani::proof_for_contract]for the required unsafe APIs.#[kani::proof]harnesses for safe APIs across allocation, conversion, trait implementation, downcast,ThinBox, andWithHeaderbehavior.bool, unit, arrays, slices, strings,dyn Any,dyn Error, and allocator-awareGlobalcases.cfg(kani)so normal std behavior is unchanged.Scope assumptions
Tis instantiated with representative concrete types allowed by the challenge.Global.Verification
All added Challenge 29 harnesses pass locally with Kani.
Resolves #526
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.