简体   繁体   中英

Satisfying Proof Obligations for memcpy? [Frama-C]

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: memcpy_proof_obligations

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM