720 likes | 900 Views
Automatic Abstraction in SMT-Based Unbounded Software Model Checking. Anvesh Komuravelli Carnegie Mellon University. Joint work with Arie Gurfinkel , Sagar Chaki and Edmund Clarke. The Problem. Safe. + Proof. Automatic analysis for assertion failures. Program P + Assertions. Unsafe.
E N D
Automatic Abstraction in SMT-Based Unbounded Software Model Checking AnveshKomuravelli Carnegie Mellon University Joint work with ArieGurfinkel, SagarChaki and Edmund Clarke
The Problem Safe + Proof Automatic analysis for assertion failures Program P + Assertions Unsafe + Counterexample Is it empty? Unknown + Partial Proof error(P) reach(P) Software Model Checking
Over-approximation Driven (OD) error(P) reach(P)
Over-approximation driven (OD) error(P) reach(P)
Under-approximation Driven (UD) reach(P) error(P)
Under-approximation driven (UD) error(P) reach(P)
Our Strategy error(P) reach(P) Under-approx. Abstract Under-approx.
Our Strategy error(P) reach(P) Under-approx. Abstract Under-approx. Refine
Our Strategy error(P) reach(P) Under-approx. Abstract Under-approx. Refine Abstract
Our Strategy error(P) reach(P) And so on …
Our Strategy reach(P) is covered error(P) reach(P) Abstractions guide the SMT solver to look for general proofs
It’s based on UD Under-approximations … … A b s t r a c t … …
It’s based on UD Under-approximations … need not be monotonic … A b s t r a c t … …
Spacer is based on UD Under-approximations … non-trivial abstraction … A b s t r a c t … …
Spacer Program Abstract Under-Approximate Refine Proof-Based Abstraction CEGAR No No Check Safety Feasible? Feasible? Safety Proof Counterexample Yes Yes
Why Abstraction? x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = 1; w += t; z += 10t; } assert (0 ≤ y) only way to fail the assertion
UD Reasoning y ≤ 100x x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = 1; w += t; z += 10t; } assert (0 ≤ y) 1st Iteration: w = 0, z = 0
UD Reasoning y ≤ 100x x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = 1; w += t; z += 10t; } assert (0 ≤ y) 2nd Iteration: w = 1, z =10
UD Reasoning y ≤ 100x x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = 1; w += t; z += 10t; } assert (0 ≤ y) 3rd Iteration: w = 2, z = 20 And so on…
But … x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = 1; w += t; z += 10t; } assert (0 ≤ y) The value ‘1’ doesn’t matter!
But … x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = *; w += t; z += 10t; } assert (0 ≤ y)
UD Reasoning on the Abstraction y ≤ 100x All Iterations x = y = z = w = 0; while (*) { x = *; y = *; assume (0 ≤ y ≤ 100x); if (y > 10w && z ≥ 100x) { y = −y; } t = *; w += t; z += 10t; } assert (0 ≤ y) 2nd Iteration Redundant w = t, z = 10t Resolve t away z = 10w
Original Example μZ (SMT-Based Model Checker, part of Z3) Cannot solve in an hour x = y = z = w = 0; while (*) { if (*) {x++; y += 100;} else if (*) if (x ≥ 4) {x++; y++;} else if (y > 10w && z ≥ 100x) { y = −y; } t = 1; w += t; z += 10t; } assert (!(x ≥ 4 && y ≤ 2)) Solves an abstraction in < 1 sec. t = *; Spacer (our tool) Finds a proof in a min. Source: Automatically Refining Abstract Interpretations, Gulavani, Chakraborty, Nori and Rajamani, TACAS ‘08.
What’s the magic? Focused Proofs • Abstractions guide the SMT solver to look for certain kind of proofs • Avoid proofs specific to an under-approximation How to obtain abstractions? • From proofs of under-approximations! (Proof-Based Abstraction) • Hope: What’s sufficient for the under-approximation is sufficient in general • Downside: If abstraction is too coarse, need to refine (CEGAR)
Spacer Program Abstract Under-Approximate Refine Proof-Based Abstraction CEGAR No No Check Safety Feasible? Feasible? Safety Proof Counterexample Yes Yes
Schematic Example init_stmt; c = 0; while (*) { // invar_1, invar_2 // invar_3, invar_4 assume (c < k1); if (*) { v1 = e1; v2 = e2; } else { v3 = e3; v4 = e4; } v5 = e5; v6 = e6; c += 1; } assert (safe); Loop Invariants Add Counters Under-approximate Solve
Schematic Example Treat as guessed unbounded invariants. Essentially like Houdini [FL’01]. init_stmt; c = 0; assume (invar_1, invar_2); while (*) { // invar_1, invar_2 // invar_3, invar_4 assume (c < k1); if (*) { v1 = e1; v2 = e2; } else { v3 = e3; v4 = e4; } v5 = e5; v6 = e6; c += 1; assume (invar_1, invar_2); } assert (safe); Specific to under-approx. [FL’01] Houdini, an annotation assistant for ESC/Java, C. Flanagan and K.R.M. Leino, 2001 Extract Unbounded Invariants Unbounded! Strengthen with Invariants Under-approximate Feasible? Solve
Schematic Example init_stmt; c = 0; assume (invar_1, invar_2); while (*) { // invar_1, invar_2 if (*) { v1 = e1; v2 = e2; } else { v3 = e3; v4 = e4; } v5 = e5; v6 = e6; c += 1; assume (invar_1, invar_2); } assert (safe); Does not prove the assertion Under-approximate Feasible? NO Solve
Schematic Example init_stmt; c = 0; assume (invar_1, invar_2); while (*) { // invar_1, invar_2 // invar_3, invar_4 assume (c < k1); if (*) { v1 = e1; v2 = e2; } else { v3 = e3; v4 = e4; } v5 = e5; v6 = e6; c += 1; assume (invar_1, invar_2); } assert (safe); Redundant for the proof Under-approximate Feasible? NO Abstract Solve
Schematic Example init_stmt; c = 0; assume (invar_1, invar_2); while (*) { // invar_1, invar_2 // invar_3, invar_4 assume (c < k1); if (*) { v1 = e1; v2 = *; } else { v3 = e3; v4 = *; } v5 = e5; v6 = *; c += 1; assume (invar_1, invar_2); } assert (safe); Proof-Based Abstraction Under-approximate Feasible? NO Abstract Solve
Schematic Example init_stmt; c = 0; assume (invar_1, invar_2); while (*) { assume (c < k2); if (*) { v1 = e1; v2 = *; } else { v3 = e3; v4 = *; } v5 = e5; v6 = *; c += 1; assume (invar_1, invar_2); } assert (safe); k2 > k1 Abstract Counterexample! Concretize Concrete control path is infeasible Under-approximate Feasible? NO Refine Solve
Schematic Example init_stmt; c = 0; assume (invar_1, invar_2); while (*) { assume (c < k2); if (*) { v1 = e1; v2 = e2; } else { v3 = e3; v4 = e4; } v5 = e5; v6 = *; c += 1; assume (invar_1, invar_2); } assert (safe); CEGAR Under-approximate Feasible? NO Refine Solve
Schematic Example init_stmt; c = 0; assume (invar_1, invar_2); while (*) { // invar_5 // invar_6 assume (c < k2); if (*) { v1 = e1; v2 = e2; } else { v3 = e3; v4 = e4; } v5 = e5; v6 = *; c += 1; assume (invar_1, invar_2); } assert (safe); Unbounded Invariants Under-approximate Feasible? YES Solve
Spacer Program Abstract Under-Approximate Refine Proof-Based Abstraction CEGAR No No Check Safety Feasible? Feasible? Safety Proof Counterexample Yes Yes
DetailedExample x = y = z = w = 0; while (*) { if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w++; z += 10; } assert (!(x ≥ 4 && y ≤ 2)); if (nd ()) {x++; y += 100;} else if (nd () && x ≥ 4) {x++; y++;} else if (y > 10w && z ≥ 100x) {y = −y;} else assume (0); C-like non-deterministic choice (e.g. as in Promela)
DetailedExample x = y = z = w = 0; c = 0; while (*) { // (y > 10w) => (z < 100x), z ≤ 100x, // x ≤ 2, c ≤ 0 => x ≤ 0, c ≤ 1 => x ≤ 1 assume (c < 2); if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w++; z += 10; c += 1; } assert (!(x ≥ 4 && y ≤ 2)); Loop Invariants Add Counters Under-approximate Solve
DetailedExample x = y = z = w = 0; c = 0; while (*) { // (y > 10w) => (z < 100x), z ≤ 100x, // x ≤ 2, c ≤ 0 => x ≤ 0, c ≤ 1 => x ≤ 1 assume (c < 2); if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w++; z += 10; c += 1; } assert (!(x ≥ 4 && y ≤ 2)); Inductive Invariant Safe Under-approximate Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { //(y > 10w) => (z < 100x), z ≤ 100x, // x ≤ 2, c ≤ 0 => x ≤ 0, c ≤ 1 => x ≤ 1 assume (c < 2); if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w++; z += 10; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4 && y ≤ 2)); Preserved! Specific to under-approx. Extract Unbounded Invariants Depend on counter Strengthen with Invariants Under-approximate Feasible? Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { //(y > 10w) => (z < 100x), z ≤ 100x, if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w++; z += 10; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4 && y ≤ 2)); Does not prove the assertion Under-approximate Feasible? NO Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { // (y > 10w) => (z < 100x), z ≤ 100x, // x ≤ 2, c ≤ 0 => x ≤ 0, c ≤ 1 => x ≤ 1 assume (c < 2); if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w++; z += 10; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4 && y ≤ 2)); Redundant Under-approximate Feasible? NO Abstract Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { // (y > 10w) => (z < 100x), z ≤ 100x, // x ≤ 2, c ≤ 0 => x ≤ 0, c ≤ 1 => x ≤ 1 assume (c < 2); if :: x++; y = *; :: (x ≥ 4) -> x++; y = *; :: (y > 10w && z ≥ 100x) -> y = *; fi w = *; z = *; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4 && y ≤ 2)); Fails Enlarge error Under-approximate Feasible? NO Abstract Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { // (y > 10w) => (z < 100x), z ≤ 100x, // x ≤ 2, c ≤ 0 => x ≤ 0, c ≤ 1 => x ≤ 1 assume (c < 2); if :: x++; y = *; :: (x ≥ 4) -> x++; y = *; :: (y > 10w && z ≥ 100x) -> y = *; fi w = *; z = *; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4)); Under-approximate Feasible? NO Abstract Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { assume (c < 4); if :: x++; y = *; :: (x ≥ 4) -> x++; y = *; :: (y > 10w && z ≥ 100x) -> y = *; fi w = *; z = *; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4)); Counterexample! Increment x to 4 Choose y arbitrarily Concretize Concrete control path is infeasible Under-approximate Feasible? NO Refine Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { assume (c < 4); if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w = *; z = *; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4 && y ≤ 2)); Under-approximate Feasible? NO Refine Solve
DetailedExample x = y = z = w = 0; c = 0; assume (y > 10w => z < 100x, z ≤ 100x); while (*) { //(y > 10w) => (z < 100x), z ≤ 100x // y > 0, (x > 0) => (y ≥ 100) assume (c < 4); if :: x++; y += 100; :: (x ≥ 4) -> x++; y++; :: (y > 10w && z ≥ 100x) -> y = −y; fi w = *; z = *; c += 1; assume (y > 10w => z < 100x, z ≤ 100x); } assert (!(x ≥ 4 && y ≤ 2)); Unbounded Inductive Invariant Safe Under-approximate Feasible? YES Solve
Implementation Details – Unbounded Invariants Pre-Lemmas Concrete Counters Post-Lemmas Goal Find maximal such that
Implementation Details – Unbounded Invariants SAT? UNSAT SAT with true Repeat until fixed point