Search code examples
frama-c

assume statement modelling in FramaC


I want to use user assertion of value analysis plugin of Frama-C (Neon version), however I have some problem to come up with the suitable model of assume statement, which is very useful for me to apply particular constraints, for example, here is my test code:

#include "/usr/local/share/frama-c/builtin.h"

int main(void)
{
    int selection = Frama_C_interval(0,10);
    int a;
    assume(selection > 5);
    if (selection > 5)
    {
        a = 2;
    }
    else
    {
        a = 1;
    }
    //@ assert a == 2;
    return 0;
}

I want that the value of selection will be greater than 5 after this assume statement so that the assertion will be valid. My initial attempt was to write this function void assume(int a){ while(!a); return;} , but it was unsuccessful. Please help me, thanks.


Solution

  • The easiest way to constrain selection would be to use an assert (which of course won't be proved by Value). If you want to distinguish between the assert that are in fact hypotheses you make from the assert that you want to verify, you can use ACSL's naming mechanism, such as

    //@ assert assumption: selection > 5;
    

    and verify that the only assert that are unknown are the ones named assumption.

    Using an assume function cannot work as such, because it will only reduce the possible value of the a parameter to be non-zero. Value is not able to infer the relation between the value of a in assume and the value of selection in main. However, it is possible to help it a little bit. First, -slevel allows to propagate several abstract state in parallel. Second, an assert given in an disjunctive will force Value to split its state (if the -slevel is big enough to do so). Thus, with the following code

    #include "builtin.h"
    
    void assume(int a) { while(!a); return; }
    
    int main(void)
    {
         int selection = Frama_C_interval(0,10);
         int a;
         /*@ assert selection > 5 || selection <= 5; */
         assume(selection > 5);
        if (selection > 5)
        {
            a = 2;
        }
        else
        {
            a = 1;
        }
        //@ assert a == 2;
        return 0;
    }
    

    and the following command line:

    frama-c -cpp-extra-args="-I$(frama-c -print-share-path)" -val -slevel 2
    

    After the first assert (which obviously valid), Frama-C will propagate separately two states: one in which selection > 5 and one in which selection <= 5. In the first case, assume is called with 1 as argument, thus returns immediately, and the then branch of the if is taken, so that the second assert is valid. In the second state, assume is called with 0, and never returns. Thus for all cases where control reaches the second assert, it is valid.

    Note that you really need to add the first assert inside the body of main, and to copy in ACSL the argument you pass to assume. Otherwise, the state split won't occur (more precisely, you will split on a, not on selection).