Warn when quantifier range exceeds SAT solver threshold#4579
Open
feliperodri wants to merge 1 commit intomodel-checking:mainfrom
Open
Warn when quantifier range exceeds SAT solver threshold#4579feliperodri wants to merge 1 commit intomodel-checking:mainfrom
feliperodri wants to merge 1 commit intomodel-checking:mainfrom
Conversation
814d5ef to
0f3e041
Compare
c50cbc8 to
1fbc451
Compare
… ranges SAT solvers (the default backend) expand quantifiers into one term per value in the range. Unbounded quantifiers (forall!(|i| ...) which expand over all 2^64 usize values) cause silent memory exhaustion or divergence with no diagnostic. This change: - Adds warn_large_quantifier_range() in hooks.rs that checks if both quantifier bounds are compile-time integer constants and warns when the range exceeds 1000 values. For very large ranges (> 2^32), the message shows "unbounded (~2^64)" instead of the raw number. - Adds unwrap_to_constant() that resolves typecasts and symbol table references to extract integer constants, with a depth limit of 5 to guard against cycles. - Adds an expected test (large_range_warning.rs) with 3 harnesses covering unbounded forall, unbounded exists, and a small range that should not warn. Known limitation: bounded quantifiers (forall!(|i in (0, N)| ...)) use let bindings in the macro for type coercion, which hides constants from codegen. The warning currently only fires for unbounded quantifiers. The warning suggests using tighter bounds or switching to an SMT solver (#[kani::solver(z3)] or --solver z3).
1fbc451 to
eb1297c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emit a compile-time warning when an unbounded
forall!orexists!quantifier is detected. SAT solvers (the default backend) expand quantifiers into one conjunction/disjunction per value in the range, so unbounded ranges (forall!(|i| ...)which expands over all 2^64usizevalues) cause silent memory exhaustion or divergence with no diagnostic.Contributes to #3273.
Problem
Writing
forall!(|i| ...)(unbounded, ranging over allusizevalues) with the default SAT backend silently hangs or OOMs because CBMC expands the quantifier into 2^64 terms. Users get no feedback about why verification doesn't terminate.Solution
warn_large_quantifier_range()inhooks.rs: At codegen time, checks if both quantifier bounds are compile-time integer constants. If the range exceedsQUANTIFIER_RANGE_WARN_THRESHOLD(1000), emits aspan_warnsuggesting tighter bounds or an SMT solver. For unbounded ranges (~2^64), uses a human-friendly message instead of the raw integer.unwrap_to_constant(): Helper that unwraps typecasts and resolves symbol references via the symbol table to extract integer constants from bound expressions. Includes a depth limit (5) to guard against cycles.Known limitation
Bounded quantifiers (
forall!(|i in (0, 2000)| ...)) useletbindings in the macro expansion for type coercion, which hides the constant values from codegen. The warning currently only fires for unbounded quantifiers, which is the most dangerous case. Detecting large bounded ranges would require constant propagation through local variables, a potential follow-up improvement.Example warning
Testing
large_range_warning.rs— expected test with 3 harnesses:check_unbounded_forall_warns: unboundedforall!(|i| ...), verifies warning is emittedcheck_unbounded_exists_warns: unboundedexists!(|i| ...), verifies warning is emittedcheck_small_forall_no_warn: range of 10, verifies no warning (absence of output is intentional)By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.