Skip to content
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

Array copy set prep #1515

Merged
merged 18 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# Nightly

* New commands `enable_what4_eval` and `disable_what4_eval` to enable or
disable What4 translation for SAWCore expressions during Crucible symbolic
execution.

* New command `llvm_alloc_sym_init` like `llvm_alloc`, but assume that the
allocation is initialized with symbolic bytes.

* New command `set_crucible_timeout` to set the timeout for the SMT solver
during the LLVM and X86 Crucible symbolic execution. This is used for
path-sat checks, and sat checks when applying overrides.

# Version 0.9

## New Features
Expand Down
16 changes: 10 additions & 6 deletions saw-core-what4/src/Verifier/SAW/Simulator/What4.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1320,21 +1320,21 @@ parseUninterpretedSAW sym st sc ref trm app ty =
parseUninterpretedSAW sym st sc ref trm' app' t2

VBoolType
-> VBool <$> mkUninterpretedSAW sym st ref trm app BaseBoolRepr
-> VBool <$> mkUninterpretedSAW sym st sc ref trm app BaseBoolRepr

VIntType
-> VInt <$> mkUninterpretedSAW sym st ref trm app BaseIntegerRepr
-> VInt <$> mkUninterpretedSAW sym st sc ref trm app BaseIntegerRepr

VIntModType n
-> VIntMod n <$> mkUninterpretedSAW sym st ref (ArgTermFromIntMod n trm) app BaseIntegerRepr
-> VIntMod n <$> mkUninterpretedSAW sym st sc ref (ArgTermFromIntMod n trm) app BaseIntegerRepr

-- 0 width bitvector is a constant
VVecType 0 VBoolType
-> return $ VWord ZBV

VVecType n VBoolType
| Just (Some (PosNat w)) <- somePosNat n
-> (VWord . DBV) <$> mkUninterpretedSAW sym st ref trm app (BaseBVRepr w)
-> (VWord . DBV) <$> mkUninterpretedSAW sym st sc ref trm app (BaseBVRepr w)

VVecType n ety | n >= 0
-> do ety' <- termOfTValue sc ety
Expand All @@ -1349,7 +1349,7 @@ parseUninterpretedSAW sym st sc ref trm app ty =
| Just (Some idx_repr) <- valueAsBaseType ity
, Just (Some elm_repr) <- valueAsBaseType ety
-> (VArray . SArray) <$>
mkUninterpretedSAW sym st ref trm app (BaseArrayRepr (Ctx.Empty Ctx.:> idx_repr) elm_repr)
mkUninterpretedSAW sym st sc ref trm app (BaseArrayRepr (Ctx.Empty Ctx.:> idx_repr) elm_repr)

VUnitType
-> return VUnit
Expand All @@ -1367,12 +1367,16 @@ mkUninterpretedSAW ::
forall n st fs t.
B.ExprBuilder n st fs ->
SAWCoreState n ->
SharedContext ->
IORef (SymFnCache (B.ExprBuilder n st fs)) ->
ArgTerm ->
UnintApp (SymExpr (B.ExprBuilder n st fs)) ->
BaseTypeRepr t ->
IO (SymExpr (B.ExprBuilder n st fs) t)
mkUninterpretedSAW sym st ref trm (UnintApp nm args tys) ret =
mkUninterpretedSAW sym st sc ref trm (UnintApp nm args tys) ret
| Just Refl <- testEquality Ctx.empty tys =
bindSAWTerm sym st ret =<< reconstructArgTerm trm sc []
| otherwise =
do fn <- mkSymFn sym ref nm tys ret
sawRegisterSymFunInterp st fn (reconstructArgTerm trm)
W.applySymFn sym fn args
Expand Down
3 changes: 3 additions & 0 deletions saw-remote-api/src/SAWServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import Verifier.SAW.TypedTerm (TypedTerm, CryptolModule)

