Skip to content

Verify safety of str iter functions (Challenge 22)#539

Open
jrey8343 wants to merge 2 commits intomodel-checking:mainfrom
jrey8343:challenge-22-str-iter
Open

Verify safety of str iter functions (Challenge 22)#539
jrey8343 wants to merge 2 commits intomodel-checking:mainfrom
jrey8343:challenge-22-str-iter

Conversation

@jrey8343
Copy link

@jrey8343 jrey8343 commented Feb 7, 2026

Summary

Adds 17 Kani verification harnesses proving the safety of all unsafe operations in library/core/src/str/iter.rs, covering all 16 functions listed in Challenge 22 plus the __iterator_get_unchecked safety contract proof.

Functions verified

Function Harness Unsafe operation
Chars::next check_chars_next next_code_point + char::from_u32_unchecked
Chars::next_back check_chars_next_back next_code_point_reverse + char::from_u32_unchecked
Chars::advance_by check_chars_advance_by iter.advance_by(slurp).unwrap_unchecked()
Chars::advance_by (CHUNK_SIZE) check_chars_advance_by_large iter.advance_by(bytes_skipped).unwrap_unchecked()
Chars::as_str check_chars_as_str from_utf8_unchecked(self.iter.as_slice())
SplitInternal::get_end check_split_internal_get_end get_unchecked(self.start..self.end)
SplitInternal::next check_split_internal_next get_unchecked(self.start..a)
SplitInternal::next_inclusive check_split_internal_next_inclusive get_unchecked(self.start..b)
SplitInternal::next_back check_split_internal_next_back get_unchecked(b..self.end), get_unchecked(self.start..self.end)
SplitInternal::next_back (terminator) check_split_internal_next_back_terminator Recursive path with allow_trailing_empty=false
SplitInternal::next_back_inclusive check_split_internal_next_back_inclusive get_unchecked(b..self.end), get_unchecked(self.start..self.end)
SplitInternal::remainder check_split_internal_remainder get_unchecked(self.start..self.end)
MatchIndicesInternal::next check_match_indices_internal_next get_unchecked(start..end)
MatchIndicesInternal::next_back check_match_indices_internal_next_back get_unchecked(start..end)
MatchesInternal::next check_matches_internal_next get_unchecked(a..b)
MatchesInternal::next_back check_matches_internal_next_back get_unchecked(a..b)
SplitAsciiWhitespace::remainder check_split_ascii_whitespace_remainder from_utf8_unchecked
Bytes::__iterator_get_unchecked check_bytes_iterator_get_unchecked Safety contract #[requires(idx < self.0.len())]

Verification approach

  • Chars harnesses: Symbolic char via kani::any::<char>() encoded to UTF-8 via encode_utf8, covering all Unicode scalar values. Verifies no UB in next_code_point/from_u32_unchecked/from_utf8_unchecked.
  • SplitInternal/MatchIndices/Matches harnesses: Symbolic ASCII char pattern (kani::any() + assume(c.is_ascii())) with 2-byte haystack "ab", exercising both match and no-match code paths through the Searcher.
  • advance_by large: Concrete 33-byte ASCII string exercises the CHUNK_SIZE=32 branch with its chunk processing, trailing continuation byte skipping, and final character-width-based advancement.
  • Bytes: Proves the existing #[requires(idx < self.0.len())] contract is sufficient for safety.

All 17 harnesses verified locally (18 total including pre-existing check_small_slice_eq).

Test plan

  • All 17 new harnesses pass with kani verify-std using -Z loop-contracts --cbmc-args --object-bits 12
  • Pre-existing harnesses remain passing
  • Code formatted with rustfmt

Add 17 Kani verification harnesses for all unsafe operations in
library/core/src/str/iter.rs:

Chars: next, next_back, advance_by (small + CHUNK_SIZE branch), as_str
SplitInternal: get_end, next, next_inclusive, next_back,
  next_back (terminator path), next_back_inclusive, remainder
MatchIndicesInternal: next, next_back
MatchesInternal: next, next_back
SplitAsciiWhitespace: remainder
Bytes: __iterator_get_unchecked (safety contract proof)

Techniques:
- Symbolic char via kani::any::<char>() with encode_utf8 for full
  Unicode scalar value coverage (Chars harnesses)
- Symbolic ASCII char patterns with 2-byte haystack for Split/Match
  harnesses covering match and no-match paths
- Concrete 33-byte string for advance_by CHUNK_SIZE=32 branch
@jrey8343 jrey8343 requested a review from a team as a code owner February 7, 2026 03:17
@jrey8343
Copy link
Author

CI is passing — ready for review.

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