380 likes | 489 Vues
Termination bugs pose significant challenges in systems and application code, causing issues such as application hangs and unresponsive behavior. This paper explores techniques for proving termination using local termination provers and transition invariants. It introduces the TREX approach, which iteratively finds a proof of termination or identifies counterexamples. By analyzing loop contexts and deriving invariants, TREX improves the efficiency of termination proofs. We present examples illustrating the method and its effectiveness in addressing real-world termination problems.
E N D
Alternation for Termination 1 2 2 2 William Harris, AkashLal, AdityaNori SriramRajamani 1 2
Termination bugs are a real problem in systems and application code.
A Quick Search “bug code hangs”: “Gecko mediaplayer hangs the browser” “Eclipse hangs after 5 minutes or so of working” “BUG: Silverlight makes browser hang after BeginSaveChanges on some machines” “BUG: VB Hangs While Automating Excel Using OLE Control” …
Key challenge to proving termination:Analyzing the context of a loop
An Example with Non-Trivial Context f(int d, z) { int x, y; while (x > 0 && y > 0) { if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); }
Local Termination Provers For a fixed over-approximation of a loop, find a proof of termination
Local ProversSucceeding while (x > 0 && y > 0) { • assume(d > 0); if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } x y
Local Provers Failing f(intd) { intx, y; while (x > 0 && y > 0) { assume(d > 0); if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { f(1); f(2); } ??
Transition Invariants From stem and cycle of a loop, guess and check a proof of termination
Advantage of Transition Invariants A stem to a loop can include information about the loop’s context.
Transition Invariants Succeeding f(int d) { while (x > 0 && y > 0) { if (*) { x := x – d; y := *; } else { y := y – d; } } } while (x > 0 && y > 0) { x := x – d; y := *; } x • main() { • f(1); • f(2); }
Transition Invariants Succeeding f(int d) { while (x > 0 && y > 0) { if (*) { x := x – d; y := *; } else { y := y – d; } } } while (x > 0 && y > 0) { y := y - d; } y • main() { • f(1); • f(2); }
Disadvantage of Transition Invariants Stem and cycle can lead to incorrect guesses for proof of termination.
Transition Invariants Failing f(intd) { f(int d, int z) { int x, y; while (x > 0 && y > 0) { if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1); f(1, z); f(2); f(2, z); }
Key Insight of TREX From cycles through a loop, inferinvariants for proving termination.
Context Analysis via TREX f(int d, z) { int x, y; while (x > 0 && y > 0) { assume(d > 0); if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); }
Payoff of TREX’s Approach TREX can apply local proversto find a proof of termination quickly
Analysis via TREX f(int d, z) { int x, y; while (x > 0 && y > 0) { assume(d > 0); if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); } x, y
TREX in More Detail • TREX by example • Experiments
TREX iterativelyfinds a proof of termination,or finds a counterexample to termination, or refinesstronger program invariants The TREX Algorithm
TREX IterationStep 1 Find a proof of termination by applying a local termination prover
TREX IterationStep 1 f(int d, z) { int x, y; while (x > 0 && y > 0) { if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); } ??
TREX Iteration Step 2 If local prover fails, then find a counterexample cycle
TREX Iteration Step 2 f(int d, z) { int x, y; while (x > 0 && y > 0) { if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); } while (x > 0 && y > 0) { y := y – d; }
TREX Iteration Step 3 From the counterexample cycle, find a sufficient condition for non-terminationby applying a non-termination prover(TNT)
Applying a Non-Termination Prover while (x > 0 && y > 0) { y := y – d; } Non-termination if: y > 0 && d <= 0
TREX IterationStep 4 Check if the sufficient condition is reachable
TREXIterationStep 4 Non-termination if: y > 0 && d <= 0 f(int d, z) { int x, y; while (x > 0 && y > 0) { assert(d > 0); if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); } while (x > 0 && y > 0) { y := y – d; }
TREX Iteration Step 5 If the sufficient condition is unreachable, thenassume this as an invariant.
TREX Iteration Step 5 f(int d, z) { int x, y; while (x > 0 && y > 0) { assert(d > 0); if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1, z); f(2, z); } assume(d > 0); x, y
Experiments Windows Vista driver snippets
Conclusion TREX proves termination by using cycles through a loop to infer useful program invariants
Transition Invariants Succeeding f(int d) { while (x > 0 && y > 0) { if (*) { x := x – d; y := *; } else { y := y – d; } } } • main() { • f(1); • f(2); } x, y
Transition Invariants Failing f(intd) { f(int d, int z) { int x, y; while (x > 0 && y > 0) { if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1); f(1, z); f(2); f(2, z); } z = 1; f(1, z); while (x > 0 && y > 0) { assume(d = 1 && z = 1); if (*) { x := x – d; y := *; z := z – 1; } } z - 1
Transition Invariants Failing f(intd) { f(int d, int z) { int x, y; while (x > 0 && y > 0) { if (*) { x := x – d; y := *; z := z – 1; } else { y := y – d; } } } main() { int k; int z = 1; while (z < k) { z := 2 * z; } f(1); f(1, z); f(2); f(2, z); } z = 1; z := 2 * z; f(1, z); while (x > 0 && y > 0) { assume(d = 1 && z = 2); if (*) { x := x – d; y := *; z := z – 1; } } z - 2