Keywords

These keywords were added by machine and not by the authors. This process is experimental and the keywords may be updated as the learning algorithm improves.

1 Verification Approach

Ultimate Taipan (or Taipan for brevity) is a software model checker which combines trace abstraction [9, 10] and abstract interpretation [5]. The algorithm of Taipan  [8] iteratively refines an abstraction of a input program by analyzing counterexamples (cf. CEGAR [4]).

The initial abstraction of the program is an automaton with the same graph structure as the program’s control flow graph, where program locations are states, transitions are labeled with program statements, and error locations are accepting. Thus, the language of the automaton consists of all traces, i.e., sequences of statements, that, if executable, lead to an error. In each iteration, the algorithm chooses a trace from the language of the current automaton and constructs a path program from it. A path program is a projection of the (abstraction of the) program to the trace. The algorithm then uses abstract interpretation to compute fixpoints for the path program. If the fixpoints of the path program are sufficient to prove correctness, i.e., the error location is unreachable, at least the chosen trace and all other traces that are covered by the path program are infeasible. The computed fixpoints constitute a proof of correctness for the path program and can be represented as a set of state assertions. From this set of state assertions, the abstraction is refined by constructing a new automaton whose language only consists of infeasible traces and then subtracting it from the current abstraction using an automata-theoretic difference operation. If abstract interpretation was unable to prove correctness of the path program, the algorithm obtains a proof of infeasibility of the trace using either interpolating SMT solvers or a combination of unsatisfiable cores and strongest post or weakest pre [6]. If the currently analyzed trace is feasible, the trace represents a program execution that can reach the error. If the current automaton becomes empty after a difference operation, all potential error traces have been proven to be infeasible.

Fig. 1.
figure 1

Example program.

Dynamic Block Encoding. Large block encoding [1] is a technique to reduce the number of locations in a control flow graph. As Taipan relies on trace abstraction, the number of locations determines the performance of the automata operations, which impact the overall performance significantly. It is therefore beneficial to use a strong block encoding that removes as many locations as possible. Unfortunately, the resulting transitions can lead to a loss of precision during the application of an abstract post operator. Consider the example program and its control flow graph with different block encodings shown in Fig. 1. Each control flow graph consists of a set of program locations \( LOC \), an initial location (\(\ell _3\) in Fig. 1), a set of error locations (\(\{\ell _6\}\) in Fig. 1), and a transition relation \(\rightarrow \,\subseteq LOC \times TF \times LOC \) which defines the transitions between the locations and labels each transition with a transition formula from the set of transition formulas \( TF \). Transition formulas encode the semantics of the program as first-order logic formulas over various SMT theories. In Ultimate, a transition formula \(\psi \) is a tuple \((\varphi , IN , OUT , AUX , pv )\) where \(\varphi \) is a closed formula over the three disjoined sets of input (\( IN \)), output (\( OUT \)), and auxiliary (\( AUX \)) variables, and \( pv : IN \cup OUT \rightarrow \mathcal {V}\) is an injective function that maps variables occurring in \(\varphi \) to program variables. We write output variables as primed variables and input variables as unprimed variables.

