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
Related
Sample code:
void main(){
unsigned int x;
x = 1U << 31; // OK
x = 1 << 31; // Sign overflowed
return;
}
frama-c-gui -eva main.c:
void main(void)
{
unsigned int x;
x = 1U << 31;
/*# assert Eva: signed_overflow: 1 << 31 ≤ 2147483647; */
x = (unsigned int)(1 << 31);
return;
}
Get red alarm because of signed overflow on line 4. I have existing code with ton of hardware registers defined with mask bits and shifting bits like this. It's unreasonable to modify the code add "U" for all the mask bits. Is there a option in eval plugin to treat these constants as unsigned integer?
There are some options in the kernel to control which kinds of alarms should be emitted (see frama-c -kernel-h or the manual, especially its section 6.3, for more information).
In your particular case, you are probably interested in -no-warn-signed-overflow, that will disable alarms related to overflows on signed arithmetic. Eva will then assume 2-complement arithmetic, and emit a warning about that if the situation occurs, but only once for the whole analysis.
Consider the following C code:
#include <assert.h>
//# requires p < q;
void f(char *p, char *q)
{
assert(p <= q-1);
}
//# requires a < b;
void g(int a, int b)
{
assert(a <= b-1);
}
Using alt-ergo, frama-c successfully proves that the assertion in g() holds but fail to prove the same with f(). Why?
Formally, pointers and integers are two very different things. In particular, C semantics states that pointer comparison is well defined only for pointers that points in the same allocated block (or one offset past the end of said allocated block) . This is reflected in the model used by the WP plugin of Frama-C in the definition of addr_le and friends (see $(frama-c -print-share-path)/wp/why3/Memory.why), where the pointers are checked to have the same address before the comparison is done on their offset.
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'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.