Skip to content

Commit 919d427

Browse files
authored
Merge pull request #2758 from GaloisInc/bh/llvm-setup-errors
More LLVMSetup error checking
2 parents bf09a34 + 982545e commit 919d427

File tree

9 files changed

+74
-19
lines changed

9 files changed

+74
-19
lines changed

CHANGES.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,26 @@ This release supports [version
66

77
## Changes
88

9+
* `llvm_verify` now enforces that an `llvm_return` specification is
10+
included for any function with a non-void return type.
11+
To write a spec that asserts nothing about the return value,
12+
`llvm_return` may be used with a fresh variable declared with
13+
`llvm_fresh_var` in the post-state section, like this:
14+
15+
do {
16+
...
17+
llvm_execute_func <args>;
18+
...
19+
ret <- llvm_fresh_var "ret" <type>;
20+
llvm_return (llvm_term ret);
21+
}
22+
23+
* `jvm_verify` now enforces that a `jvm_return` specification is
24+
included for any method with a non-void return type.
25+
To write a spec that asserts nothing about the return value,
26+
`jvm_return` may be used with a fresh variable declared with
27+
`jvm_fresh_var` in the post-state section.
28+
929
* The `cryptol_load` and `cryptol_prims` commands now fail if used
1030
in a nested scope, instead of behaving strangely.
1131

intTests/test0061_path_sat/test.saw

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ m <- llvm_load_module "termination.bc";
33
let g_spec = do {
44
x <- llvm_fresh_var "x" (llvm_int 64);
55
llvm_execute_func [llvm_term x];
6+
// unspecified return value
7+
ret <- llvm_fresh_var "ret" (llvm_int 64);
8+
llvm_return (llvm_term ret);
69
};
710

811
llvm_verify m "g1" [] false g_spec z3;

intTests/test0064_detect_vacuity/test.saw

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ let bad_spec = do {
88
llvm_precond {{ a == 1 }};
99
llvm_execute_func [llvm_term a];
1010
llvm_postcond {{ a == 2 }};
11+
// unspecified return value
12+
ret <- llvm_fresh_var "ret" (llvm_int 32);
13+
llvm_return (llvm_term ret);
1114
};
1215

1316
m <- llvm_load_module "test.bc";

intTests/test0067_term_eqs/test.saw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ let f_false_spec = do {
1414

1515
let test_spec = do {
1616
llvm_execute_func [];
17+
crucible_return (crucible_term {{ 0:[32] }});
1718
};
1819

1920
f_ov <- llvm_unsafe_assume_spec m "f" f_spec;
2021
f_false_ov <- llvm_unsafe_assume_spec m "f" f_false_spec;
2122
llvm_verify m "test_f" [f_ov] false test_spec trivial;
2223
fails (llvm_verify m "test_f" [f_false_ov] false test_spec trivial);
23-

intTests/test_sanitize/test.saw

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ let f_spec = do {
55
x <- llvm_fresh_var "x" (llvm_int 32);
66
y <- llvm_fresh_var "y" (llvm_int 32);
77
llvm_execute_func [llvm_term x, llvm_term y];
8+
// unspecified return value
9+
z <- llvm_fresh_var "z" (llvm_int 32);
10+
llvm_return (llvm_term z);
811
};
912

1013
llvm_verify m_norm "f" [] false f_spec z3;

intTests/test_stack_traces/trace004.log.good

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,40 @@
44
just llvm_stack
55
Stack trace:
66
(builtin) in llvm_stack
7-
trace004.saw:15:32-15:42 in (callback)
7+
trace004.saw:15:39-15:49 in (callback)
88
(builtin) in llvm_verify
9-
trace004.saw:15:1-15:45 (at top level)
9+
trace004.saw:15:8-15:52 in (callback)
10+
(builtin) in fails
11+
trace004.saw:15:1-15:52 (at top level)
12+
13+
== Anticipated failure message ==
14+
Stack trace:
15+
(builtin) in llvm_verify
16+
trace004.saw:15:8-15:52 in (callback)
17+
(builtin) in fails
18+
trace004.saw:15:1-15:52 (at top level)
19+
Missing llvm_execute_func specification when verifying foo
1020

11-
Verifying foo...
12-
Simulating foo...
13-
Checking proof obligations foo...
14-
Proof succeeded! foo
1521

1622
------------------------------------------------------------
1723
llvm_stack via let
1824
Stack trace:
1925
(builtin) in llvm_stack
2026
trace004.saw:22:13-22:23 in spec0
21-
trace004.saw:23:32-23:37 in (callback)
27+
trace004.saw:23:39-23:44 in (callback)
2228
(builtin) in llvm_verify
23-
trace004.saw:23:1-23:40 (at top level)
29+
trace004.saw:23:8-23:47 in (callback)
30+
(builtin) in fails
31+
trace004.saw:23:1-23:47 (at top level)
32+
33+
== Anticipated failure message ==
34+
Stack trace:
35+
(builtin) in llvm_verify
36+
trace004.saw:23:8-23:47 in (callback)
37+
(builtin) in fails
38+
trace004.saw:23:1-23:47 (at top level)
39+
Missing llvm_execute_func specification when verifying foo
2440

25-
Verifying foo...
26-
Simulating foo...
27-
Checking proof obligations foo...
28-
Proof succeeded! foo
2941

3042
------------------------------------------------------------
3143
do-block

intTests/test_stack_traces/trace004.saw

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ print "";
99

1010

1111
// Test just llvm_stack by itself.
12-
// This probably should not actually verify, but it does...
12+
// This should not actually verify.
1313
print "------------------------------------------------------------";
1414
print "just llvm_stack";
15-
llvm_verify mod "foo" [] false llvm_stack z3;
15+
fails (llvm_verify mod "foo" [] false llvm_stack z3);
1616
print "";
1717

1818
// Test just llvm_stack via a let-binding.
19-
// This probably should not actually verify, but it does...
19+
// This should not actually verify.
2020
print "------------------------------------------------------------";
2121
print "llvm_stack via let";
2222
let spec0 = llvm_stack;
23-
llvm_verify mod "foo" [] false spec0 z3;
23+
fails (llvm_verify mod "foo" [] false spec0 z3);
2424
print "";
2525

2626
// Test with an inline do-block.

saw-central/src/SAWCentral/Crucible/Common/Setup/Builtins.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ crucible_execute_func ::
108108
[MS.SetupValue ext] ->
109109
CrucibleSetup ext ()
110110
crucible_execute_func args = do
111+
st <- get
111112
tps <- use (csMethodSpec . MS.csArgs)
113+
when (st ^. csPrePost == MS.PostState) $
114+
fail "duplicate execute_func declaration"
112115
csPrePost .= MS.PostState
113116
csMethodSpec . MS.csArgBindings .= Map.fromList [ (i, (t,a))
114117
| i <- [0..]

saw-central/src/SAWCentral/Crucible/LLVM/Builtins.hs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,20 @@ withMethodSpec pathSat lm nm setup action =
574574
-- execute commands of the method spec
575575
io $ W4.setCurrentProgramLoc sym setupLoc
576576

577-
578577
setupState <-
579578
(execStateT
580579
(runReaderT (runLLVMCrucibleSetupM setup)
581580
(Setup.makeCrucibleSetupRO))
582581
st0)
583582
let methodSpec = setupState ^. Setup.csMethodSpec
584583
cc1 = setupState ^. Setup.csCrucibleContext
584+
585+
-- check for missing llvm_execute_func
586+
unless (setupState ^. Setup.csPrePost == PostState) $
587+
io $ throwMethodSpec methodSpec $ Text.unpack $
588+
"Missing llvm_execute_func specification when verifying " <>
589+
methodSpec^.csName
590+
585591
io $ checkSpecArgumentTypes cc1 methodSpec
586592
io $ checkSpecReturnType cc1 methodSpec
587593

@@ -909,7 +915,12 @@ checkSpecReturnType cc mspec =
909915
, "Expected: " <> Text.pack (show retTy)
910916
, "but given value of type: " <> Text.pack (show retTy')
911917
]
912-
(Nothing, _) -> return ()
918+
(Nothing, Just retTy) ->
919+
throwMethodSpec mspec $ Text.unpack $ Text.unlines
920+
[ "Missing return value specification for function with non-void return type"
921+
, "Expected: " <> Text.pack (show retTy)
922+
]
923+
(Nothing, Nothing) -> pure ()
913924

914925
-- | Evaluate the precondition part of a Crucible method spec:
915926
--

0 commit comments

Comments
 (0)