Skip to content

Fail verification when the solver backend drops quantifiers - #4719

Open
tautschnig wants to merge 5 commits into
model-checking:mainfrom
tautschnig:surface-ignored-quantifiers
Open

Fail verification when the solver backend drops quantifiers#4719
tautschnig wants to merge 5 commits into
model-checking:mainfrom
tautschnig:surface-ignored-quantifiers

Conversation

@tautschnig

Copy link
Copy Markdown
Member

Description

CBMC's SAT-based backends only support quantifiers with constant bounds (boolbv_quantifier.cpp's eager instantiation). A kani::forall!/kani::exists! with a symbolic bound reaches the backend's quantifier post-processing, which has no handling: the expression is replaced with unconstrained values, and CBMC reports only a low-visibility warning: ignoring forall among its status messages — which Kani currently swallows entirely.

The consequences are severe for usability:

  • a kani::assume containing such a quantifier is silently not enforced: the harness may report VERIFICATION:- SUCCESSFUL while covering none of the intended property (found while building quantified element-validity assumptions for autoharness slice generation, where the vacuous assume was only caught by a non-tautological probe);
  • a kani::assert containing one may fail spuriously.

This PR detects CBMC's ignoring-quantifier messages in the output parser, counts them on VerificationResult, and renders a prominent warning after the result (on both successful and failed outcomes), explaining the effect and suggesting #[kani::solver(z3)], which handles these quantifiers (verified: the same harnesses verify correctly, fast, under z3).

