-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds stacked borrows to Kani, strengthening its model of pointers to detect violations of Rust's aliasing model. It does this by automatically instrumenting code with hooks at every stack and heap allocation, ensuring that a live mutable pointer is never aliased. This instrumentation is subject to several limitations: 1. Currently, function calls are not permitted. To implement them, the "protector" mechanism of the stacked borrows calculus has to be implemented first. 2. Only one byte is monitored; it is picked nondeterministic-ally at the beginning of the instrumented code. Function contracts may need to keep track of relations between multiple references and raw pointers in their pre & post conditions, and are therefore not yet tracked. 3. The address of locals is taken before they are initialized; because of this, optimizations to the "local storage" part of the stack frame may break this analysis. In our cases so far, no such optimizations are performed. It also means that initialization must be checked separately using the Uninit pass 4. Arrays are not yet modelled 5. Malloc is not yet modelled 7. Pointer manipulation is not yet modelled 8. Two phase borrows are not yet modelled. Two phase borrows: The rust compiler will desugar the following: ```rust fn p(mut x: Vec<usize>) { x.push(x.len()) } ``` to ```rust fn p(mut x: Vec<usize>) { let y: &mut Vec<i32> = &mut x; let z: usize = Vec::len(x); Vec::push(y, z) } ``` Marking the borrow into y as "two phase." This may be enabled in the future via a hack (ref: https://www.ralfj.de/blog/2023/06/02/tree-borrows.html) and so the aliasing model may in the future change to accommodate these differently. 10. There are numerous unhandled syntactic constructs. - Assignments that Copy/Move - Terminators - Fields - Arrays/Slices/Indices These constructs _must_ be handled in the future to say that we have ported stacked borrows to Kani. Currently, print statements are made; these constructs are expected to do pointer manipulation, but to no effect. In the future, we will want to instrument all of these. We need By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: Jacob Salzberg <[email protected]>
- Loading branch information
1 parent
6ac5183
commit ffaa0bd
Showing
20 changed files
with
1,512 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
kani-compiler/src/kani_middle/transform/check_aliasing/function_cache.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
//! This module contains a cache of resolved generic functions | ||
use crate::kani_middle::find_fn_def; | ||
use rustc_middle::ty::TyCtxt; | ||
|
||
type Result<T> = std::result::Result<T, super::MirError>; | ||
|
||
|
||
/// Caches function instances for later lookups. | ||
#[derive(Default, Debug)] | ||
pub struct Cache { | ||
/// The cache | ||
cache: Vec<NamedFnDef>, | ||
} | ||
|
||
fn try_get_or_insert<T, P, F>(vec: &mut Vec<T>, p: P, f: F) -> Result<&mut T> | ||
where | ||
F: FnOnce() -> Result<T>, | ||
P: Fn(&T) -> bool, | ||
T: PartialEq, | ||
{ | ||
if let Some(i) = vec.iter().position(p) { | ||
Ok(&mut vec[i]) | ||
} else { | ||
vec.push(f()?); | ||
Ok(vec.last_mut().unwrap()) | ||
} | ||
} | ||
|
||
impl Cache { | ||
/// Register the signature the to the cache | ||
/// in the given compilation context, ctx | ||
pub fn register( | ||
&mut self, | ||
ctx: &TyCtxt, | ||
signature: Signature, | ||
) -> Result<&> { | ||
let test_sig = signature.clone(); | ||
let Cache { cache } = self; | ||
try_get_or_insert( | ||
cache, | ||
|item| item.signature == test_sig, | ||
|| { | ||
let fndef = find_fn_def(*ctx, &signature.diagnostic) | ||
.ok_or(MirError::new(format!("Not found: {}", &signature.diagnostic)))?; | ||
let instance = MirInstance::resolve(fndef, &GenericArgs(signature.args.clone()))?; | ||
Ok(NamedFnDef::new(signature, instance)) | ||
}, | ||
) | ||
.map(|entry| &entry.instance) | ||
} | ||
} |
Oops, something went wrong.