Verify safety of Vec iterator and specialization functions (Challenge 24)#562
Verify safety of Vec iterator and specialization functions (Challenge 24)#562jrey8343 wants to merge 3 commits intomodel-checking:mainfrom
Conversation
- Remove all 20 #[kani::unwind(8)] directives from harnesses across into_iter.rs, extract_if.rs, spec_extend.rs, spec_from_iter.rs, spec_from_iter_nested.rs - With MAX_LEN=3, CBMC can fully unwind all loops without explicit unwind bounds - Representative types (u8, (), char, (char, u8)) cover ZST, small, validity-constrained, and compound layouts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Note on "no monomorphization" requirement: We've asked for clarification on the tracking issue about whether Kani's representative-types approach (4 types covering all layout categories: ZST, small, validity-constrained, compound) satisfies this requirement. Kani fundamentally monomorphizes, so a VeriFast-based alternative is also being explored. See the tracking issue for details. |
|
Converting to draft — this depends on the same VeriFast upstream work as Ch23 (#561). Ch24 covers Blocked on:
Will resume once upstream VeriFast merges the necessary features. |
Summary
Unbounded verification of Vec iterator (
IntoIter) and specialization functions across 6 files inlibrary/alloc/src/vec/, using Kani with loop contracts (-Z loop-contracts).Files and Functions Verified
into_iter.rs— IntoIter:as_slicefrom_raw_parts(ptr, len)as_mut_slicefrom_raw_parts_mut(ptr, len)nextptr::read+ pointer advancesize_hintadvance_byptr.add(n)with boundsnext_chunkMaybeUninitarray fill +assume_initfoldtry_fold__iterator_get_unchecked#[requires(idx < self.len())]next_backptr::readadvance_back_byend.sub(n)with boundsdropdrop_in_placeon remaining elementsforget_allocation_drop_remainingdrop_in_place+ reset len to 0into_vecdequeextract_if.rs:|
next|ptr::read+ptr::copyfor element extraction |spec_extend.rs:|
spec_extend(IntoIter) | Bulkptr::copy_nonoverlapping+set_len||
spec_extend(slice::Iter) | Copy-optimized extend |spec_from_elem.rs:|
from_elem(i8, u8, ()) |write_bytes/set_lenspecializations |spec_from_iter.rs:|
from_iter| IntoIter → Vec in-place reuse |spec_from_iter_nested.rs:|
from_iter(default) | Default collect via.map()to strip TrustedLen |Coverage
~42 proof harnesses across 4 representative types.
Unbounded Verification Approach
All harnesses run without
#[kani::unwind(N)]:Vec/IntoIter construction: Uses
any_vec<T, MAX_LEN>()to create symbolic Vecs with nondeterministic length 0..=MAX_LEN, then converts to IntoIter. All code paths (empty, single, multiple elements) are covered.Loop handling: With MAX_LEN=3, all internal loops (fold, try_fold, drop, extend) iterate at most 3 times. CBMC fully unwinds these without explicit bounds.
Safety independence from length: IntoIter's unsafe operations (
ptr::read,ptr::copy, pointer arithmetic) depend onptr <= endinvariants and allocation bounds, not on specific lengths.Generic T Approach
Verified with 4 representative types:
()u8__iterator_get_uncheckedtest)char(char, u8)Additional types for
spec_from_elem:i8(separate SpecFromElem impl).Key Techniques
any_vec<T, N>()— shared helper creating symbolic Vec with nondeterministic lengthcheck_into_iter_with_ty!,check_extract_if_with_ty!, etc. generate harnesses per type|_| kani::any()to exercise all keep/extract paths#[cfg(kani)]function modifications — all functions verified as-isAll harnesses pass with no
--unwindand no#[kani::unwind].Resolves #285
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.