Skip to content

Challenge 27: Verify Arc/Weak safety in alloc::sync with Kani#587

Open
v3risec wants to merge 1 commit intomodel-checking:mainfrom
v3risec:challenge-27-arc
Open

Challenge 27: Verify Arc/Weak safety in alloc::sync with Kani#587
v3risec wants to merge 1 commit intomodel-checking:mainfrom
v3risec:challenge-27-arc

Conversation

@v3risec
Copy link
Copy Markdown

@v3risec v3risec commented Apr 21, 2026

Summary

This PR adds Kani-based verification artifacts for Arc/Weak safety in library/alloc/src/sync.rs for Challenge 27.

The change introduces:

  • safety contracts for all required unsafe Arc/Weak functions listed in the challenge
  • proof harness modules under #[cfg(kani)] for those unsafe functions and a broad safe-function subset
  • atomic-aware contracts and harnesses that check pointer layout/alignment/allocation consistency and key strong/weak refcount invariants
  • shared helper-based construction for nondeterministic unsized slice inputs, so Arc<[T]> / Weak<[T]> paths can be exercised in a reusable way

No non-verification runtime behavior is changed in normal builds.

Verification Coverage Report

Unsafe functions (required by Challenge 27)

Coverage: 12 / 12 (100%)

Verified set includes:

  • Arc<mem::MaybeUninit<T>,A>::assume_init
  • Arc<[mem::MaybeUninit<T>],A>::assume_init
  • Arc<T:?Sized>::from_raw
  • Arc<T:?Sized>::increment_strong_count
  • Arc<T:?Sized>::decrement_strong_count
  • Arc<T:?Sized,A:Allocator>::from_raw_in
  • Arc<T:?Sized,A:Allocator>::increment_strong_count_in
  • Arc<T:?Sized,A:Allocator>::decrement_strong_count_in
  • Arc<T:?Sized,A:Allocator>::get_mut_unchecked
  • Arc<dyn Any+Send+Sync,A:Allocator>::downcast_unchecked
  • Weak<T:?Sized>::from_raw
  • Weak<T:?Sized,A:Allocator>::from_raw_in

Safe functions (Challenge 27 list)

Stable passing coverage: 54 / 58 (93.1%)

This exceeds the challenge threshold (>= 75%).

Covered safe functions (54/58), grouped by API category:

Allocation

  • Arc<T>::new
  • Arc<T>::new_uninit
  • Arc<T>::new_zeroed
  • Arc<T>::pin
  • Arc<T>::try_pin
  • Arc<T>::try_new
  • Arc<T>::try_new_uninit
  • Arc<T>::try_new_zeroed
  • Arc<T,A:Allocator>::new_in
  • Arc<T,A:Allocator>::new_uninit_in
  • Arc<T,A:Allocator>::new_zeroed_in
  • Arc<T,A:Allocator>::new_cyclic_in
  • Arc<T,A:Allocator>::pin_in
  • Arc<T,A:Allocator>::try_pin_in
  • Arc<T,A:Allocator>::try_new_in
  • Arc<T,A:Allocator>::try_new_uninit_in
  • Arc<T,A:Allocator>::try_new_zeroed_in
  • Arc<T,A:Allocator>::try_unwrap
  • Arc<T,A:Allocator>::into_inner
  • Arc<T:?Sized,A:Allocator>::into_inner_with_allocator

Slice

  • Arc<[T]>::new_uninit_slice
  • Arc<[T]>::new_zeroed_slice
  • Arc<[T]>::into_array
  • Arc<[T],A:Allocator>::new_uninit_slice_in
  • Arc<[T],A:Allocator>::new_zeroed_slice_in
  • ArcFromSlice<T: Copy>::from_slice

Conversion and pointer

  • Arc<T:?Sized,A:Allocator>::into_raw_with_allocator
  • Arc<T:?Sized,A:Allocator>::as_ptr
  • Arc<T:?Sized,A:Allocator>::inner
  • Arc<T:?Sized,A:Allocator>::from_box_in
  • Clone<T:?Sized, A:Allocator>::clone for Arc
  • Arc<T:?Sized+CloneToUninit, A:Allocator+Clone>::make_mut
  • Arc<T:?Sized, A:Allocator>::get_mut
  • Drop<T:?Sized, A:Allocator>::drop for Arc
  • Arc<dyn Any+Send+Sync,A:Allocator>::downcast

Weak and trait-related operations

  • Weak<T:?Sized,A:Allocator>::as_ptr
  • Weak<T:?Sized,A:Allocator>::into_raw_with_allocator
  • Weak<T:?Sized,A:Allocator>::upgrade
  • Weak<T:?Sized,A:Allocator>::inner
  • Drop<T:?Sized, A:Allocator>::drop for Weak

Default and conversions

  • Default<T:Default>::default
  • Default<core::ffi::CStr>::default
  • Default<[T]>::default
  • From<&str>::from
  • From<Vec<T,A:Allocator+Clone>>::from
  • From<Arc<str>>::from

UniqueArc / UniqueArcUninit and traits

  • UniqueArcUninit<T:?Sized, A:Allocator>::new
  • UniqueArcUninit<T:?Sized, A:Allocator>::data_ptr
  • Drop<T:?Sized, A:Allocator>::drop for UniqueArcUninit
  • UniqueArc<T:?Sized,A:Allocator>::into_arc
  • UniqueArc<T:?Sized,A:Allocator+Clone>::downgrade
  • Deref<T:?Sized,A:Allocator>::deref
  • DerefMut<T:?Sized,A:Allocator>::deref_mut
  • Drop<T:?Sized, A:Allocator>::drop for UniqueArc

Not yet listed as standalone harness targets (4/58)

  • Default<str>::default
  • ArcFromSlice<T: Clone>::from_slice
  • TryFrom<Arc<[T],A:Allocator>>::try_from
  • ToArcSlice<T, I>::to_arc_slice

Current Criteria Met

  • Required unsafe functions covered: all 12/12 required unsafe functions in Challenge 27 are annotated with contracts and verified.
  • Safe-function threshold met: 54/58 safe functions are in the stable passing set (93.1%), exceeding the challenge threshold of at least 75%.
  • Challenge scope allowances respected: generic T is instantiated with representative concrete types allowed by the challenge, and allocator-focused proofs are limited to standard-library allocator scope (Global).

Approach

The verification strategy combines contracts for unsafe entry points with executable proof harnesses:

  1. Contracts for unsafe functions
  • Attach kani::requires preconditions for pointer validity, alignment soundness, same-allocation checks, and refcount well-formedness.
  • Use atomic-aware conditions where needed for Arc strong/weak counters.
  • Attach postconditions and mutation footprints where appropriate for refcount-changing operations.
  1. Harness-backed behavioral checks
  • Add dedicated #[kani::proof] / #[kani::proof_for_contract] modules for required unsafe functions and safe-function coverage targets.
  • Cover ownership-state-sensitive APIs by constructing representative states such as unique ownership, shared strong ownership, and externally held weak references.
  1. Helper-based unsized generalization
  • Introduce shared helper functions for nondeterministic vector/slice construction and reuse them across Arc<[T]> / Weak<[T]> harnesses.
  • Use those helpers to exercise ?Sized slice cases without duplicating setup logic across harnesses.
  1. Challenge alignment
  • Keep all verification code under cfg(kani) so normal std behavior is unchanged.
  • Target the Challenge 27 success criteria directly: full required unsafe coverage and safe coverage above the required threshold.

Scope assumptions (per challenge allowance)

  • Harnesses instantiate representative concrete types including signed/unsigned widths (i8..i128, u8..u128), bool, (), arrays, vectors, slices, str, CStr, and trait objects (dyn Any, dyn Any + Send + Sync where required by the API).
  • Allocator coverage is limited to Global.

Note on data races

This PR uses Kani proof harnesses in the current single-threaded verification setting. As a result, these proofs do not model true concurrent interleavings between multiple threads.

What is verified here is that the Arc / Weak APIs covered by these harnesses are memory-safe under the explored single-threaded executions, including pointer validity, alignment/allocation consistency, and key strong/weak reference-count invariants.

Verification

All passing harnesses listed in this report pass locally with the current Kani setup used for this repository.

Resolves #383

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@v3risec v3risec requested a review from a team as a code owner April 21, 2026 16:11
@v3risec v3risec changed the title alloc: add Arc/Weak Kani proofs for challenge 27 Challenge 27: Verify Arc/Weak safety in alloc::sync with Kani Apr 21, 2026
@feliperodri feliperodri requested a review from Copilot April 21, 2026 17:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@feliperodri feliperodri added the Challenge Used to tag a challenge label Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Challenge Used to tag a challenge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Challenge 27: Verify atomically reference-counted Cell implementation

3 participants