A Glimpse of a Verifying C Compiler – Extended Abstract –

The goal of the Verifying C Compiler project is to bring design by contract to C. More specifically, we are developing a verifying compiler, code name vcc, that takes annotated C programs, generates logical verification conditions from them and passes those verification conditions on to an automatic theorem prover to either prove the correctness of the program or find errors in it. C Intricacies. The vcc compiler is designed to support the verification of operating system code. As a consequence it does not only handle the type safe subset of C, but also deals with pointer arithmetic, reinterpretation of data and volatile data access. This flexibility is for example needed to verify low level system code like memory allocators, where data is interpreted in different ways by different parts of the system, or to verify algorithms implemented over polymorphic compare and swap operations. The vcc compiler uses different background axiomatizations to abstract from C's implementation defined behavior. For example the size of character type, or how integers are implemented (typically two's complement) is dealt with not by the translation to verification conditions but rather by their interpretation. The vcc compiler rejects C programs with unspecified behavior. For example , non-pure functions cannot directly be used as arguments to n-ary function applications (where n > 1), since C does not specify the evaluation order for function arguments. In addition to verifying developer-defined functional properties, the vcc compiler also checks for undefined behavior, i.e. null pointer dereferences, dangling pointers, double frees, division by zero, over and underflow. It does so by automatically inserting additional assertions into the verification conditions, which precede the translation of the partial operation. Generating these assertions can selectively be turned on and off to allow the verification of code that uses these features (for example overflow). C Memory Model. The central idea behind vcc's memory model is the subdivision of memory into several disjoint regions. Each region has a fixed size, which is determined at the time it is allocated, and is uniquely identified by a reference. A pointer consists of reference and a byte offset in the corresponding region. So vcc's memory model is in principle byte-oriented. The memory is represented as a partial updateable map mem, mapping (pointer, integer) pairs to values. The integer represents the number of bytes to access starting at the given pointer. So mem(p, n) denotes a value of size n stored …