2

I'm trying to prove a while-loop with a pointer assign in frama-c. Unfortunately, I encounter problems. I've managed to prove it if rewriting the code under test with a for-loop and with array notation. Does anyone have any ideas on how to prove this?

Code I want to prove:

/*@
 requires \valid(v+(0..n-1));
 requires v != \null;
 requires n > 0;
 assigns v[0..n-1];
 ensures \forall integer q; 0<=q<=n-1 ==> v[q]==(unsigned char)0;
*/
static void make_zero( unsigned char *v, size_t n ) {

volatile unsigned char *p = (unsigned char*)v;

      /*@
       loop invariant 0 <= n <= \at(n, Pre);
       loop invariant \forall integer j;  0 <= j < (\at(n, Pre)-n) ==> \at(p, Pre)[j] == (unsigned char)0;
       loop assigns n, p;
       loop variant n;  */

      while( n-- ){
         *p++ = 0;
      }
 }

Rewritten code:

/*@
loop invariant 0 <= i <= n;
loop invariant \forall integer j; 0 < j < i ==> p[j] == (unsigned char)0;
loop assigns i, p[0..n-1];
loop variant n-i;
*/

for(size_t i = 0; i<n; i++){
  p[i] = 0;
}
Quissy
  • 23
  • 4

1 Answers1

3

First, a remark. The precondition v != \null is redundant with \valid(v+(0..n-1)), and can be removed.

Another remark, p is a local variable which is not in scope in the Pre state. Thus \at(p, Pre) is more or less meaningless (although accepted by WP). You probably meant v -- which is simpler anyway.

Second, as is, your loop assigns is false. The cells of the array pointed to by v are also modified. You must change it to assigns n, p, v[0..\at(n, Pre)-n-1].

Third, you need another loop invariant which expresses p in terms of v and n. Otherwise, WP won't be able to model precisely what happens when *p is written, and won't be able to prove the modified loop assigns. This invariant is p == v + (\at(n, Pre)-n).

Your final problem is that you declared p volatile. This is unneeded here, and actually makes the proof impossible: the value of p may change each time it is accessed. Once you remove this qualifier, the proof is complete.

Full code for reference:

/*@
 requires \valid(v+(0..n-1));
 requires n > 0;
 assigns v[0..n-1];
 ensures \forall integer q; 0<=q<=n-1 ==> v[q]==(unsigned char)0;
*/
static void make_zero( unsigned char *v, size_t n ) {

  unsigned char *p = (unsigned char*)v;

  /*@
    loop invariant 0 <= n <= \at(n, Pre);
    loop invariant p == v+(\at(n, Pre)-n);
    loop invariant \forall integer j;  0 <= j < (\at(n, Pre)-n) ==> v[j] == (unsigned char)0;
    loop assigns n, p, v[0..\at(n, Pre)-n-1];
    loop variant n;
  */

  while( n-- ){
    *p++ = 0;
  }
}
byako
  • 3,372
  • 2
  • 21
  • 36