Repository navigation
Fold constant bitwise and shift operations, treat others as unknown - #351
Merged
Merged
Conversation
…ixes #350) Bitwise and shift operators had no case in getOperatorFromKind, so passing e.g. 1 | 4 as a refined argument reached a string switch with a null operator and crashed (String.hashCode() on null). A compile-time constant expression (literals, static final constants, JDK constants such as ZipFile.OPEN_READ | ZipFile.OPEN_DELETE) is now folded to its value with Java's semantics; any other bitwise/shift operation is an unconstrained value of its type, so a refinement that depends on it is reported as not provable. Non-short-circuit &, | and ^ on booleans map to and, or and not-equal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rcosta358
approved these changes
Oct 6, 2026
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.
Fixes #350.
Problem
A bitwise or shift operator in a refined argument crashed the verifier:
getOperatorFromKindhad no case for|,&,^,<<,>>or>>>, so the null operator reached a string switch (Cannot invoke "String.hashCode()"). Bit flags combined with|are the standard way to pass JDK mode constants, so correct code such asnew ZipFile(f, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE)could not be verified.Example
Change
StaticConstants.foldIntegralevaluates integral compile-time constant expressions (literals,static finalconstants from source or by reflection, and arithmetic, bitwise and shift operators over them) with Java's semantics for the expression's type (intvslongoverflow and shift masking).OperationsChecker: where a binary operator has no counterpart in the logic, a constant expression is folded to a literal; anything else is a fresh, unconstrained value of its type, as null comparisons already are. A compound assignment such asx |= yleavesxunknown. The non-short-circuit&,|and^on booleans map to and, or and not-equal.Tests
CorrectBitwiseConstantArgument: literals,static finalconstants, JDK constants by reflection, nested, shifts and xor,|=, boolean&/|/^.ErrorBitwiseConstantArgument: a folded constant that violates the refinement.ErrorBitwiseUnknownOperand: a non-constant operand is reported as not provable instead of crashing.mvn test: all tests pass (369).Found while building verification exercises from real Java bugs (a passport decoder passed
OPEN_DELETEwithoutOPEN_READ; the corrected program hit this crash).🤖 Generated with Claude Code