4

I am trying to prove a simple assertion using the WP plugin of frama-c. The C code was generated from a Targetlink lookup table. My aim is to provide enough annotations to the function that I can use the resulting contract to prove properties of a calling program. As a first step I wrote an assertion near the beginning of the function that compares a constant against a value obtained from dereferenced pointers, see the following example.

typedef struct MAP_Tab1DS0I2T3_b_tag {
   int Nx;
   const int * x_table;
   const int * z_table;
} MAP_Tab1DS0I2T3_b;

int LARA_GearEnaCndn_X[9] =
{
   -1, 0, 1, 2, 3, 4, 5, 6, 8
};

int LARA_GearEnaCndn_Z[9] =
{
   1, 0, 1, 1, 0, 0, 0, 0, 0
};


MAP_Tab1DS0I2T3_b Sb218_LARA_GearEnaCndn_CUR_map = {
   9,
   (const int *) &(LARA_GearEnaCndn_X[0]),
   (const int *) &(LARA_GearEnaCndn_Z[0])
};

/*@ requires x == 2; */
int Tab1DS0I2T3_b(const MAP_Tab1DS0I2T3_b * map, int x)
{
   /* SLLocal: Default storage class for local variables | Width: 8 */
   int Aux_U8;
   int Aux_U8_a;
   int Aux_U8_b;
   int Aux_U8_c;

   /* SLLutLocalConst: Default storage class for local variables | Width: 32 */
   const int * x_table /* Scaling may differ through function reuse. */;
   const int * z_table /* Scaling may differ through function reuse. */;

   x_table = map->x_table;
   z_table = map->z_table;

   //@ assert (x < x_table[(int) (map->Nx - 1)]);

   if (x <= *(x_table)) {
      /* Saturation. */
      return z_table[0];
   }
   if (x >= x_table[(int) (map->Nx - 1)]) {
      return z_table[(int) (map->Nx - 1)];
   }

   /* Linear search, start low. */
   x_table++;
   while (x > *(x_table++))    {
      z_table++;
   }
   x_table -= 2 /* 2. */;
   Aux_U8 = *(z_table++);
   Aux_U8_a = *(z_table);

   /* Interpolation. */
   Aux_U8_b = (int) (((int) x) - ((int) x_table[0]));
   Aux_U8_c = (int) (((int) x_table[1]) - ((int) x_table[0]));
   if (Aux_U8 <= Aux_U8_a) {
      /* Positive slope. */
      Aux_U8 += ((int) ((((int) (int) (Aux_U8_a - Aux_U8)) * ((int) Aux_U8_b)) /
       Aux_U8_c));
   }
   else {
      /* Negative slope. */
      Aux_U8 -= ((int) ((((int) (int) (Aux_U8 - Aux_U8_a)) * ((int) Aux_U8_b)) /
       Aux_U8_c));
   }
   return Aux_U8;
}

Can someone give me a hint which annotations I need to succeed with the proof? From a look at the Coq proof obligation I see that there are no axioms for operations like "addr_of_data" or "access" which I need for rewriting the terms. Also the information of the global variables referenced in the assertion are missing.

1 subgoals
______________________________________(1/1)
forall x_0 map_0 : Z,
is_sint32 x_0 ->
forall m_0 : array data,
x_0 = 2 ->
forall x_table_0 : Z,
x_table_0 = addr_of_data (access m_0 (addr_shift map_0 1)) ->
2 <
sint32_of_data
  (access m_0
     (addr_shift x_table_0
    (as_sint32 (sint32_of_data (access m_0 (addr_shift map_0 0)) - 1))))

BR, Harald

1 Answers1

4

The addr_of_data, addr_shift etc exioms are automatically given in the store_model.v tab of your coq-ide.

Your example nowhere states that map gets Sb218_LARA_GearEnaCndn_CUR_map as the actual parameter. Without that the assertion can be wrong.

Now, I don't know how to make wp utilize the explicit values of global initializers as parts of a proof. There are some global invariants in ACSL, but wp doesn't seem to treat them anyhow. So I'll use an explicit require statements for the needed values.

Given the following set of statements in the function header:

/*@ requires x == 2; 
    requires map->x_table == Sb218_LARA_GearEnaCndn_CUR_map.x_table;
    requires map->Nx == Sb218_LARA_GearEnaCndn_CUR_map.Nx;
    requires LARA_GearEnaCndn_X[8] == 8;
    requires Sb218_LARA_GearEnaCndn_CUR_map.Nx == 9;
    requires Sb218_LARA_GearEnaCndn_CUR_map.x_table == LARA_GearEnaCndn_X;
    requires Sb218_LARA_GearEnaCndn_CUR_map.z_table == LARA_GearEnaCndn_Z;
*/

I was able to prove the needed assertion.

The first one is yours. The second and the third ones are explicit expansion of *map=Sb218_LARA_GearEnaCndn_CUR_map in order not to mess with address ranges. The rest reflects the initializer values.

Alexander Gorshenev
  • 2,769
  • 18
  • 33
  • 4
    Regarding the initial values of global variables (including those coming from an explicit initializer) WP uses them if and only if Frama-C's option -lib-entry is not set, and if option -main is set to the function that is being proven (here Tab1DS0I2T3_b). In all other cases, their values might have been changed during another call, and you must supply those invariants yourselves, currently as requires. – byako Dec 19 '12 at 09:39
  • Thanks for your answers. With the initialization of the map variable and the -main option I was able to do the proof. – user1786344 Dec 21 '12 at 09:01