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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant