Giter VIP home page Giter VIP logo

kani's Introduction

Kani regression Nightly: CBMC Latest

The Kani Rust Verifier is a bit-precise model checker for Rust.

Kani is particularly useful for verifying unsafe code blocks in Rust, where the "unsafe superpowers" are unchecked by the compiler.


Kani verifies:

  • Memory safety (e.g., null pointer dereferences)
  • User-specified assertions (i.e., assert!(...))
  • The absence of panics (e.g., unwrap() on None values)
  • The absence of some types of unexpected behavior (e.g., arithmetic overflows)

Installation

To install the latest version of Kani (Rust 1.58+; Linux or Mac), run:

cargo install --locked kani-verifier
cargo kani setup

See the installation guide for more details.

How to use Kani

Similar to testing, you write a harness, but with Kani you can check all possible values using kani::any():

use my_crate::{function_under_test, meets_specification, precondition};

#[kani::proof]
fn check_my_property() {
   // Create a nondeterministic input
   let input = kani::any();

   // Constrain it according to the function's precondition
   kani::assume(precondition(input));

   // Call the function under verification
   let output = function_under_test(input);

   // Check that it meets the specification
   assert!(meets_specification(input, output));
}

Kani will then try to prove that all valid inputs produce acceptable outputs, without panicking or executing unexpected behavior. Otherwise Kani will generate a trace that points to the failure. We recommend following the tutorial to learn more about how to use Kani.

GitHub Action

Use Kani in your CI with model-checking/kani-github-action@VERSION. See the GitHub Action section in the Kani book for details.

Security

See SECURITY for more information.

Contributing

If you are interested in contributing to Kani, please take a look at the developer documentation.

License

Kani

Kani is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.

Rust

Kani contains code from the Rust project. Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses.

See the Rust repository for details.

kani's People

Contributors

aaronbembenek-aws avatar adpaco-aws avatar avanhatt avatar bdalrhm avatar bennofs avatar celinval avatar chinmaydd avatar danielsn avatar dependabot[bot] avatar feliperodri avatar fzaiser avatar giltho avatar github-actions[bot] avatar jaisnan avatar justusadam avatar karkhaz avatar markrtuttle avatar nchong-at-aws avatar ouz-a avatar qinheping avatar rahulku avatar reisnera avatar remi-delmas-3000 avatar ronakfof avatar sanjit-bhat avatar tautschnig avatar tedinski avatar vecchiot-aws avatar yoshikitakashima avatar zhassan-aws avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kani's Issues

Refactor: review `codegen_alloc_in_memory`

The intended semantics of the function codegen_alloc_in_memory are difficult to infer from the code and the documentation. The semantics of the Allocation type is hard to understand, so the codegen of the Allocation data is hard to trust. The definition of codegen_alloc_in_memory allows the function to be called with an Allocation and a String name, but the name may or may not be present in the symbol table. It is hard to understand why any invocation would call with the name already in the symbol table. Consider rewriting this function to do nothing but create a new symbol in the table with the bit pattern type and a bit pattern value. Consider another function that transmutes the value to the type of a symbol already in the symbol table.

Codegen issue: vtable struct with duplicate components

This test requires an additional check in struct_type() of cbmc/goto_program/typ.rs to ensure that the struct's components are unique. In this case, the vtable contains two foo fn pointers.

trait A {
    fn foo(&self) -> i32;
}

trait B {
    fn foo(&self) -> i32;
}

trait T : A + B {
}

struct S {
    x : i32,
    y : i32,
}

impl S {
    fn new(a:i32, b:i32) -> S {
        S {x:a, y:b}
    }
    fn new_box(a:i32, b:i32) -> Box<dyn T> { 
        Box::new(S::new(a,b))
    }
}


impl A for S {
    fn foo(&self) -> i32{
        self.x
    }
}

impl B for S {
    fn foo(&self) -> i32{
        self.y
    }
}

impl T for S {
}

fn main() {
    let t = S::new_box(1,2);
    let a = <dyn T as A>::foo(&*t);
    assert!(a == 1);
    let b = <dyn T as B>::foo(&*t);
    assert!(b == 2);
}

Ensure we are using volatile correctly

According to @danielsn:

volatile has two meanings: one is just that we can't reorder or drop the access, which CBMC never does.
It might also mean that reads should return nondet, which we don't currently model.

The code for this would be in intrinsics.rs

Demangling of variable names

Can we track the name of variables so we get
main::square::vol instead of main::Shape[0]::vtable main$$Shape[0]$$vtable_impl_for_&main$$Rectangle[0]?

Maintain a map from functions to integers to generate fresh variables

Instead of taking a c in gen_function_local_variable, maintain a map from fname to int, and generate fresh variables that way. Actually: why is this index needed at all? It seems to be part of constructing a name, but unique names shouldn't rely on someone hand-picking the right index. Instead, a map of names should be kept, and the next available slot should be chosen.

Codegen issue: Cast to fat pointer

#![feature(layout_for_ptr)]                                                                        
use std::mem;                                                                                      
use std::sync::Arc;                                                                                
use std::sync::Mutex;                                                                              

pub trait Subscriber {                                                                             
    fn process(&mut self);                                                                         
    fn interest_list(&self);                                                                       
}                                                                                                  

struct DummySubscriber {                                                                           
}                                                                                                  

impl DummySubscriber {                                                                             
    fn new() -> Self {                                                                             
        DummySubscriber {}                                                                         
    }                                                                                              
}                                                                                                  

impl Subscriber for DummySubscriber {                                                              
    fn process(&mut self) {}                                                                       
    fn interest_list(&self) {}                                                                     
}                                                                                                  

fn main() {                                                                                        
    let v = unsafe { mem::size_of_val_raw(&5i32) };                                                
    assert!(v == 4);                                                                               

    let x : [u8;13] = [0; 13];                                                                     
    let y: &[u8] = &x;                                                                             
    let v = unsafe { mem::size_of_val_raw(y) };                                                    
    assert!(v == 13);                                                                              

    let s : Arc<Mutex<dyn Subscriber>> = Arc::new(Mutex::new(DummySubscriber::new()));             
}

Find a more elegant replacement for the `codegen_simple_intrinsic` macro

Relevant comment in intrinsics.rs

        // Codegens a simple intrinsic: ie. one which maps directly to a matching goto construct
        // We need to use this macro form because of a known limitation in rust
        // `codegen_simple_intrinsic!(self.get_sqrt(), Type::float())` gives the error message:
        //   error[E0499]: cannot borrow `*self` as mutable more than once at a time
        //    --> src/librustc_codegen_llvm/gotoc/intrinsic.rs:76:63
        //    |
        // 76 |                 codegen_simple_intrinsic!(self.get_sqrt(), Type::double())
        //    |                 ---- ------------------------                 ^^^^ second mutable borrow occurs here
        //    |                 |    |
        //    |                 |    first borrow later used by call
        //    |                 first mutable borrow occurs here

        //  To solve this, we need to store the `self.get_sqrt()` into a temporary variable.
        //  Using the macro form allows us to keep the call as a oneliner, while still making rust happy.

Transmute sizeof failure

const SIZE1: usize = 1;
const SIZE2: usize = 2;

pub static TABLE1: [(u64, u64); SIZE1] = [
    (0, 0),
];

pub static TABLE2: [(u64, u64); SIZE2] = [
    (0, 0),
    (0, 0),
];

fn main() {
    assert!(TABLE1[0].0 == 0);
}

Fails with:

thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `256`,
 right: `128`', compiler/rustc_codegen_llvm/src/gotoc/cbmc/goto_program/expr.rs:686

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.