import SAWScript.Crucible.LLVM.Builtins (CheckPointsToType)
import SAWScript.Crucible.LLVM.X86 (defaultStackBaseAlign)
import qualified SAWScript.Crucible.Common as CC (defaultSAWCoreBackendTimeout)
import qualified SAWScript.Crucible.Common.MethodSpec as CMS (ProvedSpec, GhostGlobal)
import qualified SAWScript.Crucible.LLVM.MethodSpecIR as CMS (SomeLLVM, LLVMModule)
import SAWScript.Options (Options(..), processEnv, defaultOptions)
Expand Down Expand Up @@ -220,9 +221,11 @@ initialState readFileFn =
, rwDebugIntrinsics = True
, rwWhat4HashConsing = False
, rwWhat4HashConsingX86 = False
, rwWhat4Eval = False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's open ticket about plumbing this new option through the RPC server.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it's worth, it's fairly easy to add support for toggling options like this in saw-remote-api. You basically just add a new constructor here, and then update the code in setOption, parseOption, and instance Doc.DescribedMethod SetOptionParams OK accordingly.

, rwStackBaseAlign = defaultStackBaseAlign
, rwProofs = []
, rwPreservedRegs = []
, rwCrucibleTimeout = CC.defaultSAWCoreBackendTimeout
}
return (SAWState emptyEnv bic [] ro rw M.empty)

Expand Down
21 changes: 16 additions & 5 deletions src/SAWScript/Crucible/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ module SAWScript.Crucible.Common
, setupProfiling
, SAWCruciblePersonality(..)
, newSAWCoreBackend
, newSAWCoreBackendWithTimeout
, defaultSAWCoreBackendTimeout
, sawCoreState
) where

Expand All @@ -24,7 +26,8 @@ import Lang.Crucible.Simulator.Profiling
import Lang.Crucible.Backend (AbortExecReason(..), ppAbortExecReason, IsSymInterface)
import Lang.Crucible.Backend.Online
import qualified Data.Parameterized.Nonce as Nonce
import qualified What4.Solver.Yices as Yices
import qualified What4.Solver.Z3 as Z3
import qualified What4.Protocol.SMTLib2 as SMT2
RyanGlScott marked this conversation as resolved.
Show resolved Hide resolved
import qualified What4.Config as W4
import qualified What4.Expr as W4
import qualified What4.Interface as W4
Expand All @@ -40,16 +43,24 @@ import Verifier.SAW.SharedTerm as SC
import Verifier.SAW.Simulator.What4.ReturnTrip (SAWCoreState, newSAWCoreState)

-- | The symbolic backend we use for SAW verification
type Sym = OnlineBackendUserSt Nonce.GlobalNonceGenerator Yices.Connection SAWCoreState (W4.Flags W4.FloatReal)
type Sym = OnlineBackendUserSt Nonce.GlobalNonceGenerator (SMT2.Writer Z3.Z3) SAWCoreState (W4.Flags W4.FloatReal)

data SAWCruciblePersonality sym = SAWCruciblePersonality


newSAWCoreBackend :: SC.SharedContext -> IO Sym
newSAWCoreBackend sc =
newSAWCoreBackend sc = newSAWCoreBackendWithTimeout sc 0

defaultSAWCoreBackendTimeout :: Integer
defaultSAWCoreBackendTimeout = 10000

newSAWCoreBackendWithTimeout :: SC.SharedContext -> Integer -> IO Sym
newSAWCoreBackendWithTimeout sc timeout =
do st <- newSAWCoreState sc
sym <- newOnlineBackend W4.FloatRealRepr Nonce.globalNonceGenerator Yices.yicesDefaultFeatures st
W4.extendConfig Yices.yicesOptions (W4.getConfiguration sym)
sym <- newOnlineBackend W4.FloatRealRepr Nonce.globalNonceGenerator (SMT2.defaultFeatures Z3.Z3) st
W4.extendConfig Z3.z3Options (W4.getConfiguration sym)
z3TimeoutSetting <- W4.getOptionSetting Z3.z3Timeout (W4.getConfiguration sym)
_ <- W4.setOpt z3TimeoutSetting timeout
return sym