Taipan computes a fixpoint for each location of a control flow graph by (repeatedly) applying an abstract post operator \( post ^{\#}\) to these transition formulas. To this end, an abstract domain \(\mathcal {D} = (A, \alpha , \gamma , \sqcup , \sqcap , \nabla , post ^{\#})\) is used, where \(A \) is a complete lattice representing all possible abstract states containing the designated abstract states \(\top \) and \(\bot \), \(\alpha \) is an abstraction function, \(\gamma \) is a concretization function, \(\sqcup \) is a join operator, \(\sqcap \) is a meet operator, \(\nabla \) is a widening operator, and \( post ^{\#}: A \times TF \rightarrow A \) is an abstract transformer which computes an abstract post state \(\sigma '\) from a given abstract pre-state \(\sigma \) and a transition formula \(\psi \). Taipan uses a combination of octagons [11] and sets of divisibility congruences [7] as abstract domain, but for brevity we explain the example using intervals.

Table 1. Application of \( post ^{\#}\) for transition formulas from Fig. 1.

In rows 1 to 3 of Table 1, we apply \( post ^{\#}\) of the interval domain in sequence to each of the transition formulas from Fig. 1b. In rows 4a and 4b we apply the same operator to the only transition formula of Fig. 1c, but process the conjunction in different orders. Although the logical \(\wedge \)-operator is commutative, the result differs. This is due to different ways of computing the abstract post state. We can express \( post ^{\#} (\sigma , A \wedge B) = \sigma '\) either as \( post ^{\#} (\sigma , A) \sqcap post ^{\#} (\sigma , B)\), as \( post ^{\#} ( post ^{\#} (\sigma , A), B)\), or as \( post ^{\#} ( post ^{\#} (\sigma , B), A)\). The interval domain cannot express the equality relation between two variables (i.e., the conjunct \(b' = a'\)), therefore, the first way will compute \( post ^{\#} (\{a:\top , b:\top \}, b' = a') = \{a:\top , b:\top \}\), effectively rendering the constraint useless. The second and third way may succeed, depending on the ordering of conjuncts. In general, the ordering is important, but in our example, it does not matter as long as \(b' = a'\) is not first.

In Taipan, we solve this problem by introducing the notion of expressibility to an abstract domain. We augment each abstract domain with an expressibility predicate \( ex \) which decides for each non-logical symbol of a transition formula (i.e., each relation, function application, variable, and constant) whether it can be represented in the domain. For example, the interval domain can represent all relations that contain at most one variable, while octagons can represent all relations of the form \(\pm x \pm y \le c\). We then apply \( post ^{\#}\) on conjuncts of a transition formula in an order induced by \( ex \), thus effectively choosing a new dynamic block encoding. For \( post ^{\#} (\sigma ,\varphi )\), our algorithm computes \(\sigma '\) by first converting the formula \(\varphi \) to DNF s.t. \(\varphi = \varphi _0 \vee \varphi _1 \vee \ldots \vee \varphi _n\). For each disjunct \(\varphi _i = \varphi _i^0 \wedge \varphi _i^1 \wedge \ldots \wedge \varphi _i^m\), we compute \( post ^{\#} (\sigma ,\varphi _i) = \sigma _i'\) as follows:

  1. 1.

    Partition the conjuncts in two classes. The first class contains conjuncts for which \( ex \) is true, the second for which \( ex \) is false.

  2. 2.

    Compute the abstract post for the conjunction of all expressible conjuncts first: \(\bigsqcap _{ ex (\varphi _i^k)} post ^{\#} (\sigma , \varphi _i^k) = \sigma ''\).

  3. 3.

    Compute the abstract post for all non-expressible conjuncts successively using the post state of the k-th application as pre-state of the \(k+1\)-th application, and the post state of the last application as final result \(\sigma _i'\) for the disjunct \(\varphi _i\): \( post ^{\#} _{\lnot ex (\varphi _i^k)}(\sigma _k, \varphi _i^k) = \sigma _{k+1}\).

The result for \( post ^{\#} (\sigma ,\psi )\) is then \(\bigsqcup _{i=0}^{n} \sigma _i' = \sigma '\).

2 Project, Setup and Configuration

Taipan is a part of the open-soure program analysis framework UltimateFootnote 1, written in Java, licensed under LGPLv3Footnote 2, and open sourceFootnote 3. The Taipan competition submission is available as a zip archiveFootnote 4. It requires a current Java installation (\(\ge \)JRE 1.8) and a working Python 2.7 installation. The submission contains an executable version of Taipan for Linux platforms, the binaries of the required SMT solvers Z3Footnote 5, CVC4Footnote 6, and MathsatFootnote 7, as well as a Python script, Ultimate.py, which maps the SV-COMP interface to Ultimate’s command line interface and selects the correct settings and the correct toolchain. In SV-COMP, Taipan is invoked through Ultimate.py with

./Ultimate.py –spec prop.prp –file input.c –architecture 32bit|64bit –full-output

where prop.prp is the SV-COMP property file, input.c is the C file that should be analyzed, 32bit or 64bit is the architecture of the input file, and –full-output enables writing all output instead of just the status of the property to stdout. The complete output of Taipan is also written to the file Ultimate.log. Depending on the status of the property, a violation [3] or correctness [2] witness may be written to the file witness.graphml.

The benchmarking tool BenchExecFootnote 8 supports Taipan through the tool-info module ultimatetaipan.py. Taipan participates in all categories, as specified by its SV-COMP benchmark definitionFootnote 9 file utaipan.xml.