New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Function stubbing #1695
Comments
Would your stubbing support the following use-case? Say I have (omitting unimportant bits):
and I prove w/ Kani that It should be safe to stub F' in for F, and vice verse anywhere else in the codebase I'd like to do proofs about. So, say I also have
Now I want to A simpler example could involve wanting to uninterpret a single deterministic function that is called multiple times. Stubbing the definition to |
If I understand your use case correctly, you want to be able to say, "Here is a function However, in some cases, it is possible to achieve this effect by lazily constructing the mapping for lazy_static! {
static ref MY_MAP: HashMap<u32, u32> = HashMap::new();
}
fn f(n: u32) -> u32 {
unsafe { *MY_MAP.entry(n).or_insert_with(|| kani::any()) }
} The trick would be using a data structure for the map that is verification friendly (so |
Thanks @aaronbembenek-aws for your response. As a developer interested in assurance, I'm familiar with standard assurance tools such as SAT/SMT, uninterpreted functions, proof reuse, rewriting, and so on. If there are tricks for emulating these tools using Kani, it would be nice, from a user perspective, for Kani to transparently provide them. As well, I'm trying to understand, in a formal way, what the function stubbing technique accomplishes. It seems like stubbing is equivalent to uninterpreting a function and then adding preconditions that constrain the function's output (which may be quite specific) inside a property. Why take a narrow approach here when you could instead implement standard assurance tools (uninterpreted functions w/ equality and pre/post conditions) and gain much more? |
CBMC actually supports uninterpreted functions: we probably should too http://www.cprover.org/cprover-manual/modeling/nondeterminism/ |
If Kani supported uninterpreted functions, could the example in the RFC be reworked to something like this?
Maybe at that point one could do away with
|
Yes, I believe these examples would work, and I agree you can do away with
Agreed -- stubs are relatively low-level, and it would be good to provide higher-level verification abstractions. We've started compiling a list here of different types of stubs we might want to automatically support.
Stubbing is more general than uninterpreted functions, since we can simulate uninterpreted functions using stubbing, but there are stubs that cannot be faithfully captured as uninterpreted functions (e.g., if the stub can return different outputs for the same input). It is also possible to give stubs pre- and postconditions. Granted, these pre- and postconditions are written in Rust. This has some potential advantages over using a custom constraint DSL (as is often used with function contracts): it's not necessary for users to learn a new syntax, and Rust code naturally captures some information that might have to be given explicitly in a logical constraint (like which memory is written). Of course, there might also be times when using logical constraints is more convenient. |
You're right. I chose a poor example here :-)
The info in the CBMC link was pretty helpful. To sum up -- a stub is nondeterministic ("separate calls to the function can return different results, even for the same inputs"), whereas uninterpreting is deterministic ("different invocations will return the same value if their inputs are the same"). A stub can be made deterministic by using memoization, though it would be best if Kani supported this natively, rather than a user having to determine how to best memoize. As well, I'm perfectly happy writing pre- and postconditions in Rust where it makes sense. This capability seems like a first step towards rewriting (now only at a function boundary, I think, am I wrong here?), which is nice to see. |
Right - it'd enable rewriting only at the unit of entire functions/methods. |
This is a tracking issue for the RFC
function_stubbing
.The goal is to allow users to specify that some functions should be replaced by mock functions (stubs) during verification. Although the current focus is on functions, the hope is that this mechanism might in the future be extended to other features (like methods and types).
The need for stubs is twofold:
There are questions to resolve:
The text was updated successfully, but these errors were encountered: