I'm trying to prove a function like strlen in C, but frama-c don't prove the
post condition and the loop variant len clause. I can't understand why!
What I've tried:
/*#
axiomatic elementNumber_axioms
{
logic unsigned elementNumber{L}(char *a);
axiom elementNumber_base{L}:
elementNumber(\null) == 0;
axiom elementNumber_step{L}:
\forall char *a;
\valid(a) ==> elementNumber(a) == elementNumber(a+1) + 1;
}
*/
/*#
assigns \nothing;
ensures \result == elementNumber(\old(s));
*/
unsigned stringlen(const char *s)
{
unsigned len = 0;
/*#
loop assigns len;
loop assigns s;
loop variant len;
*/
while(*s)
{
++s;
++len;
}
return len;
}
What am I doing wrong?
There are several issues with what you have written. A non-exhaustive list:
Your stringlen() does not handle the case where s is NULL.
If annotating the standard C strlen() function, you would not need to handle this case because the standard C strlen() function does not allow the parameter to be NULL. However, the axiomatic definition of your elementNumber() logic function defines elementNumber(\null) to be 0, and a postcondition of stringlen() is that the result equals elementNumber(s). Thus, you would need to handle this case.
The while loop in stringlen() terminates when encountering a nul byte. However, the definition of your elementNumber() logic function only depends on whether a pointer is valid.
There are no preconditions on stringlen() as to whether s, s + 1, etc. are valid.
Your elementNumber() logic function does not define a value for an invalid pointer.
You will need to specify loop invariants.
I recommend taking a look at how Frama-C annotates strlen():
/*# requires valid_string_src: valid_string(s);
# assigns \result \from s[0..];
# ensures \result == strlen(s);
#*/
extern size_t strlen (const char *s);
The strlen() logic function and valid_string() predicate are defined in share/libc/__fc_string_axiomatic.h of the source distribution, which as of this writing is Sodium-20150201.
Related
In the following minimal example (slightly altered from Allan Blanchard's excellent tutorial -- section 3.2.3.3 Side Effects):
int h = 42;
/*#
requires \valid(a) && \valid(b);
requires \valid_read(a) && \valid_read(b);
ensures *a == \old(*b) && *b == \old(*a);
*/
void swap( int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
//int test_swap(void) {
int main(void) {
int a = 37;
int b = 91;
//# assert h == 42;
swap(&a, &b);
//# assert h == 42;
return 0;
}
With this code as is above, WP is able to prove the first //# assert h == 42; in main as expected from the discussion in the tutorial.
IF the function main is renamed test_swap WP is un-able to prove the first //# assert h == 42;
Why?
I can understand why EVA cares about the presence of main, but I can not understand why WP should even care, as I am only asking WP to prove the single function main (in one case) and test_swap (in the other case).
I am using Frama-C version: 25.0-beta (Manganese)
By default, Frama-C indeed assumes (at kernel level) that the main function is the entry point of the program. That means that WP can make some assumptions about the global context (basically the initial values of global variables), but also that we might have additional verification to perform on the function. For example, here, we could write:
//# requires 0 <= h <= 100 ;
int main(void) {
...
}
In such a case, WP generates a VC for the requires of the main function and proves it:
If one really wants a behavior where the main function is just handled as any other function, the Frama-C kernel must be parameterized with the -lib-entry option. In such a case:
WP does not try to prove the requires of main,
WP cannot prove that h is 42 in the first assert.
frama-c-gui b.c -lib-entry -wp
I'm using Frama-C version Silicon-20161101. Every time a reference a pointer value *x in an ensures clause the preprocessor inserts *\old(x) unnecessarily. For example
// File swap.c:
/*# requires \valid(a) && \valid(b);
# ensures A: *a == \old(*b) ;
# ensures B: *\at(\old(b),Post) == \old(*a) ;
# assigns *a,*b ;
#*/
void swap(int *a,int *b)
{
int tmp = *a ;
*a = *b ;
*b = tmp ;
return ;
}
when processed with frama-c swap.c -print outputs
/* Generated by Frama-C */
/*# requires \valid(a) ∧ \valid(b);
ensures A: *\old(a) ≡ \old(*b);
ensures B: *\old(b) ≡ \old(*a);
assigns *a, *b;
*/
void swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
return;
}
Interestingly enough, this is still verified as correct by the WP plugin! I assume this is because *\old(a) is the post value of \old(a) (which is still the same pointer since it hasn't been changed)? Is this a bug? Is there any quick user end fix for this?
There are two points in your question. First, *\old(a) should not be confused with \old(*a): in both cases, we evaluate the pointer a in the Old state, but in *\old(a), we dereference it in the current state, while in \old(*a), the dereference is also done in the Old state.
Second, formal parameters are a bit special: as mentioned in the ACSL manual, in the post-state of the function they have the same the value as in the pre-state, even if they have been modified by the function, such as in the following:
/*#
requires \valid(a + 0 .. 1);
ensures *a == \old(*a) + 1;
ensures a[1] == \old(a[1]) + 1;
*/
void f(int *a) {
*a = *a + 1;
a++;
*a = *a + 1;
}
The rationale here is that since C has a call-by-value semantics, the outside world cannot see any internal modification made to the formal (which acts as a local variable for this purpose). In other words, as long as the contract is concerned, the value tied to a in the example above is the one of the actual argument passed to it, no matter what happens in the implementation of the function. Note that in the case of a pointer, this of course applies only to the value of the pointer itself, not to the values stored in the memory block it points to.
In order to make this semantics explicit, the type-checker wraps all occurrences of a formal parameter in an ensures clause inside \old.
You may also want to see this answer to a related, albeit not completely similar question.
I am able to prove the following program using Frama-C, which is surprising because 1) there is an assert false, and 2) the loop invariant does not hold (array a holds 1's not 2's). Am I missing something here?
/*# requires \valid(a+ (0..9)) && \valid(b+ (0..9));
*/
void test_foo(int *a, char *b) {
int i = 0;
/*# loop invariant \forall int j; 0 <= j < i ==> a[j] == 2;
loop invariant \forall int j; 0 <= j < i ==> b[j] == 'a';
*/
for (int i = 0; i < 10; i++) {
a[i] = 1;
b[i] = 'a';
}
//# assert \false;
}
I am running frama-c as:
frama-c -wp -wp-invariants -wp-prover "why3:alt-ergo" -wp-model "Typed,int,real" -wp-par 8 -wp-timeout 15 -wp-out wp.out test.c
I see same behavior on both Sodium and Magnesium versions.
-wp-invariants is not meant to handle "normal" loop invariants such as the ones you have provided, but "general inductive invariants" in the sense of ACSL section 2.4.2. You can thus remove this option from your command line. Then some proof obligations fail as expected.
Note in addition that your loop annotations are incomplete: as warned by WP, you should have a loop assigns, such as
loop assigns i, a[0 .. 9], b[0 .. 9];
Then, in order to be able to prove this loop assigns, you will need to specify i interval of variation:
loop invariant 0<=i<=10;
Finally, the fact that -wp-invariants make proof obligations behave strangely in presence of normal loop annotations should probably be considered as a bug and reported on Frama-C's bts.
I have some troubles when I try to use the default logic labels LoopEntry and LoopCurrent. Here is a simple example the different provers (alt-ergo, coq, cvc3, z3) I use are not able to prove :
/*# requires n > 0;*/
void f(int n){
int i = 0;
/*# loop invariant \at(i,LoopEntry) == 0;
# loop invariant \at(i,LoopCurrent) >= \at(i,LoopEntry);
# loop invariant 0 <= i <= n;
# loop assigns i;
# loop variant n-i;
*/
while(i < n){
i++;
}
}
In particular, the first and second invariants are not proved (no problem with the others). Now if I modify this simple example by adding a label "label" after the declaration/definition of i and if I refer to that label, and change LoopCurrent by Here (which gives this snippet :
/*# requires n > 0;*/
void f(int n){
int i = 0;
label : ;
/*# loop assigns i;
# loop invariant \at(i,label) == 0;
# loop invariant \at(i,Here) >= \at(i,label);
# loop invariant 0 <= i <= n;
# loop variant n-i;
*/
while(i < n){
i++;
}
}
)
now everything is proved.
I found the documentation about Acsl default logic labels quite easy to understand and I expected the first example to be proved as the second. Could you explain where does the problem come from?
Roo
PS1 : what does Pre refer to when used in a loop clause? The state before first loop iteration or the previous iteration??
PS2 : I'm using Frama-C Fluorine, but maybe I didn't upgrade for every minor updates
LoopCurrent and LoopEntry are indeed not supported by WP in Fluorine. This is fixed in the development version (see http://bts.frama-c.com/view.php?id=1353), and should appear in the next release.
Regarding the other pre-defined labels,
Pre always refers to the state at the beginning of the function.
Old can only be used in a contract, and refers to the pre-state of this contract (i.e. the state in which the requires and assumes clauses are evaluated). It is thus equivalent to Pre for a function contract, but not for a statement contract (unless you make a contract enclosing the main block of your function).
Here means the program point where the corresponding annotation is evaluated. In a contract, its meaning depends on the clause in which it appears.
Post can only be used in ensures, assigns, allocates or frees clauses, and refer to the state at the end of the contract.
I need to write an ACSL specification for the dependencies of a function that takes a pointer as input, and uses its content when the pointer in not NULL.
I think that this specification is correct:
/*# behavior p_null:
assumes p == \null;
assigns \result from \nothing;
behavior p_not_null:
assumes p != \null;
assigns \result from *p;
*/
int f (int * p);
but I would rather avoid the behaviors, but I don't know if this is correct (and equivalent) :
//# assigns \result from p, *p;
int f (int * p);
Can I use *p in the right part of the \from even if p might be NULL ?
Yes you can. the right part of the from indicates which locations might contribute to the value of \result, but f does not need to read from *p to compute \result (and it should better avoid it if p is NULL of course).
As a side note, the question could have also been raised for the assigns clause of the p_not_null behavior, as p!=\null does
not imply \valid(p) in C.
Nevertheless, the contract without behavior is slightly less precise than the one with behaviors, which states that when p is NULL a constant value is returned, and when p is not null, only the content of *p is used (the assigns clause without behavior allows to return e.g. *p+(int)p, or even (int)p).