4

I have this C code:

while(p->next)   p = p->next;

I want to prove that no matter how long the list is, when this loop is over, p->next equals NULL, and EIP refers to the next instruction after this loop.

But I can't. Does anyone know how to prove loops in Isabelle/HOL?

chris
  • 4,988
  • 20
  • 36
njuguoyi
  • 399
  • 4
  • 10
  • 1
    I don't know of any direct way to proof properties of C code inside Isabelle/HOL. Could you give more details of what you are trying to achieve and what you where using (or expecting to use) to do so? Maybe http://afp.sourceforge.net/entries/Simpl.shtml is of interest. Btw: what is "EIP"? – chris Nov 05 '13 at 05:19
  • Independent of the proof tool you want to use. How do you intend to handle the case where the list is circular (i.e., the loop does not terminate)? – chris Nov 05 '13 at 05:22
  • Hello @chris . Sorry I cannot tell you too much details, this is a team work, and not published yet. What I can tell you is, we are simulating X86 ISA instructions in Isabelle, like mov, jmp. The assembly code generated by gcc is translated into Isabelle, and run in Isabelle. When there is no loops, the results are very good. But we cannot deal with loops, it's far more difficult. We want to prove that for all n, this while loop will end up with p->next equals NULL and the eip (pc) will point to the next instruction below the loop. – njuguoyi Nov 05 '13 at 07:55
  • I'm not asking about details of your project ;), just more context, e.g., which logic of Isabelle are you using, how do you import C code into Isabelle, ... Without this, your question cannot be answered easily. – chris Nov 05 '13 at 08:07

1 Answers1

11

A set of tools (disclaimer: I am the author of the latter) that allows you to import C code into Isabelle/HOL for further reasoning is Michael Norrish's C Parser and AutoCorres.

Using AutoCorres, I can parse the following C file:

struct node {
    struct node *next;
    int data;
};

struct node * traverse_list(struct node *list)
{
    while (list)
        list = list->next;
    return list;
}

into Isabelle using the commands:

theory List
imports AutoCorres
begin

install_C_file "list.c"
autocorres [ts_rules = nondet] "list.c"

We can then prove a Hoare triple which states that, for any input state, the return value of the function will be NULL:

lemma "⦃ λs. True ⦄ traverse_list' l ⦃ λrv s. rv = NULL ⦄"
  (* Unfold the function definition. *)
  apply (unfold traverse_list'_def)

  (* Add an invariant to the while loop. *)
  apply (subst whileLoop_add_inv [where I="λnext s. True"])

  (* Run a VCG, and solve the conditions using the simplified. *)
  apply wp
  apply simp
  done

This is a partial correctness theorem, which somewhat states what you asked for. (In particular, it states that if the function terminates, and if it doesn't fault, then the post-condition is true).

For a more complete proof, you would need to add a few more things to the above:

  1. You need to know that the list is valid; for instance, that intermediate nodes don't point to invalid addresses (for instance, unaligned addresses), and that the list doesn't form an loop (meaning that the while loop would never terminate).

  2. You will also want to prove termination. This is related to the second condition above, but you will likely still need to make an argument about why it is true. (A typical method would be to say that the length of the list always decreases, and hence the loop will eventually terminate).

AutoCorres does not direct concept of an instruction pointer (typically these concepts only exist at the assembly level), but a proof of termination would be similar.

AutoCorres provides some basic libraries for reasoning about linked lists in DataStructures.thy, which would be a good starting point.

davidg
  • 5,868
  • 2
  • 33
  • 51