Challenge 13: Verify safety of CStr#566
Challenge 13: Verify safety of CStr#566Samuelsills wants to merge 1 commit intomodel-checking:mainfrom
Conversation
bc1216d to
0446b60
Compare
Verify all 14 items listed in the challenge specification. 14 Kani proof harnesses, 0 failures. Bounded verification with MAX_SIZE=32. Part 4 additions: check_index_range_from and check_clone_to_uninit. Resolves model-checking#150 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
0446b60 to
a6e0a27
Compare
Verification Coverage ReportFunctions Verified (14/14 ✅)All public functions containing unsafe code in
UBs Checked (automatic via Kani/CBMC)
Verification Approach
|
There was a problem hiding this comment.
Pull request overview
Adds the remaining Kani proof harness coverage for Challenge 13 (CStr safety) by verifying trait-implementation behavior, and documents the verification status in the challenge write-up.
Changes:
- Adds Kani proof harness for
CStr’sIndex<RangeFrom<usize>>slicing behavior. - Adds Kani proof harness for
CStr’sCloneToUninitimplementation. - Extends the Challenge 13 markdown with a verification summary table covering all 14 items.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
library/core/src/ffi/c_str.rs |
Adds new Kani harnesses for Index<RangeFrom<usize>> and CloneToUninit trait impl verification. |
doc/src/challenges/0013-cstr.md |
Documents the verification completion/status for all Challenge 13 checklist items. |
| unsafe { | ||
| c_str.clone_to_uninit(dest.as_mut_ptr()); | ||
| } | ||
|
|
||
| // Verify the clone copied the correct bytes | ||
| assert_eq!(&dest[..len], bytes_with_nul); |
There was a problem hiding this comment.
check_clone_to_uninit currently passes a destination buffer that is larger than size_of_val(c_str) (always MAX_SIZE). That can mask out-of-bounds writes: an implementation bug that writes past len bytes could still stay within the array and avoid triggering UB checks, even though it would be UB for callers that provide exactly size_of_val(self) bytes as allowed by the trait contract. Consider passing a pointer to a region with exactly len bytes of remaining space (e.g., offset into the fixed array), so any overwrite beyond len is detected, and compare the written region against bytes_with_nul.
| unsafe { | |
| c_str.clone_to_uninit(dest.as_mut_ptr()); | |
| } | |
| // Verify the clone copied the correct bytes | |
| assert_eq!(&dest[..len], bytes_with_nul); | |
| // Provide exactly `len` bytes of space to `clone_to_uninit` by offsetting | |
| // into the fixed-size array. Any write past `len` will then be out of bounds. | |
| let start = MAX_SIZE - len; | |
| unsafe { | |
| c_str.clone_to_uninit(dest[start..].as_mut_ptr()); | |
| } | |
| // Verify the clone copied the correct bytes into the region we passed in | |
| assert_eq!(&dest[start..start + len], bytes_with_nul); |
|
|
||
| | Item | Status | | ||
| |------|--------| | ||
| | `Invariant` trait for `&CStr` | Implemented (lines 193-207) | |
There was a problem hiding this comment.
This summary hard-codes source line ranges (e.g., "Implemented (lines 193-207)") which will become stale as the file evolves. Prefer a stable reference (file path + item name/harness name) or a link/anchor rather than embedding line numbers in the challenge documentation.
| | `Invariant` trait for `&CStr` | Implemented (lines 193-207) | | |
| | `Invariant` trait for `&CStr` | Implemented in the `CStr` invariant verification harness | |
| | Function | Contract | Harness | Status | | ||
| |----------|----------|---------|--------| | ||
| | `from_ptr` | `#[requires]` + `#[ensures]` | `check_from_ptr_contract` | VERIFIED | | ||
| | `from_bytes_with_nul_unchecked` | `#[requires]` + `#[ensures]` | `check_from_bytes_with_nul_unchecked` | VERIFIED | | ||
| | `strlen` | `#[requires]` + `#[ensures]` | `check_strlen_contract` | VERIFIED | |
There was a problem hiding this comment.
In this table you refer to from_bytes_with_nul_unchecked, but earlier in the challenge description the function name is misspelled as from_bytes_with_nul_uncheked. It would be clearer if the document used a consistent spelling throughout (and corrected the earlier typo).
Summary
Verify all 14 items listed in Challenge 13. 14 Kani proof harnesses, 0 failures. Bounded verification with MAX_SIZE=32 as permitted by challenge assumptions.
Part 1: Invariant trait for CStr (pre-existing).
Part 2: Harnesses for all 9 safe methods (pre-existing).
Part 3: Contracts and harnesses for all 3 unsafe functions (pre-existing).
Part 4: New harnesses for trait implementations:
check_index_range_from: verifiesIndex<RangeFrom<usize>>preserves the CStr invariant when slicing from any valid start index.check_clone_to_uninit: verifiesCloneToUninitcopies correct bytes to the destination with no undefined behavior. Note: a formal#[requires]contract could not be added because the safety crate's proc macro does not currently support methods insideunsafe impl Traitblocks. Safety is verified via CBMC's built-in memory model checks.Resolves #150
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.