Synthesising Interprocedural Bit-Precise Termination Proofs

Hong-Yi Chen, Cristina David, Daniel Kroening, Peter Schrammel and Bjorn¨ Wachter Department of , University of Oxford, fi[email protected]

Abstract—Proving program termination is key to guaranteeing does terminate with mathematical integers, but does not ter- absence of undesirable behaviour, such as hanging programs and minate with machine integers if n equals the largest unsigned even security vulnerabilities such as denial-of-service attacks. To integer. On the other hand, the following code: make termination checks scale to large systems, interprocedural termination analysis seems essential, which is a largely unex- void foo2 ( unsigned x ) { while ( x>=10) x ++; } plored area of research in termination analysis, where most effort has focussed on difficult single-procedure problems. We present does not terminate with mathematical integers, but terminates a modular termination analysis for programs using template- with machine integers because unsigned machine integers based interprocedural summarisation. Our analysis combines a wrap around. context-sensitive, over-approximating forward analysis with the A second challenge is to make termination analysis scale to inference of under-approximating preconditions for termination. Bit-precise termination arguments are synthesised over lexico- larger programs. The yearly Software Verification Competition graphic linear ranking function templates. Our experimental (SV-COMP) [6] includes a division in termination analysis, results show that our tool 2LS outperforms state-of-the-art alter- which reflects a representative picture of the state-of-the-art. natives, and demonstrate the clear advantage of interprocedural The SV-COMP’15 termination benchmarks contain challeng- reasoning over monolithic analysis in terms of efficiency, while ing termination problems on smaller programs with at most retaining comparable precision. 453 instructions (average 53), contained at most 7 functions I.INTRODUCTION (average 3), and 4 loops (average 1). In this paper, we present a technique that we have suc- Termination bugs can compromise safety-critical software cessfully run on programs that are one magnitude larger, systems by making them irresponsive, e.g., termination bugs containing up to 5000 instructions. Larger instances require can be exploited in denial-of-service attacks [1]. Termination different algorithmic techniques to scale, e.g., modular inter- guarantees are therefore instrumental for software reliability. procedural analysis rather than monolithic analysis. This poses Termination provers, static analysis tools that aim to construct several conceptual and practical challenges that do not arise in a termination proof for a given input program, have made monolithic termination analysers. For example, when proving tremendous progress. They enable automatic proofs for com- termination of a program, a possible approach is to try to plex loops that may require linear lexicographic (e.g. [2], [3]) prove that all procedures in the program terminate universally, or non-linear termination arguments (e.g. [4]) in a completely i.e., in any possible calling context. However, this criterion is automatic way. However, there remain major practical chal- too optimistic, as termination of individual procedures often lenges in analysing real-world code. depends on the calling context, i.e., procedures terminate First of all, as observed by [5], most approaches in the conditionally only in specific calling contexts. literature are specialised to linear arithmetic over unbounded Hence, an interprocedural analysis strategy is to verify uni- mathematical integers. Although, unbounded arithmetic may versal program termination in a top-down manner by proving reflect the intuitively-expected program behaviour, the pro- termination of each procedure relative to its calling contexts, gram actually executes over bounded machine integers. The and propagating upwards which calling contexts guarantee semantics of C allows unsigned integers to wrap around when termination of the procedure. It is too difficult to determine they over/underflow. Hence, arithmetic on k-bit-wide unsigned these contexts precisely; analysers thus compute preconditions k integers must be performed modulo-2 . According to the C for termination. A sufficient precondition identifies those pre- standards, over/underflows of signed integers are undefined states in which the procedure will definitely terminate, and is behaviour, but practically also wrap around on most architec- thus suitable for proving termination. By contrast, a necessary tures. Thus, accurate termination analysis requires a bit-precise precondition identifies the pre-states in which the procedure analysis of program semantics. Tools must be configurable may terminate. Its negation are those states in which the with architectural specifications such as the width of data procedure will not terminate, which is useful for proving types and endianness. The following examples illustrate that nontermination. termination behaviour on machine integers can be completely In this paper we focus on the computation of sufficient pre- different than on mathematical integers. For example, the conditions. Preconditions enable information reuse, and thus following code: scalability, as it is frequently possible to avoid repeated anal- void foo1 ( unsigned n ) { f o r ( unsigned x =0; x<=n ; x + + ) ; } ysis of parts of the code base, e.g. libraries whose procedures are called multiple times or did not undergo modifications 1 unsigned f ( unsigned z ) { 1 unsigned h ( unsigned y ) { between successive analysis runs. 2 unsigned w=0; 2 unsigned x ; 3 i f ( z>0) w=h ( z ) ; 3 f o r ( x =0; x<10; x+=y ) ; 4 return w; 4 return x ; Contributions: 5 } 5 } 1) We propose an for interprocedural termination Fig. 1. Example. analysis. The approach is based on a template-based static 0 0 0 0 0 0 Initf ((z), (w , z , g )) ≡ (w =0 ∧ z =z ∧ g ) analysis using SAT solving. It combines context-sensitive, 0 0 0 Transf ((w, z, g), (w , z , g )) ≡ (g ∧ h0((z), (w1))∧ 0 0 summary-based interprocedural analysis with the infer- w =(z>0?w1:w) ∧ ¬g ) ence of preconditions for termination based on template Outf ((w, z, g), (rf )) ≡ (rf =w) ∧ ¬g 0 0 0 0 abstractions. We focus on non-recursive programs, which Inith((y), (x , y )) ≡ (x =0 ∧ y =y) 0 0 0 0 cover a large portion of software written, especially in Transh((x, y), (x , y )) ≡ (x =x+y ∧ x<10 ∧ y =y) domains such as embedded systems. Outh((x, y), (rh)) ≡ (rh=x ∧ ¬(x<10)) 2) We provide an implementation of the approach in 2LS, a Fig. 2. Encoding of Example 1. static analysis tool for C programs. Our instantiation of the algorithm uses template polyhedra and lexicographic, Moreover, we write x and x with the understanding that the linear ranking functions templates. The analysis is bit- former is a vector, whereas the latter is a scalar. precise and purely relies on SAT-solving techniques. Each call to a procedure h at call site i in a procedure f p in p out 3) We report the results of an experimental evaluation on is modeled by a placeholder predicate hi(x i, x i) 597 procedural SV-COMP benchmarks with in total 1.6 occurring in the formula Transf for f. The placeholder pred- million lines of code that demonstrates the scalability and icate ranges over intermediate variables representing its actual p in p out applicability of the approach to programs with thousands input and output parameters x i and x i, respectively. of lines of code. Placeholder predicates evaluate to true, which corresponds to havocking procedure calls. In procedure f in Fig. 2, the II.PRELIMINARIES placeholder for the procedure call to h is h0((z), (w1)) with the actual input and output parameters z and w1, respectively. In this section, we introduce basic notions of interprocedural A full description of the program encoding is given in the and termination analysis. extended version of our paper [7]. Program model and notation. We assume that programs Basic concepts. Moving on to interprocedural analysis, we 1 are given in terms of acyclic call graphs, where individual introduce formal notation for the basic concepts below: procedures f are given in terms of symbolic input/output transition systems. Formally, the input/output transition system Definition 1 (Invariants, Summaries, Calling Contexts). For a procedure given by (Init, Trans, Out) we define: of a procedure f is a triple (Init f , Transf , Out f ), where 0 Transf (x, x ) is the transition relation; the input relation • An invariant is a predicate Inv such that: in Init f (x , x) defines the initial states of the transition sys- in 0 in in ∀x , x, x : Init(x , x) =⇒ Inv(x) tem and relates them to the inputs x ; the output relation 0 0 out ∧ Inv(x) ∧ Trans(x, x ) =⇒ Inv(x ) Out f (x, x ) connects the transition system to the outputs xout of the procedure. Inputs are procedure parameters, global • Given an invariant Inv, a summary is a predicate Sum variables, and memory objects that are read by f. Outputs such that: are return values, and potential side effects such as global ∀xin, x, x0, xout : Init(xin, x) ∧ Inv(x0) ∧ Out(x0, xout) variables and memory objects written by f. Internal states x =⇒ Sum(xin, xout) are commonly the values of variables at the loop heads in f. These relations are given as first-order logic formulae • Given an invariant Inv, the calling context for a pro- resulting from the logical encoding of the program semantics. cedure call h at call site i in the given procedure is a predicate CallCtx such that Fig. 2 shows the encoding of the two procedures in Fig. 1 into hi 2 in 0 p in p out such formulae. The inputs x of f are (z) and the outputs ∀x, x , x i, x i : xout consist of the return value denoted (r ). The transition 0 p in p out f Inv(x) ∧ Trans(x, x ) =⇒ CallCtx hi (x i, x i) relation of h encodes the loop over the internal state variables (x, y). We may need to introduce Boolean variables g to model These concepts have the following roles: Invariants abstract the control flow, as shown in f. Multiple and nested loops can the behaviour of loops. Summaries abstract the behaviour of be similarly encoded in Trans. called procedures; they are used to strengthen the placeholder predicates. Calling contexts abstract the caller’s behaviour Note that we view these formulae as predicates, e.g. w.r.t. the procedure being called. When analysing the callee, Trans(x, x0), with given parameters x, x0, and mean the the calling contexts are used to constrain its inputs and outputs. substitution Trans[a/x, b/x0] when we write Trans(a, b). In Sec. III we will illustrate these notions on the program in Fig. 1. 1 We consider non-recursive programs with multiple procedures. 2c?a:b is the conditional operator, which returns a if c evaluates to true, Since we want to reason about termination, we need the and b otherwise. notions of ranking functions and preconditions for termination. Definition 2 (Ranking function). A ranking function for a Algorithm 1: analyze o o u procedure (Init, Trans, Out) with invariant Inv is a function 1 global Sums , Invs , Preconds ; o r from the set of program states to a well-founded domain 2 function analyzeForward(f, CallCtx f ) such that ∀x, x0 : Inv(x) ∧ Trans(x, x0) =⇒ r(x) > r(x0). 3 foreach procedure call h in f do o o o 4 CallCtx h = compCallCtx (f, CallCtx f , h); 0 o o We denote by RR(x, x ) the constraints that guarantee that 5 if needToReAnalyze (h, CallCtx h) then o r is a ranking function. The existence of a ranking function 6 analyzeForward(h, CallCtx h); for a procedure guarantees its universal termination. o o o o o 7 join ((Sums [f], Invs [f]), compInvSum (f, CallCtx f )) The weakest termination precondition for a procedure de- u 8 function analyzeBackward(f, CallCtx f ) scribes the inputs for which it terminates. If it is true, the u 9 termConds = CallCtx f ; procedure terminates universally; if it is false, then it does 10 foreach procedure call h in f do u u u not terminate for any input. Since the weakest precondition 11 CallCtx h = compCallCtx (f, CallCtx f , h); u u is intractable to compute or even uncomputable, we under- 12 if needToReAnalyze (h, CallCtx h) then u approximate the precondition. A sufficient precondition for 13 analyzeBackward(h, CallCtx h); u termination guarantees that the program terminates for all xin 14 termConds ← termConds ∧ Preconds [h]; that satisfy it. joinu(Precondsu[f], 15 compPrecondTerm(f, Invso[f], termConds); Definition 3 (Precondition for termination). Given a proce- 16 function analyze(f ) dure (Init, Trans, Out), a sufficient precondition for termina- entry 17 analyzeForward(fentry , true); tion is a predicate Precond such that 18 analyzeBackward(fentry , true); u 19 Preconds [f ] ∃RR, Inv : ∀xin, x, x0 : return entry ; Precond(xin) ∧ Init(xin, x) =⇒ Inv(x) ∧ Inv(x) ∧ Trans(x, x0) =⇒ Inv(x0) ∧ RR(x, x0) procedure call in f an under-approximating calling context Note that false is always a trivial model for Precond, but u not a very useful one. CallCtx (using under-approximate summaries, as described in Sec. IV), and recurs only if necessary (Line 12). Finally, we III.OVERVIEW OF THE APPROACH compute the under-approximating precondition for termination In this section, we introduce the architecture of our interpro- (Line 15). This precondition is inferred w.r.t. the termination cedural termination analysis. Our analysis combines, in a non- conditions that have been collected: the backward calling trivial synergistic way, the inference of invariants, summaries, context (Line 9), the preconditions for termination of the calling contexts, termination arguments, and preconditions, callees (Line 14), and the termination arguments for f itself which have a concise characterisation in second-order logic (see Sec. IV). Note that superscripts o and u in predicate (see Definitions 1, and 3). At the lowest level our approach symbols indicate over- and underapproximation, respectively. relies on a solver backend for second-order problems, which Challenges. Our algorithm uses over- and under- is described in Sec. V. approximation in a systematic way in order to address To see how the different analysis components fit together, the challenging problem of finding meaningful preconditions we now go through the pseudo-code of our termination by a context-sensitive interprocedural termination analysis. analyser (Algorithm 1). Function analyze is given the entry • The precondition in Definition 3 admits the trivial so- procedure fentry of the program as argument and proceeds in lution false for Precond. How do we find a good two analysis phases. candidate? To this end, we “bootstrap” the process with Phase one is an over-approximate forward analysis, given a candidate precondition: a single value of xin, for in subroutine analyzeForward, which recursively descends which we compute a termination argument. The key into the call graph from the entry point fentry . Subroutine observation is that the resulting termination argument is analyzeForward infers for each procedure call in f an over- typically more general, i.e., it shows termination for many approximating calling context CallCtx o, using procedure sum- further entry states. The more general precondition is then maries and other previously-computed information. Before computed by precondition inference w.r.t. the termination analyzing a callee, the analysis checks if the callee has already argument. been analysed and, whether the stored summary can be re- • A second challenge is to compute under-approximations. used, i.e., if it is compatible with the new calling context Obviously, the predicates in the definitions in Sec. II can CallCtx o. Finally, once summaries for all callees are available, be over-approximated by using abstract domains such as the analysis infers loop invariants and a summary for f itself, intervals. However, there are only few methods for under- which are stored for later re-use by means of a join operator. approximating analysis. In this work, we use a method The second phase is an under-approximate backward anal- similar to [8] to obtain under-approximating precondi- ysis, subroutine analyzeBackward, which infers termination tions w.r.t. property p: we infer an over-approximating preconditions. Again, we recursively descend into the call precondition w.r.t. ¬p and negate the result. In our case, graph. Analogous to the forward analysis, we infer for each p is the termination condition termConds. Example 1. We illustrate the algorithm on the simple example Algorithm 2: analyze for universal termination o o given as Fig. 1 with the encoding in Fig. 2. f calls a procedure 1 global Sums , Invs , termStatus; o h. Procedure h terminates if and only if its argument y is 2 function analyzeForward(f, CallCtx f ) non-zero, i.e., procedure f only terminates conditionally. The 3 foreach procedure call h in f do o o o h z>0 4 CallCtx h = compCallCtx (f, CallCtx f , h); call of is guarded by the condition , which guarantees o o 5 if needToReAnalyze (h, CallCtx h) then universal termination of procedure f. o 6 analyzeForward(h, CallCtx ); Let us assume that unsigned integers are 32 bits wide, and h o o o o o we use an interval abstract domain for invariant, summary 7 join ((Sums [f], Invs [f]), compInvSum (f, CallCtx f )) 0 and precondition inference, but the abstract domain with the 8 function analyzeBackward (f) elements {true, false} for computing calling contexts, i.e., we 9 termStatus[f] = compTermArg(f); can prove that calls are unreachable. We use M := 232−1. 10 foreach procedure call h in f do u o 11 if needToReAnalyze (h, CallCtx h) then Our algorithm proceeds as follows. The first phase is 0 analyzeForward, which starts from the entry procedure f. 12 analyzeBackward (h); 13 join(termStatus[f], termStatus[h]); By descending into the call graph, we must compute an over- approximating calling context CallCtx o for procedure h for h 14 function analyze(fentry ) which no calling context has been computed before. This 15 analyzeForward(fentry , true); 0 calling context is true. Hence, we recursively analyse h. Given 16 analyzeBackward (fentry ); that h does not contain any procedure calls, we compute the 17 return termStatus[fentry ]; o over-approximating summary Sumh = (0≤y≤M ∧0≤rh≤M) o and invariant Inv h = (0≤x≤M ∧ 0≤y≤M). Now, this information can be used in order to compute Sumo = f Note that this is not a formalisation exercise, but these are (0≤z≤M ∧ 0≤r ≤M) and invariant Inv o = true for the f f precisely the formulae solved by our synthesis backend, which entry procedure f. is described in Section V. The backwards analysis starts again from the entry proce- dure f. It computes an under-approximating calling context A. Universal Termination CallCtx u for procedure h, which is true, before descending h For didactical purposes, we start with a simplification of into the call graph. It then computes an under-approximating Algorithm 1 that is able to show universal termination (see precondition for termination Precond u = (1≤y≤M) or, more h Algorithm 2). This variant reduces the backward analysis to precisely, an under-approximating summary whose projection a call to compTermArg and propagating back the qualitative onto the input variables of h is the precondition Precond u. h result obtained: terminating, potentially non-terminating, or By applying this summary at the call site of h in f, we can non-terminating. now compute the precondition for termination Precond u = f This section states the constraints that are solved to compute (0≤z≤M) of f, which proves universal termination of f. the outcome of the functions underlined in Algorithm 2 and We illustrate the effect of the choice of the abstract domain establish its soundness: on the analysis of the example program. Assume we replace o • compCallCtx (Def. 4) the {true, false} domain by the interval domain. In this o o • compInvSum (Def. 5) case, analyzeForward computes CallCtx h = (1≤z≤M ∧ • compTermArg (Lemma 3) 0≤w1≤M). The calling context is computed over the actual parameters z and w1. It is renamed to the formal parameters y o o and rh (the return value) when CallCtx h is used for constrain- Definition 4 (compCallCtx ). A forward calling context ing the pre/postconditions in the analysis of h. Subsequently, CallCtx o for h in procedure f in calling context CallCtx o hi i f analyzeBackward computes the precondition for termination is a satisfiability witness of the following formula: of h using the union of all calling contexts in the program. ∃CallCtx o , Inv o : ∀xin, x, x0, xout, xp in , xp out : hi f i i Since h terminates unconditionally in these calling contexts, o in out o u CallCtx f (x , x ) ∧ Summsf =⇒ we trivially obtain Precond h = (1≤y≤M), which in turn in o  f Init f (x , x) =⇒ Inv f (x) proves universal termination of . o 0 ∧ Inv f (x) ∧ Transf (x, x ) IV. INTERPROCEDURAL TERMINATION ANALYSIS =⇒ Inv o (x0) ∧ (g ⇒ CallCtx o (xp in , xp out ) f hi hi i i We can view Alg. 1 as solving a series of formulae with Summso = V g =⇒ f calls hj in f hj in second-order predicate logic with existentially quantified o p in p out predicates, for which we are seeking satisfiability witnesses.3 Sums [h](x j, x j) where g is the guard condition of procedure call h in In this section, we state the constraints we solve, including all hj j f capturing the branch conditions from conditionals. For the side constraints arising from the interprocedural analysis. example, gh0 of the procedure call to h in f in Fig. 1 is o 3 To be precise, we are not only looking for witness predicates but (good z > 0. Sums [h] is the currently available summary for h approximations of) weakest or strongest predicates. Finding such biased (cf. global variables in Alg. 1). witnesses is a feature of our synthesis . CallCtx o is over-approximating. Since Def. 4 and Def. 5 are interdependent, we can Lemma 1. hi Remark 1. compute them iteratively until a fixed point is reached in order Proof sketch. CallCtx o when f is the entry-point procedure f to improve the precision of calling contexts, invariants and is true; also, the summaries Sumo are initially assumed to hj summaries. However, for efficiency reasons, we perform only be true, i.e. over-approximating. Hence, given that CallCtx o f the first iteration of this (greatest) fixed point computation. Summso CallCtx o and f are over-approximating, hi is over- approximating by the soundness of the synthesis (see Thm. 3 Lemma 3 (compTermArg). A procedure f with forward o in Sec. V). invariants Inv f terminates if there is a termination argument RRf : Example 2. Let us consider procedure f in Fig. 1. f is the ∃RR : ∀x, x0 : entry procedure, hence we have CallCtx o ((z), (r )) = true f f f Inv o (x) ∧ Trans (x, x0) ∧ Summso ∧ Assertions (x) (= (0≤z≤M ∧ 0≤r ≤M) where M := 232−1 when using f f f f f =⇒ RR (x, x0) the interval abstract domain for 32 bit integers). Then, we f instantiate Def. 4 (for procedure f) to compute CallCtx o . We Assertions in this formula correspond to assert() state- h0 assume that we have not yet computed a summary for h, thus, ments in the code. They can be assumed to hold because o Sumh is true. Remember that the placeholder h0((z), (w1)) assertion-violating traces terminate. Over-approximating for- evaluates to true. ward information may lead to inclusion of spurious non- o o 0 0 0 terminating traces. For that reason, we might not find a ∃CallCtx , Inv : ∀z, w1, w, w , z , g, g , rf : h0 f termination argument although the procedure is terminating. 0≤z≤M ∧ 0≤rf ≤M ∧ (z>0 =⇒ true) =⇒ 0 o  As we essentially under-approximate the set of terminating w=0 ∧ z =z ∧ g =⇒ Inv f ((w, z, g)) o procedures, we will not give false positives. Regarding the ∧ Inv f ((w, z, g))∧ 0 0 0 solving algorithm for this formula, we refer to Sec. V. g ∧ h0((z), (w1)) ∧ w =(z>0?w1:w) ∧ z =z ∧ ¬g =⇒ Inv o ((w0, z0, g0)) ∧ (z>0 ⇒ CallCtx o ((z), (w )) Example 4. Let us consider function h in Fig. 1. Assume we f hi 1 A solution is Inv o = true, and CallCtx o ((z), (w )) = have the invariant 0≤x≤M ∧1≤y≤M. Thus, we have to solve f h0 1 0 0 (1≤z≤M ∧ 0≤w1≤M). ∃RRh : 0≤x≤M ∧ 1≤y≤M ∧ x =x+y ∧ x<10 ∧ y =y∧ 0 0 o o true ∧ true =⇒ RRh((x, y), (x , y )) Definition 5 (compInvSum ). A forward summary Sumf and o o When using a linear ranking function template c · x + c · y, invariants Inv f for procedure f in calling context CallCtx f 1 2 0 are satisfiability witnesses of the following formula: we obtain as solution, for example, RRh = (−x> − x ). o o in 0 00 out ∃Sumf , Inv f : ∀x , x, x , x , x : If there is no trace from procedure entry to exit, then we can o in out o CallCtx f (x , x ) ∧ Summsf =⇒ prove non-termination, even when using over-approximations: in o 00 00 out Init f (x , x) ∧ Inv f (x ) ∧ Out f (x , x ) o o in out  Lemma 4 (line 7 of analyze). A procedure f in forward =⇒ Inv f (x) ∧ Sumf (x , x ) o o o 0 o 0  calling context CallCtx f , and forward invariants Inv f never ∧ Inv f (x) ∧ Transf (x, x ) =⇒ Inv f (x ) o terminates if its summary Sumf is false. Sumo and Inv o are over-approximating. Lemma 2. f f Termination information is then propagated in the (acyclic) o Proof sketch. By Lemma 1, CallCtx f is over-approximating. call graph (join in line 13 in Algorithm 2): o Also, the summaries Sumsf are initially assumed to be o Proposition 1. A procedure f is declared true, i.e. over-approximating. Hence, given that CallCtx f and o o o (1) non-terminating if it is non-terminating by Lemma 4. Summsf are over-approximating, Sumf and Inv f are over- (2) terminating if approximating by the soundness of the synthesis (Thm. 3). (a) all its procedure calls hi that are potentially reach- able (i.e. with CallCtx o 6= false) are declared termi- Example 3. Let us consider procedure h in Fig. 1. We have hi o nating, and computed CallCtx ((y), (rh)) = (1≤y≤M ∧ 0≤rh≤M) h0 (b) f itself is terminating according to Lemma 3; (with actual parameters renamed to formal ones). Then, we (3) potentially non-terminating, otherwise. need to obtain witnesses Inv o and Sumo to the satifiability h0 h0 of the instantiation of Def. 5 (for procedure h) as given below. Our implementation is more efficient than Algorithm 2 o o 0 0 00 00 because it avoids computing a termination argument for f if ∃Inv , Sum : ∀y, x, x , y , x , y , rf : h0 h0 one of its callees is potentially non-terminating. 1≤y≤M ∧ 0≤rh≤M ∧ true =⇒ 0 o 00 00 00 00 (x=0 ∧ y =y) ∧ Inv h((x , y )) ∧ (rh=x ∧ ¬(x <10) Theorem 1. If the entry procedure of a program is declared o 0 o  =⇒ Inv h((x, y )) ∧ Sumh((y), (rh)) terminating, then the program terminates universally. If the o 0 0 ∧ Inv h((x, y)) ∧ (x =(x+y ∧ x<10) ∧ y=y ) entry procedure of a program is declared non-terminating, o 0 0  =⇒ Inv h((x , y )) then the program never terminates. A solution is Inv o = (0≤x≤M ∧1≤y≤M) and Sumo = h0 h0 Proof sketch. By induction over the acyclic call graph using (1≤y≤M ∧ 10≤r ≤M), for instance. h Prop. 1. Algorithm 3: compPrecondTerm time, we will assume we have the invariant 0 ≤ x ≤ M (with 32 Input: procedure f with invariant Inv, additional termination M := 2 − 1). We bootstrap by assuming Precond = false conditions termConds and searching for values of y satisfying true ∧¬false ∧x=0∧ Output: precondition Precond 0 ≤ x ≤ M. One possibility is y = 0. We then compute 1 (Precond, p) ← (false, true); in the invariant under the precondition y = 0 and get x = 0. 2 ϕ = Init(x , x) ∧ Inv(x) let ; Obviously, we cannot find a termination argument in this case. 3 while true do in 4 ψ ← p ∧ ¬Precond(x ) ∧ ϕ; Hence, we start over and search for values of y satisfying in 0 5 solve ψ for x , x, x ; y 6= 0 ∧ ¬false ∧ x=0 ∧ 0≤x≤M. This formula is for instance 6 if UNSAT then return Precond; satisfied by y = 1. This time we get the invariant 0≤x≤10 7 else and the ranking function −x. Thus, we have to solve in 8 let χ be a model of ψ; 0 in in 0 9 let Inv = compInv(f, x =χ ); ∃e : P(y, e) ∧ 0≤x≤M ∧ x =x+y ∧ x<10 0 0 10 let RR = compTermArg(f, Inv ); ⇒ ¬(−x> − x ) in in 11 if RR = true then p ← p ∧ (x 6= χ ); 12 else to compute an over-approximating precondition over the 13 let θ = termConds ∧ RR; 0 template P (for details on templates see Section V). In this 14 let Precond = ¬compNecPrecond(f, ¬θ); 0 case, P(y, e) turns out to be y = 0, therefore its negation 15 Precond ← Precond ∨ Precond ; y 6= 0 is the Precond that we get. Finally, we have to check for further precondition candidates, but y 6= 0 ∧ ¬(y 6= 0) ∧ x=0 ∧ 0≤x≤M is obviously UNSAT. Hence, we return the sufficient precondition for termination y 6= 0. B. Preconditions for Termination Before introducing conditional termination, we have to talk about preconditions for termination. If a procedure terminates conditionally like procedure h in C. Conditional Termination Fig. 1 compTermArg (Lemma 3) will not be able to find a satisfying predicate RR. However, we would like to know under which preconditions, i.e. values of y in above example, We now extend the formalisation to Algorithm 1, which the procedure terminates. additionally requires the computation of under-approximating We can state this problem as defined in Def. 3. In Algo- calling contexts and sufficient preconditions for termination rithm 3 we search for Precond, Inv, and RR in an interleaved (procedure compPrecondTerm, see Alg. 3). manner. Note that false is a trivial solution for Precond; we First, compPrecondTerm computes in line 9 an over- o thus have to aim at finding a good under-approximation of the approximating invariant Inv fp entailed by the candidate pre- o maximal solution (weakest precondition) for Precond. condition. Inv fp is computed through Def. 5 by conjoining We bootstrap the process by assuming Precond = false the candidate precondition to the antecedent. Then, line 10 in in and search for values of x (Line 5). If such a value χ computes the corresponding termination argument RRf by o o exists, we can compute an invariant under the precondition applying Lemma 3 using Inv fp instead of Inv f . Since the candidate xin = χin (Line 9) and use Lemma 3 to search for termination argument is under-approximating, we are sure that the corresponding termination argument (Line 10). f terminates for this candidate precondition if RRf 6= true. If we fail to find a termination argument (RR = true), Then, in line 14 of compPrecondTerm, we compute under- we block the precondition candidate (Line 11) and restart approximating (sufficient) preconditions for traces satisfying the bootstrapping process. Otherwise, the algorithm returns a the termination argument RR via over-approximating the termination argument RR that is valid for the concrete value traces violating RR. χin of xin. Now we need to find a sufficiently weak Precond for which RR guarantees termination. To this end, we com- Now, we are left to specify the formulae corresponding to pute an over-approximating precondition for those inputs for the following functions: u which we cannot guarantee termination (¬θ in Line 14, which • compCallCtx (Def. 6) includes additional termination conditions coming from the • compNecPrecond (Def. 7) ∼ backward calling context and preconditions of procedure calls, We use the superscript u to indicate negations of under- see Sec. IV-C). The negation of this precondition is an under- approximating information. We compute under-approximating approximation of those inputs for which f terminates. Finally, calling contexts as follows: we add this negated precondition to our Precond (Line 15) before we start over the bootstrapping process to find precon- Definition 6 (compCallCtx u). The backward calling context dition candidates outside the current precondition (¬Precond) CallCtx u for procedure call h in procedure f in backward hi i for which we might be able to guarantee termination. u o calling context CallCtx f and forward invariants Inv f is ∼ Let us consider again function h in Fig. 1. This CallCtx u ≡ ¬CallCtx u , the negation of a satisfiability Example 5. hi hi ∼ witnesses for: with Preconds u = W g =⇒ f calls hj in f hj u p in p out ∼ ∼ ¬Precond [h](x j, x j). ∃CallCtx u , Inv u : ∀xin, x, x0, xp in , xp out , xout : hi f i i u in out o This formula is similar to Def. 5, but w.r.t. backward calling ¬CallCtx f (x , x ) ∧ Inv f (x)∧ ∼ contexts and summaries, and strengthened by the (forward) o u o Summsf ∧ Summsf ∧ Assertionsf (x) =⇒ invariants Inv . We denote the negation of the witnesses found ∼ f ∼ out u  u u Out(x, x ) =⇒ Inv f (x) for the summary and the invariant by Sum ≡ ¬Sum and ∼ f f ∼ u 0 0 u u ∧ Inv f (x ) ∧ Trans(x, x ) Inv ≡ ¬Inv , respectively. ∼ ∼ f f u u p in p out  =⇒ Inv f (x) ∧ (ghi =⇒ CallCtx h (x , x )) u u u i Lemma 6. Precond f , Sumf and Inv f are under- ∼ approximating. with Summs u = V g =⇒ f calls hj in f hj u p in p out Proof sketch. We compute an over-approximation of the ¬Sum [h](x j, x j) negation of the precondition w.r.t. the negation of the Lemma 5. CallCtx u is under-approximating. hi under-approximating termination argument and the nega- Proof sketch. The computation is based on the negation of tion of further under-approximating information (backward the under-approximating calling context of f and the negated calling context, preconditions of procedure calls) — by under-approximating summaries for the function calls in f. By the soundness of the synthesis (see Thm. 3 in Sec. V), Thm. 3, this leads to an over-approximation of the negation this over-approximates the non-terminating traces, and hence under-approximates the terminating ones. Hence, the pre- of the calling context for hi. condition is a sufficient precondition for termination. The ∼ f 0 u u in out Example 6. Let us assume that in procedure in Fig. 1, we term ¬RRf (x, x ) ∨ Precondsf ∨ ¬CallCtx f (x , x ) ∧ u in 0 out have CallCtx f ((z), (rf )) = (11≤rf ≤M), i.e. f is called in Init(x , x) ∧ Out(x , x ) characterises non-terminating a context where a return value of less than 11 would cause states in the invariants of f: for these, either the termination non-termination of the caller. Then, we instantiate Def. 6 argument for f is not satisfied or the precondition for termi- (for procedure f) to compute CallCtx u . We assume that h0 nation of one of the callees does not hold or we are outside we have already computed the over-approximating summary the calling context. Sumo = (1≤z≤M ∧ 10≤w ≤M), but not yet computed an h0 1 u Example 7. We will instantiate Def. 7 for procedure h under-approximating summary for h, thus, Sumh is false. u in Fig. 1, assuming that we have CallCtx ((y), (rh)) = ∼ ∼ h u u 0 0 0 ∃CallCtx , Inv : ∀z, w1, w, w , z , g, g , rf : (y=0 ∨ 11≤rh≤M), as computed in the previous example. h0 f o Inv h = true and h does not have any procedure calls, thus 0≤rf ≤10 ∧ true∧ ∼ ∼ o u u (z>0 ⇒ 1≤z≤M ∧ 10≤w1≤M) ∧ (z>0 ⇒ true) ∧ true =⇒ Summsh = true, Summsh = true, and Precondsh = false. ∼ u  Assume we have the termination argument candidate RRh = rf =w ∧ ¬g =⇒ Inv f ((w, z, g)) ∼ 0 u (−x > −x ). ∧ Inv f ((w, z, g))∧ 0 0 0 The second conjunct in the consequent of the top-level g ∧ h0((z), (w1)) ∧ w =(z>0?w1:w) ∧ z =z ∧ ¬g ∼ ∼ implication is satisfied either for y=0 making ¬RRh true or =⇒ Inv u((w0, z0, g0)) ∧ (z>0 ⇒ CallCtx u ((z), (w )) f hi 1 y≤10 violating the calling context (third disjunct). ∼ ∼ ∼ u u u Hence, a solution is Precond h = (0 ≤ y ≤ 10), A solution is Inv f = true, and CallCtx h = (1≤z≤M ∧ ∼ ∼ u 0 u u 0≤w ≤10), i.e. CallCtx = (z=0 ∨ 11≤w ≤M). Inv h = (0 ≤ x ≤ 19∧0 ≤ y ≤ 10), and Sumh = (0≤y≤10∧ 1 h0 1 0≤rh≤10). I.e. a sufficient precondition for termination is Definition 7 (Line 14 of compPrecondTerm). A precondi- Precond u = (11≤y≤M). u h tion for termination Precond f in backward calling context u o u Theorem 2. A procedure f terminates for all values of xin CallCtx f and with forward invariants Inv f is Precond f ≡ ∼ u u satisfying Precond f . ¬Precond f , i.e. the negation of a satisfiability witness ∼ Precond u for: Proof sketch. By induction over the acyclic call graph using f Lemmae 5 and 6. ∼ ∼ ∼ ∃Precond u , Inv u, Sum u : ∀xin, x, x0, x00, xout : hi f f D. Context-Sensitive Summaries u in out o ¬CallCtx f (x , x ) ∧ Inv f (x)∧ ∼ The key idea of interprocedural analysis is to avoid re- o u Summsf ∧ Summsf ∧ Assertionsf (x) =⇒ analysing procedures that are called multiple times. For that ∼ in 00 u 00 out reason, Algorithm 1 first checks whether it can re-use already Init(x , x ) ∧ Inv f (x ) ∧ Out(x, x ) ∼ ∼ ∼ u u in out u in  computed information. For that purpose, summaries are stored =⇒ Inv f (x) ∧ Sumf (x , x ) ∧ Precond f (x ) o o ∼ as implications CallCtx ⇒ Sum . As the call graph is 0 u u in out o ∧ (¬RRf (x, x ) ∨ Preconds ∨ ¬CallCtx (x , x )∧ CallCtx f f traversed, the possible calling contexts hi for a proce- Init(xin, x) ∧ Out(x0, xout))∧ dure h are collected over the call sites i. NeedToReAnalyzeo ∼ ∼ u 0 0 u  (Line 5 in Alg. 1) checks whether the current calling context Inv f (x ) ∧ Trans(x, x ) =⇒ Inv f (x) o o CallCtx W CallCtx MPLEMENTATION hi is subsumed by calling contexts i hi that VI.I o we have already encountered, and if so, Sums [h] is reused; We have implemented the algorithm in 2LS [17], a static otherwise it needs to be recomputed and joined conjunctively analysis tool for C programs built on the CPROVER frame- with previously inferred summaries. The same considerations work, using MiniSat 2.2.0 as back-end solver. Other SAT and apply to invariants, termination arguments and preconditions. SMT solvers with incremental solving support would also be applicable. Our approach enables us to use a single solver V. TEMPLATE-BASED STATIC ANALYSIS instance per procedure to solve a series of second-order queries In this section, we give a brief overview of our synthesis as required by Alg. 1. This is essential as our synthesis algo- engine, which serves as a backend for our approach (it solves rithms make thousands of solver calls. Architectural settings the formulae in Definitions 4, 5, 7, and 6 (see Sec. IV)). (e.g. bitwidths) can be provided on the command line. Our synthesis engine employs template-based static anal- Discussions about technical issues w.r.t. bit-preciseness and ysis to compute ranking functions, invariants, summaries, the computation of intraprocedural termination arguments can and calling contexts, i.e., implementations of functions be found in the extended version [7]. o o compInvSum and compCallCtx from the second-order con- VII.EXPERIMENTS straints defined in Sec. IV. To be able to effectively solve second-order problems, we reduce them to first-order by We performed experiments to support the following claims: restricting the space of solutions to expressions of the form 1) Interprocedural termination analysis (IPTA) is faster than T (x, d) where monolithic termination analysis (MTA). 2) The precision of IPTA is comparable to MTA. • d are parameters to be instantiated with concrete values 3) 2LS outperforms existing termination analysis tools. and x are the program variables. 4) 2LS’s analysis is bit-precise. • T is a template that gives a blueprint for the shape of 5) 2LS computes usable preconditions for termination. the formulas to be computed. Choosing a template is We used the product line benchmarks of the [18] benchmark analogous to choosing an abstract domain in abstract repository. In contrast to other categories, this benchmark set interpretation. To allow for a flexible choice, we consider contains programs with non-trivial procedural structure. This template polyhedra [9]. benchmark set contains 597 programs with 1100 to 5700 We state here a soundness result: lines of code (2705 on average),4 33 to 136 procedures (67 on average), and 4 to 10 loops (5.5 on average). Of these Theorem 3. Any satisfiability witness d of the reduction of benchmarks, 264 terminate universally, whereas 333 never the second order constraint for invariants in Def. 1 using terminate. template T The experiments were run on a Xeon X5667 at 3 GHz ∃d, ∀xin, x, x0 : Init(xin, x) =⇒ T (x, d) running Fedora 20 with 64-bit binaries. Memory and CPU time ∧ T (x, d) ∧ Trans(x, x0) =⇒ T (x0, d) were restricted to 16 GB and 1800 seconds per benchmark, respectively (using [19]). Using 2LS with interval templates satisfies ∀x : Inv(x) =⇒ T (x, d), i.e. T (x, d) is a sound was sufficient to obtain reasonable precision. over-approximating invariant. Similar soundness results hold Modular termination analysis is fast We compared IPTA true for summaries and calling contexts. with MTA (all procedures inlined). Table I shows that IPTA This ultimately follows from the soundness of abstract times out on 2.3 % of the benchmarks vs. 39.7 % for MTA. interpretation [10]. Similar approaches have been described, The geometric mean speed-up of IPTA w.r.t. MTA on the for instance, by [11], [12], [13]. However, these methods benchmarks correctly solved by both approaches is 1.37. consider programs over mathematical integers. In order to investigate how the 30 m timeout affects MTA, Ranking functions require specialised synthesis techniques. we randomly selected 10 benchmarks that timed out for 30 m To achieve both expressiveness and efficiency, we generate and re-ran them: 1 finished in 32 m, 3 after more than 1 h, linear lexicographic functions [14], [15]. Our ranking-function 6 did not finish within 2 h. synthesis approach is similar to the TAN tool [16] but extends Modular termination analysis is precise Again, we com- the approach from monolithic to lexicographic ranking func- pare IPTA with MTA. Table I shows that IPTA proves 94 % of tions. Further, unlike TAN, our synthesis engine is much more the terminating benchmarks, whereas only 10 % were proven versatile and configurable, e.g., it also produces summaries and by MTA. MTA can prove all never-terminating benchmarks invariants. including 13 benchmarks where IPTA times out. MTA times Due to space limitations, we refer to the extended ver- out on the benchmarks that cause 13 additional potentially sion [7], which includes a detailed description of the synthesis non-terminating outcomes for IPTA. engine, our program encoding, encoding of bit-precise arith- 2LS outperforms existing termination analysis tools We metic, and tailored second-order solving techniques for the compared 2LS with two termination tools for C programs from different constraints that occur in our analysis. In the following section, we discuss the implementation. 4Measured using cloc 1.53. TABLE I 1 void ex15 ( i n t m, i n t n , i n t p , i n t q ) { TOOL COMPARISON (∗see text). 2 f o r ( i n t i = n ; i >= 1 ; i = i − 1) 3 f o r ( i n t j = 1 ; j <= m; j = j + 1) 4 f o r ( i n t k = i ; k <= p ; k = k + 1) 5 f o r ( i n t l = q ; l <= j ; l = l + 1) 6 ; 7 } 2LS IPTA 2LS MTA TAN Ultimate terminating 249 26 18 50 Fig. 3. Example ABC_ex15.c from the Loopus benchmarks. non-terminating 320 333 3 324∗

