Lazy Abstraction Jinseong Jeon ARCS, KAIST
CS750b, KAIST2/26 References Lazy Abstraction –Thomas A. Henzinger et al., POPL ’02 Software verification with BLAST –and tutorial slide (SPIN ’05) plus, BLAST slide –presented by Tai Hyo Kim (KPRG)
CS750b, KAIST3/26 Program’s Behaviors State transition pc 3 old 2 new 2 pc 4 old 2 new 3 new++;
CS750b, KAIST4/26 Safety Verification Initial Error Safe for s 2 Initial, s’ 2 Error 9 . s ! s’ ?
CS750b, KAIST5/26 Size does matter! Problem: Infinite state graph Solution: Abstraction! How? Galois connection, Predicate abstraction, etc.
CS750b, KAIST6/26 Predicate Abstraction Predicate old == new, etc. Predicate ' states « p ¬ = { s 2 S | s ² p } #abstract states is finite
CS750b, KAIST7/26 Abstraction State transition pc 3 old 2 new 2 pc 4 old 2 new 3 new++; transition p : p p, (old == new)
CS750b, KAIST8/26 Abstraction (cont’)
CS750b, KAIST9/26 Analysis on Abstraction Analyze finite graph Over Approximate: Safe ) System Safe No false negatives Problem: Spurious counter.ex. vS S (over approximate) E vE (soundness of verifier) vE E (completeness of verifier) vE S (false positive) vS E (false negative) VerifierReal System vSS vEE
CS750b, KAIST10/26 Counter ex. -guided Refinement Solution: Use spurious counter ex. to refine abstraction imprecision due to merge 1. Add predicates to distinguish states across cut 2. Build refined abstraction
CS750b, KAIST11/26 Iterative Abstract-Refine 1. Add predicates to distinguish states across cut 2. Build refined abstraction 3. Repeat search till real counter ex. or system proved safe
CS750b, KAIST12/26 Software Model-checking AbstractionVerificationRefinement Program Property safe C.E. unsafe real error [error-free] [too coarse abstraction] BLAST
CS750b, KAIST13/26 BLAST –Berkeley Lazy Abstraction Software verification Tool Lazy Abstraction –tightly integrates verifying 3 steps –increases granularity on demand –reuses what the previous iterations calculate
CS750b, KAIST14/26 Abstraction Cost Reachable Problem #abstract states = 2 #predicates Observe Fraction of state space reachable #Preds ~ 100’s, #States ~ 2 100, #Reach ~ 1000’s
CS750b, KAIST15/26 S1: Only Abstract Reachable States Solution Build abstraction during search Reachable
CS750b, KAIST16/26 S2: Don’t Refine Error-Free Regions Solution Don’t refine error-free regions Error Free
CS750b, KAIST17/26 A Locking Example Example() { 1: if (*) { 7: do { get_lock = 0; 8: if (*) { 9: lock(); get_lock++; } 10: if (get_lock) { 11: unlock(); } 12: } while (*) } 2: do { lock(); old = new; 3: if (*) { 4: unlock(); new++; } 5: } while (new != old); 6: unlock(); return; } lock() { if (LOCK == 0) { LOCK = 1; } else { ERROR } unlock() { if (LOCK == 1) { LOCK = 0; } else { ERROR } lock unlock
CS750b, KAIST18/26 Control Flow Automaton Example() { 1: if (*) { 7: do { get_lock = 0; 8: if (*) { 9: lock(); get_lock++; } 10: if (get_lock) { 11: unlock(); } 12: } while (*) } 2: do { lock(); old = new; 3: if (*) { 4: unlock(); new++; } 5: } while (new != old); 6: unlock(); return; } ret [T] [new!=old] [new==old] [get_lock!=0] [get_lock==0] lock() old=new unlock() new++ get_lock=0 lock() get_lock++ unlock()
CS750b, KAIST19/26 Lazy Abstraction Framework 1.Forward search Approximate forward symbolic transition Generate reachability tree in depth-first order 2.Backwards c.e. analysis Precise backward computation to a pivot node 3.Search with new predicates Add a minimal set of new predicates to refine Continue Step 1 from the pivot node
CS750b, KAIST20/26 Forward Search 2: do { lock(); old = new; 3: if (*) { 4: unlock(); new++; } 5: } while (new != old); 6: unlock(); return; Predicates: LOCK 1 1 Reachability Tree err LOCK = 0 [T] lock() old=new LOCK = 0 LOCK = 1 [T] unlock() new++ LOCK = 1 LOCK = 0 [new==old] unlock() LOCK =
CS750b, KAIST21/26 Backwards C.E. Analysis err LOCK = 0 lock() old=new LOCK = 0 LOCK = 1 unlock() new++ LOCK = 1 LOCK = 0 unlock() LOCK = 0 [new == old] {LOCK = 0 } {LOCK = 0, new==old } {LOCK = 1, new+1==old } {LOCK = 0, new+1==new } WP(p,op): Weakest Preconditions = { p’ 2 P | n ! op n’, n ² p’ ) n’ ² p } « p ¬« p ¬ n’ OP « WP(p,op) ¬ n « p ¬ = { s 2 S | s ² p } p n’ [c] c Æ p n p n’ x=e p[e/x] n n’ n r r’= post(r, ) E E ’= pre( E, ) r’ Å E ; r Å E ’ = ;
CS750b, KAIST22/26 Search with new Predicates 2: do { lock(); old = new; 3: if (*) { 4: unlock(); new++; } 5: } while (new != old); 6: unlock(); return; Predicates: LOCK, new = old LOCK = 0 lock() old=new LOCK = 0 LOCK = 1 Æ new = old [T] unlock() new++ LOCK = 1 Æ new = old LOCK = 0 Æ new old FALSE [new!=old] LOCK = 0 Æ new old < LOCK = 0 5 [T] LOCK = 1 Æ new = old 26 6 [new==old] FALSE LOCK = 1 Æ new = old ret unlock() LOCK = 0 Æ new = old Safe!
CS750b, KAIST23/26 Savings 1 2 LOCK = 0 7 err new pred get_lock = LOCK = 0 Æ... COVERED! new pred get_lock = 0 new pred new = old
CS750b, KAIST24/26 Local Predicate Use Use predicates needed at location #Preds. grows with program size #Preds per location small Local Predicate use Ex: 2n states Global Predicate use Ex: 2 n states
CS750b, KAIST25/26 Experiments funlock: the locking example read: serial driver floppy: floppy driver
CS750b, KAIST26/26 Conclusions Lazy Abstraction –iterates the abstract-check-refine loop tightly –avoids redundant abstraction and checking by adding predicates in case of need by remaining prior results as possible Something interesting(?), but omitted here: –generic design of the algorithm –several formalisms and correctness theorems