\chapter{Introduction}

\section{Bounded Model Checking for ANSI-C}

Many safety-critical software systems are legacy designs, i.e., written in a
low level language such as ANSI-C or even assembly language, or at least
contain components that are written in this manner. Very often performance
requirements enforce the use of these languages. These systems are a bigger
security and safety problem than programs written in high level languages.

The verification of low level ANSI-C code is challenging due to extensive
use of arithmetic, pointers and pointer arithmetic, and bit-wise operators.

We describe a tool that formally verifies ANSI-C programs. The properties
checked include pointer safety and array bounds, and user-provided
assertions. The tool implements a technique called Bounded Model Checking
(BMC). In BMC, the transition relation for a complex state machine and its
specification are jointly unwound to obtain a Boolean formula, which is then
checked for satisfiability by using a SAT procedure. If the formula is
satisfiable, a counterexample is extracted from the output of the SAT
procedure. If the formula is not satisfiable, the program can be unwound
more to determine if a longer counterexample exists. The tool checks that
sufficient unwinding is done to ensure that no longer counterexample can
exist by means of {\it unwinding assertions}.

A design goal of the tool is to check conformance of the program with the
ANSI-C standard \cite{ISO:1999:IIP}. Thus, architecture specific extensions
of C are rejected by the tool. This ensures that the program shows the same
behavior on all ANSI-C compliant compilers and architectures.

\section{A Short Tutorial}

\subsection{First Steps}

Like a compiler, \cbmc{} takes the name of {\tt .c} files on the command
line. \cbmc{} then translates the program and merges the function
definitions from the various {\tt .c} files, just like a linker. But instead
of producing a binary for execution, \cbmc{} performs symbolic simulation on
the program. By default, it then prints the equations obtained from the
symbolic simulation.

As an example, consider the following simple program, named {\tt file1.c}:
%
\begin{alltt}\small
int puts(const char *s) \{ \}

int main(int argc, char **argv) \{
  int i;

  if(argc>=1)
    puts(argv[1]);
\}
\end{alltt}

Of course, this program is faulty, as the {\tt argv} array might have only
one element, and then the array access {\tt argv[1]} is out of bounds.
Now, run \cbmc{} as follows:
%
\begin{alltt}
  cbmc file1.c
\end{alltt}

\cbmc{} will print the equations it generates from the program. Note that it
prints a comment together with the equations, in this case ''array {\tt
argv} upper bound'' together with the location of the faulty array access.
\cbmc{} prints the equation since the built-in simplifier is not able to
determine its validity. In these cases, \cbmc{} allows passing the equation
to a stronger solver using the option {\tt --decide}:
%
\begin{alltt}
  cbmc file1.c --decide
\end{alltt}

With this option, \cbmc{} transforms the equation you have seen before into
CNF and passes it to a SAT solver. It can now detect that the equation is
actually not valid, and thus, there is a bug in the program. It prints a
counterexample trace, i.e., a program trace that ends in a state which
violates the property. In case of the example, it ends in the faulty array
access. It also shows the values the input variables must have for the bug
to occur. In this example, {\tt argc} must be one to trigger the
out-of-bounds array access. If you change the condition in the example to
{\tt argc>=2}, the bug is fixed and \cbmc{} will report a successful
verification run.

\subsection{Verifying Modules}

In the example above, we used a program that starts with a {\tt main}
function. However, \cbmc{} is aimed at embedded software, and these
kinds of programs usually have different entry points. Furthermore, \cbmc{}
is also useful for verifying program modules. Consider the following example,
called {\tt file2.c}:
%
\begin{alltt}\small
int array[10];

int sum() \{
  unsigned i, sum;

  sum=0;

  for(i=0; i<10; i++)
    sum+=array[i];
\}
\end{alltt}
%
In order to set the entry point to the {\tt sum} function, run
%
\begin{alltt}
  cbmc file2.c --function sum
\end{alltt}

