Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion rmc-docs/src/install-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Create a test file:

```rust
// File: test.rs
fn main() {
pub fn main() {
assert!(1 == 2);
}
```
Expand Down
17 changes: 11 additions & 6 deletions scripts/cargo-rmc
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,20 @@ def main():

if EXIT_CODE_SUCCESS != rmc.goto_to_c(cbmc_runnable_filename, c_runnable_filename, args.verbose, args.dry_run):
return 1

rmc.gen_c_postprocess(c_runnable_filename, args.dry_run)

rmc.cargo_build(args.crate, args.target_dir,
args.verbose, args.debug, args.mangler, args.dry_run, [])

pattern = os.path.join(args.target_dir, "debug", "deps", "*.json")
jsons = glob.glob(pattern)
rmc.ensure(len(jsons) == 1, f"Unexpected number of json outputs: {len(jsons)}")

if not args.dry_run:
rmc.ensure(len(jsons) == 1, f"Unexpected number of json outputs: {len(jsons)}")
else:
# Add a dummy value so dry-run works.
jsons = ["dry-run.json"]

cbmc_filename = os.path.join(args.target_dir, "cbmc.out")
c_filename = os.path.join(args.target_dir, "cbmc.c")
Expand Down Expand Up @@ -101,15 +106,15 @@ def parse_args():

exclude_flags = []
rmc_flags.add_flags(parser, {"default-target": "target"}, exclude_flags=exclude_flags)

return parser

# Determine what crate to analyze from flags
def get_crate_from_args(args):
validate(args)
return args.crate or args.crate_flag or "."

# Combine the command line parameter to get a config file;
# Combine the command line parameter to get a config file;
# return None if no_config_toml is set
def get_config_toml(no_config_toml, config_toml, args):
crate = get_crate_from_args(args)
Expand Down Expand Up @@ -154,7 +159,7 @@ def parse_args():

# Check for conflicting flags
def validate(args):
rmc.ensure(not (args.crate and args.crate_flag), "Please provide a single crate to verify.")
rmc.ensure(not (args.crate and args.crate_flag), "Please provide a single crate to verify.")
rmc.ensure(not (args.no_config_toml and args.config_toml), "Incompatible flags: --config-toml, --no-config-toml")

# Fix up args before returning
Expand Down Expand Up @@ -239,7 +244,7 @@ def extract_flags_from_toml(path):
success = False
for flag in flags:
add_flag(flag, flags[flag])

rmc.ensure(success)
return flag_list

Expand Down
19 changes: 4 additions & 15 deletions scripts/rmc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def main():

if EXIT_CODE_SUCCESS != rmc.goto_to_c(goto_runnable_filename, c_runnable_filename, args.verbose, args.dry_run):
return 1

rmc.gen_c_postprocess(c_runnable_filename, args.dry_run)

json_filename = base + ".json"
Expand Down Expand Up @@ -76,7 +76,7 @@ def main():

if "--function" not in args.cbmc_args:
args.cbmc_args.extend(["--function", args.function])

if args.visualize:
# Use a separate set of flags for coverage checking (empty for now)
cover_args = []
Expand All @@ -100,14 +100,8 @@ def parse_args():
input_group.add_argument("input", help="Rust file to verify", nargs="?")
input_group.add_argument("--input", help="Rust file to verify", dest="input_flag", metavar="INPUT")

exclude_flags = [
# In the future we hope to make this configurable in the command line.
# For now, however, changing this from "main" breaks rmc.
# Issue: https://github.com/model-checking/rmc/issues/169
"--function"
]
rmc_flags.add_flags(parser, {"default-target": "."}, exclude_flags=exclude_flags)

rmc_flags.add_flags(parser, {"default-target": "."})

return parser

# Check for conflicting flags
Expand All @@ -124,11 +118,6 @@ def parse_args():
if args.quiet:
args.verbose = False

# In the future we hope to make this configurable in the command line.
# For now, however, changing this from "main" breaks rmc.
# Issue: https://github.com/model-checking/rmc/issues/169
args.function = "main"

# Add some CBMC flags by default unless `--no-default-checks` is being used
if args.default_checks:
rmc.add_selected_default_cbmc_flags(args)
Expand Down
29 changes: 16 additions & 13 deletions scripts/rmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def edit_output(self, text):
def is_exe(name):
from shutil import which
return which(name) is not None

