Predicate abstraction for software verification

Software verification is an important and difficult problem. Many static checking techniques for software require annotations from the programmer in the form of method specifications and loop invariants. This annotation overhead, particularly of loop invariants, is a significant hurdle in the acceptance of static checking. We reduce the annotation burden by inferring loop invariants automatically.Our method is based on predicate abstraction, an abstract interpretation technique in which the abstract domain is constructed from a given set of predicates over program variables. A novel feature of our approach is that it infers universally-quantified loop invariants, which are crucial for verifying programs that manipulate unbounded data such as arrays. We present heuristics for generating appropriate predicates for each loop automatically; the programmer can specify additional predicates as well. We also present an efficient algorithm for computing the abstraction of a set of states in terms of a collection of predicates.Experiments on a 44KLOC program show that our approach can automatically infer the necessary predicates and invariants for all but 31 of the 396 routines that contain loops.

[1]  Steven M. German,et al.  A synthesizer of inductive assertions , 1975, IEEE Transactions on Software Engineering.

[2]  Zohar Manna,et al.  The Temporal Logic of Reactive and Concurrent Systems , 1991, Springer New York.

[3]  Edmund M. Clarke,et al.  Counterexample-guided abstraction refinement , 2003, 10th International Symposium on Temporal Representation and Reasoning, 2003 and Fourth International Conference on Temporal Logic. Proceedings..

[4]  Ralph-Johan Back,et al.  Refinement Calculus: A Systematic Introduction , 1998 .

[5]  Charles Gregory Nelson,et al.  Techniques for program verification , 1979 .

[6]  Natarajan Shankar,et al.  Abstract and Model Check While You Prove , 1999, CAV.

[7]  David L. Dill,et al.  Experience with Predicate Abstraction , 1999, CAV.

[8]  Chandramohan A. Thekkath,et al.  Frangipani: a scalable distributed file system , 1997, SOSP.

[9]  Cormac Flanagan,et al.  Avoiding exponential explosion: generating compact verification conditions , 2001, POPL '01.

[10]  Patrick Cousot,et al.  Abstract interpretation: a unified lattice model for static analysis of programs by construction or approximation of fixpoints , 1977, POPL.

[11]  Ben Wegbreit,et al.  The synthesis of loop predicates , 1974, CACM.

[12]  Zohar Manna,et al.  Logical analysis of programs , 1976, CACM.

[13]  Nicolas Halbwachs,et al.  Automatic discovery of linear restraints among variables of a program , 1978, POPL.

[14]  Randal E. Bryant,et al.  Graph-Based Algorithms for Boolean Function Manipulation , 1986, IEEE Transactions on Computers.

[15]  Norihisa Suzuki,et al.  Implementation of an array bound checker , 1977, POPL.

[16]  Edsger W. Dijkstra,et al.  A Discipline of Programming , 1976 .

[17]  Greg Nelson,et al.  A generalization of Dijkstra's calculus , 1989, ACM Trans. Program. Lang. Syst..

[18]  K. Rustan M. Leino,et al.  Extended static checking , 1998, PROCOMET.

[19]  Richard J. Waldinger,et al.  A more mechanical approach to program verification , 1974, Symposium on Programming.

[20]  K. Rustan M. Leino,et al.  Checking Java Programs via Guarded Commands , 1999, ECOOP Workshops.

[21]  Hassen Saïdi,et al.  Powerful Techniques for the Automatic Generation of Invariants , 1996, CAV.

[22]  Hassen Saïdi,et al.  Construction of Abstract State Graphs with PVS , 1997, CAV.

[23]  Zohar Manna,et al.  Automatic Generation of Invariants and Intermediate Assertions , 1997, Theor. Comput. Sci..