Skip to content

Commit 0ae8eb0

Browse files
authored
feat: enable deterministic playback for variables optimized out due to --slice-formula (#1512)
* initial slice-formula stuff * mark u8_2 as unused * fix: change parser to accept goto_symex_return lhs * docs: update comment * docs: allow unused test case vars to be anything * ui: improve leftover det vals error msg
1 parent ccccda9 commit 0ae8eb0

File tree

5 files changed

+53
-3
lines changed

5 files changed

+53
-3
lines changed

kani-driver/src/call_cbmc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl KaniSession {
117117
args.push("--validate-ssa-equation".into());
118118
}
119119

120-
if !self.args.visualize && !self.args.no_slice_formula {
120+
if !self.args.visualize && !self.args.gen_exe_trace && !self.args.no_slice_formula {
121121
args.push("--slice-formula".into());
122122
}
123123

kani-driver/src/exe_trace.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ struct ExeTrace {
250250
/// ...,
251251
/// { "description": "assertion failed: x", "status": "FAILURE", "trace": [
252252
/// ...,
253-
/// { "assignmentType": "variable", "lhs": "var_0",
253+
/// { "assignmentType": "variable", "lhs": "goto_symex$$return_value...",
254254
/// "sourceLocation": { "function": "kani::any_raw_internal::<u8, 1_usize>" },
255255
/// "stepType": "assignment", "value": { "binary": "00000001", "data": "101", "width": 8 } }
256256
/// ..., ] }
@@ -371,7 +371,7 @@ mod parser {
371371
trace_entry["value"]["width"].as_u64(),
372372
) {
373373
if step_type == "assignment"
374-
&& lhs == "var_0"
374+
&& lhs.starts_with("goto_symex$$return_value")
375375
&& func.starts_with("kani::any_raw_internal")
376376
{
377377
let declared_width = width_u64 as usize;

library/kani/src/exe_trace.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ pub fn exe_trace_run<F: Fn()>(mut local_det_vals: Vec<Vec<u8>>, proof_harness: F
2424
});
2525
// Since F is a type argument, there should be a direct, static call to proof_harness().
2626
proof_harness();
27+
// This code will not run if a user assertion fails on deterministic playback.
28+
// But if you comment out the failing assertion during playback,
29+
// this can be used to know if too many det vals were loaded into the deterministic test case.
30+
DET_VALS.with(|glob_det_vals| {
31+
let ref_glob_det_vals = &*glob_det_vals.borrow();
32+
assert!(
33+
ref_glob_det_vals.is_empty(),
34+
"At the end of deterministic playback, there were still these deterministic values left over `{:?}`. \
35+
This either happened because: \
36+
1) Your code/harness changed after you generated this deterministic test. \
37+
2) There's a bug in Kani. Please report the issue here: <https://github.com/model-checking/kani/issues/new?assignees=&labels=bug&template=bug_report.md>",
38+
ref_glob_det_vals
39+
);
40+
});
2741
}
2842

2943
/// Executable trace implementation of kani::any_raw_internal.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
VERIFICATION:- FAILED
2+
3+
Executable trace
4+
```
5+
#[test]
6+
fn kani_exe_trace_harness
7+
let det_vals: Vec<Vec<u8>> = vec![
8+
//
9+
vec![
10+
// 101
11+
vec![101, 0],
12+
//
13+
vec![
14+
// 102ul
15+
vec![102, 0, 0, 0, 0, 0, 0, 0]
16+
];
17+
kani::exe_trace_run(det_vals, harness);
18+
}
19+
```
20+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// kani-flags: --harness harness --enable-unstable --gen-exe-trace
5+
6+
//! We explicitly don't check what concrete values are returned for `_u8_1` and `_u8_3` as they could be anything.
7+
//! In practice, though, they will likely be 0.
8+
9+
#[kani::proof]
10+
pub fn harness() {
11+
let _u8_1: u8 = kani::any();
12+
let u8_2: u16 = kani::any();
13+
let _u8_3: u32 = kani::any();
14+
let u8_4: u64 = kani::any();
15+
assert!(!(u8_2 == 101 && u8_4 == 102));
16+
}

0 commit comments

Comments
 (0)