Skip to content

Commit a9d9c3f

Browse files
authored
Integrate goto-synthesizer into Kani (rust-lang#2204)
1 parent 7a7ba05 commit a9d9c3f

File tree

8 files changed

+92
-0
lines changed

8 files changed

+92
-0
lines changed

kani-driver/src/args.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,16 @@ pub struct KaniArgs {
228228
#[arg(long, hide_short_help = true, requires("enable_unstable"))]
229229
pub no_slice_formula: bool,
230230

231+
/// Synthesize loop contracts for all loops.
232+
#[arg(
233+
long,
234+
hide_short_help = true,
235+
requires("enable_unstable"),
236+
conflicts_with("unwind"),
237+
conflicts_with("default_unwind")
238+
)]
239+
pub synthesize_loop_contracts: bool,
240+
231241
/// Randomize the layout of structures. This option can help catching code that relies on
232242
/// a specific layout chosen by the compiler that is not guaranteed to be stable in the future.
233243
/// If a value is given, it will be used as the seed for randomization
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
use crate::util::warning;
5+
use anyhow::Result;
6+
use std::ffi::OsString;
7+
use std::path::Path;
8+
use std::process::Command;
9+
10+
use crate::session::KaniSession;
11+
12+
impl KaniSession {
13+
/// Synthesize loop contracts for a goto binary `input` and produce a new goto binary `output`
14+
/// The synthesizer we use is `goto-synthesizer` built in CBMC codebase, which is an enumerative
15+
/// loop-contracts synthesizer. `goto-synthesizer` enumerates and checks if a candidate can be
16+
/// used to prove some assertions, and applies found invariants when all checks pass.
17+
pub fn synthesize_loop_contracts(&self, input: &Path, output: &Path) -> Result<()> {
18+
if !self.args.quiet {
19+
println!("Running loop contract synthesizer.");
20+
warning("This process may not terminate.");
21+
warning(
22+
"Loop-contracts synthesizer is not compatible with unwinding bounds. Unwind bounds will be ignored.",
23+
);
24+
}
25+
26+
let args: Vec<OsString> = vec![
27+
"--loop-contracts-no-unwind".into(),
28+
input.to_owned().into_os_string(), // input
29+
output.to_owned().into_os_string(), // output
30+
];
31+
32+
let mut cmd = Command::new("goto-synthesizer");
33+
cmd.args(args);
34+
35+
self.run_suppress(cmd)?;
36+
37+
Ok(())
38+
}
39+
}

kani-driver/src/harness_runner.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ impl<'sess, 'pr> HarnessRunner<'sess, 'pr> {
6565
&harness,
6666
)?;
6767

68+
if self.sess.args.synthesize_loop_contracts {
69+
self.sess.synthesize_loop_contracts(&specialized_obj, &specialized_obj)?;
70+
}
71+
6872
let result = self.sess.check_harness(&specialized_obj, &report_dir, harness)?;
6973
Ok(HarnessResult { harness, result })
7074
})

kani-driver/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod call_cbmc;
2323
mod call_cbmc_viewer;
2424
mod call_goto_cc;
2525
mod call_goto_instrument;
26+
mod call_goto_synthesizer;
2627
mod call_single_file;
2728
mod cbmc_output_parser;
2829
mod cbmc_property_renderer;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERIFICATION:- SUCCESSFUL
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// kani-flags: --enable-unstable --synthesize-loop-contracts
5+
6+
// Check if goto-synthesizer is correctly called, and synthesizes the required
7+
// loop invariants.
8+
9+
#[kani::proof]
10+
fn main() {
11+
let mut y: i32 = kani::any_where(|i| *i > 0);
12+
13+
while y > 0 {
14+
y = y - 1;
15+
}
16+
17+
assert!(y == 0);
18+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERIFICATION:- SUCCESSFUL
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
// kani-flags: --enable-unstable --synthesize-loop-contracts
5+
6+
// Check if goto-synthesizer is correctly called, and synthesizes the required
7+
// loop invariants.
8+
9+
#[kani::proof]
10+
fn main() {
11+
let mut x: u64 = kani::any_where(|i| *i > 1);
12+
13+
while x > 1 {
14+
x = x - 1;
15+
}
16+
17+
assert!(x == 1);
18+
}

0 commit comments

Comments
 (0)