A proper fix (quantifier instantiation in CBMC's SAT backend) is in progress upstream; this warning closes the silent-degradation window until it lands.

Testing

New expected test pins the dangerous case: a harness that succeeds only because its assertion does not depend on the (unenforced) quantified assumption, with the warning attached. Verified no-warning behavior for constant-bound quantifiers (eagerly instantiated) and under --solver z3. All quantifier expected tests and kani-driver unit tests pass.

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

CBMC's SAT-based backends only support quantifiers with constant bounds.
A quantifier with a symbolic bound reaches the backend's quantifier
post-processing, which has no handling and replaces the expression with
unconstrained values, reporting only a low-visibility 'warning: ignoring
forall' among CBMC's status messages (which Kani does not surface).

The consequences are severe for usability: a kani::assume containing such
a quantifier is silently NOT enforced -- the harness may verify
successfully while covering none of the intended property -- and a
kani::assert containing one may fail spuriously.

Detect CBMC's ignoring-quantifier messages in the output parser, count
them on VerificationResult, and render a prominent warning after the
result (on both successful and failed outcomes) explaining the effect and
suggesting an SMT solver backend (#[kani::solver(z3)]), which supports
these quantifiers.

The new expected test pins the dangerous case: a harness that SUCCEEDS
only because its final assertion does not depend on the (unenforced)
quantified assumption, with the warning attached.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig
tautschnig requested a review from a team as a code owner August 5, 2026 21:22
Copilot AI lite review requested due to automatic review settings August 5, 2026 21:22
@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 Aug 5, 2026

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.

Pull request overview

This PR improves Kani’s user-facing diagnostics around CBMC SAT-backend quantifiers by detecting CBMC “ignoring forall/exists” messages, tracking how many quantifier expressions were dropped, and emitting a prominent warning so users don’t mistake vacuous assumes (or spurious assert failures) for reliable results.

Changes:

  • Add parsing/counting of CBMC “ignoring forall/exists” messages and plumb the count into VerificationResult.
  • Render a prominent, multi-line warning when dropped quantifiers are detected.
  • Add a new expected test that pins the dangerous “vacuous assume” scenario and asserts the warning is emitted.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

File Description
tests/expected/quantifiers/ignored_quantifier_warning.rs New regression test harness that triggers a symbolic-bound quantifier being dropped.
tests/expected/quantifiers/ignored_quantifier_warning.expected Expected output asserting the new prominent warning is printed.
kani-driver/src/call_cbmc.rs Counts ignored-quantifier messages and renders a warning via VerificationResult.
Cargo.lock Updates locked charon version (appears unrelated to the PR’s stated scope).
Suppressed comments (1)

kani-driver/src/call_cbmc.rs:461

  • The ignored-quantifier warning is appended after format_result/format_coverage, which already ends with the final VERIFICATION:- ... line. This means the warning currently prints after the overall status line (and with an extra blank line), but the new expected test output places the warning before VERIFICATION:- ... so it’s not missed on successful runs.
                if self.ignored_quantifiers > 0 {
                    result.push('\n');
                    result.push_str(&ignored_quantifiers_warning(self.ignored_quantifiers));
                }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread kani-driver/src/call_cbmc.rs Outdated
@feliperodri feliperodri added this to the Contracts milestone Aug 6, 2026
@feliperodri feliperodri added the Z-Quantifiers Issues related to quantifiers label Aug 6, 2026
… verdict

Three fixes to the ignored-quantifier warning change:

- Add the new `ignored_quantifiers` field to the two `VerificationResult`
  literals in `sarif.rs`'s test module. Without them `cargo test`/
  `cargo clippy --tests` fail to compile (`missing field
  ignored_quantifiers`), which is what broke the clippy-check and the
  kani-driver unit tests in the regression job.

- Rename the regression test from `ignored_quantifier_warning` to
  `dropped_quantifier_warning`. compiletest skips any test whose path
  contains "ignore" (see `tools/compiletest/src/header.rs`), so the test
  was silently ignored and never actually ran.

- Render the warning immediately before the `VERIFICATION:- ...` line
  rather than after it, so a reliability warning is not missed when the
  run otherwise reports success (this also matches the order in the
  `.expected` file). Falls back to appending when there is no such line
  (e.g. coverage output).

Signed-off-by: Felipe Monteiro <felisous@amazon.com>
Commit 65c183c ("Warn prominently when the solver backend drops
quantifiers") inadvertently swept in a stale charon submodule pointer
(607f5683 -> dee66030, a downgrade from 0.1.88 to 0.1.73) and the
matching Cargo.lock change. These are unrelated to the quantifier
warning feature. Restore charon to 607f5683 / 0.1.88.
…ntifiers-fixes

# Conflicts:
#	kani-driver/src/call_cbmc.rs
When CBMC's SAT backend cannot encode a quantifier with non-constant
bounds, it drops it and replaces it with an unconstrained value. A
`kani::assume` containing such a quantifier is then silently not
enforced, so a "SUCCESSFUL" verdict can be vacuous -- an unsound false
negative, which Kani must never produce.

Instead of only printing a warning, force the verification to FAIL
(VerificationStatus::Failure / FailedProperties::Error) when any
quantifier was dropped, and render an error directing users to an SMT
solver backend that supports quantifiers, e.g. `#[kani::solver(z3)]`.

Also:
- Fix a merge-integration bug: schema_utils_test.rs constructed
  VerificationResult without the `ignored_quantifiers` field, breaking
  the test build.
- Rename the dropped_quantifier_warning expected test to
  dropped_quantifier_error and update it to assert VERIFICATION:- FAILED.
- Document the solver-backend limitation in the quantifiers reference.
@feliperodri

Copy link
Copy Markdown
Member

Behavior change (experimental -Z quantifiers): Previously, when the SAT solver backend dropped a quantifier with non-constant bounds, Kani printed a warning but still reported SUCCESSFUL. Because a kani::assume containing such a quantifier is silently not enforced, that "success" could be vacuous (an unsound false negative). Kani now reports VERIFICATION:- FAILED in this case and directs users to an SMT backend that supports quantifiers (e.g., #[kani::solver(z3)]). Proofs that relied on the old warn-and-pass behavior will now fail — correctly.

@tautschnig do you agree to merge it with this new behavior?

@feliperodri feliperodri changed the title Warn prominently when the solver backend drops quantifiers Fail verification when the solver backend drops quantifiers Aug 14, 2026
@feliperodri feliperodri added the [F] Soundness Kani failed to detect an issue label Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[F] Soundness Kani failed to detect an issue Z-CompilerBenchCI Tag a PR to run benchmark CI Z-EndToEndBenchCI Tag a PR to run benchmark CI Z-Quantifiers Issues related to quantifiers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants