Skip to content

Commit

Permalink
Merge branch 'main' into kanicov-tool
Browse files Browse the repository at this point in the history
  • Loading branch information
adpaco-aws committed Oct 4, 2024
2 parents 094ad75 + f3ed5e8 commit a6abae5
Show file tree
Hide file tree
Showing 27 changed files with 155 additions and 85 deletions.
17 changes: 1 addition & 16 deletions kani-driver/src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ where
.unwrap()
}

#[allow(dead_code)]
pub fn print_obsolete(verbosity: &CommonArgs, option: &str) {
if !verbosity.quiet {
warning(&format!(
Expand Down Expand Up @@ -189,14 +190,6 @@ pub struct VerificationArgs {
#[arg(long, hide_short_help = true)]
pub only_codegen: bool,

/// Deprecated flag. This is a no-op since we no longer support the legacy linker and
/// it will be removed in a future Kani release.
#[arg(long, hide = true, conflicts_with("mir_linker"))]
pub legacy_linker: bool,
/// Deprecated flag. This is a no-op since we no longer support any other linker.
#[arg(long, hide = true)]
pub mir_linker: bool,

/// Specify the value used for loop unwinding in CBMC
#[arg(long)]
pub default_unwind: Option<u32>,
Expand Down Expand Up @@ -524,14 +517,6 @@ impl ValidateArgs for VerificationArgs {
}
}

if self.mir_linker {
print_obsolete(&self.common_args, "--mir-linker");
}

if self.legacy_linker {
print_obsolete(&self.common_args, "--legacy-linker");
}

// TODO: these conflicting flags reflect what's necessary to pass current tests unmodified.
// We should consider improving the error messages slightly in a later pull request.
if natives_unwind && extra_unwind {
Expand Down
43 changes: 35 additions & 8 deletions library/kani/src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
//! simple division function `my_div`:
//!
//! ```
//! fn my_div(dividend: u32, divisor: u32) -> u32 {
//! fn my_div(dividend: usize, divisor: usize) -> usize {
//! dividend / divisor
//! }
//! ```
Expand All @@ -35,8 +35,12 @@
//! allows us to declare constraints on what constitutes valid inputs to our
//! function. In this case we would want to disallow a divisor that is `0`.
//!
//! ```ignore
//! ```
//! # use kani::requires;
//! #[requires(divisor != 0)]
//! # fn my_div(dividend: usize, divisor: usize) -> usize {
//! # dividend / divisor
//! # }
//! ```
//!
//! This is called a precondition, because it is enforced before (pre-) the
Expand All @@ -51,7 +55,11 @@
//! approximation of the result of division for instance could be this:
//!
//! ```
//! #[ensures(|result : &u32| *result <= dividend)]
//! # use kani::ensures;
//! #[ensures(|result : &usize| *result <= dividend)]
//! # fn my_div(dividend: usize, divisor: usize) -> usize {
//! # dividend / divisor
//! # }
//! ```
//!
//! This is called a postcondition and it also has access to the arguments and
Expand All @@ -66,9 +74,11 @@
//! order does not matter. In our example putting them together looks like this:
//!
//! ```
//! #[kani::requires(divisor != 0)]
//! #[kani::ensures(|result : &u32| *result <= dividend)]
//! fn my_div(dividend: u32, divisor: u32) -> u32 {
//! use kani::{requires, ensures};
//!
//! #[requires(divisor != 0)]
//! #[ensures(|result : &usize| *result <= dividend)]
//! fn my_div(dividend: usize, divisor: usize) -> usize {
//! dividend / divisor
//! }
//! ```
Expand All @@ -84,9 +94,18 @@
//! function we want to check.
//!
//! ```
//! # use kani::{requires, ensures};
//! #
//! # #[requires(divisor != 0)]
//! # #[ensures(|result : &usize| *result <= dividend)]
//! # fn my_div(dividend: usize, divisor: usize) -> usize {
//! # dividend / divisor
//! # }
//! #
//! #[kani::proof_for_contract(my_div)]
//! fn my_div_harness() {
//! my_div(kani::any(), kani::any()) }
//! my_div(kani::any(), kani::any());
//! }
//! ```
//!
//! The harness is checked like any other by running `cargo kani` and can be
Expand All @@ -104,10 +123,18 @@
//! the contract will be used automatically.
//!
//! ```
//! # use kani::{requires, ensures};
//! #
//! # #[requires(divisor != 0)]
//! # #[ensures(|result : &usize| *result <= dividend)]
//! # fn my_div(dividend: usize, divisor: usize) -> usize {
//! # dividend / divisor
//! # }
//! #
//! #[kani::proof]
//! #[kani::stub_verified(my_div)]
//! fn use_div() {
//! let v = vec![...];
//! let v = kani::vec::any_vec::<char, 5>();
//! let some_idx = my_div(v.len() - 1, 3);
//! v[some_idx];
//! }
Expand Down
33 changes: 31 additions & 2 deletions library/kani/src/invariant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
/// ```
/// You can specify its safety invariant as:
/// ```rust
/// # #[derive(kani::Arbitrary)]
/// # pub struct MyDate {
/// # day: u8,
/// # month: u8,
/// # year: i64,
/// # }
/// # fn days_in_month(_: i64, _: u8) -> u8 { 31 }
///
/// impl kani::Invariant for MyDate {
/// fn is_safe(&self) -> bool {
/// self.month > 0
Expand All @@ -49,12 +57,33 @@
/// }
/// ```
/// And use it to check that your APIs are safe:
/// ```rust
/// ```no_run
/// # use kani::Invariant;
/// #
/// # #[derive(kani::Arbitrary)]
/// # pub struct MyDate {
/// # day: u8,
/// # month: u8,
/// # year: i64,
/// # }
/// #
/// # fn days_in_month(_: i64, _: u8) -> u8 { todo!() }
/// # fn increase_date(_: &mut MyDate, _: u8) { todo!() }
/// #
/// # impl Invariant for MyDate {
/// # fn is_safe(&self) -> bool {
/// # self.month > 0
/// # && self.month <= 12
/// # && self.day > 0
/// # && self.day <= days_in_month(self.year, self.month)
/// # }
/// # }
/// #
/// #[kani::proof]
/// fn check_increase_date() {
/// let mut date: MyDate = kani::any();
/// // Increase date by one day
/// increase_date(date, 1);
/// increase_date(&mut date, 1);
/// assert!(date.is_safe());
/// }
/// ```
Expand Down
2 changes: 2 additions & 0 deletions library/kani/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#![feature(ptr_metadata)]
#![feature(f16)]
#![feature(f128)]
// Need to add this since we are deprecating `kani::check`. Remove this when we remove that API.
#![allow(deprecated)]

// Allow us to use `kani::` to access crate features.
extern crate self as kani;
Expand Down
2 changes: 1 addition & 1 deletion library/kani/src/shadow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//!
//! # Example
//!
//! ```
//! ```no_run
//! use kani::shadow::ShadowMem;
//! use std::alloc::{alloc, Layout};
//!
Expand Down
3 changes: 2 additions & 1 deletion library/kani/src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use crate::{any, assume};
///
/// # Example:
///
/// ```rust
/// ```no_run
/// # fn foo(_: &[i32]) {}
/// let arr = [1, 2, 3];
/// let slice = kani::slice::any_slice_of_array(&arr);
/// foo(slice); // where foo is a function that takes a slice and verifies a property about it
Expand Down
98 changes: 68 additions & 30 deletions library/kani_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ macro_rules! kani_lib {
pub use kani_core::*;
kani_core::kani_intrinsics!(core);
kani_core::generate_arbitrary!(core);
kani_core::check_intrinsic!();

pub mod mem {
kani_core::kani_mem!(core);
Expand All @@ -58,6 +59,10 @@ macro_rules! kani_lib {
kani_core::kani_intrinsics!(std);
kani_core::generate_arbitrary!(std);

kani_core::check_intrinsic! {
msg="This API will be made private in future releases.", vis=pub
}

pub mod mem {
kani_core::kani_mem!(std);
}
Expand Down Expand Up @@ -85,7 +90,7 @@ macro_rules! kani_intrinsics {
///
/// The code snippet below should never panic.
///
/// ```rust
/// ```no_run
/// let i : i32 = kani::any();
/// kani::assume(i > 10);
/// if i < 0 {
Expand All @@ -95,7 +100,7 @@ macro_rules! kani_intrinsics {
///
/// The following code may panic though:
///
/// ```rust
/// ```no_run
/// let i : i32 = kani::any();
/// assert!(i < 0, "This may panic and verification should fail.");
/// kani::assume(i > 10);
Expand All @@ -118,7 +123,7 @@ macro_rules! kani_intrinsics {
///
/// # Example:
///
/// ```rust
/// ```no_run
/// let x: bool = kani::any();
/// let y = !x;
/// kani::assert(x || y, "ORing a boolean variable with its negation must be true")
Expand All @@ -138,35 +143,15 @@ macro_rules! kani_intrinsics {
assert!(cond, "{}", msg);
}

/// Creates an assertion of the specified condition and message, but does not assume it afterwards.
///
/// # Example:
///
/// ```rust
/// let x: bool = kani::any();
/// let y = !x;
/// kani::check(x || y, "ORing a boolean variable with its negation must be true")
/// ```
#[cfg(not(feature = "concrete_playback"))]
#[inline(never)]
#[rustc_diagnostic_item = "KaniCheck"]
pub const fn check(cond: bool, msg: &'static str) {
let _ = cond;
let _ = msg;
}

#[cfg(feature = "concrete_playback")]
#[inline(never)]
#[rustc_diagnostic_item = "KaniCheck"]
pub const fn check(cond: bool, msg: &'static str) {
assert!(cond, "{}", msg);
}

/// Creates a cover property with the specified condition and message.
///
/// # Example:
///
/// ```rust
/// ```no_run
/// # use crate::kani;
/// #
/// # let array: [u8; 10] = kani::any();
/// # let slice = kani::slice::any_slice_of_array(&array);
/// kani::cover(slice.len() == 0, "The slice may have a length of 0");
/// ```
///
Expand All @@ -193,7 +178,11 @@ macro_rules! kani_intrinsics {
/// In the snippet below, we are verifying the behavior of the function `fn_under_verification`
/// under all possible `NonZeroU8` input values, i.e., all possible `u8` values except zero.
///
/// ```rust
/// ```no_run
/// # use std::num::NonZeroU8;
/// # use crate::kani;
/// #
/// # fn fn_under_verification(_: NonZeroU8) {}
/// let inputA = kani::any::<core::num::NonZeroU8>();
/// fn_under_verification(inputA);
/// ```
Expand Down Expand Up @@ -231,7 +220,11 @@ macro_rules! kani_intrinsics {
/// In the snippet below, we are verifying the behavior of the function `fn_under_verification`
/// under all possible `u8` input values between 0 and 12.
///
/// ```rust
/// ```no_run
/// # use std::num::NonZeroU8;
/// # use crate::kani;
/// #
/// # fn fn_under_verification(_: u8) {}
/// let inputA: u8 = kani::any_where(|x| *x < 12);
/// fn_under_verification(inputA);
/// ```
Expand Down Expand Up @@ -460,3 +453,48 @@ macro_rules! kani_intrinsics {
}
};
}

#[macro_export]
macro_rules! check_intrinsic {
($(msg=$msg:literal, vis=$vis:vis)?) => {
/// Creates a non-fatal property with the specified condition and message.
///
/// This check will not impact the program control flow even when it fails.
///
/// # Example:
///
/// ```no_run
/// let x: bool = kani::any();
/// let y = !x;
/// kani::check(x || y, "ORing a boolean variable with its negation must be true");
/// kani::check(x == y, "A boolean variable is always different than its negation");
/// kani::cover!(true, "This should still be reachable");
/// ```
///
/// # Deprecated
///
/// This function was meant to be internal only, and it was added to Kani's public interface
/// by mistake. Thus, it will be made private in future releases.
/// Instead, we recommend users to either use `assert` or `cover` to create properties they
/// would like to verify.
///
/// See <https://github.com/model-checking/kani/issues/3561> for more details.
#[cfg(not(feature = "concrete_playback"))]
#[inline(never)]
#[rustc_diagnostic_item = "KaniCheck"]
// TODO: Remove the `#![allow(deprecated)]` inside kani's crate once this is made private.
$(#[deprecated(since="0.55.0", note=$msg)])?
$($vis)? const fn check(cond: bool, msg: &'static str) {
let _ = cond;
let _ = msg;
}

#[cfg(feature = "concrete_playback")]
#[inline(never)]
#[rustc_diagnostic_item = "KaniCheck"]
$(#[deprecated(since="0.55.0", note=$msg)])?
$($vis)? const fn check(cond: bool, msg: &'static str) {
assert!(cond, "{}", msg);
}
};
}
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# SPDX-License-Identifier: Apache-2.0 OR MIT

[toolchain]
channel = "nightly-2024-10-01"
channel = "nightly-2024-10-03"
components = ["llvm-tools", "rustc-dev", "rust-src", "rustfmt"]
4 changes: 2 additions & 2 deletions scripts/kani-regression.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ cargo test -p cprover_bindings
cargo test -p kani-compiler
cargo test -p kani-driver
cargo test -p kani_metadata
# skip doc tests and enable assertions to fail
cargo test -p kani --lib --features concrete_playback
# Use concrete playback to enable assertions failure
cargo test -p kani --features concrete_playback
# Test the actual macros, skipping doc tests and enabling extra traits for "syn"
# so we can debug print AST
RUSTFLAGS=--cfg=kani_sysroot cargo test -p kani_macros --features syn/extra-traits --lib
Expand Down
2 changes: 1 addition & 1 deletion tests/cargo-kani/asm/global/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ crate_with_global_asm = { path = "crate_with_global_asm" }

[package.metadata.kani]
# Issue with MIR Linker on static constant.
flags = { enable-unstable = true, ignore-global-asm = true, mir-linker = true }
flags = { enable-unstable = true, ignore-global-asm = true }
Loading

0 comments on commit a6abae5

Please sign in to comment.