\subsection{Loop Unwinding}

You will note that \cbmc{} unwinds the {\tt for} loop in the program. As
\cbmc{} performs Bounded Model Checking, all loops have to have a finite
upper run-time bound in order to guarantee that all bugs are found. \cbmc{}
actually checks that enough unwinding is performed. As an example, consider
{\tt binsearch.c}:
%
\begin{alltt}\small
int binsearch(int x) \{
  int a[16];
  signed low=0, high=16;

  while(low<high) \{
    signed middle=low+((high-low)>>1);

    if(a[middle]<x)
      high=middle;
    else if(a[middle]>x)
      low=middle+1;
    else // a[middle]=x !
      return middle;
  \}
   
  return -1;
\}
\end{alltt}

If you run \cbmc{} on this function, you will notice that the unwinding does
not stop. The built-in simplifier is not able to determine a run time bound
for this loop. The unwinding bound has to be given as a command line
argument:
%
\begin{alltt}
  cbmc binsearch.c --function binsearch --unwind 5 --decide
\end{alltt}

\cbmc{} not only verifies the array bounds (note that this actually depends
on the result of the right shift), but also checks that enough unwinding is
done, i.e., it proves a run-time bound. For any lower unwinding bound, there
are traces that require more loop iterations. Thus, \cbmc{} will produce an
appropriate counterexample.

\subsection{Unbounded Loops}

However, \cbmc{} can also be used for programs with unbounded loops. In this
case, \cbmc{} is used for bug hunting only; \cbmc{} does not attempt to find
all bugs. Consider the following program:
%
\begin{alltt}\small
_Bool nondet_bool();
_Bool LOCK = 0;

_Bool lock() \{
  if(nondet_bool()) \{  
    assert(!LOCK);
    LOCK=1;
    return 1; \}
   
  return 0;
\}

void unlock() \{
  assert(LOCK);
  LOCK=0;
\}

int main() \{
  unsigned got_lock = 0;
  int times;

  while(times > 0) \{
    if(lock()) \{
      got_lock++;
      /* critical section */
    \}
    
    if(got_lock!=0)
      unlock();

    got_lock--;
    times--;  
\}  \} 
\end{alltt}

The {\tt while} loop in the {\tt main} function has no (useful) run-time
bound. Thus, the {--unwind} parameter has to be used in order to prevent
infinite unwinding. However, you will note that \cbmc{} will detect that not
enough unwinding is done and aborts with an unwinding assertion violation.

In order to disable this test, run \cbmc{} with the parameter {\tt
--no-unwinding-assertions}. For an unwinding bound of one, no bug is found.
But already for a bound of two, \cbmc{} detects a trace that violates an
assertion. Without unwinding assertions, \cbmc{} does not prove the program
correct, but it can be helpful to find program bugs.

\subsection{A Note About the ANSI-C Library}

The ANSI-C library that comes with any C compiler is usually not usable for
\cbmc{}. It usually comes as binary and not as source code, and furthermore
usually contains architecture dependent code. In case of the GNU C Library,
even the prototypes in the {\tt .h} file contain code that is not compliant
with the ANSI-C standard. \cbmc{} ships with prototypes that are standard
compliant. You need to define this path as include path for the ANSI-C
pre-processor.

E.g., assuming the {\tt bash} shell is used and {\tt gcc} is
the pre-processor, this statement adjusts the path accordingly:
%
\begin{alltt}\small
export C_INCLUDE_PATH=/path-to-cprover/examples/ansi-c-lib/
\end{alltt}

This directory only contains the prototypes, no implementation of the
library functions is currently provided.

\section{Outline}

In chapter \ref{ansi_c_language_features_sec}, we describe the ANSI-C
language features supported by \cbmc{}. In chapter
\ref{hardware_verification_sec}, we describe how \cbmc{} can be used to
check conformance of hardware designs with an ANSI-C specification. Chapter
\ref{command_line_sec} describes the command line interface.

