880 research outputs found
Predicate Abstraction with Indexed Predicates
Predicate abstraction provides a powerful tool for verifying properties of
infinite-state systems using a combination of a decision procedure for a subset
of first-order logic and symbolic methods originally developed for finite-state
model checking. We consider models containing first-order state variables,
where the system state includes mutable functions and predicates. Such a model
can describe systems containing arbitrarily large memories, buffers, and arrays
of identical processes. We describe a form of predicate abstraction that
constructs a formula over a set of universally quantified variables to describe
invariant properties of the first-order state variables. We provide a formal
justification of the soundness of our approach and describe how it has been
used to verify several hardware and software designs, including a
directory-based cache coherence protocol.Comment: 27 pages, 4 figures, 1 table, short version appeared in International
Conference on Verification, Model Checking and Abstract Interpretation
(VMCAI'04), LNCS 2937, pages = 267--28
Lost in Abstraction: Monotonicity in Multi-Threaded Programs (Extended Technical Report)
Monotonicity in concurrent systems stipulates that, in any global state,
extant system actions remain executable when new processes are added to the
state. This concept is not only natural and common in multi-threaded software,
but also useful: if every thread's memory is finite, monotonicity often
guarantees the decidability of safety property verification even when the
number of running threads is unknown. In this paper, we show that the act of
obtaining finite-data thread abstractions for model checking can be at odds
with monotonicity: Predicate-abstracting certain widely used monotone software
results in non-monotone multi-threaded Boolean programs - the monotonicity is
lost in the abstraction. As a result, well-established sound and complete
safety checking algorithms become inapplicable; in fact, safety checking turns
out to be undecidable for the obtained class of unbounded-thread Boolean
programs. We demonstrate how the abstract programs can be modified into
monotone ones, without affecting safety properties of the non-monotone
abstraction. This significantly improves earlier approaches of enforcing
monotonicity via overapproximations
On Verifying Complex Properties using Symbolic Shape Analysis
One of the main challenges in the verification of software systems is the
analysis of unbounded data structures with dynamic memory allocation, such as
linked data structures and arrays. We describe Bohne, a new analysis for
verifying data structures. Bohne verifies data structure operations and shows
that 1) the operations preserve data structure invariants and 2) the operations
satisfy their specifications expressed in terms of changes to the set of
objects stored in the data structure. During the analysis, Bohne infers loop
invariants in the form of disjunctions of universally quantified Boolean
combinations of formulas. To synthesize loop invariants of this form, Bohne
uses a combination of decision procedures for Monadic Second-Order Logic over
trees, SMT-LIB decision procedures (currently CVC Lite), and an automated
reasoner within the Isabelle interactive theorem prover. This architecture
shows that synthesized loop invariants can serve as a useful communication
mechanism between different decision procedures. Using Bohne, we have verified
operations on data structures such as linked lists with iterators and back
pointers, trees with and without parent pointers, two-level skip lists, array
data structures, and sorted lists. We have deployed Bohne in the Hob and Jahob
data structure analysis systems, enabling us to combine Bohne with analyses of
data structure clients and apply it in the context of larger programs. This
report describes the Bohne algorithm as well as techniques that Bohne uses to
reduce the ammount of annotations and the running time of the analysis
Towards a Constrained-based Verification of Parameterized Cryptographic Protocols
International audienceAlthough many works have been dedicated to standard protocols like Needham-Schroeder very few address the more challenging class of group protocol s. We present a synchronous model for group protocols, that generalizes standard protocol models by permitting unbounded lists inside messages. In this extended model we propose a correct and complete set of inference rules for checking security properties in presence of an active intruder for the class of well-tagged protocols. Our inference system generalizes the ones that are implemented in several tools for a bounded number of sessions and fixed size lists in message. In particular when applied to protocols whose specification does not contain unbounded lists our inference system provides a decision procedure for secrecy in the case of a fixed number of sessions
Regular Abstractions for Array Systems
Verifying safety and liveness over array systems is a highly challenging
problem. Array systems naturally capture parameterized systems such as
distributed protocols with an unbounded number of processes. Such distributed
protocols often exploit process IDs during their computation, resulting in
array systems whose element values range over an infinite domain. In this
paper, we develop a novel framework for proving safety and liveness over array
systems. The crux of the framework is to overapproximate an array system as a
string rewriting system (i.e. over a finite alphabet) by means of a new
predicate abstraction that exploits the so-called indexed predicates. This
allows us to tap into powerful verification methods for string rewriting
systems that have been heavily developed in the last few decades (e.g. regular
model checking). We demonstrate how our method yields simple, automatically
verifiable proofs of safety and liveness properties for challenging examples,
including Dijkstra's self-stabilizing protocol and the Chang-Roberts leader
election protocol
Cell morphing: from array programs to array-free Horn clauses
International audienceAutomatically verifying safety properties of programs is hard.Many approaches exist for verifying programs operating on Boolean and integer values (e.g. abstract interpretation, counterexample-guided abstraction refinement using interpolants), but transposing them to array properties has been fraught with difficulties.Our work addresses that issue with a powerful and flexible abstractionthat morphes concrete array cells into a finite set of abstractones. This abstraction is parametric both in precision and in theback-end analysis used.From our programs with arrays, we generate nonlinear Horn clauses overscalar variables only, in a common format with clear and unambiguouslogical semantics, for which there exist several solvers. We thusavoid the use of solvers operating over arrays, which are still veryimmature.Experiments with our prototype VAPHOR show that this approach can proveautomatically and without user annotationsthe functional correctness of several classical examples, including \emph{selection sort}, \emph{bubble sort}, \emph{insertion sort}, as well as examples from literature on array analysis
Verification of Imperative Programs by Constraint Logic Program Transformation
We present a method for verifying partial correctness properties of
imperative programs that manipulate integers and arrays by using techniques
based on the transformation of constraint logic programs (CLP). We use CLP as a
metalanguage for representing imperative programs, their executions, and their
properties. First, we encode the correctness of an imperative program, say
prog, as the negation of a predicate 'incorrect' defined by a CLP program T. By
construction, 'incorrect' holds in the least model of T if and only if the
execution of prog from an initial configuration eventually halts in an error
configuration. Then, we apply to program T a sequence of transformations that
preserve its least model semantics. These transformations are based on
well-known transformation rules, such as unfolding and folding, guided by
suitable transformation strategies, such as specialization and generalization.
The objective of the transformations is to derive a new CLP program TransfT
where the predicate 'incorrect' is defined either by (i) the fact 'incorrect.'
(and in this case prog is not correct), or by (ii) the empty set of clauses
(and in this case prog is correct). In the case where we derive a CLP program
such that neither (i) nor (ii) holds, we iterate the transformation. Since the
problem is undecidable, this process may not terminate. We show through
examples that our method can be applied in a rather systematic way, and is
amenable to automation by transferring to the field of program verification
many techniques developed in the field of program transformation.Comment: In Proceedings Festschrift for Dave Schmidt, arXiv:1309.455
Mechanising an algebraic rely-guarantee refinement calculus
PhD ThesisDespite rely-guarantee (RG) being a well-studied program logic established in the 1980s, it
was not until recently that researchers realised that rely and guarantee conditions could be
treated as independent programming constructs. This recent reformulation of RG paved the
way to algebraic characterisations which have helped to better understand the difficulties that
arise in the practical application of this development approach.
The primary focus of this thesis is to provide automated tool support for a rely-guarantee
refinement calculus proposed by Hayes et. al., where rely and guarantee are defined as
independent commands. Our motivation is to investigate the application of an algebraic
approach to derive concrete examples using this calculus. In the course of this thesis, we
locate and fix a few issues involving the refinement language, its operational semantics and
preexisting proofs. Moreover, we extend the refinement calculus of Hayes et. al. to cover
indexed parallel composition, non-atomic evaluation of expressions within specifications,
and assignment to indexed arrays. These extensions are illustrated via concrete examples.
Special attention is given to design decisions that simplify the application of the mechanised
theory. For example, we leave part of the design of the expression language on the
hands of the user, at the cost of the requiring the user to define the notion of undefinedness
for unary and binary operators; and we also formalise a notion of indexed parallelism that is
parametric on the type of the indexes, this is done deliberately to simplify the formalisation of
algorithms. Additionally, we use stratification to reduce the number of cases in in simulation
proofs involving the operational semantics. Finally, we also use the algebra to discuss the
role of types in program derivation
- …