Abstract

Many software model checkers only detect counterexamples with deep loops after exploring numerous spurious and increasingly longer counterexamples. We propose a technique that aims at eliminating this weakness by constructing auxiliary paths that represent the effect of a range of loop iterations. Unlike acceleration, which captures the exact effect of arbitrarily many loop iterations, these auxiliary paths may under-approximate the behaviour of the loops. In return, the approximation is sound with respect to the bit-vector semantics of programs. Our approach supports arbitrary conditions and assignments to arrays in the loop body, but may as a result introduce quantified conditionals. To reduce the resulting performance penalty, we present two quantifier elimination techniques specially geared towards our application. Loop under-approximation can be combined with a broad range of verification techniques. We paired our techniques with lazy abstraction and bounded model checking, and evaluated the resulting tool on a number of buffer overflow benchmarks, demonstrating its ability to efficiently detect deep counterexamples in C programs that manipulate arrays.

Highlights

  • The generation of diagnostic counterexamples is a key feature of model checking

  • Counterexamples are important in software model checking, as bugs in software frequently require thousands of transitions to be executed, and are difficult to reproduce without the help of an explicit error trace

  • We evaluated the resulting tool on a large suite of benchmarks known to contain deep paths, demonstrating our ability to efficiently detect deep counterexamples in C programs that manipulate arrays

Read more

Summary

Introduction

The generation of diagnostic counterexamples is a key feature of model checking. Counterexamples serve as witness for the refutation of a property, and are an invaluable aid to the engineer for understanding and repairing the fault. The primary reason for the inability of many existing tools to discover such “deep” bugs is that exploration is performed in a breadth-first fashion: the detection of an unsafe execution traversing a loop involves the repeated refutation of increasingly longer spurious counterexamples. Bounded model checking (BMC) is optimised for discovering bugs up to a given depth k, but the computational cost grows exponentially in k. Our approximation can be combined soundly with a broad range of verification engines, including predicate abstraction, lazy abstraction with interpolation [19], and bounded software model checking [5]. To demonstrate this versatility, we combined our technique with lazy abstraction and the Cbmc [5] model checker. We evaluated the resulting tool on a large suite of benchmarks known to contain deep paths, demonstrating our ability to efficiently detect deep counterexamples in C programs that manipulate arrays

Notation and preliminaries
A motivating example
Approximating paths with loops
Under-approximation techniques
Syntactic matching
Constraint-based acceleration
Assignments to arrays
Assumptions and feasibility of paths
Arithmetic overflows
Path selection
Eliminating quantifiers from approximations
Eliminating quantifiers over monotonic predicates
Eliminating quantifiers in membership tests for array indices
Implementation and experimental results
Related work
Conclusion and future work
Full Text
Published version (Free)

Talk to us

Join us for a 30 min session where you can share your feedback and ask us any queries you have

Schedule a call