78 research outputs found

    Compositional Verification of Rich Program Properties in Separation Logic

    No full text
    Recent advances in deductive program verification correlate with the evolution of logics for modular reasoning about complex programs. Verification techniques built upon these logics require automation to help to verify practically essential rich program properties that summarize data structures via quantification or some form of abstraction. However, many such properties are higher-order (e.g., data structure comprehensions like sequence-fold), precluding automation. Furthermore, some rich properties (e.g., reachability between dynamically interlinked objects) are non-compositional; that is, one cannot compose the property of a data structure based solely on the properties of its disjoint sub-structures. However, compositionality is a prerequisite of automated modular reasoning (due to the problem commonly known as framing). If compositionality holds, the programmer can independently reason about each method in an application without considering the implementation of other methods, e.g., library code. The goal of this thesis is to develop compositional — i.e., automated and modular — techniques for verifying rich program properties. We build on top of separation logic, a prominent program logic that enables modular reasoning about heap-transforming, concurrently executed programs. The specification language of separation logic expresses memory safety properties, but complementary techniques for handling rich properties are underdeveloped, especially in an automated setting. The two classes of rich properties that we consider are data structure comprehensions and heap reachability properties. An additional goal of the thesis is to develop techniques for automated verification debugging, aiding the programmer in authoring formal specifications and verified programs. Our first contribution is a technique for reasoning about the class of (higher-order, compositional) comprehensive properties. These properties summarize data structures containing potentially unbounded (and statically unknown) object sets via a finite number of values. Our encoding reduces comprehensions to first-order logic by modeling them as uninterpreted functions and leveraging native features of separation logic, most notably, the iterated separating conjunction connective. We develop a first-order axiomatization of these functions, automating framing and the lemmas required for SMT-based verification of characteristic benchmark programs. Our technique supports comprehensions over data structures regardless of how their objects are accessed and ordered, e.g., general heap graphs in addition to index-based array structures. Our second contribution is a technique for reasoning about the class of (non-compositional) heap reachability properties. These properties express the existence or the absence of directed paths connecting dynamically interlinked heap objects. For each method, we specify reachability only locally within the fragment of the heap on which the method operates. We identify relative convexity, a novel relation between the heap fragments of a callee and its client, which enables (first-order) reachability framing, i.e., propagating reachability properties from the heap fragment of a callee to the larger heap fragment of its client, enabling precise, modular reasoning. Our technique supports practically important data structures, namely, acyclic graphs with a bounded outdegree and (potentially cyclic) graphs with at most one path (modulo cycles) between each pair of nodes. Our third contribution is a technique for generating counterexample heap reachability models for verification debugging. We propose a general procedure for extracting heap models from partial SMT models. We then extend this procedure to extract (state-dependent) local heap reachability relations. To refer to relevant program states in a heap model, we employ lightweight instrumentation of the source program. Our technique is agnostic to the verifier implementation, supporting symbolic execution and verification condition generation with only minor adaptations. Our algorithm extracts first-class heap reachability relations needed for specifying complex heap configurations, e.g., acyclic or disjoint structures. We automatically visualize the output heap reachability models and demonstrate the practicality of our technique in two scenarios: debugging a failed verification and inspecting a verified heap-transforming program
    • …
    corecore