-
Notifications
You must be signed in to change notification settings - Fork 73
Add vacuity detection in MIR and JVM backends. #2339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
all: test.linked-mir.json Test.class | ||
|
||
test.linked-mir.json: test.rs | ||
saw-rustc $< | ||
|
||
Test.class: Test.java | ||
javac -g $< |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
This test checks for vacuous proofs in the MIR, and JVM backends. It skips | ||
LLVM as that is already tested in test0064. | ||
|
||
It corresponds to issue https://github.com/GaloisInc/saw-script/issues/2028 | ||
|
||
Each function includes a contradictory precondition (e.g., x != x), and SAW | ||
should detect this and emit a vacuity warning before successfully proving the | ||
function. |
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
public class Test { | ||
public static void fun_jvm() { | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"version":1,"fns":[{"abi":{"kind":"Rust"},"args":[],"body":{"blocks":[{"block":{"data":[],"terminator":{"kind":"Return","pos":"test.rs:2:19: 2:19"}},"blockid":"bb0"}],"vars":[{"is_zst":true,"mut":{"kind":"Mut"},"name":"_0","ty":"ty::Tuple::e93222e871854c41"}]},"name":"test/648686db::fun_rs","return_ty":"ty::Tuple::e93222e871854c41","spread_arg":null}],"adts":[],"statics":[],"vtables":[],"traits":[],"intrinsics":[{"inst":{"def_id":"test/648686db::fun_rs","kind":"Item","substs":[]},"name":"test/648686db::fun_rs"}],"tys":[{"name":"ty::Tuple::e93222e871854c41","ty":{"kind":"Tuple","tys":[]}}],"roots":["test/648686db::fun_rs"]} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// test.rs | ||
pub fn fun_rs() {} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// test.saw | ||
enable_experimental; | ||
|
||
let fun_rs_spec = do { | ||
x <- mir_fresh_var "x" mir_u32; | ||
mir_precond {{ x != x }}; | ||
mir_execute_func []; | ||
}; | ||
mir_mod <- mir_load_module "test.linked-mir.json"; | ||
mir_verify mir_mod "test::fun_rs" [] false fun_rs_spec z3; | ||
|
||
let fun_jvm_spec = do { | ||
x <- jvm_fresh_var "x" java_int; | ||
jvm_precond {{ x != x }}; // Always false | ||
jvm_execute_func []; | ||
}; | ||
|
||
cls <- java_load_class "Test"; | ||
jvm_verify cls "fun_jvm" [] false fun_jvm_spec z3; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/bin/bash | ||
|
||
n=$( $SAW --detect-vacuity test.saw 2>&1 | tee /dev/stderr | grep -c "Contradiction detected" ) | ||
|
||
if [ "$n" -eq 2 ]; then | ||
echo "Found 2 expected contradictions" | ||
exit 0 | ||
else | ||
echo "Expected 2 contradictions, found $n" | ||
exit 1 | ||
fi |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
{-# LANGUAGE RankNTypes #-} | ||
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE LambdaCase #-} | ||
{-# LANGUAGE OverloadedStrings #-} | ||
|
||
module SAWCentral.Crucible.Common.Vacuity ( | ||
checkAssumptionsForContradictions | ||
) where | ||
|
||
import Prelude hiding (fail) | ||
|
||
import Control.Lens | ||
import Control.Monad (forM_) | ||
import Control.Monad.Extra (findM, whenM) | ||
import Data.Function | ||
import Data.List | ||
import qualified What4.ProgramLoc as W4 | ||
import qualified What4.Interface as W4 | ||
import qualified Lang.Crucible.Backend as Crucible | ||
import SAWCore.SharedTerm | ||
import SAWCoreWhat4.ReturnTrip | ||
import SAWCentral.Proof | ||
import SAWCentral.TopLevel | ||
import SAWCentral.Value | ||
import SAWCentral.Options | ||
import qualified SAWCentral.Crucible.Common as Common | ||
import SAWCentral.Crucible.Common.MethodSpec (CrucibleMethodSpecIR) | ||
import qualified SAWCentral.Crucible.Common.MethodSpec as MS | ||
|
||
type AssumptionReason = (MS.ConditionMetadata, String) | ||
|
||
-- | Checks whether the given list of assumptions contains a contradiction, and | ||
-- if so, computes and displays a minimal set of contradictory assumptions. | ||
checkAssumptionsForContradictions :: | ||
Show (MS.MethodId ext) => | ||
Common.Sym -> | ||
CrucibleMethodSpecIR ext -> | ||
ProofScript () -> | ||
[Crucible.LabeledPred Term AssumptionReason] -> | ||
TopLevel () | ||
checkAssumptionsForContradictions sym methodSpec tactic assumptions = | ||
whenM | ||
(assumptionsContainContradiction sym methodSpec tactic assumptions) | ||
(computeMinimalContradictingCore sym methodSpec tactic assumptions) | ||
|
||
-- | Checks for contradictions within the given list of assumptions, by asking | ||
-- the solver about whether their conjunction entails falsehood. | ||
assumptionsContainContradiction :: | ||
Show (MS.MethodId ext) => | ||
Common.Sym -> | ||
CrucibleMethodSpecIR ext -> | ||
ProofScript () -> | ||
[Crucible.LabeledPred Term AssumptionReason] -> | ||
TopLevel Bool | ||
assumptionsContainContradiction sym methodSpec tactic assumptions = | ||
do | ||
st <- io $ Common.sawCoreState sym | ||
let sc = saw_ctx st | ||
let ploc = methodSpec^.MS.csLoc | ||
(goal',pgl) <- io $ | ||
do | ||
-- conjunction of all assumptions | ||
assume <- scAndList sc (toListOf (folded . Crucible.labeledPred) assumptions) | ||
-- implies falsehood | ||
goal <- scImplies sc assume =<< toSC sym st (W4.falsePred sym) | ||
goal' <- boolToProp sc [] goal | ||
return $ (goal', | ||
ProofGoal | ||
{ goalNum = 0 | ||
, goalType = "vacuousness check" | ||
, goalName = show (methodSpec^.MS.csMethod) | ||
, goalLoc = show (W4.plSourceLoc ploc) ++ " in " ++ show (W4.plFunction ploc) | ||
, goalDesc = "vacuousness check" | ||
, goalSequent = propToSequent goal' | ||
, goalTags = mempty | ||
}) | ||
res <- runProofScript tactic goal' pgl Nothing | ||
"vacuousness check" False False | ||
case res of | ||
ValidProof _ _ -> return True | ||
InvalidProof _ _ _ -> return False | ||
UnfinishedProof _ -> | ||
-- TODO? is this the right behavior? | ||
do printOutLnTop Warn "Could not determine if preconditions are vacuous" | ||
return True | ||
|
||
-- | Given a list of assumptions, computes and displays a smallest subset of | ||
-- them that are contradictory among each themselves. This is **not** | ||
-- implemented efficiently. | ||
computeMinimalContradictingCore :: | ||
Show (MS.MethodId ext) => | ||
Common.Sym -> | ||
CrucibleMethodSpecIR ext -> | ||
ProofScript () -> | ||
[Crucible.LabeledPred Term AssumptionReason] -> | ||
TopLevel () | ||
computeMinimalContradictingCore sym methodSpec tactic assumes = | ||
do | ||
printOutLnTop Warn "Contradiction detected! Computing minimal core of contradictory assumptions:" | ||
-- test subsets of assumptions of increasing sizes until we find a | ||
-- contradictory one | ||
let cores = sortBy (compare `on` length) (subsequences assumes) | ||
findM (assumptionsContainContradiction sym methodSpec tactic) cores >>= \case | ||
Nothing -> | ||
printOutLnTop Warn "No minimal core: the assumptions did not contains a contradiction." | ||
Just core -> | ||
forM_ core $ \assume -> | ||
case assume^.Crucible.labeledPredMsg of | ||
(loc, reason) -> printOutLnTop Warn (show loc ++ ": " ++ reason) | ||
printOutLnTop Warn "Because of the contradiction, the following proofs may be vacuous." |
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
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
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.