Skip to content

Respect new_unchecked precondition in IndexRange proof harnesses - #623

Open
tautschnig wants to merge 1 commit into
model-checking:mainfrom
tautschnig:fix-index-range-harnesses
Open

Respect new_unchecked precondition in IndexRange proof harnesses#623
tautschnig wants to merge 1 commit into
model-checking:mainfrom
tautschnig:fix-index-range-harnesses

Conversation

@tautschnig

Copy link
Copy Markdown
Member

The proof_for_contract harnesses for IndexRange::next_unchecked and IndexRange::next_back_unchecked, introduced in a0fca1c (#451), construct their IndexRange via IndexRange::new_unchecked(start, end) with entirely unconstrained start and end. That violates new_unchecked's documented safety precondition (and #[requires] contract) start <= end: the assumption provided by the contract under verification only takes effect at the call to next_unchecked / next_back_unchecked, after the UB of the unchecked constructor call has already happened.

The violation is currently invisible in CI because run-kani.sh passes --no-assert-contracts; with dependency contracts asserted (the Kani default since model-checking/kani#3802), proof_for_index_range_next_back_unchecked fails on the asserted start <= end clause.

This PR constrains both harnesses with kani::assume(start <= end). The stronger start < end required by the functions under verification continues to be assumed from their own contracts, preserving the intent of the harnesses.

Verified with Kani 152c6a8c + CBMC 6.10.0: all three ops::index_range::verify harnesses pass both with and without --no-assert-contracts.

Found while investigating what still blocks removing --no-assert-contracts from run-kani.sh: this is one of two genuine latent contract violations that asserting dependency contracts surfaces (the other: #622).

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

The proof_for_contract harnesses for IndexRange::next_unchecked and
IndexRange::next_back_unchecked, introduced in commit
a0fca1c ("A bunch of LLM-generated
contracts (model-checking#451)"), construct their IndexRange via
`IndexRange::new_unchecked(start, end)` with entirely unconstrained
`start` and `end`. That violates new_unchecked's documented safety
precondition (and #[requires] contract) `start <= end`: the assumption
provided by the contract under verification only takes effect at the
call to next_unchecked / next_back_unchecked, after the UB of the
unchecked constructor call has already happened.

The violation is currently invisible in CI because run-kani.sh passes
--no-assert-contracts; with dependency contracts asserted (the Kani
default since model-checking/kani#3802),
proof_for_index_range_next_back_unchecked fails on the asserted
`start <= end` clause.

Constrain both harnesses with `kani::assume(start <= end)`. The
stronger `start < end` required by the functions under verification
continues to be assumed from their own contracts, preserving the intent
of the harnesses.

Verified (Kani 152c6a8c + CBMC 6.10.0) that all three
ops::index_range::verify harnesses pass both with and without
--no-assert-contracts.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 16:41
@tautschnig
tautschnig requested a review from a team as a code owner August 3, 2026 16:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Kani contract-proof harnesses for IndexRange::next_unchecked and IndexRange::next_back_unchecked so they do not invoke IndexRange::new_unchecked with inputs that violate its documented safety precondition (start <= end). This prevents a latent UB/contract violation from being masked when dependency contracts are asserted (the Kani default).

Changes:

  • Add kani::assume(start <= end) in the proof_for_contract harness for IndexRange::next_unchecked.
  • Add kani::assume(start <= end) in the proof_for_contract harness for IndexRange::next_back_unchecked.
  • Document why this assumption is needed (constructor precondition) and why the stricter start < end condition is still covered by the verified functions’ own contracts.

@feliperodri feliperodri added the Maintenance Maintenance related issues for the challange label Aug 3, 2026
Comment on lines +253 to +256
// Respect new_unchecked's safety precondition (start <= end); the
// stronger requirement of next_unchecked (start < end) is assumed
// from its contract.
kani::assume(start <= end);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be part of the requires clause for new_unchecked?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Maintenance Maintenance related issues for the challange

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants