Presentation is loading. Please wait.

Presentation is loading. Please wait.

Program Verification by Lazy Abstraction

Similar presentations


Presentation on theme: "Program Verification by Lazy Abstraction"— Presentation transcript:

1 Program Verification by Lazy Abstraction
Lecture 1 Ranjit Jhala UC San Diego With: Tom Henzinger, Rupak Majumdar, Ken McMillan, Gregoire Sutre, Adam Chlipala

2 Software Validation Large scale reliable software is hard to build and test Different groups write different components Integration testing is a nightmare

3 Property Checking Programmer gives partial specifications
Code checked for consistency w/ spec Different from program correctness Specifications are not complete Is there a complete spec for Word ? Emacs ?

4 Interface Usage Rules Rules in documentation
Order of operations & data access Resource management Incomplete, unenforced, wordy Violated rules ) bad behavior System crash or deadlock Unexpected exceptions Failed runtime checks

5 Property 1: Double Locking
unlock “An attempt to re-acquire an acquired lock or release a released lock will cause a deadlock.” Calls to lock and unlock must alternate.

6 Property 2: Drop Root Privilege
[Chen-Dean-Wagner ’02] “User applications must not run with root privilege” When execv is called, must have suid  0

7 Property 3 : IRP Handler [Fahndrich] MPR3 CallDriver MPR completion
synch not pending returned SKIP2 IPC Skip return child status DC Complete request not Pend PPC prop N/A no prop start NP Pending NP MPR1 start P Mark Pending IRP accessible SKIP1 MPR2 [Fahndrich]

8 Does a given usage rule hold?
Undecidable! Equivalent to the halting problem Restricted computable versions are prohibitively expensive (PSPACE) Why bother ? Just because a problem is undecidable, it doesn’t go away! May be do this through an example

9 Example Example ( ) { 1: do{ lock(); old = new; q = q->next;
2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4: } while(new != old); 5: unlock (); return; lock unlock

10 What a program really is…
State Transition pc lock old new q  3  5  0x133a 3: unlock(); new++; 4:} … pc lock old new q  4  5  6  0x133a Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4: } while(new != old); 5: unlock (); return;}

11 The Safety Verification Problem
Error Safe Initial Is there a path from an initial to an error state ? Problem: Infinite state graph Solution : Set of states ' logical formula

12 Representing States as Formulas
states satisfying F {s | s ² F } F FO fmla over prog. vars [F1] Å [F2] F1 Æ F2 [F1] [ [F2] F1 Ç F2 May be do this through an example [F] : F [F1] µ [F2] F1 implies F2 i.e. F1Æ: F2 unsatisfiable

13 Idea 1: Predicate Abstraction
Predicates on program state: lock old = new States satisfying same predicates are equivalent Merged into one abstract state #abstract states is finite

14 Abstract States and Transitions
pc lock old new q  3  5  0x133a 3: unlock(); new++; 4:} … pc lock old new q  4  5  6  0x133a Theorem Prover lock old=new : lock : old=new

15 Abstraction State Existential Lifting Theorem Prover lock : lock
pc lock old new q  3  5  0x133a 3: unlock(); new++; 4:} … pc lock old new q  4  5  6  0x133a Theorem Prover lock old=new : lock : old=new Existential Lifting

16 Abstraction State lock : lock old=new : old=new 3: unlock(); new++;
pc lock old new q  3  5  0x133a 3: unlock(); new++; 4:} … pc lock old new q  4  5  6  0x133a lock old=new : lock : old=new

17 Analyze Abstraction Problem Analyze finite graph No false negatives
Over Approximate: Safe ) System Safe No false negatives Problem Spurious counterexamples

18 Idea 2: Counterex.-Guided Refinement
Solution Use spurious counterexamples to refine abstraction !

19 Idea 2: Counterex.-Guided Refinement
Solution Use spurious counterexamples to refine abstraction 1. Add predicates to distinguish states across cut 2. Build refined abstraction Imprecision due to merge

20 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 Till real counterexample or system proved safe [Kurshan et al 93] [Clarke et al 00] [Ball-Rajamani 01]

21 Lazy Abstraction BLAST Safe Abstract Refine Trace Yes C Program No
Property Trace

22 Problem: Abstraction is Expensive
Reachable Problem #abstract states = 2#predicates Exponential Thm. Prover queries Observe Fraction of state space reachable #Preds ~ 100’s, #States ~ 2100 , #Reach ~ 1000’s

23 Solution1: Only Abstract Reachable States
Safe Solution Build abstraction during search Problem #abstract states = 2#predicates Exponential Thm. Prover queries

24 Solution2: Don’t Refine Error-Free Regions
Problem #abstract states = 2#predicates Exponential Thm. Prover queries Solution Don’t refine error-free regions

25 Key Idea: Reachability Tree
Initial Unroll Abstraction 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 Find min infeasible suffix - Learn new predicates - Rebuild subtree with new preds. 4 5 3

26 Key Idea: Reachability Tree
Initial Unroll Abstraction 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 6 Find min infeasible suffix - Learn new predicates - Rebuild subtree with new preds. 4 5 7 3 3 Error Free

27 Key Idea: Reachability Tree
Initial Unroll 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 6 Find min spurious suffix - Learn new predicates - Rebuild subtree with new preds. 4 5 7 8 3 3 1 8 1 Error Free S1: Only Abstract Reachable States S2: Don’t refine error-free regions SAFE

28 Build-and-Search Reachability Tree Predicates: LOCK 1 1 Example ( ) {
1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 1 Reachability Tree Predicates: LOCK

29 Build-and-Search Reachability Tree Predicates: LOCK 1 2 1 2
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); lock() old = new q=q->next 1 : LOCK 2 LOCK 1 2 Reachability Tree Predicates: LOCK

30 Build-and-Search Reachability Tree Predicates: LOCK 1 2 3 1 2 3
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK [q!=NULL] 3 LOCK 1 2 3 Reachability Tree Predicates: LOCK

31 Build-and-Search Reachability Tree Predicates: LOCK 1 2 3 4 4 1 2 3
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK 3 q->data = new unlock() new++ LOCK 4 : LOCK 4 1 2 3 Reachability Tree Predicates: LOCK

32 Build-and-Search Reachability Tree Predicates: LOCK 1 2 3 4 5 5 4 1 2
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK 3 LOCK 4 : LOCK [new==old] 5 : LOCK 5 4 1 2 3 Reachability Tree Predicates: LOCK

33 Build-and-Search Reachability Tree Predicates: LOCK 1 2 3 4 5 5 4 1 2
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK 3 LOCK 4 : LOCK 5 : LOCK 5 unlock() 4 : LOCK 1 2 3 Reachability Tree Predicates: LOCK

34 Analyze Counterexample
1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK lock() old = new q=q->next 2 LOCK [q!=NULL] 3 LOCK q->data = new unlock() new++ 4 : LOCK [new==old] 5 : LOCK 5 unlock() 4 : LOCK 1 2 3 Reachability Tree Predicates: LOCK

35 Analyze Counterexample
1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK old = new 2 LOCK 3 LOCK new++ 4 : LOCK [new==old] 5 : LOCK 5 Inconsistent 4 : LOCK new == old 1 2 3 Reachability Tree Predicates: LOCK

36 Repeat Build-and-Search
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 1 Reachability Tree Predicates: LOCK, new==old

37 Repeat Build-and-Search
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK lock() old = new q=q->next 2 LOCK , new==old 1 2 Reachability Tree Predicates: LOCK, new==old

38 Repeat Build-and-Search
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK , new==old LOCK , new==old 3 q->data = new unlock() new++ 4 : LOCK , : new = old 4 1 2 3 Reachability Tree Predicates: LOCK, new==old

39 Repeat Build-and-Search
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK , new==old LOCK , new==old 3 4 : LOCK , : new = old [new==old] 4 1 2 3 Reachability Tree Predicates: LOCK, new==old

40 Repeat Build-and-Search
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK , new==old LOCK , new==old 3 4 : LOCK , : new = old [new!=old] 1 : LOCK, : new == old 4 4 1 2 3 Reachability Tree Predicates: LOCK, new==old

41 Repeat Build-and-Search
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK , new==old SAFE LOCK , new==old 3 4 4 : LOCK , : new = old LOCK , new=old 1 5 5 : LOCK, : new == old 4 4 4 1 : LOCK , new==old 2 3 Reachability Tree Predicates: LOCK, new==old

42 Key Idea: Reachability Tree
Initial Unroll 1. Pick tree-node (=abs. state) 2. Add children (=abs. successors) 3. On re-visiting abs. state, cut-off 1 2 3 6 Find min spurious suffix - Learn new predicates - Rebuild subtree with new preds. 4 5 7 8 3 3 1 8 1 Error Free S1: Only Abstract Reachable States S2: Don’t refine error-free regions SAFE

43 Two handwaves SAFE Reachability Tree Predicates: LOCK, new==old 1 2 3
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK 2 LOCK , new==old SAFE LOCK , new==old 3 4 4 : LOCK , : new = old LOCK , new=old 1 5 5 : LOCK, : new == old 4 4 4 1 : LOCK , new==old 2 3 Reachability Tree Predicates: LOCK, new==old

44 Two handwaves SAFE Q. How to compute “successors” ? Reachability Tree
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK Q. How to compute “successors” ? 2 LOCK , new==old SAFE LOCK , new==old 3 LOCK , new==old 3 q->data = new unlock() new++ 4 4 4 : LOCK , : new = old : LOCK , : new = old LOCK , new=old 1 5 5 : LOCK, : new == old 4 4 4 1 : LOCK , new==old 2 3 Reachability Tree Predicates: LOCK, new==old

45 Two handwaves SAFE Q. How to compute “successors” ?
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK Q. How to compute “successors” ? 2 LOCK , new==old SAFE LOCK , new==old 3 4 4 : LOCK , : new = old LOCK , new=old Q. How to find predicates ? 1 5 5 Refinement : LOCK, : new == old 4 4 4 1 : LOCK , new==old 2 3 Predicates: LOCK, new==old

46 Two handwaves SAFE Q. How to compute “successors” ? Refinement
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); 1 : LOCK Q. How to compute “successors” ? 2 LOCK , new==old SAFE LOCK , new==old 3 4 4 : LOCK , : new = old LOCK , new=old 1 5 5 Refinement : LOCK, : new == old 4 4 4 1 : LOCK , new==old 2 3 Predicates: LOCK, new==old

47 Weakest Preconditions
WP(P,OP) Weakest formula P’ s.t. if P’ is true before OP then P is true after OP [WP(P, OP)] OP [P]

48 Weakest Preconditions
WP(P,OP) Weakest formula P’ s.t. if P’ is true before OP then P is true after OP [WP(P, OP)] OP [P] P[e/x] new+1 = old Assign new = new+1 x = e P new = old

49 Weakest Preconditions
WP(P,OP) Weakest formula P’ s.t. if P’ is true before OP then P is true after OP [WP(P, OP)] OP [P] c ) P new=old ) new=old Assume Branch [new=old] [c] P new = old

50 How to compute successor ?
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); LOCK , new==old 3 F OP 4 ? : LOCK , : new = old For each p Check if p is true (or false) after OP Q: When is p true after OP ? - If WP(p, OP) is true before OP ! - We know F is true before OP - Thm. Pvr. Query: F ) WP(p, OP) Predicates: LOCK, new==old

51 How to compute successor ?
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); LOCK , new==old 3 F OP 4 ? For each p Check if p is true (or false) after OP Q: When is p false after OP ? - If WP(: p, OP) is true before OP ! - We know F is true before OP - Thm. Pvr. Query: F ) WP(: p, OP) Predicates: LOCK, new==old

52 How to compute successor ?
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4:}while(new != old); 5: unlock (); LOCK , new==old 3 F OP 4 ? : new = old : LOCK , : new = old For each p Check if p is true (or false) after OP Q: When is p false after OP ? - If WP(: p, OP) is true before OP ! - We know F is true before OP - Thm. Pvr. Query: F ) WP(: p, OP) Predicate: new==old True ? (LOCKÆ new==old) ) (new + 1 = old) NO False ? (LOCKÆ new==old) ) (new + 1  old) YES

53 Lazy Abstraction Problem: Abstraction is Expensive
Yes Safe C Program Abstract Refine No Property Trace Problem: Abstraction is Expensive Solution: 1. Abstract reachable states, Avoid refining error-free regions Key Idea: Reachability Tree

54 Property: IRP Handler [Fahndrich] MPR3 CallDriver MPR completion synch
not pending returned SKIP2 IPC Skip return child status DC Complete request not Pend PPC prop N/A no prop start NP Pending NP MPR1 start P Mark Pending IRP accessible SKIP1 MPR2 [Fahndrich]

55 Results Program kbfiltr 12k 1 34 floppy 17k 7 93 diskprf 14k 5 71
Property3: IRP Handler Win NT DDK Results Program Lines* Time(mins) Predicates kbfiltr 12k 1 34 floppy 17k 7 93 diskprf 14k 5 71 cdaudio 18k 20 85 parport 61k DNF parclss 138k * Pre-processed

56 #Predicates grows with program size
while(1){ 1: if (p1) lock() ; if (p1) unlock() ; 2: if (p2) lock() ; if (p2) unlock() ; n: if (pn) lock() ; if (pn) unlock() ; } T F Tracking lock not enough Problem: p1,…,pn needed for verification Exponential reachable abstract states

57 #Predicates grows with program size
while(1){ 1: if (p1) lock() ; if (p1) unlock() ; 2: if (p2) lock() ; if (p2) unlock() ; n: if (pn) lock() ; if (pn) unlock() ; } : LOCK LOCK, p1 : LOCK, : p1 : LOCK, p1 : LOCK, : p1 : LOCK p1p2 p1: p2 : p1 p2 : p1: p2 2n Abstract States Problem: p1,…,pn needed for verification Exponential reachable abstract states

58 Predicates useful locally
while(1){ 1: if (p1) lock() ; if (p1) unlock() ; 2: if (p2) lock() ; if (p2) unlock() ; n: if (pn) lock() ; if (pn) unlock() ; } : LOCK p1 LOCK , p1 : LOCK, : p1 : LOCK , p1 : LOCK : LOCK : LOCK : LOCK , : p1 LOCK , p2 : LOCK , : p2 : LOCK p2 pn 2n Abstract States Solution: Use predicates only where needed Using Counterexamples: Q1. Find predicates Q2. Find where predicates are needed

59 Lazy Abstraction Safe Abstract Refine Trace
Yes Safe C Program Abstract Refine No Property Trace Problem: #Preds grows w/ Program Size Solution: Localize pred. use, find where preds. needed Ctrex. Trace Pred. Map PC  Preds. Refine

60 Counterexample Traces
1: x = ctr; 2: ctr = ctr + 1; 3: y = ctr; 4: if (x = i-1){ 5: if (y != i){ ERROR: } } 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) y = x +1

61 Trace Formulas Thm: Trace is feasible , TF is satisfiable Trace
1: x = ctr 2: ctr = ctr+1 3: y = ctr 4: assume(x=i-1) 5: assume(yi) 1: x1 = ctr0 2: ctr1 = ctr0+1 3: y1 = ctr1 4: assume(x1=i0-1) 5: assume(y1i0) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Trace SSA Trace Trace Feasibility Formula Thm: Trace is feasible , TF is satisfiable

62 The Present State… … is all the information the
Trace 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) … is all the information the executing program has here State… 1. … after executing trace past (prefix) 2. … knows present values of variables 3. … makes trace future (suffix) infeasible At pc4, which predicate on present state shows infeasibility of future ?

63 What Predicate is needed ?
Trace Trace Formula (TF) 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0 +1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0

64 What Predicate is needed ?
Trace Trace Formula (TF) 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Relevant Information Predicate … 1. … after executing trace prefix … implied by TF prefix

65 What Predicate is needed ?
Trace Trace Formula (TF) 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 x1 x1 Relevant Information Predicate … 1. … after executing trace prefix 2. … has present values of variables … implied by TF prefix … on common variables

66 What Predicate is needed ?
Trace Trace Formula (TF) 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Relevant Information Predicate … 1. … after executing trace prefix 2. … has present values of variables 3. … makes trace suffix infeasible … implied by TF prefix … on common variables … & TF suffix is unsatisfiable

67 What Predicate is needed ?
Trace Trace Formula (TF) 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Relevant Information Predicate … 1. … after executing trace prefix 2. … has present values of variables 3. … makes trace suffix infeasible … implied by TF prefix … on common variables … & TF suffix is unsatisfiable

68 Interpolant = Predicate !
Trace Trace Formula 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Predicate at 4: y= x+1 - Interpolate + y1 = x1 + 1 Craig Interpolant [Craig 57] Computable from Proof of Unsat [Krajicek 97] [Pudlak 97] Predicate … … implied by TF prefix … on common variables … & TF suffix is unsatisfiable

69 Another interpretation …
Trace Formula x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Predicate at 4: y= x+1 After exec prefix - - Interpolate Can exec suffix + + y1 = x1 + 1 Unsat = Empty Intersection = Trace Infeasible Interpolant  = Overapproximate states after prefix That cannot execute suffix

70 Interpolant = Predicate !
Trace Trace Formula 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Predicate at 4: y= x+1 - Interpolate + y1 = x1 + 1 Craig Interpolant [Craig 57] Computable from Proof of Unsat [Krajicek 97] [Pudlak 97] Predicate … … implied by TF prefix … on common variables … & TF suffix is unsatisfiable

71 Interpolant = Predicate !
Trace Trace Formula 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Predicate at 4: y= x+1 - Interpolate Q. How to compute interpolants ? … + y1 = x1 + 1 Craig Interpolant [Craig 57] Computable from Proof of Unsat [Krajicek 97] [Pudlak 97] Predicate … … implied by TF prefix … on common variables … & TF suffix is unsatisfiable

72 Building Predicate Maps
2: x= ctr Trace Trace Formula - 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 Interpolate x1 = ctr0 + Cut + Interpolate at each point Pred. Map: pci  Interpolant from cut i

73 Building Predicate Maps
2: x = ctr 3: x= ctr-1 Trace Trace Formula 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 - Interpolate + x1= ctr1-1 Cut + Interpolate at each point Pred. Map: pci  Interpolant from cut i

74 Building Predicate Maps
2: x = ctr 3: x= ctr - 1 4: y= x + 1 Trace Trace Formula 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 - + Interpolate y1= x1+1 Cut + Interpolate at each point Pred. Map: pci  Interpolant from cut i

75 Building Predicate Maps
2: x = ctr 3: x= ctr - 1 4: y= x + 1 5: y = i Trace Trace Formula 1: x = ctr 2: ctr = ctr + 1 3: y = ctr 4: assume(x = i-1) 5: assume(y  i) x1 = ctr0 Æ ctr1 = ctr0+ 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 - + Interpolate y1= i0 Cut + Interpolate at each point Pred. Map: pci  Interpolant from cut i

76 Local Predicate Use Verification scales …
Use predicates needed at location #Preds. grows with program size #Preds per location small Predicate Map 2: x = ctr 3: x= ctr - 1 4: y= x + 1 5: y = i Verification scales … Local Predicate use Ex: 2n states Global Predicate use Ex: 2n states

77 Results Program kbfiltr 12k 1 3 72 6.5 floppy 17k 7 25 240 7.7 diskprf
Property3: IRP Handler Win NT DDK Results Program Lines* Previous Time(mins) Time (mins) Predicates Total Average kbfiltr 12k 1 3 72 6.5 floppy 17k 7 25 240 7.7 diskprf 14k 5 13 140 10 cdaudio 18k 20 23 256 7.8 parport 61k DNF 74 753 8.1 parclss 138k 77 382 7.2 * Pre-processed

78 Localizing Program kbfiltr 12k 1 3 72 6.5 floppy 17k 7 25 240 7.7
Property3: IRP Handler Win NT DDK Localizing Program Lines* Previous Time(mins) Time (mins) Predicates Total Average kbfiltr 12k 1 3 72 6.5 floppy 17k 7 25 240 7.7 diskprf 14k 5 13 140 10 cdaudio 18k 20 23 256 7.8 parport 61k DNF 74 753 8.1 parclss 138k 77 382 7.2 * Pre-processed

79 Q. How to compute interpolants ?

80 Proof of Unsatisfiability
x1 = ctr0 Æ ctr1 = ctr0 + 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 x1 = ctr0 x1 = i0 -1 ctr0 = i0-1 ctr1= ctr0+1 ctr1 = i0 y1= ctr1 y1= i0 y1 i0 ; Trace Formula Proof of Unsatisfiability

81 Another Proof of Unsatisfiability
£ (-1) £ 1 x1 = ctr0 x1 = i0 -1 ctr0 = i0-1 ctr1= ctr0+1 ctr1 = i0 y1= ctr1 y1= i0 y1 i0 ; Proof of Unsatisfiability x1– ctr0=0 x1-i0 +1=0 £ 1 ctr0-i0+1=0 ctr1- ctr0-1=0 £ 1 ctr1-i0 =0 y1-ctr1=0 £ 1 y1-i0=0 y1-i0 0 0 0 Rewritten Proof

82 Interpolant from Rewritten Proof ?
£ (-1) £ 1 x1 = ctr0 Æ ctr1 = ctr0 + 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 x1– ctr0=0 x1-i0 +1=0 £ 1 ctr0-i0+1=0 ctr1- ctr0-1=0 £ 1 ctr1-i0 =0 y1-ctr1=0 Interpolate £ 1 y1-i0=0 y1-i0 0 0 0 Trace Formula Rewritten Proof

83 Interpolant from Rewritten Proof ?
x1 = ctr0 Æ ctr1 = ctr0 + 1 Æ y1 = ctr1 Æ x1 = i0 - 1 Æ y1  i0 x1– ctr0=0 £ (-1) ctr1- ctr0-1=0 £ 1 y1-ctr1=0 £ 1 Interpolate y1-x1-1=0 y1=x1+1 Trace Formula Interpolant !

84 Lazy Abstraction Safe Abstract Refine Trace
Yes Safe C Program Abstract Refine No Property Trace Problem: #Preds grows w/ Program Size Solution: Localize pred. use, find where preds. needed Refine Trace Feas Formula Ctrex. Trace Proof of Unsat Pred. Map PC  Preds. Thm Pvr Interpolate

85 Recap … Lazy Abstraction for Sequential Programs Predicates:
Abstract infinite program states Counterexample-guided Refinement: Find predicates tailored to prog, property Abstraction : Expensive Reachability Tree Refinement : Find predicates, use locations Proof of unsat of TF + Interpolation

86 A Choice Procedure Summaries Finish

87 Next: Modular Lazy Abstraction
Using Procedure Summaries

88 An example main(){  1: if (flag){ 2: y = inc(x,flag);
3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv;

89 Inline Calls in Reach Tree
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; Initial 1 2 4 1,2 1,4 2,2 3,2 2,4 3,4 inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; 4,2 4,2 4,4 4,4 3 3 5 5

90 Inline Calls in Reach Tree
Problem Repeated analysis for “inc” Exploding call contexts Initial 1 2 4 int x; //global f1(){ 1: x = 0; 2: if(*) f2(); 3: else f2(); 4: if (x<0) ERROR; return; } 1,2 1,4 f2(){ 1: if(*) f3(); 2: else f3(); return; } f3(){ 1: if(*) f4(); 2: else f4(); return; } 2,2 3,2 2,4 3,4 f4(){ 1: if(*) f5(); 2: else f5(); return; } fn(){ 1: x ++; return; } 4,2 4,2 4,4 4,4 3 3 5 5 2n nodes in Reach Tree

91 Inline Calls in Reach Tree
Problem Repeated analysis for “inc” Exploding call contexts Cyclic call graph (Recursion) Infinite Tree! Initial 1 2 4 1,2 1,4 2,2 3,2 2,4 3,4 4,2 4,2 4,4 4,4 3 3 5 5

92 Solution : Procedure Summaries
Summaries: Input/Output behavior Plug summaries in at each callsite … instead of inlining entire procedure [Sharir-Pnueli 81, Reps-Horwitz-Sagiv 95] Summary = set of (F  F’) F : Precondition formula describing input state F’ : Postcondition formula describing output state

93 Solution : Procedure Summaries
Summaries: Input/Output behavior Plug summaries in at each callsite … instead of inlining entire procedure [Sharir-Pnueli 81, Reps-Horwitz-Sagiv 95, Ball-Rajamani 01] Summary = set of (F  F’) F : Precondition formula describing input state F’ : Postcondition formula describing output state inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; (: sign=0  rv > a) (sign = 0  rv < a) Q. How to compute, use summaries ?

94 Lazy Abstraction + Procedure Summaries
Yes Safe C Program Abstract Refine No Property Trace Q. How to compute, use summaries ?

95 Abstraction with Summaries
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main 1 [flag!=0] 2 : flag=0 a=x sign=flag : sign=0 inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a

96 Abstraction with Summaries
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main inc 1 : sign=0 1 [sign!=0] 2 : flag=0 : sign=0 2 a=x sign=flag rv=a+1 : sign=0 rv>a 4 inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a),

97 Summary Successor main inc Predicates: flag=0 , y>x , y<z
1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main inc 1 : sign=0 1 2 a=x sign=flag : flag=0 2 assume rv>a 3 y>x y=rv rv>a 4 inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a),

98 Abstraction with Summaries
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main inc 1 : sign=0 1 [flag==0] [sign=0] 2 4 : flag=0 flag=0 2 3 y>x 3 sign=0 rv>a 4 [y<=x] a=x sign=flag inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a),

99 Abstraction with Summaries
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main inc 1 : sign=0 1 1 sign=0 2 4 : flag=0 flag=0 2 3 2 3 y>x 3 sign=0 rv>a 4 4 rv<a a=x sign=flag inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a), (sign=0  rv<a)

100 Summary Successor main inc Predicates: flag=0 , y>x , y<z
1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main inc 1 : sign=0 1 1 sign=0 2 4 : flag=0 flag=0 2 3 2 3 y>x 3 3 y<z rv>a 4 4 rv<a a=x sign=flag inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; assume rv<a y=rv Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a), (sign=0  rv<a)

101 Abstraction with Summaries
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; main inc 1 : sign=0 1 1 sign=0 2 4 : flag=0 flag=0 2 3 2 3 y>x 3 3 y<z rv>a 4 4 rv<a [y>=z] inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; Predicates: flag=0 , y>x , y<z sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a), (sign=0  rv<a)

102 Another Call … main inc Predicates: flag=0 ,y>x,y<z, y1>z1
1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; main inc 1 : sign=0 1 1 sign=0 2 4 : flag=0 flag=0 2 3 2 3 y>x 3 3 y<z rv>a 4 4 rv<a inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; 6 6 a=z1 sign=1 : sign=0 Predicates: flag=0 ,y>x,y<z, y1>z1 sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a), (sign=0  rv<a)

103 Another Call … Note: Predicates are well-scoped … SAFE main inc
1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } 6: y1 = inc(z1,1); 7: if (y1<=z1) ERROR; return; main inc 1 : sign=0 1 1 sign=0 2 4 : flag=0 flag=0 2 3 2 3 y>x 3 3 y<z rv>a 4 4 rv<a Note: Predicates are well-scoped … inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv; 6 6 SAFE a=z1 sign=1 y1>z1 7 assume rv>a y1=rv Predicates: flag=0 ,y>x,y<z, y1>z1 sign=0 , rv>a , rv<a Summary: (: sign=0  rv>a), (sign=0  rv<a)

104 Lazy Abstraction + Procedure Summaries
Yes Safe C Program Abstract Refine No Property Trace Q. How to find scoped predicates ?

105 Traces with Procedure Calls
Trace Formula pc1: x1 = 3 pc2: assume (x1>0) pc3: x3 = f1(x1) pc4: y2 = y1 pc5: y3 = f2(y2) pc6: z2 = z1+1 pc7: z3 = 2*z2 pc8: return z3 pc9: return y3 pc10: x4 = x3+1 pc11: x5 = f3(x4) pc12: assume(w1<5) pc13: return w1 pc14: assume x4>5 pc15: assume (x1=x3+2) pc1: x1 = 3 pc2: assume (x1>0) pc3: x3 = f1(x1) pc4: y2 = y1 pc5: y3 = f2(y2) pc6: z2 = z1+1 pc7: z3 = 2*z2 pc8: return z3 pc9: return y3 pc10: x4 = x3+1 pc11: x5 = f3(x4) pc12: assume(w1<5) pc13: return w1 pc14: assume x4>5 pc15: assume(x1=x3+2) Find predicate needed at point i i i

106 Interprocedural Analysis
Trace Trace Formula NO Find predicate needed at point i YES i i NO Require at each point i: Scoped predicates YES: Variables visible at i NO: Caller’s local variables

107 Problems with Cutting - + i i
Trace Trace Formula - i i + Caller variables common to - and + Unsuitable interpolant: not well-scoped

108 Scoped Cuts Trace Trace Formula Call begins i i

109 Scoped Cuts + - i i Predicate at pci = Interpolant from cut i Trace
Trace Formula Call begins + - i i Predicate at pci = Interpolant from cut i

