Skip to content

Evaluate overflow_checks() to the session's setting - #4980

Open
srivatsansamraj wants to merge 2 commits into
model-checking:mainfrom
srivatsansamraj:overflow-checks-intrinsic
Open

srivatsansamraj wants to merge 2 commits into
model-checking:mainfrom
srivatsansamraj:overflow-checks-intrinsic

Conversation

@srivatsansamraj

Copy link
Copy Markdown
Contributor

Kani evaluated every Operand::RuntimeChecks to false, including overflow_checks(), although it compiles every crate with -Coverflow-checks=on and refuses to run without it. Library code that branches on the intrinsic took its false branch: pow wrapped where Rust panics on overflow, so Kani reported success for code that panics (#4970); funnel_shl and funnel_shr wrapped the shift amount; and the iterator of core::range::RangeFrom reported an overflow one call before Rust panics.

overflow_checks() now evaluates to the session's overflow-checks setting, as rustc's codegen does, and ub_checks() and contract_checks() calls that reach codegen stay false.

On the standard library (verify-rust-std cd371e035c7), the 18 automatic harnesses for unsigned pow and the funnel shifts now report the overflow panic in place of success, and the 6 for signed pow fail on the overflow in place of an unwinding assertion. The checked path costs more on symbolic inputs: the i128 pow automatic harness went from 0.48 s to 10 s, and a u64 pow with symbolic base and exponent from 0.3-0.7 s to 53-109 s to find the overflow. The tests/perf s2n-quic varint proofs, five of which call pow with constant exponents, went from 49.5 s to 50.7 s.

tests/expected/intrinsics/overflow-checks checks that overflow_checks() is true, that unsigned and signed pow and funnel_shl report their overflow panics, that 2u32.pow(31) still verifies, and that the RangeFrom iterator yields its maximum value and panics on the next call. On main the intrinsic check fails, the three overflow harnesses verify and the iterator fails at its maximum value.

Resolves #4970

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

@srivatsansamraj
srivatsansamraj requested review from a team as code owners October 6, 2026 05:16
@srivatsansamraj

Copy link
Copy Markdown
Contributor Author

@CYJ904 @Tianshu-Huang @wodex1nhaoIeng @acearyanarun for review. Rust's pow asks overflow_checks() whether to panic on overflow or to wrap. Kani always compiles with overflow checks on, but answered "no", so pow wrapped and Kani reported success for code that panics. It now answers with the real setting. On the standard library, 18 automatic harnesses for unsigned pow and the funnel shifts go from success to a real overflow panic, and a symbolic pow gets slower because every multiplication is now checked.

@github-actions github-actions Bot added Z-EndToEndBenchCI Tag a PR to run benchmark CI Z-CompilerBenchCI Tag a PR to run benchmark CI labels Oct 6, 2026
@srivatsansamraj
srivatsansamraj force-pushed the overflow-checks-intrinsic branch from f0dfe67 to 990fadc Compare October 9, 2026 16:53
@feliperodri feliperodri self-assigned this Oct 22, 2026
@feliperodri
feliperodri requested a balanced review from Copilot November 6, 2026 18:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

2 open issues
What changed in this PR

Aligns Kani’s codegen behavior for core::intrinsics::overflow_checks() with the active rustc session overflow-checks setting, fixing incorrect library branching that previously masked overflows/panics.

Changes:

  • Evaluate Operand::RuntimeChecks::OverflowChecks using tcx.sess.overflow_checks() instead of hard-coding false.
  • Keep ub_checks() and contract_checks() evaluated to false when they reach codegen.
  • Add a regression test and expected output to ensure overflow_checks() is true and overflow-dependent library behavior matches Rust.
File Description
tests/​expected/​intrinsics/​overflow-checks/​main.rs Adds regression harnesses covering overflow_checks(), pow, funnel shifts, and RangeFrom overflow behavior.
tests/​expected/​intrinsics/​overflow-checks/​expected Captures expected Kani results demonstrating panic/assertion failures for overflow paths and correct harness counts.
kani-compiler/​src/​codegen_cprover_gotoc/​codegen/​operand.rs Implements session-driven evaluation for OverflowChecks while leaving UbChecks/ContractChecks disabled.

Review effort: Lite

@@ -0,0 +1,19 @@
check_overflow_checks_intrinsic.assertion\
Status: SUCCESS\
Description: "assertion failed: core::intrinsics::overflow_checks()"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Status: SUCCESS is the assertion holding, which is the expected result here.


#[kani::proof]
fn check_funnel_shl_overflow() {
let _ = u32::MAX.funnel_shl(u32::MAX, u32::BITS);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 7a1933b49: both harnesses that rely on a panic now have a cover after the call.

@feliperodri feliperodri left a comment

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.

The fix is right: overflow_checks() now matches the session's setting, as rustc does, so Kani reports the overflow panics a native build hits.

Before merge:

  1. Before this change, Kani reported success where a native build panics, so this is a soundness gap. Please add [F] Soundness and [C] Bug.
  2. The expected output adds a failure in <u8 as Step>::forward. Please say in the description whether it's intended, and why.
  3. Please add a kani::cover! marker to check_overflow_checks_intrinsic, like the pow harnesses.
  4. audit fails. Please confirm it fails on main. Three jobs are cancelled. Please re-run them.

Kani evaluated every `Operand::RuntimeChecks` to `false`, including
`overflow_checks()`, although it compiles every crate with
`-Coverflow-checks=on` and refuses to run without it. Library code that
branches on the intrinsic therefore took its path without overflow
checks: `pow` on signed and unsigned integers wrapped instead of
panicking on overflow (model-checking#4970), `funnel_shl` and `funnel_shr` wrapped
the shift amount, and the iterator of `core::range::RangeFrom` reported
an overflow one call before Rust panics.

`overflow_checks()` now evaluates to the session's overflow-checks
setting, as rustc's own codegen does, and `ub_checks()` and
`contract_checks()` calls that reach codegen stay `false`. The arms
name each variant, so a new kind of runtime check cannot fall into
`false` unnoticed.

`tests/expected/intrinsics/overflow-checks` checks that
`overflow_checks()` itself is `true`, that unsigned and signed `pow`
and `funnel_shl` report their overflow panics, that `2u32.pow(31)`
still verifies, and that the `RangeFrom` iterator yields its maximum
value and panics on the call after it. Without the change, the
intrinsic check fails, the three overflow harnesses verify and the
iterator fails at its maximum value.
The funnel shift and the `RangeFrom` harnesses passed only because the
call panics; a cover after each call now fails the test if the call
returns.
@srivatsansamraj
srivatsansamraj force-pushed the overflow-checks-intrinsic branch from 990fadc to 7a1933b Compare November 7, 2026 06:21

This branch has not been deployed

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

Labels

Z-CompilerBenchCI Tag a PR to run benchmark CI Z-EndToEndBenchCI Tag a PR to run benchmark CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kani misses pow overflow panics

3 participants