Repository navigation
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Some harnesses invoke undefined behavior, and bounded inputs leave required unbounded and reachable-state cases unproven.
Review effort: Balanced
Findings: 1
Open (4)
What changed in this PR
Adds Kani verification for Challenge 22’s str iterator safety obligations.
Changes:
- Adds 30 iterator and contract harnesses.
- Models searcher behavior and symbolic strings.
- Enables required unstable APIs under Kani.
| File | Description |
|---|---|
library/alloc/src/str.rs |
Adds Challenge 22 verification harnesses and helpers. |
library/alloc/src/lib.rs |
Enables remainder API features for Kani builds. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…sses Address Copilot review on model-checking#706: - symbolic_str now uses alloc_zeroed (valid UTF-8, no read of uninitialized memory); merge the former symbolic_str_zeroed into it since the content-independent proofs stub the searcher and never depend on nondeterministic content. - Add mixed front/back advanced-state harnesses for the double-ended Split/Matches iterators, exercising the both-cursors-moved state. The searcher stubs gain a two-sided no-cross clause (DoubleEndedSearcher consistency), a no-op for the single-direction harnesses.
feliperodri
left a comment
There was a problem hiding this comment.
Challenge 22 requires: "The verification must be unbounded---it must hold for str of arbitrary length." That requirement is final. A Kani solution will only be accepted if it is unbounded in the input size for every required function. This PR still verifies at least part of the challenge with bounded harnesses (kani::unwind bounds and/or fixed-size inputs), so I'm requesting changes until every required function is verified without a bound on the input size.


Towards #279.
Kani harnesses for Challenge 22: Verify the safety of
striter functions: the 15 safe functions with unsafe code incore::str::iter, plus theBytes::__iterator_get_uncheckedsafety contract. 33 harnesses in a new#[cfg(kani)] mod verify, all gated so non-Kani builds are unchanged.The challenge grants four assumptions:
slice,str::pattern, andstr::validations(1–3), and that every iterator comes from valid UTF-8 (4). Under assumption 2, the pattern searchers are modeled by spec-cited stubs at their call sites, so these proofs don't re-verify thestr::patterninternals (Challenges 20/21).Success criteria
__iterator_get_unchecked: write and prove the contractproof_for_contract. The#[requires(idx < self.0.len())]contract already exists in main (core/src/str/iter.rs). This PR proves it.kani::any()length, capped only by CBMC's--object-bits 12pointer-offset budget, not a fixed array.advance_byadditionally caps its skip count (see Limitations).What the harnesses check
#[cfg(kani)]rewrites. The diff adds theverifymodule and one kani-gatedfeature(str_split_remainder, str_split_whitespace_remainder)line inalloc/src/lib.rs(those methods are unstable). Symbolic inputs sit on zeroed backing (alloc_zeroed), valid UTF-8 by construction, so the module lives inalloc::str.SplitInternal, 9Matches/MatchIndices) stub the searchers at their call sites under assumption 2. A stub returns any range that is in-bounds, on UTF-8 boundaries, and monotonic, a superset of the real searcher's outputs. No-UB under the stub therefore gives no-UB for the real searcher.Chars::nextandnext_backare proven jointly over arbitrary length and arbitrary valid-UTF-8 content, both ends.Limitations
advance_byskip count is unwind-bounded while thestrlength stays symbolic. A loop invariant on the chunk-skip loop hits two Kani walls we filed: a combinator-fold.sum()with no attach site (kani#4893, open), and awhile … && letlet-chain that#[kani::loop_invariant]could not compile (kani#4943) — now fixed in Kani (kani#4948), but after the Kani commit this repo pins, so it still blocks here. Same open committee question as the other unbounded-verification challenges.advance_byon macOS CI.check_advance_by_charsverifies on the Linux runner (all safety checks pass) but exceeds Kani's per-harness CBMC time budget on the slower macOS runner, where the autoharness job reports a timeout. The limit is runner wall-clock, not coverage or a missing property.SplitInternal/MatchesInternalfields are private tocore, so an arbitrary post-k-call state would need a shipped-code change this diff avoids. The safety obligation depends on current field values, not the call count, so depth 1–2 exercises the same shape as a deeper state.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.