sawCoreState :: Sym -> IO (SAWCoreState Nonce.GlobalNonceGenerator)
Expand Down
46 changes: 32 additions & 14 deletions src/SAWScript/Crucible/LLVM/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ module SAWScript.Crucible.LLVM.Builtins
, llvm_alloc_readonly
, llvm_alloc_readonly_aligned
, llvm_alloc_with_size
, llvm_alloc_sym_init
, llvm_symbolic_alloc
, llvm_alloc_global
, llvm_fresh_expanded_val
Expand Down Expand Up @@ -487,7 +488,7 @@ withMethodSpec ::
LLVMModule arch ->
String {- ^ Name of the function -} ->
LLVMCrucibleSetupM () {- ^ Boundary specification -} ->
((?lc :: Crucible.TypeContext, ?memOpts::Crucible.MemOptions, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
((?lc :: Crucible.TypeContext, ?memOpts::Crucible.MemOptions, ?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
LLVMCrucibleContext arch -> MS.CrucibleMethodSpecIR (LLVM arch) -> TopLevel a) ->
TopLevel a
withMethodSpec pathSat lm nm setup action =
Expand Down Expand Up @@ -533,6 +534,7 @@ withMethodSpec pathSat lm nm setup action =
verifyMethodSpec ::
( ?lc :: Crucible.TypeContext
, ?memOpts::Crucible.MemOptions
, ?w4EvalTactic :: W4EvalTactic
, Crucible.HasPtrWidth (Crucible.ArchWidth arch)
, Crucible.HasLLVMAnn Sym
) =>
Expand Down Expand Up @@ -739,7 +741,7 @@ checkSpecReturnType cc mspec =
-- Returns a tuple of (arguments, preconditions, pointer values,
-- memory).
verifyPrestate ::
(Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
(?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
Options ->
LLVMCrucibleContext arch ->
MS.CrucibleMethodSpecIR (LLVM arch) ->
Expand Down Expand Up @@ -853,7 +855,7 @@ checkRegisterCompatibility mt mt' =
return (st == st')

resolveArguments ::
(?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
(?lc :: Crucible.TypeContext, ?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
LLVMCrucibleContext arch ->
Crucible.MemImpl Sym ->
MS.CrucibleMethodSpecIR (LLVM arch) ->
Expand Down Expand Up @@ -925,7 +927,7 @@ setupGlobalAllocs cc mspec mem0 = foldM go mem0 $ mspec ^. MS.csGlobalAllocs
-- function spec, write the given value to the address of the given
-- pointer.
setupPrePointsTos :: forall arch.
(?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
(?lc :: Crucible.TypeContext, ?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
MS.CrucibleMethodSpecIR (LLVM arch) ->
Options ->
LLVMCrucibleContext arch ->
Expand Down Expand Up @@ -954,7 +956,7 @@ setupPrePointsTos mspec opts cc env pts mem0 = foldM go mem0 pts
-- | Sets up globals (ghost variable), and collects boolean terms
-- that should be assumed to be true.
setupPrestateConditions ::
(?lc :: Crucible.TypeContext, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
(?lc :: Crucible.TypeContext, ?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
MS.CrucibleMethodSpecIR (LLVM arch) ->
LLVMCrucibleContext arch ->
Crucible.MemImpl Sym ->
Expand Down Expand Up @@ -1007,20 +1009,19 @@ assertEqualVals cc v1 v2 =

-- TODO(langston): combine with/move to executeAllocation
doAlloc ::
(Crucible.HasPtrWidth (Crucible.ArchWidth arch)) =>
(?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
LLVMCrucibleContext arch ->
AllocIndex ->
LLVMAllocSpec ->
StateT MemImpl IO (LLVMPtr (Crucible.ArchWidth arch))
doAlloc cc i (LLVMAllocSpec mut _memTy alignment sz loc fresh)
doAlloc cc i (LLVMAllocSpec mut _memTy alignment sz loc fresh initialization)
| fresh = liftIO $ executeFreshPointer cc i
| otherwise =
StateT $ \mem ->
do let sym = cc^.ccBackend
sz' <- liftIO $ resolveSAWSymBV cc Crucible.PtrWidth sz
let l = show (W4.plSourceLoc loc)
liftIO $
Crucible.doMalloc sym Crucible.HeapAlloc mut l mem sz' alignment
liftIO $ doAllocSymInit sym mem mut alignment sz' l initialization

--------------------------------------------------------------------------------

Expand All @@ -1045,6 +1046,7 @@ ppGlobalPair cc gp =
registerOverride ::
( ?lc :: Crucible.TypeContext
, ?memOpts::Crucible.MemOptions
, ?w4EvalTactic :: W4EvalTactic
, Crucible.HasPtrWidth wptr
, wptr ~ Crucible.ArchWidth arch
, Crucible.HasLLVMAnn Sym
Expand Down Expand Up @@ -1087,6 +1089,7 @@ registerOverride opts cc sim_ctx top_loc cs =
registerInvariantOverride ::
( ?lc :: Crucible.TypeContext
, ?memOpts::Crucible.MemOptions
, ?w4EvalTactic :: W4EvalTactic
, Crucible.HasPtrWidth (Crucible.ArchWidth arch)
, Crucible.HasLLVMAnn Sym
) =>
Expand Down Expand Up @@ -1168,6 +1171,7 @@ withBreakpointCfgAndBlockId context name parent k =
verifySimulate ::
( ?lc :: Crucible.TypeContext
, ?memOpts::Crucible.MemOptions
, ?w4EvalTactic :: W4EvalTactic
, Crucible.HasPtrWidth wptr
, wptr ~ Crucible.ArchWidth arch
, Crucible.HasLLVMAnn Sym
Expand Down Expand Up @@ -1287,6 +1291,7 @@ scAndList sc = conj . filter nontrivial
verifyPoststate ::
( ?lc :: Crucible.TypeContext
, ?memOpts::Crucible.MemOptions
, ?w4EvalTactic :: W4EvalTactic
, Crucible.HasPtrWidth wptr
, wptr ~ Crucible.ArchWidth arch
, Crucible.HasLLVMAnn Sym
Expand Down Expand Up @@ -1355,7 +1360,7 @@ verifyPoststate cc mspec env0 globals ret =
setupLLVMCrucibleContext ::
Bool {- ^ enable path sat checking -} ->
LLVMModule arch ->
((?lc :: Crucible.TypeContext, ?memOpts::Crucible.MemOptions, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
((?lc :: Crucible.TypeContext, ?memOpts::Crucible.MemOptions, ?w4EvalTactic :: W4EvalTactic, Crucible.HasPtrWidth (Crucible.ArchWidth arch), Crucible.HasLLVMAnn Sym) =>
LLVMCrucibleContext arch -> TopLevel a) ->
TopLevel a
setupLLVMCrucibleContext pathSat lm action =
Expand All @@ -1370,6 +1375,8 @@ setupLLVMCrucibleContext pathSat lm action =
crucible_assert_then_assume_enabled <- gets rwCrucibleAssertThenAssume
what4HashConsing <- gets rwWhat4HashConsing
laxPointerOrdering <- gets rwLaxPointerOrdering
what4Eval <- gets rwWhat4Eval
crucibleTimeout <- gets rwCrucibleTimeout
Crucible.llvmPtrWidth ctx $ \wptr ->
Crucible.withPtrWidth wptr $
do let ?lc = ctx^.Crucible.llvmTypeCtx
Expand All @@ -1378,10 +1385,11 @@ setupLLVMCrucibleContext pathSat lm action =
}
let ?intrinsicsOpts = Crucible.defaultIntrinsicsOptions
let ?recordLLVMAnnotation = \_ _ -> return ()
let ?w4EvalTactic = W4EvalTactic { doW4Eval = what4Eval }
cc <-
io $
do let verbosity = simVerbose opts
sym <- Common.newSAWCoreBackend sc
sym <- Common.newSAWCoreBackendWithTimeout sc crucibleTimeout

let cfg = W4.getConfiguration sym
verbSetting <- W4.getOptionSetting W4.verbosity cfg
Expand Down Expand Up @@ -1866,9 +1874,10 @@ llvm_alloc_with_mutability_and_size ::
Crucible.Mutability ->
Maybe (Crucible.Bytes) ->
Maybe Crucible.Alignment ->
LLVMAllocSpecInit ->
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
llvm_alloc_with_mutability_and_size mut sz alignment lty =
llvm_alloc_with_mutability_and_size mut sz alignment initialization lty =
LLVMCrucibleSetupM $
do cctx <- getLLVMCrucibleContext
loc <- getW4Position "llvm_alloc"
Expand Down Expand Up @@ -1913,13 +1922,14 @@ llvm_alloc_with_mutability_and_size mut sz alignment lty =
, _allocSpecBytes = sz''
, _allocSpecLoc = loc
, _allocSpecFresh = False
, _allocSpecInit = initialization
}

llvm_alloc ::
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
llvm_alloc =
llvm_alloc_with_mutability_and_size Crucible.Mutable Nothing Nothing
llvm_alloc_with_mutability_and_size Crucible.Mutable Nothing Nothing LLVMAllocSpecNoInitialization

llvm_alloc_aligned ::
Int ->
Expand All @@ -1932,7 +1942,7 @@ llvm_alloc_readonly ::
L.Type ->
LLVMCrucibleSetupM (AllLLVM SetupValue)
llvm_alloc_readonly =
llvm_alloc_with_mutability_and_size Crucible.Immutable Nothing Nothing
llvm_alloc_with_mutability_and_size Crucible.Immutable Nothing Nothing LLVMAllocSpecNoInitialization

llvm_alloc_readonly_aligned ::
Int ->
Expand All @@ -1952,6 +1962,7 @@ llvm_alloc_aligned_with_mutability mut n lty =
mut
Nothing
(Just alignment)
LLVMAllocSpecNoInitialization
lty

coerceAlignment :: Int -> CrucibleSetup (LLVM arch) Crucible.Alignment
Expand All @@ -1975,8 +1986,13 @@ llvm_alloc_with_size sz lty =
Crucible.Mutable
(Just (Crucible.toBytes sz))
Nothing
LLVMAllocSpecNoInitialization
lty

llvm_alloc_sym_init :: L.Type -> LLVMCrucibleSetupM (AllLLVM SetupValue)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious: does this work in practice when you apply in an a specification that is assumed with llvm_unsafe_assume_spec? The reason I ask is that I'm doing something quite similar to this as part of ongoing work in #1461, and I couldn't make it work without making some nontrivial changes to the way doInvalidate works in crucible.

I suppose this is a long-winded way of asking for some more test cases using llvm_alloc_sym_init. I'm not sure if you plan to do this as part of this PR or as part of a later PR, however.

llvm_alloc_sym_init =
llvm_alloc_with_mutability_and_size Crucible.Mutable Nothing Nothing LLVMAllocSpecSymbolicInitialization

llvm_symbolic_alloc ::
Bool ->
Int ->
Expand Down Expand Up @@ -2008,6 +2024,7 @@ llvm_symbolic_alloc ro align_bytes sz =
, _allocSpecBytes = sz
, _allocSpecLoc = loc
, _allocSpecFresh = False
, _allocSpecInit = LLVMAllocSpecNoInitialization
}
n <- Setup.csVarCounter <<%= nextAllocIndex
Setup.currentState . MS.csAllocs . at n ?= spec
Expand Down Expand Up @@ -2057,6 +2074,7 @@ constructFreshPointer mid loc memTy =
, _allocSpecBytes = sz
, _allocSpecLoc = loc
, _allocSpecFresh = True
, _allocSpecInit = LLVMAllocSpecNoInitialization
}
-- TODO: refactor
case mid of
Expand Down
11 changes: 11 additions & 0 deletions src/SAWScript/Crucible/LLVM/MethodSpecIR.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ module SAWScript.Crucible.LLVM.MethodSpecIR
, csParentName
-- * LLVMAllocSpec
, LLVMAllocSpec(..)
, LLVMAllocSpecInit(..)
, allocSpecType
, allocSpecAlign
, allocSpecMut
, allocSpecLoc
, allocSpecBytes
, allocSpecFresh
, allocSpecInit
, mutIso
, isMut
-- * LLVMModule
Expand Down Expand Up @@ -188,6 +190,14 @@ type instance MS.MethodId (LLVM _) = LLVMMethodId
--------------------------------------------------------------------------------
-- *** LLVMAllocSpec

-- | Allocation initialization policy
data LLVMAllocSpecInit
= LLVMAllocSpecSymbolicInitialization
-- ^ allocation is initialized with a fresh symbolic array of bytes
| LLVMAllocSpecNoInitialization
-- ^ allocation not initialized
deriving (Eq, Ord, Show)

data LLVMAllocSpec =
LLVMAllocSpec
{ _allocSpecMut :: CL.Mutability
Expand All @@ -196,6 +206,7 @@ data LLVMAllocSpec =
, _allocSpecBytes :: Term
, _allocSpecLoc :: ProgramLoc
, _allocSpecFresh :: Bool -- ^ Whether declared with @crucible_fresh_pointer@
, _allocSpecInit :: LLVMAllocSpecInit
}
deriving (Eq, Show)

Expand Down
Loading