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).
Related
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'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.
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.
How would I get my variables out of a vector?
I can't use the binary insertion operators or the equal operators.
Earlier, I declared a vector<someStruct> *vObj and allocated it, then returned the vObj
and called it in this function:
vector<sameStruct> firstFunc();
for (unsigned int x = 0; x < v->size(); x++)
{
v[x];
}
when I debug it, v[x] now has the full contents of the original vector, as it did before without the subscript/index.
But I don't think I've done anything to progress beyond that.
I just have about 4 variables inside my vector; when I debug it, it has the information that I need, but I can't get to it.
As it is written v is a pointer to a vector of structs.
When you index directly into v all you are doing is pointer arithmatic. v[x] is the vector of structs at position x (assuming that v is an array if it is just a single object at the end of the pointer then v[x] for x>0 is just garbage). This is because it is applying the [x] not to the vector pointed to by v but to the pointer v itself.
You need to dereference the pointer and then index into the vector using something like:
(*v)[x];
At this point you have a reference to the object at the xth position of the vector to get at its member functions / variables use:
(*v)[x].variable;
or
(*v)[x].memberfunction(parameters);
If you do not want to dereference the vector then access the element within it you might try something like:
v->at(x);
v->at(x).variable;
v->at(x).memberfunction;
This way you are accessing a member function of an object in exactly the same manner as when you called:
v->size();
I hope that this helps.
To use the [] operator to access elements you must do so on object, not a pointer to an object.
Try;
(*vec)[x];
E.g.
for (int i = 0; i < vec->size(); i++)
{
printf("Value at %d is %d\n", i, (*vec)[i]);
}
Note that when calling functions on a pointer you usually use the -> operator instead of the . operator, but you could easily do (*vec).some_func(); instead.
Operators such as [], --, ++ and so on can act both on objects and pointers. With objects they act as function calls, but on pointers they act as mathematical operations on the address.
For example;
pointer[nth];
*(pointer + nth);
Have exactly the same effect - they return the nth object from the start of the pointer. (note the location of the * in the second example, it's called after the offset is applied.
Two other tips;
You can also avoid the need to dereference like this by passing the vector as a reference, not a pointer. It's not always a suitable option but it does lead to cleaner code.
void my_func(std::vector<int>& vector)
{
// vector can then be used as a regular variable
}
If you're going to be passing vectors of a specific type to functions a lot then you can use a typedef both for clarity and to save on typing.
typedef std::vector<int> IntVector;
void my_func(IntVector& vector)
{
}