We've been using Frama-C for 'experimental' static analysis on a commercial project (integrated into our CI, with a few selective blocking checks, on a small section of the overall codebase).
One of the snags that comes up relates to satisfying the proof obligations that the wp
plugin generates anytime it encounters a memcpy
call. Specifically, the three obligations below:
From the 'goal' notes, it looks like Frama-C is trying to prove that the destination and source memory are valid, .
I've tried adding requires \\valid()
preconditions, but that doesn't seem to help. In these instances, the memcpy
call within the function under test is copying data from an input parameter to the function, and placing that data into a local variable (scoped within the function).
To further complicate matters, the local variable where the data is being copied is an attribute within a packed struct.
Concretely, I'm hoping that someone out there is able to share some real examples of memcpy
uses where the goals introduced by wp
can be satisfied (eg what preconditions must I add to make it provable?)
If it matters, I'm running Frama-C Magnesium-20151002 (according to apt-get on Ubuntu 16, this is 'up to date'), and invoking with the following parameters:
frama-c -wp -wp-split -wp-dynamic -lib-entry -wp-proof alt-ergo -wp-report
Also related, but missing a clear working example: Frama-c : Trouble understanding WP memory models
As you mentioned in you comment, the proper solution is to use -wp-model "Typed+Cast"
in order to let WP accept casts to/from void*
(more precisely, it will consider that p
and (void*)p
are the same thing for any pointer, which will be sufficient for proving the requires
of memcpy
). Now, as mentioned in the answer to the question you linked to, the main issue of this memory model (and the reason why it is not the default) is that it is inherently unsafe : it relies on hypotheses that by definition cannot be assessed by WP itself. Here is a small example that highlights this issue:
int x;
char* c;
/*@ assigns c;
ensures c == ((char *)&x);
*/
void g(void) {
c = &x;
}
/*@ assigns \nothing;
ensures \separated(&x,c);
*/
void f() {
}
void main () {
g();
f();
//@ assert \false;
}
Basically, the default Typed
memory model ensures the separation between the location pointed to by c
and x
(ie the post-condition of f
), because int
and char
are different, and you neither can prove the post-condition of g
or use it as an hypothesis to derive \\false
in main
, because the equality can't be expressed in the model at all.
Now, if you use Typed+Cast
, the post-condition of g
is now properly understood, and completely trivial to prove. WP won't let you prove at the same time that &x
and c
are separated, because they are involved together in an assignment. However, in f
no such assignment exists, and the post-condition is also easily proved, leading to proving \\false
in main
since we have two contradictory statements about &x
and c
. More generally, WP relies on a local alias analysis to track potential aliases between pointers of different types (a global analysis would defeat the purpose of having a modular analyzer). Passing option -wp-model +Cast
can thus be seen as way to tell WP "Trust me, the program won't create miss-typed aliases". It is however possible to pass alias information by hand (or with the help of eg a yet-to-be-written global alias detection plug-in). For instance, with option -wp-alias-vars x,c
the post-condition of f
becomes Unknown
(ie the separation between &x
and c
is not an assumption anymore, even for f
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.