potentially non-term. 14 1 425 0 1 void createBack( s t r u c t SDL Surface ∗ b a c k s u r f ) timed out 14 237 150 43 2 { 3 s t r u c t SDL Rect pos ; errors 0 0 1 180 4 s t r u c t SDL Surface ∗img = images[img back]−>image ; total run time (h) 58.7 119.6 92.8 23.9 5 6 f o r ( i n t x =0; ! ( s >=(∗ b a c k s u r f)−>h ) ; s +=img−>h ) { 7 f o r ( i n t y =0; ! ( y>=(∗ b a c k s u r f)−>w ) ; y+=img−>w) { 8 pos . x = ( signed short int ) x ; the SV-COMP termination competition, namely TAN [20] 9 pos . y = ( signed short int ) y ; and Ultimate [21]. 10 SDL UpperBlit(img, NULL, ∗ b a c k surf , &pos); 11 ... Unfortunately, the tools [22], [23], [24], [25], and [26] have 12 }}} limitations regarding the subset of C that they can handle that Fig. 4. Example createBack from Debian package abe. make them unable to analyze any of the benchmarks out of the box. We describe these limitations in the experiments log in the results of our experiments on these benchmarks when [17]. Unfortunately, we did not succeed to generate the correct considering machine integers: input files in the intermediate formats required by T2 [27] and • Only 2 of the programs terminate, and are correctly KiTTeL [28] using the recommended frontends [29] and [30]. identified by both 2LS and Loopus. TAN [16] and KiTTeL/KoAT [5] support bit-precise C • For the rest of 13 non-terminating programs, Loopus semantics. Ultimate uses mathematical integer reasoning but claims they terminate, whereas 2LS correctly classifies 9 tries to ensure conformance with bit-vector semantics. Also, as potentially non-terminating (including ABC_ex15.c Ultimate uses a semantic decomposition of the program [31] in Fig. 3) and times out on 4. to make its analysis efficient. 2LS computes usable preconditions for termination This For each of the tools, Table I lists the number of instances experiment was performed on benchmarks extracted from solved, timed out or aborted because of an internal error. We Debian packages and the linear algebra library CLapack. also give the total run time, which shows that analysis times The quality of preconditions, i.e. usability or ability to help are roughly halved by the modular/interprocedural approaches the developer to spot problems in the code, is difficult to (2LS IPTA, Ultimate) in comparison with the monolithic quantify. We give several examples where functions terminate approaches (2LS MTA, TAN). Ultimate spends less time on conditionally. The abe package of Debian contains a function, those benchmarks that it can prove terminating, however, these given as Fig. 4, where increments of the iteration in a loop are only 19 % of the terminating benchmarks (vs. 94 % for are not constant but dynamically depend on the dimensions 2LS). If Ultimate could solve those 180 benchmarks on which of an image data structure. Here, 2LS infers the precondition it fails due to unsupported features of C, we would expect its img → h > 0 ∧ img → w > 0. performance to be comparable to 2LS. The example in Fig. 5 is taken from the benchmark Ultimate and 2LS have different capabilities regarding non- basename in the busybox-category of SVCOMP 2015, termination. 2LS can show that a program never terminates for which contains simplified versions of Debian packages. The all inputs, whereas Ultimate can show that there exists a poten- termination of function full_write depends on the return tially non-terminating execution. To make the comparison fair, value of its callee function safe_write. Here, 2LS infers we counted benchmarks flagged as potentially non-terminating the calling context cc > 0, i.e. the contract for the function by Ultimate, but which are actually never-terminating, in the safe_write, such that the termination of full_write is ∗ non-terminating category in Table I (marked ). guaranteed. Given a proof that safe_write terminates and 2LS’s analysis is bit-precise We compared 2LS with returns a strictly positive value regardless of the arguments it Loopus on a collection of 15 benchmarks (ABC_ex01.c to is called with, we can conclude that full_write terminates ABC_ex15.c) taken from the Loopus benchmark suite [23]. universally. While they are short (between 7 and 41 LOC), the main The program in Fig. 6 is a code snippet taken from the characteristic of these programs is the fact that they exhibit summation procedure sasum within [32], the C version of the different terminating behaviours for mathematical integers and popular LAPACK linear algebra library. The loop in procedure bit-vectors. For illustration, ABC_ex15.c (Fig. 3) terminates f does not terminate if incx = 0. If incx > 0 (incx < 0) the with mathematical integers, but not with machine integers termination argument is that i increases (decreases). Therefore, if, for instance, m equals INT_MAX. Next, we summarise incx 6= 0 is a termination precondition for f. using specific abstract domains. For illustration, let us consider 1 signed long int f u l l w r i t e ( signed i n t fd , 2 c on s t void ∗buf , unsigned long int len , the following example traversing a singly-linked list. 3 unsigned long int cc ) { L i s t x ; while ( x != NULL) { x = x−>n e x t ; } 4 signed long int t o t a l = ( signed long int ) 0 ; 5 f o r ( ; !(len == 0ul); Deciding the termination of such a program requires knowl- 6 l e n = l e n − ( unsigned long int ) cc ) { 7 cc= s a f e write(fd, buf, len); edge about the shape of the data structure pointed by x, 8 i f ( cc < 0 l ) { namely, the program only terminates if the list is acyclic. Thus, 9 i f (!(total == 0l)) we would require an abstract domain capable of capturing 10 return t o t a l ; 11 return cc ; such a property and also relate the shape of the data structure 12 } to its length. Similar to [15], we could use [40] in order 13 total = total + cc; to abstract heap-manipulating programs to arithmetic ones. 14 buf = ( c on s t void ∗ )(( c on s t char ∗) buf + cc ) ; 15 }} Another option is using an abstract interpretation based on Fig. 5. Example from SVCOMP 2015 busybox. separation logic formulae which tracks the depths of pieces of heaps similarly to [41]. 1 i n t f ( i n t ∗sx , i n t n , i n t i n c x ) { 2 i n t n in c x = n ∗ i n c x ; Strings and arrays Similar to dynamic data structures, 3 i n t stemp =0; handling strings and arrays requires specific abstract domains. 4 f o r ( i n t i =0; incx <0 ? i >= n in c x : i <= n i nc x ; 5 i += i n c x ) { String abstractions that reduce null-terminated strings to inte- 6 stemp += sx[i −1]; gers (indices, length, and size) are usually sufficient in many 7 } practical cases; scenarios where termination is dependent on 8 return stemp ; 9 } the content of arrays are much harder and would require quantified invariants [42]. Note that it is favorable to run a Fig. 6. Non-unit increment from CLapack. safety checker before the termination checker. The latter can assume that assertions for buffer overflow checks hold which VIII.LIMITATIONS,RELATED WORKS strengthens invariants and makes termination proofs easier. AND FUTURE DIRECTIONS Recursion We currently use downward fixed point iterations Our approach makes significant progress towards analysing for computing calling contexts and invariants that involve real-world software, advancing the state-of-the-art of termina- summaries (see Remark 1). This is cheap but gives only tion analysis of large programs. Conceptually, we decompose imprecise results in the presence of recursion, which would the analysis into a sequence of well-defined second-order pred- impair the termination analysis. We could handle recursions by icate logic formulae with existentially quantified predicates. In detecting cycles in the call graph and switching to an upward addition to [33], we consider context-sensitive analysis, under- iteration scheme in such situations. Moreover, an adaptation approximate backwards analysis, and make the interaction regarding the generation of the ranking function templates is with termination analysis explicit. Notably, these seemingly necessary. An alternative approach would be to make use of tedious formulae are actually solved by our generic template- the theoretic framework presented in [43] for verifying total based synthesis algorithm, making it an efficient alternative to correctness and liveness properties of while programs with predicate abstraction. recursion. An important aspect of our analysis is that it is bit-precise. Template refinement We currently use interval templates As opposed to the synthesis of termination arguments for lin- together with heuristics for selecting the variables that should ear programs over integers (rationals) [34], [35], [2], [36], [37], be taken into consideration. This is often sufficient in practice, [14], [15], this subclass of termination analyses is substantially but it does not exploit the full power of the machinery in place. less covered. While [16], [38] present methods based on a While counterexample-guided abstraction refinement (CE- reduction to Presburger arithmetic, and a template-matching GAR) techniques are prevalent in predicate abstraction [44], approach for predefined classes of ranking functions based attempts to use them in abstract interpretation are rare [45]. on reduction to SAT- and QBF-solving, [39] only compute We consider our template-based abstract interpretation that intraprocedural termination arguments. automatically synthesises abstract transformers more amenable There are still a number of limitations to be addressed, all to refinement techniques than classical abstract interpretations of which connect to open challenges subject to active research. where abstract transformers are implemented manually. While some are orthogonal (e.g., data structures, strings, Sufficient preconditions to termination Conditional ter- refinement) to our interprocedural analysis framework, others mination has recently attracted increased interest [8], [46], (recursion, necessary preconditions) require extensions of it. In [47], [48], [49]. In this paper, we compute sufficient precon- this section, we discuss related work, as well as, characteristics ditions, i.e. under-approximating preconditions to termination and limitations of our analysis, and future directions (cost via computing over-approximating preconditions to potential analysis and concurrency). non-termination. The same concept is used by other works Dynamically allocated data structures We currently ig- [8], [46]. However, they consider only a single procedure nore heap-allocated data. This limitation could be lifted by and do not leverage their results to perform interprocedural analysis on large benchmarks which adds, in particular, the [4] A. R. Bradley, Z. Manna, and H. B. Sipma, “Termination of polynomial additional challenge of propagating under-approximating in- programs,” in Verification, Model Checking, and Abstract Interpretation, vol. 3385 of LNCS, pp. 113–129, Springer, 2005. formation up to the entry procedure (e.g. [50]). Moreover, [5] S. Falke, D. Kapur, and C. Sinz, “Termination analysis of imperative by contrast to Cook et al [8] who use an heuristic FINITE- programs using bitvector arithmetic,” in Verified Software: Theories, operator left unspecified for bootstrapping their preconditions, Tools, Experiments, vol. 7152 of LNCS, pp. 261–277, Springer, 2012. [6] D. Beyer, “Status report on software verification – (competition summary our bootstrapping is systematic through constraint solving. SV-COMP 2014),” in Tools and Algorithms for the Construction and We could compute necessary preconditions by computing Analysis of Systems, vol. 8413 of LNCS, Springer, 2014. over-approximating preconditions to potential termination (and [7] H.-Y. Chen, C. David, D. Kroening, P. Schrammel, and B. Wachter, “Synthesising interprocedural bit-precise termination proofs (extended negating the result). However, this requires a method for version),” tech. rep., University of Oxford, 2015. http://arxiv.org/abs/ proving that there exist non-terminating executions, which 1505.04581. is a well-explored topic. While [51] dynamically enumerate [8] B. Cook, S. Gulwani, T. Lev-Ami, A. Rybalchenko, and M. Sagiv, “Prov- ing conditional termination,” in Computer-Aided Verification, vol. 5123 lasso-shaped candidate paths for counterexamples, and then of LNCS, pp. 328–340, Springer, 2008. statically prove their feasibility, [52] prove nontermination [9] S. Sankaranarayanan, H. B. Sipma, and Z. Manna, “Scalable analysis of via reduction to safety proving and [53] uses bi-abduction linear systems using mathematical programming,” in Verification, Model Checking, and Abstract Interpretation, vol. 3385 of LNCS, pp. 25–41, to construct summaries of terminating and non-terminating Springer, 2005. behaviors for each method. In order to prove both termination [10] P. Cousot and R. Cousot, “Abstract interpretation: A unified lattice model and non-termination, [54] compose several program analyses for static analysis of programs by construction or approximation of fixpoints,” in Principles of Programming Languages, pp. 238–252, 1977. (termination provers for multi-path loops, non-termination [11] T. M. Gawlitza and H. Seidl, “Precise relational invariants through provers for cycles, and safety provers). strategy iteration,” in Computer Science Logic, vol. 4646 of LNCS, pp. 23–40, Springer, 2007. Cost analysis A potential future application for our work is [12] S. Gulwani, S. Srivastava, and R. Venkatesan, “Program analysis as con- cost and resource analysis. Instances of this type of analyses straint solving,” in Design and Implementation, are the worst case execution time (WCET) analysis [55], as pp. 281–292, ACM, 2008. [13] Y. Li, A. Albarghouthi, Z. Kincaid, A. Gurfinkel, and M. Chechik, “Sym- well as bound and amortised complexity analysis [56], [57], bolic optimization with SMT solvers,” in Principles of Programming [58]. The control flow refinement approach [59], [60] instru- Languages, pp. 607–618, ACM, 2014. ments a program with counters and uses progress invariants [14] A. R. Bradley, Z. Manna, and H. B. Sipma, “Linear ranking with reachability,” in Computer-Aided Verification, pp. 491–504, 2005. to compute worst case or average case bounds. [15] B. Cook, A. See, and F. Zuleger, “Ramsey vs. lexicographic termination Concurrency Our current analysis handles single-threaded proving,” in Tools and Algorithms for the Construction and Analysis of Systems, pp. 47–61, 2013. C programs. One way of extending the analysis to multi- [16] D. Kroening, N. Sharygina, A. Tsitovich, and C. M. Wintersteiger, “Ter- threaded programs is using the rely-guarantee technique which mination analysis with compositional transition invariants,” in Computer- is proposed in [61], and explored in several works [62], [63], Aided Verification, vol. 6174 of LNCS, pp. 89–103, Springer, 2010. [17] http://www.cprover.org/wiki/doku.php?id=2ls for program analysis [64] for termination analysis. In our setting, the predicates (version 0.1). for environment assumptions can be used in a similar way as [18] https://svn.sosy-lab.org/software/sv-benchmarks/tags/svcomp14/ invariants and summaries are used in the analysis of sequential product-lines/. [19] O. Roussel, “Controlling a solver execution with the runsolver tool,” programs. Journal on Satisfiability, Boolean Modeling and Computation, vol. 7, no. 4, pp. 139–144, 2011. IX.CONCLUSIONS [20] http://www.cprover.org/termination/ (version SV-COMP-2014). While many termination provers mainly target small, hard [21] M. Heizmann, D. Dietsch, J. Leike, B. Musa, and A. Podelski, “Ultimate automizer with array interpolation - (competition contribution),” in Tools programs, the termination analysis of larger code bases has and Algorithms for the Construction and Analysis of Systems, vol. 9035 received little attention. We present an algorithm for interpro- of LNCS, Springer, 2015. http://ultimate.informatik.uni-freiburg.de/ cedural termination analysis for non-recursive programs. To (version SV-COMP-2015). [22] T. Stroder,¨ C. Aschermann, F. Frohn, J. Hensel, and J. Giesl, “AProVE: our knowledge, this is the first paper that describes in full detail Termination and Memory Safety of C programs - (competition contri- the entire machinery necessary to perform such an analysis. bution),” in Tools and Algorithms for the Construction and Analysis of Our approach relies on a bit-precise static analysis combining Systems, vol. 9035 of LNCS, Springer, 2015. http://aprove.informatik. rwth-aachen.de (version 2014). SMT solving, template polyhedra and lexicographic, linear [23] http://forsyte.at/software/loopus/ with http://sourceforge.net/projects/ ranking function templates. We provide an implementation of virtualboximage/files/Ubuntu%20Linux/11.10/ubuntu 11.10-x86.7z/ the approach in the static analysis tool 2LS, and demonstrate download. [24] http://www.di.ens.fr/∼urban/sv-comp2015.zip (version SV-COMP- the applicability of the approach to programs with thousands 2015). of lines of code. [25] T. C. Le, C. Gherghina, A. Hobor, and W. Chin, “A resource-based logic for termination and non-termination proofs,” in ICFEM, vol. 8829 REFERENCES of LNCS, Springer, 2014. http://loris-7.ddns.comp.nus.edu.sg/∼project/ hiptnt/plus/. [1] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-1890. [26] A. Podelski and A. Rybalchenko, “ARMC: the logical choice for [2] A. M. Ben-Amram and S. Genaim, “On the linear ranking problem software model checking with abstraction refinement,” in Practical for integer linear-constraint loops,” in Principles of Programming Lan- Aspects of Declarative Languages, vol. 4354 of LNCS, Springer, 2007. guages, pp. 51–62, ACM, 2013. https://www7.in.tum.de/∼rybal/armc/ (version August 2011). [3] J. Leike and M. Heizmann, “Ranking templates for linear loops,” in Tools [27] http://research.microsoft.com/en-us/projects/t2/ (version 2014-10). and Algorithms for the Construction and Analysis of Systems, vol. 8413 [28] https://github.com/s-falke/kittel-koat (revision c05eab4b3c). of LNCS, pp. 172–186, Springer, 2014. [29] http://research.microsoft.com/en-us/projects/slayer/ (version 1.1). [30] https://github.com/mmjb/llvm2kittel (revision 6fc38707f7). conditional termination,” in Static Analysis Symposium, vol. 8723 of [31] M. Heizmann, J. Hoenicke, and A. Podelski, “Termination analysis LNCS, Springer, 2014. by learning terminating programs,” in Computer-Aided Verification, [50] P. Ganty, R. Iosif, and F. Konecny,´ “Underapproximation of procedure vol. 8559 of LNCS, pp. 797–813, Springer, 2014. summaries for integer programs,” in Tools and Algorithms for the [32] http://www.netlib.org/clapack/cblas/sasum.c. Construction and Analysis of Systems, vol. 7795 of LNCS, pp. 245–259, [33] S. Grebenshchikov, N. P. Lopes, C. Popeea, and A. Rybalchenko, Springer, 2013. “Synthesizing software verifiers from proof rules,” in Programming [51] A. Gupta, T. A. Henzinger, R. Majumdar, A. Rybalchenko, and R.- Language Design and Implementation, pp. 405–416, 2012. G. Xu, “Proving non-termination,” in Principles of Programming Lan- [34] B. Cook, A. Podelski, and A. Rybalchenko, “Termination proofs for guages, pp. 147–158, ACM, 2008. systems code,” in Programming Language Design and Implementation, [52] H. Y. Chen, B. Cook, C. Fuhs, K. Nimkar, and P. W. O’Hearn, “Proving pp. 415–426, ACM, 2006. nontermination via safety,” in Tools and Algorithms for the Construction [35] W. Lee, B.-Y. Wang, and K. Yi, “Termination analysis with algorithmic and Analysis of Systems, pp. 156–171, 2014. learning,” in Computer-Aided Verification, pp. 88–104, 2012. [53] T. C. Le, S. Qin, and W. Chin, “Termination and non-termination spec- [36] A. Podelski and A. Rybalchenko, “Transition invariants,” in Logic in ification inference,” in Conference on Programming Language Design Computer Science, pp. 32–41, IEEE Computer Society, 2004. and Implementation, pp. 489–498, 2015. [37] M. Heizmann, J. Hoenicke, J. Leike, and A. Podelski, “Linear ranking [54] W. R. Harris, A. Lal, A. V. Nori, and S. K. Rajamani, “Alternation for for linear lasso programs,” in Automated Technology for Verification and termination,” in Static Analysis Symposium, pp. 304–319, 2010. Analysis, pp. 365–380, 2013. [55] R. Wilhelm, J. Engblom, A. Ermedahl, N. Holsti, S. Thesing, D. Whal- [38] B. Cook, D. Kroening, P. Rummer,¨ and C. M. Wintersteiger, “Ranking ley, G. Bernat, C. Ferdinand, R. Heckmann, T. Mitra, F. Mueller, function synthesis for bit-vector relations,” in Tools and Algorithms for I. Puaut, P. Puschner, J. Staschulat, and P. Stenstrom,¨ “The Worst-case the Construction and Analysis of Systems, vol. 6015 of LNCS, pp. 236– Execution Time Problem—Overview of Methods and Survey of Tools,” 250, Springer, 2010. Transactions on Embedded Computing Systems, vol. 7, no. 3, 2008. [39] C. David, D. Kroening, and M. Lewis, “Unrestricted termination and [56] C. Alias, A. Darte, P. Feautrier, and L. Gonnord, “Multi-dimensional non-termination arguments for bit-vector programs,” in European Sym- rankings, program termination, and complexity bounds of flowchart posium on Programming, pp. 183–204, 2015. programs,” in Static Analysis Symposium, vol. 6337 of LNCS, pp. 117– [40] S. Magill, M.-H. Tsai, P. Lee, and Y.-K. Tsay, “Automatic numeric 133, Springer, 2010. abstractions for heap-manipulating programs,” in Principles of Program- [57] M. Brockschmidt, F. Emmes, S. Falke, C. Fuhs, and J. Giesl, “Alternat- ming Languages, pp. 211–222, 2010. ing runtime and size complexity analysis of integer programs,” in Tools [41] J. Berdine, B. Cook, D. Distefano, and P. W. O’Hearn, “Automatic and Algorithms for the Construction and Analysis of Systems, vol. 8413 termination proofs for programs with shape-shifting heaps,” in CAV, of LNCS, pp. 140–155, Springer, 2014. pp. 386–400, 2006. [58] M. Sinn, F. Zuleger, and H. Veith, “A simple and scalable static analysis [42] K. L. McMillan, “Quantified invariant generation using an interpolating for bound analysis and amortized complexity analysis,” in Computer- saturation prover,” in Tools and Algorithms for the Construction and Aided Verification, vol. 8559 of LNCS, pp. 745–761, Springer, 2014. Analysis of Systems, vol. 4963 of LNCS, pp. 413–427, Springer, 2008. [59] S. Gulwani, S. Jain, and E. Koskinen, “Control-flow refinement and [43] A. Podelski, I. Schaefer, and S. Wagner, “Summaries for while programs progress invariants for bound analysis,” in Programming Language with recursion,” in European Symposium on Programming, vol. 3444 of Design and Implementation, pp. 375–385, 2009. LNCS, pp. 94–107, Springer, 2005. [60] H. Y. Chen, S. Mukhopadhyay, and Z. Lu, “Control flow refinement and [44] E. M. Clarke, O. Grumberg, S. Jha, Y. Lu, and H. Veith, symbolic computation of average case bound,” in Automated Technology “Counterexample-guided abstraction refinement,” in Computer-Aided for Verification and Analysis, pp. 334–348, 2013. Verification, vol. 1855 of LNCS, pp. 154–169, Springer, 2000. [61] C. B. Jones, “Tentative steps toward a development method for interfer- [45] F. Ranzato, O. Rossi-Doria, and F. Tapparo, “A forward-backward ing programs,” ACM Trans. Program. Lang. Syst., vol. 5, pp. 596–619, abstraction refinement algorithm,” in Verification, Model Checking, and Oct. 1983. Abstract Interpretation, vol. 4905 of LNCS, pp. 248–262, Springer, 2008. [62] B. Cook, A. Podelski, and A. Rybalchenko, “Proving thread termina- [46] M. Bozga, R. Iosif, and F. Konecny,´ “Deciding conditional termination,” tion,” in Programming Language Design and Implementation, pp. 320– in Tools and Algorithms for the Construction and Analysis of Systems, 330, ACM, 2007. vol. 7214 of LNCS, pp. 252–266, Springer, 2012. [63] A. Gupta, C. Popeea, and A. Rybalchenko, “Predicate abstraction and [47] P. Ganty and S. Genaim, “Proving termination starting from the end,” refinement for verifying multi-threaded programs,” in Principles of in Computer-Aided Verification, vol. 8044 of LNCS, Springer, 2013. Programming Languages, pp. 331–344, ACM, 2011. [48] D. Masse,´ “Policy iteration-based conditional termination and ranking [64] C. Popeea and A. Rybalchenko, “Compositional termination proofs for functions,” in Verification, Model Checking, and Abstract Interpretation, multi-threaded programs,” in Tools and Algorithms for the Construction vol. 8318 of LNCS, Springer, 2014. and Analysis of Systems, vol. 7214 of LNCS, pp. 237–251, Springer, [49] C. Urban and A. Mine,´ “A decision tree abstract domain for proving 2012.