What do I do when CBMC won't stop?

CBMC goes through several stages. CBMC can theoretically get stuck in any stage, but the most commonly slow stages are

  • Doing the symbolic execution
  • Generating the SAT formula from the symbolic execution
  • Solving the SAT formula with the SAT solver

Almost always the problem is just one or two lines of code. For example, under certain circumstances something as simple as

  memcpy(dst, src, length);

can cause CBMC to become stuck generating the SAT formula that results from considering all places dst and src might be pointing.

The first problem is to find the line of code. Most programmers are used to delta debugging in which the programmer performs a kind of binary search on the code to find the problem. Delete more and more from the bottom of the function under test until CBMC no longer hangs. The problem is in the last block of code (the last line) deleted that caused CBMC to terminate.

The second problem is to fix the problem. Usually the solution involves some form of function abstraction. It is a known problem, for example, for the standard library functions memcpy, memmove, and memset to be a problem. It is a common solution to abstract these functions to havoc the entire destination object and not just the portion being updated. This works because functions under test commonly copy data to the output and never look at the data actually copied. A simple stub for memcpy would be

void memcpy(char *dst, char *src, size_t length) {
  __CPROVER_havoc(dst);
}

A better stub would check that src and dst are nonnull pointers to nonoverlapping regions of memory. For a good stub, see memcpy in the AWS C Common repository.

A final tip is that sometimes it is interesting to know which stage of CBMC is taking so long. The output of CBMC can general indicate where the problem is. Running CBMC with

  cbmc --flush

will flush to the terminal log messages saying that a given stage is starting or finishing. This usually gives some hint. The most difficult stage to debug is why CBMC is taking so long to generate the SAT formula. If the problem is the SAT solver is taking too long, you may be able to figure out what is going on by running CBMC with one flag at a time (eg, check --bounds-check and then check --unsigned-overflow-check) until you can identify the check that is taking so much time.