
Model Checking, Theorem Proving, and Abstract Interpretation: The Convergence of Formal Verification Technologies Tom Henzinger EPFL Three Verification Communities • Model checking: -automatic, but inefficient (does not scale) -successful in hardware verification • Theorem proving: -precise, but interactive (requires user intervention) -much recent progress in decision procedures • Static analysis: -efficient, but imprecise (many false positives) -standard in compilers Convergence • Not just interaction of model checkers, theorem provers, and static analyzers via a shared code database • But deep integration of the three technologies within a single tool • Is it a model checker exploring states? A theorem prover manipulating formulas? A static analyzer interpreting an abstract program? All of the above ! Property Checking • Programmer gives partial specifications – Is there a complete spec for Word ? Emacs ? – Often implicit: code annotations, memory safety, race freedom • Code checked for consistency with specification • Different from program correctness – Partial specs of large programs rather than complete specs of small programs Interface Usage Rules • Rules in documentation – Order of operations and data access – Incomplete, unenforced, wordy • Rule violations lead to bad behavior – System crash or deadlock – Unexpected exceptions Property 1: Double Locking lock unlock unlock lock “An attempt to re-acquire an acquired lock or release a released lock will cause a deadlock.” Calls to lock and unlock must alternate. Property 2: IRP Handler start NP CallDriver SKIP1 SKIP2 return Skip child status CallDriver IPC MPR3 synch d NP rne prop CallDriver etu ng r completion PPC ndi MPR t pe Complete no completion CallDriver MPR1 request return MPR2 DC not Pend no prop synch completion CallDriver IRP accessible N/A N/A start P CallDriver Mark Pending SKIP1 SKIP2 Skip CallDriver IPC MPR3 synch ed NP CallDriver return turn prop g re PPC Pending din completion en MPR Complete not p CallDriver completion request MPR2 MPR1 DC no prop completion CallDriver Win NT DDK N/A [Fahndrich] Locking Example ExampleExample ()() {{ 11::do do {{ lock();lock(); oldold == new;new; lock qq == q->next;q->next; 2: if (q != NULL) { 2: if (q != NULL) { unlock 33::q->data q->data == new;new; unlock();unlock(); unlock lock newnew ++;++; }} 44::} } whilewhile (new(new !=!= old);old); 55:: unlock();unlock(); return;return; }} The Model Checking View: Programs are State Transition Systems state transition pc → 3 33:: unlock();unlock(); pc → 4 lock → new++;new++; lock → old → 5 44:: old → 5 new → 5 new → 6 q → 0x133a q → 0x133a ExampleExample ()() {{ 11:: dodo {{ lock();lock(); oldold == newnew;; qq == q->next;q->next; 22:: ifif (q(q !=!= NULL)NULL) {{ 33:: q->dataq->data == new;new; unlock();unlock(); newnew ++;++; [Clarke-Emerson, Queille-Sifakis] }} 44:: }} whilewhile (new(new !=!= old);old); 55:: unlock();unlock(); return;}return;} The Safety Verification Problem Error Safe Theorem proving: guess and verify inductive invariant Initial Is there a path from an initial state to an error state ? The Safety Verification Problem Error Safe Model checking: explore all reachable states Initial Is there a path from an initial state to an error state ? Problem: infinite state graph Solution: set of states ' logical formula Predicate Abstraction •Predicateson program state: lock old = new • States satisfying same predicates are equivalent: merged into one abstract state • Number of abstract states is finite [Cousot-Cousot, Graf-Saidi] Abstract States and Transitions pc → 3 33:: unlock();unlock(); pc → 4 lock → new++;new++; lock → old → 5 44:: old → 5 new → 5 new → 6 q → 0x133a q → 0x133a Theorem Prover lock ¬ lock [Cousot-Cousot, Graf-Saidi] old=new ¬ old=new Abstraction pc → 3 33:: unlock();unlock(); pc → 4 lock → new++;new++; lock → old → 5 44:: old → 5 new → 5 new → 6 q → 0x133a q → 0x133a Theorem Prover lock ¬ lock Existential Lifting old=new ¬ old=new Analyze Abstraction • Analyze finite graph • Overapproximation: –safe ⇒ program safe – no false negatives •Problem: spurious counterexamples – false positives! Counterexample-guided Refinement Solution: Use spurious counterexamples to refine abstraction 1. Add predicates to distinguish states across cut Imprecision due to merge Iterative Abstraction Refinement Solution: Use spurious counterexamples to refine abstraction 1. Add predicates to distinguish states across cut 2. Build refined abstraction eliminates counterexample 3. Repeat search until real counterexample found [Kurshan et al., Clarke et al.] or program proved safe [Ball-Rajamani 01: SLAM] How to Compute Successors ? ExampleExample (( )) {{ 11:: do{do{ LOCK , new=old 3 F lock();lock(); oldold == new;new; OP q = q->next; q = q->next; 4 22:: ifif (q(q !=!= NULL){NULL){ ¬ LOCK , ¬ new=old ? 33:: q->dataq->data == new;new; unlock(); unlock(); For each predicate p newnew ++;++; }} check if p is true (or false) after OP 44:}while(new:}while(new !=!= old);old); 55:: unlock();unlock(); }} Q: When is p true after OP ? -if WP( p,OP) is true before OP - we know F is true before OP - Thm Prover query: F ⇒ WP( p, OP) ? Predicates: LOCK, new=old How to Compute Successors ? ExampleExample (( )) {{ 1: do{ 1: do{ LOCK , new=old 3 q->data = new lock(); F lock(); unlock() oldold == new;new; q = q->next; new++ q = q->next; 4 22:: ifif (q(q !=!= NULL){NULL){ ¬ LOCK , ¬ new=old ? 33:: q->dataq->data == new;new; unlock(); unlock(); For each predicate p newnew ++;++; }} check if p is true (or false) after OP 44:}while(new:}while(new !=!= old);old); 55:: unlock();unlock(); }} Q: When is p true after OP ? -if WP( p, OP) is true before OP - we know F is true before OP - Thm Prover query: F ⇒ WP( p, OP) Predicate: new=old True ? (LOCK , new=old) ⇒ (new + 1 = old) NO False ? (LOCK , new=old) ⇒ (new + 1 ≠ old) YES Abstraction is Expensive Reachable Problem: Observe: #predicates -#abstract states = 2 often only fraction of state space -exponential Thm Prover queries reachable Abstract Only Reachable States Safe Problem: Solution: -#abstract states = 2#predicates build abstraction during search -exponential Thm Prover queries Don’t Refine Error-Free Regions Error Free Problem: Solution: -#abstract states = 2#predicates Refine only spurious -exponential Thm Prover queries counterexamples Putting It Together: Lazy Abstraction Initial 1 Unroll abstraction 1. Pick tree node (= abs. state) 2 2. Add children (= abs. successors) 3. On revisiting abs. state, cut off 3 4 5 Find min. spurious suffix - learn new predicates 3 - rebuild subtree with new predicates Abstract Reachability Tree [Henzinger-Jhala-Majumdar-Sutre 03: BLAST] Putting It Together: Lazy Abstraction Initial 1 Unroll abstraction 1. Pick tree node (= abs. state) 2 2. Add children (= abs. successors) 3. On revisiting abs. state, cut off 3 6 4 5 7 Find min. spurious suffix - learn new predicates 3 3 - rebuild subtree with new predicates Error Free Putting It Together: Lazy Abstraction Initial 1 Unroll abstraction 1. Pick tree node (= abs. state) 2 2. Add children (= abs. successors) 3. On revisiting abs. state, cut off 3 6 4 5 7 8 Find min. spurious suffix - learn new predicates 3 3 1 8 1 - rebuild subtree with new predicates Error Free Only abstract reachable states SAFE Don’t refine error-free regions Abstract Interpretation ExampleExample (( )) {{ 11:: do{do{ lock();lock(); old = new; old = new; 1 ¬ LOCK qq == q->next;q->next; 22:: ifif (q(q !=!= NULL){NULL){ 33:: q->dataq->data == new;new; unlock();unlock(); newnew ++;++; }} 44:}while(new:}while(new !=!= old);old); 55::unlock();unlock(); }} 1 Abstract Reachability Tree Predicates: LOCK Abstract Interpretation ExampleExample (( )) {{ 11:: do{do{ lock();lock(); old = new; old = new; lock() 1 ¬ LOCK qq == q->next;q->next; 22:: ifif (q(q !=!= NULL){NULL){ old = new 3: q->data = new; 3: q->data = new; q=q->next 2 LOCK unlock();unlock(); newnew ++;++; }} 44:}while(new:}while(new !=!= old);old); 55:: unlockunlock ();(); }} 1 2 Abstract Reachability Tree Predicates: LOCK Abstract Interpretation ExampleExample (( )) {{ 11:: do{do{ lock();lock(); old = new; old = new; 1 ¬ LOCK qq == q->next;q->next; 22:: ifif (q(q !=!= NULL){NULL){ 3: q->data = new; 3: q->data = new; 2 LOCK unlock();unlock(); [q!=NULL] newnew ++;++; }} 44:}while(new:}while(new !=!= old);old); 3 LOCK 55:: unlock();unlock(); }} 1 2 3 Abstract Reachability Tree Predicates: LOCK Abstract Interpretation ExampleExample (( )) {{ 11:: do{do{ lock();lock(); old = new; old = new; 1 ¬ LOCK qq == q->next;q->next; 22:: ifif (q(q !=!= NULL){NULL){ 3: q->data = new; 3: q->data = new; 2 LOCK unlock();unlock(); newnew ++;++; }} 44:}while(new:}while(new !=!= old);old); q->data = new 3 LOCK 55:: unlock();unlock(); }} unlock() new++ 4 ¬ LOCK 4 1 2 3 Abstract Reachability Tree Predicates: LOCK Abstract Interpretation ExampleExample (( )) {{ 11:: do{do{ lock();lock(); old = new; old = new; 1 ¬ LOCK qq == q->next;q->next; 22:: ifif (q(q !=!= NULL){NULL){ 3: q->data = new; 3: q->data = new; 2 LOCK unlock();unlock(); newnew ++;++; }} 44:}while(new:}while(new !=!= old);old); 3 LOCK 55:: unlock();unlock(); }} 4 ¬ LOCK [new==old] 5 ¬ LOCK 5 4 1 2 3 Abstract Reachability Tree Predicates: LOCK Abstract Interpretation ExampleExample (( )) {{ 11:: do{do{ lock();lock(); old = new; old = new; 1 ¬ LOCK qq == q->next;q->next; 22:: ifif (q(q !=!= NULL){NULL){ 3: q->data = new; 3: q->data = new; 2 LOCK unlock();unlock(); newnew ++;++; }} 44:}while(new:}while(new !=!= old);old); 3 LOCK 55:: unlock();unlock(); }} 4 ¬ LOCK 5 ¬ LOCK 5 unlock() 4 ¬ LOCK 1 2
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages61 Page
-
File Size-