Skip to content

Challenge 13: contracts and proofs for CStr trait implementations and safe methods - #670

Open
kasimte wants to merge 1 commit into
model-checking:mainfrom
kasimte:challenge-13-cstr
Open

Challenge 13: contracts and proofs for CStr trait implementations and safe methods#670
kasimte wants to merge 1 commit into
model-checking:mainfrom
kasimte:challenge-13-cstr

Conversation

@kasimte

@kasimte kasimte commented Sep 2, 2026

Copy link
Copy Markdown

Towards #150.

This adds Challenge 13 work: the two trait implementations from criterion 4 had no verification, and the criterion 2 methods were exercised by test harnesses but carried no contracts stating what they guarantee.

This PR adds:

  • Safety contracts for the two trait implementations, CloneToUninit and Index<RangeFrom<usize>>, each proven with proof_for_contract. Slicing a CStr from an out-of-bounds position is documented to panic, and that panic path now has its own proof (should_panic).
  • Contracts on seven safe methods stating what each one guarantees — for example, that count_bytes agrees with the length of the byte view, and that the pointer from as_ptr covers the whole string including its final NUL byte.
  • A fidelity check for the safety invariant itself: on arbitrary bytes, is_safe accepts exactly the well-formed strings (non-empty, NUL at the end, no NUL in the middle) and rejects everything else — both outcomes proven reachable.
  • A reachability witness (kani::cover) next to every assumption, confirming the assumed input sets are non-empty.
Challenge success criterion Status in this PR
1. Implement the Invariant trait for CStr every harness that produces a CStr asserts it, and the fidelity check above compares is_safe against its documented meaning (the trait implementation itself was already in-tree)
2. Verify the safety invariant holds after calling each of the 9 listed safe methods 7 gain contracts (from_bytes_until_nul, from_bytes_with_nul, count_bytes, is_empty, to_bytes, to_bytes_with_nul, as_ptr); bytes and to_str stay harness-proven, with the reason explained in a comment at each function
3. Annotate and verify safety contracts for the 3 unsafe functions (from_ptr, from_bytes_with_nul_unchecked, strlen) the fidelity check above verifies the is_safe predicate their postconditions use (the contracts and proofs themselves were already in-tree, unchanged)
4. Verify the two trait implementations are safe (CloneToUninit, Index<RangeFrom<usize>>) both contracted and proven; the out-of-bounds panic has a should_panic proof

Bounds: the challenge explicitly allows bounded harnesses ("Harnesses may be bounded"). Inputs go up to 32 bytes; the pre-existing from_bytes_with_nul harness keeps its in-tree bound of 16, two new harnesses use 16, and one uses 8 to fit CI's per-harness time limit — each new bound explained in a comment where it appears.

All 23 harnesses (22 in ffi::c_str::verify, 1 in clone::verify) pass via scripts/run-kani.sh, with every cover property satisfied. The UNREACHABLE properties in the run output are library-internal helper checks and panic paths the proofs never reach. The change only adds code: 246 lines added, none removed.

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

@kasimte
kasimte requested a review from a team as a code owner September 2, 2026 20:45
@feliperodri

Copy link
Copy Markdown
Member

Thanks @kasimte — this is a strong, sound submission for Challenge 13. It's complete and clean on our vacuity checks (no cfg(kani) body swaps, no trivial invariant, no decorative contracts, symbolic inputs), it's purely additive (+246/−0), it upgrades 7 of the 9 safe methods from plain proofs to real #[ensures] + proof_for_contract, and the OOB #[should_panic] Index harness plus qualified-path contract proofs on both trait methods are nice touches.

Heads-up for transparency: we reviewed all four open Challenge 13 solutions together, and we're prioritizing #638 in the review process as the front-runner — it's the most complete (it also contracts bytes/to_str, which this PR leaves as base plain proofs, and adds an invariant-fidelity harness). Your low-churn approach is genuinely appealing, so we're keeping this open as the strong alternative; if #638 stalls or we find it weakens any base coverage, this is our fallback. Really appreciate the work.

@feliperodri feliperodri added the Challenge Used to tag a challenge label Sep 12, 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.

2 participants