PhD Thesis: Abstract Execution
Table of Contents
Abstract
Abstract programs contain schematic placeholders representing potentially infinitely many concrete programs. They naturally occur in multiple areas of computer science concerned with correctness: rule-based compilation and optimization, code refactoring and other source-to-source transformations, program synthesis, Correctness-by-Construction, and more. Mechanized correctness arguments about abstract programs are frequently conducted in interactive environments. While this permits expressing arbitrary properties quantifying over programs, substantial effort has to be invested to prove them manually by writing proof scripts. Existing approaches to proving abstract program properties automatically, on the other hand, lack expressiveness. Frequently, they only support placeholders representing all possible instantiations; in some cases, minor refinements are supported.
We implemented AE by extending the program verifier KeY. Specifically for relational verification of abstract Java programs, we developed REFINITY, a graphical KeY frontend. We used REFINITY it in our signature application of AE: to model well-known statement-level refactoring techniques and prove their conditional safety. Several yet undocumented behavioral preconditions for safe refactorings originated in this case study, which is one of very few attempts to statically prove behavioral correctness of statement-level refactorings, and the only one to cover them to that extent.
AE extends Symbolic Execution (SE) for abstract programs. As a foundational contribution, we propose a general framework for SE based on the semantics of symbolic states. It natively integrates state merging by supporting m-to-n transitions. We define two orthogonal correctness notions, exhaustiveness and precision, and formally prove their relation to program proving and bug detection.
Finally, we introduce Modal Trace Logic (MTL), a trace-based logic to represent a variety of different program verification tasks, especially for relational verification. It is a “plug-in” logic which can be integrated on-demand with formal languages that have a trace semantics. The core of MTL is the trace modality, which allows expressing that a specification approximates an implementation after a trace abstraction step. We demonstrate the versatility of this approach by formalizing concrete verification tasks in MTL, ranging from functional verification over program synthesis to program evolution. To reason about MTL problems, we translate them to symbolic traces. We suggest Symbolic Trace Logic (STL), which comes with a sequent calculus to prove symbolic trace inclusions. This requires checking symbolic states for subsumption; to that end, we provide two generally useful notions of symbolic state subsumption. This framework relates as follows to the other parts of this thesis: We use the language of abstract programs to express synthesis and compilation, which connects MTL to AE. Moreover, symbolic states of STL are based on our framework for SE.
Errata
This section lists possible errata discovered in my PhD thesis after publication as well as additional remarks. I will update it whenever something noteworthy is discovered.
Sect. 3.1, Defn. 3.4: Labeled Symbolic Execution State
The definition is correct; anyway, I want to show an equivalent one more precisely capturing the intuition of the weakest precondition semantics of labeled SESs:
Definition 3.4 (Labeled Symbolic Execution State). We write $s^\varphi$ for the Labeled Symbolic Execution State $s$ with postcondition $\varphi$. Its semantics $\mathit{val}(K,\sigma|s^\varphi)$ is defined s.t. for all formulas $\psi$, $\mathit{val}(K,\sigma|\psi)=\mathit{tt}$ implies $\mathit{val}(K,\sigma|s^\varphi)=\mathit{tt}$ if, and only if, it holds that $K,\sigma\models\psi$ and for all $\sigma'\in\mathit{concr}_K,$ $K,\sigma'\models\varphi$.