Skip to content

Commit 24e423d

Browse files
authored
Merge pull request #873 from GaloisInc/path-sat-fix
Path sat fix
2 parents ceb583b + b362d9e commit 24e423d

File tree

10 files changed

+82
-20
lines changed

10 files changed

+82
-20
lines changed

deps/what4

3.58 KB
Binary file not shown.
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <stdint.h>
2+
3+
uint64_t g1(uint64_t x) {
4+
int i = 0;
5+
uint64_t r = x;
6+
do {
7+
r = r+1;
8+
} while ( i++ < 3 && r == 0 );
9+
return r;
10+
}
11+
12+
// NB the termination of the following loop
13+
// is a bit tricky because of the interaction
14+
// between short-cutting '&&' and the 'i++'
15+
// expression.
16+
uint64_t g2(uint64_t x) {
17+
int i = 0;
18+
uint64_t r = x;
19+
do {
20+
r = r+1;
21+
} while ( r == 0 && i++ < 3 );
22+
return r;
23+
}

intTests/test0061_path_sat/test.saw

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
m <- llvm_load_module "termination.bc";
2+
3+
let g_spec = do {
4+
x <- crucible_fresh_var "x" (llvm_int 64);
5+
crucible_execute_func [crucible_term x];
6+
};
7+
8+
crucible_llvm_verify m "g1" [] false g_spec z3;
9+
10+
// NB: path sat checking is required for this
11+
// to terminate in a reasonable time
12+
crucible_llvm_verify m "g2" [] true g_spec z3;

intTests/test0061_path_sat/test.sh

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$SAW test.saw

src/SAWScript/Crucible/JVM/Builtins.hs

+4
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,10 @@ setupCrucibleContext bic opts jclass =
707707
let gen = globalNonceGenerator
708708
sym <- io $ Crucible.newSAWCoreBackend W4.FloatRealRepr sc gen
709709
io $ CJ.setSimulatorVerbosity (simVerbose opts) sym
710+
711+
-- TODO! there's a lot of options setup we need to replicate
712+
-- from SAWScript.Crucible.LLVM.Builtins
713+
710714
return JVMCrucibleContext { _jccJVMClass = jclass
711715
, _jccCodebase = cb
712716
, _jccBackend = sym

src/SAWScript/Crucible/LLVM/Builtins.hs

+17-10
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ import qualified What4.Expr.Builder as W4
132132

133133
-- crucible
134134
import qualified Lang.Crucible.Backend as Crucible
135+
import qualified Lang.Crucible.Backend.Online as Crucible
135136
import qualified Lang.Crucible.Backend.SAWCore as CrucibleSAW
136137
import qualified Lang.Crucible.CFG.Core as Crucible
137138
import qualified Lang.Crucible.CFG.Extension as Crucible
@@ -269,7 +270,7 @@ crucible_llvm_verify ::
269270
TopLevel (SomeLLVM MS.CrucibleMethodSpecIR)
270271
crucible_llvm_verify bic opts (Some lm) nm lemmas checkSat setup tactic =
271272
do lemmas' <- checkModuleCompatibility lm lemmas
272-
withMethodSpec bic opts lm nm setup $ \cc method_spec ->
273+
withMethodSpec bic opts checkSat lm nm setup $ \cc method_spec ->
273274
do (res_method_spec, _) <- verifyMethodSpec bic opts cc method_spec lemmas' checkSat tactic Nothing
274275
returnProof $ SomeLLVM res_method_spec
275276

@@ -281,7 +282,7 @@ crucible_llvm_unsafe_assume_spec ::
281282
LLVMCrucibleSetupM () {- ^ Boundary specification -} ->
282283
TopLevel (SomeLLVM MS.CrucibleMethodSpecIR)
283284
crucible_llvm_unsafe_assume_spec bic opts (Some lm) nm setup =
284-
withMethodSpec bic opts lm nm setup $ \_ method_spec ->
285+
withMethodSpec bic opts False lm nm setup $ \_ method_spec ->
285286
do printOutLnTop Info $
286287
unwords ["Assume override", (method_spec ^. csName)]
287288
returnProof $ SomeLLVM method_spec
@@ -298,7 +299,7 @@ crucible_llvm_array_size_profile ::
298299
crucible_llvm_array_size_profile assume bic opts (Some lm) nm lemmas setup = do
299300
cell <- io $ newIORef (Map.empty :: Map Text.Text [Crucible.FunctionProfile])
300301
lemmas' <- checkModuleCompatibility lm lemmas
301-
withMethodSpec bic opts lm nm setup $ \cc ms -> do
302+
withMethodSpec bic opts False lm nm setup $ \cc ms -> do
302303
void . verifyMethodSpec bic opts cc ms lemmas' True assume $ Just cell
303304
profiles <- io $ readIORef cell
304305
pure . fmap (\(fnm, prof) -> (Text.unpack fnm, prof)) $ Map.toList profiles
@@ -310,13 +311,13 @@ crucible_llvm_compositional_extract ::
310311
String ->
311312
String ->
312313
[SomeLLVM MS.CrucibleMethodSpecIR] ->
313-
Bool ->
314+
Bool {- ^ check sat -} ->
314315
LLVMCrucibleSetupM () ->
315316
ProofScript SatResult ->
316317
TopLevel (SomeLLVM MS.CrucibleMethodSpecIR)
317318
crucible_llvm_compositional_extract bic opts (Some lm) nm func_name lemmas checkSat setup tactic =
318319
do lemmas' <- checkModuleCompatibility lm lemmas
319-
withMethodSpec bic opts lm nm setup $ \cc method_spec ->
320+
withMethodSpec bic opts checkSat lm nm setup $ \cc method_spec ->
320321
do let value_input_parameters = mapMaybe
321322
(\(_, setup_value) -> setupValueAsExtCns setup_value)
322323
(Map.elems $ method_spec ^. MS.csArgBindings)
@@ -447,13 +448,14 @@ checkModuleCompatibility llvmModule = foldM step []
447448
withMethodSpec ::
448449
BuiltinContext ->
449450
Options ->
451+
Bool {- ^ path sat -} ->
450452
LLVMModule arch ->
451453
String {- ^ Name of the function -} ->
452454
LLVMCrucibleSetupM () {- ^ Boundary specification -} ->
453455
((?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
454456
LLVMCrucibleContext arch -> MS.CrucibleMethodSpecIR (LLVM arch) -> TopLevel a) ->
455457
TopLevel a
456-
withMethodSpec bic opts lm nm setup action =
458+
withMethodSpec bic opts pathSat lm nm setup action =
457459
do (nm', parent) <- resolveSpecName nm
458460
let edef = findDefMaybeStatic (modAST lm) nm'
459461
let edecl = findDecl (modAST lm) nm'
@@ -468,7 +470,7 @@ withMethodSpec bic opts lm nm setup action =
468470

469471
Crucible.llvmPtrWidth (mtrans ^. Crucible.transContext) $ \_ ->
470472
fmap NE.head $ forM defOrDecls $ \defOrDecl ->
471-
setupLLVMCrucibleContext bic opts lm $ \cc ->
473+
setupLLVMCrucibleContext bic opts pathSat lm $ \cc ->
472474
do let sym = cc^.ccBackend
473475

474476
pos <- getPosition
@@ -1204,11 +1206,12 @@ verifyPoststate opts sc cc mspec env0 globals ret =
12041206
setupLLVMCrucibleContext ::
12051207
BuiltinContext ->
12061208
Options ->
1209+
Bool {- ^ enable path sat checking -} ->
12071210
LLVMModule arch ->
12081211
((?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
12091212
LLVMCrucibleContext arch -> TopLevel a) ->
12101213
TopLevel a
1211-
setupLLVMCrucibleContext bic opts lm action =
1214+
setupLLVMCrucibleContext bic opts pathSat lm action =
12121215
do halloc <- getHandleAlloc
12131216
let llvm_mod = modAST lm
12141217
let mtrans = modTrans lm
@@ -1234,6 +1237,10 @@ setupLLVMCrucibleContext bic opts lm action =
12341237
cacheTermsSetting <- W4.getOptionSetting W4.cacheTerms cfg
12351238
_ <- W4.setOpt cacheTermsSetting what4HashConsing
12361239

1240+
-- enable online solver interactions if path sat checking is on
1241+
enableOnlineSetting <- W4.getOptionSetting Crucible.enableOnlineBackend cfg
1242+
_ <- W4.setOpt enableOnlineSetting pathSat
1243+
12371244
W4.extendConfig
12381245
[ W4.opt
12391246
enableSMTArrayMemoryModel
@@ -1447,7 +1454,7 @@ crucible_llvm_extract bic opts (Some lm) fn_name =
14471454
when (any L.isAlias defTypes) $
14481455
throwTopLevel "Type aliases are not supported by `crucible_llvm_extract`."
14491456
Left err -> throwTopLevel (displayVerifExceptionOpts opts err)
1450-
setupLLVMCrucibleContext bic opts lm $ \cc ->
1457+
setupLLVMCrucibleContext bic opts False lm $ \cc ->
14511458
case Map.lookup (fromString fn_name) (Crucible.cfgMap (ccLLVMModuleTrans cc)) of
14521459
Nothing -> throwTopLevel $ unwords ["function", fn_name, "not found"]
14531460
Just (_,cfg) -> io $ extractFromLLVMCFG opts (biSharedContext bic) cc cfg
@@ -1461,7 +1468,7 @@ crucible_llvm_cfg ::
14611468
crucible_llvm_cfg bic opts (Some lm) fn_name =
14621469
do let ctx = modTrans lm ^. Crucible.transContext
14631470
let ?lc = ctx^.Crucible.llvmTypeCtx
1464-
setupLLVMCrucibleContext bic opts lm $ \cc ->
1471+
setupLLVMCrucibleContext bic opts False lm $ \cc ->
14651472
case Map.lookup (fromString fn_name) (Crucible.cfgMap (ccLLVMModuleTrans cc)) of
14661473
Nothing -> throwTopLevel $ unwords ["function", fn_name, "not found"]
14671474
Just (_,cfg) -> return (LLVM_CFG cfg)

src/SAWScript/Crucible/LLVM/MethodSpecIR.hs

+4-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ import Data.Parameterized.Some (Some(Some))
120120
import qualified Data.Parameterized.Map as MapF
121121

122122
import qualified What4.Expr.Builder as B
123+
import What4.Protocol.Online (OnlineSolver)
123124
import What4.ProgramLoc (ProgramLoc)
124125

125126
import qualified Lang.Crucible.Backend.SAWCore as Crucible
@@ -140,6 +141,7 @@ import Verifier.SAW.Rewriter (Simpset)
140141
import Verifier.SAW.SharedTerm
141142
import Verifier.SAW.TypedTerm
142143

144+
143145
--------------------------------------------------------------------------------
144146
-- ** Language features
145147

@@ -291,7 +293,8 @@ showLLVMModule (LLVMModule name m _) =
291293
--------------------------------------------------------------------------------
292294
-- ** Ghost state
293295

294-
instance Crucible.IntrinsicClass (Crucible.SAWCoreBackend n solver (B.Flags B.FloatReal)) MS.GhostValue where
296+
instance OnlineSolver solver =>
297+
Crucible.IntrinsicClass (Crucible.SAWCoreBackend n solver (B.Flags B.FloatReal)) MS.GhostValue where
295298
type Intrinsic (Crucible.SAWCoreBackend n solver (B.Flags B.FloatReal)) MS.GhostValue ctx = TypedTerm
296299
muxIntrinsic sym _ _namerep _ctx prd thn els =
297300
do when (ttSchema thn /= ttSchema els) $ fail $ unlines $

src/SAWScript/Crucible/LLVM/X86.hs

+19-7
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ import qualified Lang.Crucible.Simulator.Operations as C
9494
import qualified Lang.Crucible.Simulator.OverrideSim as C
9595
import qualified Lang.Crucible.Simulator.RegMap as C
9696
import qualified Lang.Crucible.Simulator.SimError as C
97+
import qualified Lang.Crucible.Simulator.PathSatisfiability as C
9798

9899
import qualified Lang.Crucible.LLVM.DataLayout as C.LLVM
99100
import qualified Lang.Crucible.LLVM.Extension as C.LLVM
@@ -226,11 +227,11 @@ crucible_llvm_verify_x86 ::
226227
FilePath {- ^ Path to ELF file -} ->
227228
String {- ^ Function's symbol in ELF file -} ->
228229
[(String, Integer)] {- ^ Global variable symbol names and sizes (in bytes) -} ->
229-
Bool {-^ Whether to enable path satisfiability checking (currently ignored) -} ->
230+
Bool {- ^ Whether to enable path satisfiability checking -} ->
230231
LLVMCrucibleSetupM () {- ^ Specification to verify against -} ->
231232
ProofScript SatResult {- ^ Tactic used to use when discharging goals -} ->
232233
TopLevel (SomeLLVM MS.CrucibleMethodSpecIR)
233-
crucible_llvm_verify_x86 bic opts (Some (llvmModule :: LLVMModule x)) path nm globsyms _checkSat setup tactic
234+
crucible_llvm_verify_x86 bic opts (Some (llvmModule :: LLVMModule x)) path nm globsyms checkSat setup tactic
234235
| Just Refl <- testEquality (C.LLVM.X86Repr $ knownNat @64) . C.LLVM.llvmArch
235236
$ modTrans llvmModule ^. C.LLVM.transContext = do
236237
let ?ptrWidth = knownNat @64
@@ -277,7 +278,7 @@ crucible_llvm_verify_x86 bic opts (Some (llvmModule :: LLVMModule x)) path nm gl
277278
]
278279

279280
liftIO $ printOutLn opts Info "Examining specification to determine preconditions"
280-
methodSpec <- buildMethodSpec bic opts llvmModule nm (show addr) setup
281+
methodSpec <- buildMethodSpec bic opts llvmModule nm (show addr) checkSat setup
281282

282283
let ?lc = modTrans llvmModule ^. C.LLVM.transContext . C.LLVM.llvmTypeCtx
283284

@@ -346,13 +347,23 @@ crucible_llvm_verify_x86 bic opts (Some (llvmModule :: LLVMModule x)) path nm gl
346347
pure $ C.regValue r
347348

348349
liftIO $ printOutLn opts Info "Simulating function"
349-
liftIO $ C.executeCrucible [] initial >>= \case
350+
351+
psatf <-
352+
if checkSat then
353+
do f <- liftIO (C.pathSatisfiabilityFeature sym (C.considerSatisfiability sym))
354+
pure [C.genericToExecutionFeature f]
355+
else
356+
pure []
357+
358+
let execFeatures = psatf
359+
360+
liftIO $ C.executeCrucible execFeatures initial >>= \case
350361
C.FinishedResult{} -> pure ()
351362
C.AbortedResult{} -> printOutLn opts Warn "Warning: function never returns"
352363
C.TimeoutResult{} -> fail "Execution timed out"
353364

354365
stats <- checkGoals sym opts sc tactic
355-
366+
356367
returnProof $ SomeLLVM (methodSpec & MS.csSolverStats .~ stats)
357368
| otherwise = fail "LLVM module must be 64-bit"
358369

@@ -424,10 +435,11 @@ buildMethodSpec ::
424435
LLVMModule LLVMArch ->
425436
String {- ^ Name of method -} ->
426437
String {- ^ Source location for method spec (here, we use the address) -} ->
438+
Bool {- ^ check sat -} ->
427439
LLVMCrucibleSetupM () ->
428440
TopLevel (MS.CrucibleMethodSpecIR LLVM)
429-
buildMethodSpec bic opts lm nm loc setup =
430-
setupLLVMCrucibleContext bic opts lm $ \cc -> do
441+
buildMethodSpec bic opts lm nm loc checkSat setup =
442+
setupLLVMCrucibleContext bic opts checkSat lm $ \cc -> do
431443
let methodId = LLVMMethodId nm Nothing
432444
let programLoc =
433445
W4.mkProgramLoc (W4.functionNameFromText $ Text.pack nm)

0 commit comments

Comments
 (0)