Skip to content

Commit

Permalink
SyGuS, find SMT array write of a fixed size (#2037)
Browse files Browse the repository at this point in the history
* Find SMT array write of a fixed size.

* Load SMT array with concrete size.

* Add test.

* Add noSatisfyingWriteFreshConstant option.

* Add invariant substitution to getPoststateObligations.

* Bump what4.

* wip

* wip

* Use simplified term in resolveSAWPred.

* Bump crucible.

* Remove unused sc.

* Use simplified term in resolveSAWPred.

* Bump crucible.

* Update src/SAWScript/Crucible/LLVM/Builtins.hs

Co-authored-by: Ryan Scott <[email protected]>

* Fix -Wunused-matches warning

* Bump crucible, what4 submodules

This bumps:

* The `crucible` submodule to bring in the changes from
  GaloisInc/crucible#1178
* The `what4` submodule to bring in the changes from
  GaloisInc/what4#256

* Remove debugging-only code

* Bump cryptol-specs to incorporate GaloisInc/cryptol-specs#72

* Repair AES example to work with `type Nk = AES256`

* Add expert options for enabling What4-, Crucible-related SyGuS features

* Split off separate llvm_verify_fixpoint_chc_x86 command

* Only enable doPtrCmp optimizations with SimpleFixpointCHC

* crucible: Revert popFrame refactoring

* Uniformly apply pushMuxOps option to all ExprBuilders

SAW creates a variety of different ExprBuilders in the course of a typical SAW
script, but we were only applying the pushMuxOps option to some of them. This
patch makes the treatment a bit more comprehensive.

Unfortunately, doing so requires a rather uncomfortable amount of extra
plumbing in `SAWScript.Proof`, but I'm not sure how to do better without
refactoring all of `SAWScript.Proof` to use `TopLevel` instead of `IO` (and
it's unclear if that is desirable).

* Bump cryptol-specs, what4, crucible submodules to latest

* Bump what4, crucible submodules

* Adapt to recent crucible-llvm API changes

---------

Co-authored-by: Andrei Stefanescu <[email protected]>
  • Loading branch information
RyanGlScott and andreistefanescu authored May 15, 2024
1 parent 1722a84 commit 70fe999
Show file tree
Hide file tree
Showing 27 changed files with 511 additions and 104 deletions.
2 changes: 1 addition & 1 deletion deps/crucible
Submodule crucible updated 93 files
+4 −1 .github/Dockerfile-crux-llvm
+4 −1 .github/Dockerfile-crux-mir
+6 −2 .github/ci.sh
+14 −11 .github/workflows/README.md
+3 −2 .github/workflows/crucible-go-build.yml
+3 −2 .github/workflows/crucible-jvm-build.yml
+3 −2 .github/workflows/crucible-wasm-build.yml
+19 −69 .github/workflows/crux-llvm-build.yml
+28 −11 .github/workflows/crux-mir-build.yml
+36 −0 .github/workflows/lint.yml
+11 −72 .hlint.yaml
+0 −289 cabal.GHC-8.10.7.config
+1 −1 cabal.GHC-9.2.8.config
+1 −1 cabal.GHC-9.4.5.config
+1 −1 cabal.GHC-9.6.2.config
+0 −1 cabal.project
+1 −1 crucible-jvm/src/Lang/Crucible/JVM/Overrides.hs
+6 −6 crucible-jvm/src/Lang/Crucible/JVM/Simulate.hs
+21 −0 crucible-llvm/CHANGELOG.md
+5 −1 crucible-llvm/crucible-llvm.cabal
+10 −8 crucible-llvm/src/Lang/Crucible/LLVM.hs
+277 −0 crucible-llvm/src/Lang/Crucible/LLVM/Functions.hs
+4 −48 crucible-llvm/src/Lang/Crucible/LLVM/Globals.hs
+77 −283 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics.hs
+120 −0 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Cast.hs
+176 −182 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Common.hs
+941 −439 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/LLVM.hs
+601 −465 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libc.hs
+15 −17 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Libcxx.hs
+109 −0 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Match.hs
+3 −3 crucible-llvm/src/Lang/Crucible/LLVM/Intrinsics/Options.hs
+51 −48 crucible-llvm/src/Lang/Crucible/LLVM/MemModel.hs
+149 −69 crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Generic.hs
+27 −8 crucible-llvm/src/Lang/Crucible/LLVM/MemModel/MemLog.hs
+8 −0 crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Options.hs
+1 −1 crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Pointer.hs
+2 −2 crucible-llvm/src/Lang/Crucible/LLVM/MemModel/Value.hs
+19 −5 crucible-llvm/src/Lang/Crucible/LLVM/QQ.hs
+1,421 −0 crucible-llvm/src/Lang/Crucible/LLVM/SimpleLoopFixpointCHC.hs
+30 −32 crucible-llvm/src/Lang/Crucible/LLVM/SymIO.hs
+0 −1 crucible-llvm/src/Lang/Crucible/LLVM/Translation/Expr.hs
+2 −2 crucible-llvm/test/TestMemory.hs
+0 −5 crucible-mc/CHANGELOG.md
+0 −13 crucible-mc/LICENSE
+0 −2 crucible-mc/README
+0 −2 crucible-mc/Setup.hs
+0 −33 crucible-mc/crucible-mc.cabal
+0 −96 crucible-mc/exe/Main.hs
+0 −28 crucible-mc/exe/Print.hs
+0 −12 crucible-mc/test/Makefile
+0 −7 crucible-mc/test/example.c
+4 −4 crucible-mir/src/Mir/Intrinsics.hs
+1 −1 crucible-symio/crucible-symio.cabal
+1 −1 crucible-wasm/src/Lang/Crucible/Wasm/Memory.hs
+1 −1 crucible/crucible.cabal
+18 −0 crucible/src/Lang/Crucible/Analysis/Fixpoint/Components.hs
+65 −0 crucible/src/Lang/Crucible/Backend.hs
+1 −1 crucible/src/Lang/Crucible/Backend/ProofGoals.hs
+0 −1 crucible/src/Lang/Crucible/CFG/Expr.hs
+15 −0 crucible/src/Lang/Crucible/FunctionHandle.hs
+0 −1 crucible/src/Lang/Crucible/Simulator/EvalStmt.hs
+2 −2 crucible/src/Lang/Crucible/Simulator/Evaluation.hs
+1 −10 crucible/src/Lang/Crucible/Types.hs
+2 −2 crux-llvm/README.md
+1 −1 crux-llvm/crux-llvm.cabal
+3 −0 crux-llvm/src/Crux/LLVM/Config.hs
+109 −116 crux-llvm/src/Crux/LLVM/Overrides.hs
+9 −10 crux-llvm/src/Crux/LLVM/Simulate.hs
+2 −1 crux-llvm/svcomp/mk-svcomp-bindist.sh
+94 −0 crux-llvm/test-data/golden/T1177.c
+1 −0 crux-llvm/test-data/golden/T1177.config
+1 −0 crux-llvm/test-data/golden/T1177.z3.good
+6 −3 crux-llvm/test-data/golden/T785a.c
+9 −2 crux-llvm/test-data/golden/T785b.c
+1 −1 crux-llvm/test-data/golden/T785b.z3.good
+1 −1 crux-llvm/test-data/golden/golden/double_free.c
+35 −25 crux-llvm/test-data/golden/isinf.c
+9 −3 crux-llvm/test-data/golden/isnan.c
+5 −0 crux-llvm/test-data/golden/special-functions.c
+8 −1 crux-llvm/test/Test.hs
+1 −1 crux-mir/README.md
+1 −1 crux-mir/crux-mir.cabal
+1 −1 crux-mir/src/Mir/Overrides.hs
+1 −1 crux/crux.cabal
+0 −1 crux/src/Crux.hs
+1 −1 dependencies/mir-json
+1 −1 dependencies/what4
+12 −13 uc-crux-llvm/src/UCCrux/LLVM/Overrides/Check.hs
+8 −24 uc-crux-llvm/src/UCCrux/LLVM/Overrides/Polymorphic.hs
+22 −25 uc-crux-llvm/src/UCCrux/LLVM/Overrides/Skip.hs
+12 −14 uc-crux-llvm/src/UCCrux/LLVM/Overrides/Spec.hs
+23 −27 uc-crux-llvm/src/UCCrux/LLVM/Overrides/Unsound.hs
+12 −16 uc-crux-llvm/src/UCCrux/LLVM/Run/Simulate.hs
16 changes: 9 additions & 7 deletions examples/aes/aes.saw
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ print "Proving encrypt_lemma...";
encrypt_lemma <-
time (prove_print (unint_z3 ["AESRound"])
(rewrite (cryptol_ss())
{{ \(state0 : State) (ks : [9]RoundKey) ->
{{ \(state0 : State) (ks : [13]RoundKey) ->
(rounds where rounds = [state0] # [ AESRound (rk, s) | rk <- ks | s <- rounds ]) ! 0 ==
AESRound(ks@8,AESRound(ks@7,AESRound(ks@6,AESRound(ks@5,AESRound(ks@4,
AESRound(ks@3,AESRound(ks@2,AESRound(ks@1,AESRound(ks@0,state0)))))))))
AESRound(ks@12,AESRound(ks@11,AESRound(ks@10,AESRound(ks@9,
AESRound(ks@8,AESRound(ks@7,AESRound(ks@6,AESRound(ks@5,AESRound(ks@4,
AESRound(ks@3,AESRound(ks@2,AESRound(ks@1,AESRound(ks@0,state0)))))))))))))
}}));

print "Proving decrypt_lemma...";
decrypt_lemma <-
time (prove_print (unint_z3 ["AESInvRound"])
(rewrite (cryptol_ss())
{{ \(state0 : State) (ks : [9]RoundKey) ->
{{ \(state0 : State) (ks : [13]RoundKey) ->
(rounds where rounds = [state0] # [ AESInvRound (rk, s) | rk <- reverse ks | s <- rounds ]) ! 0 ==
AESInvRound(ks@0,AESInvRound(ks@1,AESInvRound(ks@2,AESInvRound(ks@3,AESInvRound(ks@4,
AESInvRound(ks@5,AESInvRound(ks@6,AESInvRound(ks@7,AESInvRound(ks@8,state0)))))))))
AESInvRound(ks@5,AESInvRound(ks@6,AESInvRound(ks@7,AESInvRound(ks@8,
AESInvRound(ks@9,AESInvRound(ks@10,AESInvRound(ks@11,AESInvRound(ks@12,state0)))))))))))))
}}));

print "Proving msgToState_stateToMsg(rme)...";
Expand Down Expand Up @@ -65,7 +67,7 @@ InvMixColumns_MixColumns <-
print "Proving aesDecrypt_aesEncrypt(rewriting)...";
dec_enc <-
time (prove_print do {
unfolding ["aesEncrypt", "aesDecrypt"];
unfolding ["aesEncrypt", "aesEncryptWithKeySchedule", "aesDecrypt"];
simplify (addsimps [encrypt_lemma,
decrypt_lemma]
(cryptol_ss()));
Expand Down Expand Up @@ -112,7 +114,7 @@ MixColumns_InvMixColumns <-
print "Proving aesEncrypt_aesDecrypt(rewriting)...";
enc_dec <-
time (prove_print do {
unfolding ["aesEncrypt", "aesDecrypt"];
unfolding ["aesEncrypt", "aesEncryptWithKeySchedule", "aesDecrypt"];
simplify (addsimps [encrypt_lemma,
decrypt_lemma]
(cryptol_ss()));
Expand Down
11 changes: 11 additions & 0 deletions intTests/test_smt_array_load_concrete_size/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CC = clang
CFLAGS = -g -emit-llvm -frecord-command-line -O1

all: test.bc

test.bc: test.c
$(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
rm -f test.bc
8 changes: 8 additions & 0 deletions intTests/test_smt_array_load_concrete_size/Mix.cry
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Mix where

import Array

type ByteArray = Array[64][8]

mix : {l} (width l <= 64) => ByteArray -> [64] -> [l][8] -> ByteArray
mix block n data = arrayCopy block n (arrayRangeUpdate (arrayConstant 0) 0 data) 0 `(l)
Binary file not shown.
13 changes: 13 additions & 0 deletions intTests/test_smt_array_load_concrete_size/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdint.h>
#include <string.h>

int mix(uint8_t block[128], uint32_t n, uint8_t *data, size_t len) {
size_t left = 128 - n;

if (len < left) {
memcpy(block + n, data, len);
} else {
memcpy(block + n, data, left);
}
return 1;
}
66 changes: 66 additions & 0 deletions intTests/test_smt_array_load_concrete_size/test.saw
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
enable_experimental;

import "Mix.cry";
let arrayRangeEq = parse_core "arrayRangeEq 64 (Vec 8 Bool)";

m <- llvm_load_module "test.bc";

let i8 = llvm_int 8;
let i32 = llvm_int 32;

let alloc_init_readonly ty v = do {
p <- llvm_alloc_readonly ty;
llvm_points_to p v;
return p;
};

let ptr_to_fresh_readonly n ty = do {
x <- llvm_fresh_var n ty;
p <- alloc_init_readonly ty (llvm_term x);
return (x, p);
};

let mix_spec len res_block_len range_eq_len = do {
block <- llvm_fresh_cryptol_var "block" {| ByteArray |};
block_ptr <- llvm_symbolic_alloc false 1 {{ 128:[64] }};
llvm_points_to_array_prefix block_ptr block {{ 128:[64] }};

(data, data_ptr) <- ptr_to_fresh_readonly "data" (llvm_array len i8);

n <- llvm_fresh_var "n" i32;
llvm_precond({{ n < 128 }});

llvm_execute_func [block_ptr, (llvm_term n), data_ptr, (llvm_term {{ `len : [64] }})];

let res = {{ mix block (0 # n) data }};
res_block <- llvm_fresh_cryptol_var "res_block" {| ByteArray |};
llvm_points_to_array_prefix block_ptr res_block {{ `res_block_len:[64] }};
llvm_postcond {{ arrayRangeEq res_block 0 res 0 `range_eq_len }};

llvm_return (llvm_term {{ 1 : [32]}});
};

llvm_verify m "mix"
[]
true
(mix_spec 1 128 128)
(do {
w4_unint_z3 [];
});

llvm_verify m "mix"
[]
true
(mix_spec 1 0 0)
(do {
w4_unint_z3 [];
});

fails (llvm_verify m "mix"
[]
true
(mix_spec 1 129 0)
(do {
w4_unint_z3 [];
}));

6 changes: 6 additions & 0 deletions intTests/test_smt_array_load_concrete_size/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

set -e

$SAW test.saw

2 changes: 2 additions & 0 deletions saw-remote-api/src/SAWServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ initialState readFileFn =
, rwProofs = []
, rwPreservedRegs = []
, rwAllocSymInitCheck = True
, rwWhat4PushMuxOps = False
, rwNoSatisfyingWriteFreshConstant = True
, rwCrucibleTimeout = CC.defaultSAWCoreBackendTimeout
, rwPathSatSolver = CC.PathSat_Z3
, rwSkipSafetyProofs = False
Expand Down
6 changes: 4 additions & 2 deletions src/SAWScript/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,8 @@ goal_eval unints =
execTactic $ tacticChange $ \goal ->
do sc <- getSharedContext
unintSet <- resolveNames unints
sqt' <- traverseSequentWithFocus (io . evalProp sc unintSet) (goalSequent goal)
what4PushMuxOps <- gets rwWhat4PushMuxOps
sqt' <- traverseSequentWithFocus (io . evalProp sc what4PushMuxOps unintSet) (goalSequent goal)
return (sqt', EvalEvidence unintSet)

extract_uninterp ::
Expand Down Expand Up @@ -2097,7 +2098,8 @@ specialize_theorem thm ts =
do sc <- getSharedContext
db <- SV.getTheoremDB
pos <- SV.getPosition
(thm', db') <- io (specializeTheorem sc db pos "specialize_theorem" thm (map ttTerm ts))
what4PushMuxOps <- gets rwWhat4PushMuxOps
(thm', db') <- io (specializeTheorem sc what4PushMuxOps db pos "specialize_theorem" thm (map ttTerm ts))
SV.putTheoremDB db'
SV.returnProof thm'

Expand Down
17 changes: 13 additions & 4 deletions src/SAWScript/Crucible/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ import Lang.Crucible.Backend
import Lang.Crucible.Backend.Online (OnlineBackend, newOnlineBackend)
import qualified Data.Parameterized.Nonce as Nonce
import What4.Protocol.Online (OnlineSolver(..))
import qualified What4.Solver.CVC5 as CVC5
import qualified What4.Solver.Z3 as Z3
import qualified What4.Solver.Yices as Yices
import qualified What4.Protocol.SMTLib2 as SMT2

import qualified What4.Config as W4
import qualified What4.Expr as W4
import qualified What4.Expr.Builder as W4
import qualified What4.Interface as W4
import qualified What4.ProgramLoc as W4 (plSourceLoc)

Expand All @@ -67,18 +69,21 @@ type Sym = W4.ExprBuilder Nonce.GlobalNonceGenerator SAWCoreState (W4.Flags W4.F
type Backend solver = OnlineBackend solver Nonce.GlobalNonceGenerator SAWCoreState (W4.Flags W4.FloatReal)

data SomeOnlineBackend =
forall solver. OnlineSolver solver =>
forall solver. OnlineSolver solver =>
SomeOnlineBackend (Backend solver)

data SAWCruciblePersonality sym = SAWCruciblePersonality

sawCoreState :: Sym -> IO (SAWCoreState Nonce.GlobalNonceGenerator)
sawCoreState sym = pure (sym ^. W4.userState)

newSAWCoreExprBuilder :: SC.SharedContext -> IO Sym
newSAWCoreExprBuilder sc =
newSAWCoreExprBuilder :: SC.SharedContext -> Bool -> IO Sym
newSAWCoreExprBuilder sc what4PushMuxOps =
do st <- newSAWCoreState sc
W4.newExprBuilder W4.FloatRealRepr st Nonce.globalNonceGenerator
sym <- W4.newExprBuilder W4.FloatRealRepr st Nonce.globalNonceGenerator
pushMuxOpsSetting <- W4.getOptionSetting W4.pushMuxOpsOption $ W4.getConfiguration sym
_ <- W4.setOpt pushMuxOpsSetting what4PushMuxOps
pure sym

defaultSAWCoreBackendTimeout :: Integer
defaultSAWCoreBackendTimeout = 10000
Expand All @@ -89,14 +94,18 @@ newSAWCoreBackend pss sym = newSAWCoreBackendWithTimeout pss sym 0
newSAWCoreBackendWithTimeout :: PathSatSolver -> Sym -> Integer -> IO SomeOnlineBackend
newSAWCoreBackendWithTimeout PathSat_Yices sym timeout =
do bak <- newOnlineBackend sym Yices.yicesDefaultFeatures
W4.extendConfig Z3.z3Options (W4.getConfiguration sym)
W4.extendConfig Yices.yicesOptions (W4.getConfiguration sym)
W4.extendConfig CVC5.cvc5Options (W4.getConfiguration sym)
yicesTimeoutSetting <- W4.getOptionSetting Yices.yicesGoalTimeout (W4.getConfiguration sym)
_ <- W4.setOpt yicesTimeoutSetting timeout
return (SomeOnlineBackend (bak :: Backend Yices.Connection))

newSAWCoreBackendWithTimeout PathSat_Z3 sym timeout =
do bak <- newOnlineBackend sym (SMT2.defaultFeatures Z3.Z3)
W4.extendConfig Z3.z3Options (W4.getConfiguration sym)
W4.extendConfig Yices.yicesOptions (W4.getConfiguration sym)
W4.extendConfig CVC5.cvc5Options (W4.getConfiguration sym)
z3TimeoutSetting <- W4.getOptionSetting Z3.z3Timeout (W4.getConfiguration sym)
_ <- W4.setOpt z3TimeoutSetting timeout
return (SomeOnlineBackend (bak :: Backend (SMT2.Writer Z3.Z3)))
Expand Down
2 changes: 1 addition & 1 deletion src/SAWScript/Crucible/JVM/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ setupCrucibleContext jclass =
cb <- getJavaCodebase
sc <- getSharedContext
pathSatSolver <- gets rwPathSatSolver
sym <- io $ newSAWCoreExprBuilder sc
sym <- io $ newSAWCoreExprBuilder sc False
bak <- io $ newSAWCoreBackend pathSatSolver sym
opts <- getOptions
io $ CJ.setSimulatorVerbosity (simVerbose opts) sym
Expand Down
2 changes: 1 addition & 1 deletion src/SAWScript/Crucible/JVM/BuiltinsJVM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ jvm_extract c mname = do
ctx <- getJVMTrans

io $ do -- only the IO monad, nothing else
sym <- newSAWCoreExprBuilder sc
sym <- newSAWCoreExprBuilder sc False
SomeOnlineBackend bak <- newSAWCoreBackend pathSatSolver sym
st <- sawCoreState sym
CJ.setSimulatorVerbosity verbosity sym
Expand Down
Loading

0 comments on commit 70fe999

Please sign in to comment.