110 Common Variables + - i i Predicate at pci = Interpolant from i-cut
Trace Trace Formula Common Variables Formals + - Formals i i Current locals Well-scoped Predicate at pci = Interpolant from i-cut

111 Example Trace m1: assume(flag!=0) m2: y=inc(x,flag)
main(){ 1: if (flag){ 2: y = inc(x,flag); 3: if (y<=x) ERROR; } else { 4: y = inc(z,flag); 5: if (y>=z) ERROR; } return; m1: assume(flag!=0) m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) ERROR: inc(int a, int sign){ 1: if (sign){ 2: rv = a+1; } else { 3: rv = a-1; } 4: return rv;

112 Trace Formula Trace SSA Trace m1: assume(flag!=0) m2: y=inc(x,flag)
i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) m1: assume(flag0!=0) m2: a0=x0, sign0=flag0 i1: assume(sign0!=0) i2: rv0=a0+1 i4: y0=rv0 m3: assume(y0 <= x0) Trace SSA Trace

113 Trace Formula i i Trace Trace Formula m1: assume(flag!=0)
m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag0  0 Æ a0=x0 Æ sign0= flag0 Æ sign0  0 Æ rv0=a0+1 Æ y0=rv0 Æ y0 <= x0 Call begins i i Trace Trace Formula

114 Trace Formula + - i i Trace Trace Formula m1: assume(flag!=0)
m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag0  0 Æ a0=x0 Æ sign0= flag0 Æ sign0  0 Æ rv0=a0+1 Æ y0=rv0 Æ y0 <= x0 + - i i Trace Trace Formula

115 Trace Formula + - i i Trace Trace Formula m1: assume(flag!=0)
m2: y=inc(x,flag) i1: assume(sign!=0) i2: rv = a+1 i4: return rv m3: assume(y<=x) Æ flag0  0 Æ a0=x0 Æ sign0= flag0 Æ sign0  0 Æ rv0=a0+1 Æ y0=rv0 Æ y0 <= x0 a0 Interpolate + - rv0 a0 i i rv0 rv0> a0 Trace Trace Formula

116 Lazy Abstraction + Procedure Summaries
Yes Safe C Program Abstract Refine No Property Trace Q. How to find scoped predicates ? Solution: Scoped Cuts + Interpolation

117 Review : Procedures Modular Analysis via Summaries
Summary = (In,Out) vertices’ formulas Requires scoped predicates Scoped cuts + Interpolation

118 Verification by Theorem Proving
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4: } while(new != old); 5: unlock (); return; 1. Loop Invariants 2. Logical formula 3. Check Validity Invariant: lock Æ new = old Ç : lock Æ new  old

119 Verification by Theorem Proving
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4: } while(new != old); 5: unlock (); return; 1. Loop Invariants 2. Logical formula 3. Check Validity - Loop Invariants Multithreaded Programs + Behaviors encoded in logic + Decision Procedures [ESC] Precise

120 Verification by Program Analysis
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4: } while(new != old); 5: unlock (); return; 1. Dataflow Facts 2. Constraint System 3. Solve constraints - Imprecision due to fixed facts + Abstraction + Type/Flow Analyses [CQUAL, ESP, MC] Scalable

121 Verification by Model Checking
Example ( ) { 1: do{ lock(); old = new; q = q->next; 2: if (q != NULL){ 3: q->data = new; unlock(); new ++; } 4: } while(new != old); 5: unlock (); return; 1. (Finite State) Program 2. State Transition Graph 3. Reachability - Pgm ! Finite state model State explosion + State Exploration + Counterexamples Precise [SPIN, SMV, Bandera,JPF ]

122 Combining Strengths Theorem Proving Program Analysis Lazy Abstraction
- loop invariants + Behaviors encoded in logic Refine + Theorem provers Computing Successors,Refine Program Analysis - Imprecise + Abstraction Shrink state space Lazy Abstraction Model Checking - Finite-state model, state explosion + State Space Exploration Path Sensitive Analysis + Counterexamples Finding Relevant Facts

123 Lazy Abstraction: Main Ideas
Predicates: Abstract infinite program states Counterexample-guided Refinement: Find predicates tailored to prog, property Abstraction : Expensive Reachability Tree Refinement : Find predicates, use locations Proof of unsat of TF + Interpolation

124 Thank you


Download ppt "Program Verification by Lazy Abstraction"

Similar presentations


Ads by Google