def ensure_dependencies_in_path():
for program in [RMC_RUSTC_EXE, "symtab2gb", "cbmc", "cbmc-viewer", "goto-instrument", "goto-cc"]:
ensure(is_exe(program), f"Could not find {program} in PATH")
Expand Down Expand Up @@ -116,11 +116,11 @@ def run_cmd(cmd, label=None, cwd=None, env=None, output_to=None, quiet=False, ve
process = subprocess.run(
cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
env=env, cwd=cwd)

# Print status
if label != None:
print_rmc_step_status(label, process, verbose)

stdout = process.stdout
for scanner in scanners:
if scanner.match(stdout):
Expand All @@ -129,24 +129,26 @@ def run_cmd(cmd, label=None, cwd=None, env=None, output_to=None, quiet=False, ve
# Write to stdout if specified, or if failure, or verbose or debug
if (output_to == "stdout" or process.returncode != EXIT_CODE_SUCCESS or verbose or debug) and not quiet:
print(stdout)

# Write to file if given
if output_to != None and output_to != "stdout":
with open(output_to, "w") as f:
f.write(stdout)

return process.returncode

# Generates a symbol table from a rust file
def compile_single_rust_file(input_filename, output_filename, verbose=False, debug=False, keep_temps=False, mangler="v0", dry_run=False, use_abs=False, abs_type="std", symbol_table_passes=[]):
if not keep_temps:
atexit.register(delete_file, output_filename)

build_cmd = [RMC_RUSTC_EXE,
"-Z", "codegen-backend=gotoc",
build_cmd = [RMC_RUSTC_EXE,
"-Z", "codegen-backend=gotoc",
"-Z", "trim-diagnostic-paths=no",
"-Z", f"symbol-mangling-version={mangler}",
"-Z", f"symbol-mangling-version={mangler}",
"-Z", f"symbol_table_passes={' '.join(symbol_table_passes)}",
"--crate-type=lib",
"-Z", "human_readable_cgu_names",
f"--cfg={RMC_CFG}"]

if use_abs:
Expand All @@ -165,20 +167,21 @@ def compile_single_rust_file(input_filename, output_filename, verbose=False, deb
return run_cmd(build_cmd, env=build_env, label="compile", verbose=verbose, debug=debug, dry_run=dry_run)

# Generates a symbol table (and some other artifacts) from a rust crate
def cargo_build(crate, target_dir="target", verbose=False, debug=False, mangler="v0", dry_run=False, symbol_table_passes=[]):
def cargo_build(crate, target_dir, verbose=False, debug=False, mangler="v0", dry_run=False, symbol_table_passes=[]):
ensure(os.path.isdir(crate), f"Invalid path to crate: {crate}")

rustflags = [
"-Z", "codegen-backend=gotoc",
"-Z", "trim-diagnostic-paths=no",
"-Z", f"symbol-mangling-version={mangler}",
"-Z", f"symbol_table_passes={' '.join(symbol_table_passes)}",
"-Z", f"symbol_table_passes={' '.join(symbol_table_passes)}",
"-Z", "human_readable_cgu_names",
f"--cfg={RMC_CFG}"]
rustflags = " ".join(rustflags)
if "RUSTFLAGS" in os.environ:
rustflags = os.environ["RUSTFLAGS"] + " " + rustflags

build_cmd = ["cargo", "build", "--target-dir", target_dir]
build_cmd = ["cargo", "build", "--lib", "--target-dir", str(target_dir)]
build_env = {"RUSTFLAGS": rustflags,
"RUSTC": RMC_RUSTC_EXE,
"PATH": os.environ["PATH"],
Expand Down Expand Up @@ -229,7 +232,7 @@ def run_visualize(cbmc_filename, prop_args, cover_args, verbose=False, quiet=Fal
# 2) cbmc --xml-ui --cover location ~/rmc/library/rmc/rmc_lib.c <cbmc_filename> > coverage.xml
# 3) cbmc --xml-ui --show-properties ~/rmc/library/rmc/rmc_lib.c <cbmc_filename> > property.xml
# 4) cbmc-viewer --result results.xml --coverage coverage.xml --property property.xml --srcdir . --goto <cbmc_filename> --reportdir report

def run_cbmc_local(cbmc_args, output_to, dry_run=False):
cbmc_cmd = ["cbmc"] + cbmc_args + [cbmc_filename]
return run_cmd(cbmc_cmd, label="cbmc", output_to=output_to, verbose=verbose, quiet=quiet, dry_run=dry_run)
Expand Down Expand Up @@ -266,7 +269,7 @@ def run_goto_instrument(input_filename, output_filename, args, verbose=False, dr
# Generates a C program from a goto program
def goto_to_c(goto_filename, c_filename, verbose=False, dry_run=False):
return run_goto_instrument(goto_filename, c_filename, ["--dump-c"], verbose, dry_run=dry_run)

# Fix remaining issues with output of --gen-c-runnable
def gen_c_postprocess(c_filename, dry_run=False):
if not dry_run:
Expand Down
3 changes: 3 additions & 0 deletions src/test/cargo-rmc/simple-main/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ name = "empty-main"
version = "0.1.0"
edition = "2018"

[lib]
path="src/main.rs"

[dependencies]

[workspace]
2 changes: 1 addition & 1 deletion src/test/cargo-rmc/simple-main/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT
fn main() {
pub fn main() {
assert!(1 == 2);
}
2 changes: 1 addition & 1 deletion src/test/cbmc/ArithEqualOperators/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
include!("../../rmc-prelude.rs");

fn main() {
pub fn main() {
let mut a: u32 = __nondet();
a /= 2;
let mut b: u32 = __nondet();
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/ArithOperators/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
include!("../../rmc-prelude.rs");

fn main() {
pub fn main() {
let a: u32 = __nondet();
assert!(a / 2 <= a);
assert!(a / 2 * 2 >= a / 2);
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Asm/main_fixme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
#![feature(asm)]

fn main() {
pub fn main() {
unsafe {
asm!("nop");
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Assert/UninitValid/fixme_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::mem::{self, MaybeUninit};

fn main() {
pub fn main() {
// The compiler assumes that variables are properly initialized according to
// the requirements of the variable's type (e.g., a variable of reference
// type must be aligned and non-NULL). This is an invariant that must always
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Assert/ZeroValid/fixme_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use std::mem;
use std::ptr;
fn main() {
pub fn main() {
let x: &mut i32 = unsafe { mem::zeroed() }; //< undefined (should fail)
let p: *mut i32 = x;
assert!(p == ptr::null_mut()); //< verifies with RMC
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Assert/ZeroValid/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn do_test<T: std::cmp::Eq>(init: T, expected: T) {
assert!(expected == x);
}

fn main() {
pub fn main() {
do_test::<bool>(true, false);
do_test::<i8>(-42, 0);
do_test::<i16>(-42, 0);
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Assume/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

include!("../../rmc-prelude.rs");

fn main() {
pub fn main() {
let i: i32 = __nondet();
__VERIFIER_assume(i < 10);
assert!(i < 20);
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Assume/main_fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

include!("../../rmc-prelude.rs");

fn main() {
pub fn main() {
let i: i32 = __nondet();
__VERIFIER_assume(i < 10);
__VERIFIER_expect_fail(i > 20, "Blocked by assumption above.");
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/CompareExchange/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
// pub fn compare_exchange(
// &self,
// current: bool,
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/Exchange/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
let a1 = AtomicBool::new(true);
let a2 = AtomicBool::new(true);
let a3 = AtomicBool::new(true);
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/Fence/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{fence, Ordering};

fn main() {
pub fn main() {
// pub fn fence(order: Ordering)
// An atomic fence.
// Depending on the specified order, a fence prevents the compiler
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/FetchAdd/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicIsize, Ordering};

fn main() {
pub fn main() {
// pub fn fetch_add(&self, val: isize, order: Ordering) -> isize
// Adds to the current value, returning the previous value.
let a1 = AtomicIsize::new(0);
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/FetchAnd/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
// pub fn fetch_and(&self, val: bool, order: Ordering) -> bool
// Performs a logical "and" operation on the current value and
// the argument val, and sets the new value to the result.
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/FetchOr/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
// pub fn fetch_or(&self, val: bool, order: Ordering) -> bool
// Performs a logical "or" operation on the current value and
// the argument val, and sets the new value to the result.
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/FetchSub/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicIsize, Ordering};

fn main() {
pub fn main() {
// pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize
// Subtracts from the current value, returning the previous value.
let a1 = AtomicIsize::new(1);
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/FetchXor/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
// pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool
// Performs a bitwise "xor" operation on the current value and
// the argument val, and sets the new value to the result.
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/Load/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
// pub fn load(&self, order: Ordering) -> bool
// Loads a value from the bool.
// load takes an Ordering argument which describes the memory ordering
Expand Down
2 changes: 1 addition & 1 deletion src/test/cbmc/Atomics/Stable/Store/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::sync::atomic::{AtomicBool, Ordering};

fn main() {
pub fn main() {
// ppub fn store(&self, val: bool, order: Ordering)
// Stores a value into the bool.
// store takes an Ordering argument which describes the memory ordering
Expand Down
Loading