1 / 55

Path Invariants or “How To Decompose Your Program Analysis”

Path Invariants or “How To Decompose Your Program Analysis”. Tom Henzinger EPFL. Joint work with Dirk Beyer, Rupak Majumdar, and Andrey Rybalchenko (PLDI 2007). Abstraction in Program Verification.

ajay
Download Presentation

Path Invariants or “How To Decompose Your Program Analysis”

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Path Invariantsor“How To Decompose Your Program Analysis” Tom Henzinger EPFL Joint work with Dirk Beyer, Rupak Majumdar, and Andrey Rybalchenko (PLDI 2007).

  2. Abstraction in Program Verification 1 Abstract interpretation [Cousot & Cousot 77] 2 Automation using theorem proving [Graf & Saidi 96] 3 Refinement using counterexamples [Kurshan, Clarke et al.] Tools: Slam/SDV [Microsoft] Blast [UC Berkeley] Magic [CMU] FSoft [NEC] etc.

  3. Model Checking for Safety counterexample: path to defect defects program transition: x’ = x+1 program state: x = 10, y = 20, a[0] = 1, a[1] = 3, ...

  4. Concrete Reachability Safety: ReachÅDefects = ; Incremental computation: Start–initial state Next –transition relation Reach = Start [ Next(Start) [ Next2(Start) [ ... large/infinite number of iterations required

  5. Abstract Reachability Abstraction: equivalence relation on states with finite index Abstract transition relation: [Next] [Reach] = [Start] [ [Next]([Start]) [ [Next]2([Start]) [ ... [ [Next]N([Start]) [Reach]ÅDefects = ; program is safe

  6. Abstraction Refinement • too coarse abstraction leads to spurious counterexamples • refinement by finer partitioning spurious transition real counterexample= bug report

  7. Abstract-Check-Refine Loop Program + Property Build Abstraction Refined Abstraction Concretize Error Trace Model Check Abstraction Abstract Error Trace Concrete Error Trace Correctness Proof (ART)

  8. do { KeAcquireSpinLock(); nPacketsOld = nPackets; req = devExt-WLHV; if (req && req->status) { devExt->WLHV = req->Next; KeReleaseSpinLock(); irp = req->irp; if (req->status > 0) { irp->IoS.Status = SUCCESS; irp->IoS.Info = req->Status; } else { irp->IoS.Status = FAIL; irp->IoS.Info = req->Status; } SmartDevFreeBlock(req); IoCompleteRequest(irp); nPackets++; } } while (nPackets != nPacketsOld); KeReleaseSpinLock();

  9. Simplified Version Example () { 1: do { lock (); old = new; 2: if (*) { 3: unlock (); new ++; } 4: } while (new != old); 5: unlock (); ?: return; } lock () U L unlock () unlock () lock () E Safety monitor

  10. 1 lock (); old = new 2 lock () U L [T] [T] unlock () 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Control Flow Graph Example () { 1: do { lock (); old = new; 2: if (*) { 3: unlock (); new ++; } 4: } while (new != old); 5: unlock (); ?: return; }

  11. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Abstract Reachability 1 U

  12. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Abstract Reachability 1 U lock (); old = new 2 L

  13. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Abstract Reachability 1 U lock (); old = new 2 L [T] 3 L unlock (); new++ 4 U

  14. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Abstract Reachability 1 U lock (); old = new 2 L [T] 3 L unlock (); new++ 4 U [new == old] 5 U

  15. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Counterexample Path 1 U lock (); old = new 2 L [T] 3 L unlock (); new++ 4 U [new == old] 5 U unlock () ? E

  16. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Path Formula 1 U new2 = old1Æ new4 = new2 + 1 Æ new4 = old1 lock (); old = new 2 L [T] 3 L unlock (); new++ 4 U [new == old] 5 U unlock () ? E

  17. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Path Formula 1 U new2 = old1Æ new4 = new2 + 1 Æ new4 = old1 lock (); old = new 2 L [T] 3 L Unsatisfiable) counterexample spurious unlock (); new++ 4 U [new == old] 5 U unlock () ? E

  18. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Path Formula 1 U new2 = old1Æ new4 = new2 + 1 Æ new4 = old1 lock (); old = new 2 L [T] 3 L new = old is a relevant predicate unlock (); new++ 4 U [new == old] 5 U unlock () ? E

  19. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Refined Abstract Reachability 1 U lock (); old = new 2 L, new = old

  20. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Refined Abstract Reachability 1 U lock (); old = new 2 L, new = old [T] L, new = old 3 unlock (); new++ U, new  old 4

  21. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Refined Abstract Reachability 1 U lock (); old = new 2 L, new = old [T] L, new = old 3 unlock (); new++ U, new  old 4 [new == old] 5

  22. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Refined Abstract Reachability 1 U lock (); old = new 2 L, new = old [T] L, new = old 3 unlock (); new++ U, new  old 4 [new == old] [new != old] 5 1 U, new  old

  23. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Refined Abstract Reachability 1 U covered lock (); old = new 2 L, new = old [T] L, new = old 3 unlock (); new++ U, new  old 4 [new == old] [new != old] 5 1 U, new  old

  24. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Complete Abstract Reachability Tree (ART) 1 U lock (); old = new 2 L, new = old [T] [T] L, new = old 3 4 L, new = old [new != old] unlock (); new++ [new == old] 1 5 L, new = old U, new  old 4 unlock () [new == old] [new != old] 5 1 ? U, new = old U, new  old

  25. 1 lock (); old = new 2 lock () U L [T] unlock () [T] 3 [new != old] unlock () lock () unlock (); new++ 4 E [new == old] 5 unlock () ? Complete ART = Proof of Correctness Inductive invariant: (pc=2 ! new=old) Æ (pc=3 ! new=old) Æ … 1 U lock (); old = new 2 L, new = old [T] [T] L, new = old 3 4 L, new = old [new != old] unlock (); new++ [new == old] 1 5 L, new = old U, new  old 4 unlock () [new == old] [new != old] 5 1 ? U, new = old U, new  old

  26. “Lazy, Parsimonious Abstraction” • Constructing abstract transition relation is expensive: build ART • Track relevant predicates locally: only along spurious counterexamples

  27. “Lazy, Parsimonious Abstraction” • Constructing abstract transition relation is expensive: build ART • Track relevant predicates locally: only along spurious counterexamples Not limited to predicate abstraction: lazy shape analysis (CAV 07), predicated lattices [Fisher, Jhala & Majumdar], etc.

  28. Problem: Program Loops 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n );

  29. First Counterexample Path 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 1 2 4 1 5 [a+b != 3*n] E

  30. Path Formula 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 i1=0 Æ a1=0 Æ b1=0 Æ i1n0Æ a2 = a1+1 Æ b2 = b1+2 Æ i4=i1+1 Æ i4=n0Æ a2 + b2  3n0 1 2 4 1 5 [a+b != 3*n] E

  31. Path Formula 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 i1=0 Æ a1=0 Æ b1=0 Æ i1n0Æ a2 = a1+1 Æ b2 = b1+2 Æ i4=i1+1 Æ i4=n0Æ a2 + b2  3n0 1 2 4 1 Unsatisfiable: track i=0, i=1, a=0, a=1, b=0, b=2, n=1 5 [a+b != 3*n] E

  32. ART 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 1 i=0, a=0, b=0 2 i=0, a=0, b=0 4 i=0, a=1, b=2 1 i=1, a=1, b=2 5 i=1, a=1, b=2, n=1 [a+b != 3*n] E

  33. Second Counterexample Path 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 2 i=1, a=1, b=2 1 4 i=1 2 1 4 5 1 i=1, a=1, b=2 5 i=1, a=1, b=2, n=1 [a+b != 3*n] E

  34. Second Counterexample Path 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 2 i=1, a=1, b=2 1 4 i=1 2 1 4 5 [a+b != 3*n] 1 E 5

  35. Second Counterexample Path 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 2 i=1, a=1, b=2 1 4 i=1 2 1 4 5 [a+b != 3*n] 1 E 5 Track also: i=2, a=2, b=4, n=2

  36. k-th Counterexample Path 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); Track: i=0, i=1, … i=k, a=0, a=1, … a=k, b=0, b=1, … b=2k, n=k Refinement does not terminate.

  37. Solution Viewcounterexamples not as paths, but as programs!

  38. Solution Viewcounterexamples not as paths, but as programs! Path program: smallest fragment of the original program that contains a given path. Counterexample: path program that contains a given counterexample path.

  39. Counterexample = Path Program 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 i=0; a=0; b=0 [i != n] 2 a=a+1; b=b+2 1 4 i=i+1 [i == n] 5 [a+b != 3*n] E

  40. Counterexample Path Invariants 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 i=0; a=0; b=0 a+b=3i [i != n] 2 a=a+1; b=b+2 1 a+b=3i 4 i=i+1 [i == n] a+b=3i+3 5 a+b=3i Æ i=n [a+b != 3*n] E

  41. Path Invariants Tracking path invariants removes all spurious counterexample paths that lie within the path program!

  42. Path Invariants Tracking path invariants removes all spurious counterexample paths that lie within the path program! Path invariants can be constructed by any method for invariant synthesis [Karr, Cousot & Halbwachs, Manna et al., Kapur et al., etc.]. Path programs are small fragments of the original program, so there is hope that invariant synthesis can be automated.

  43. ART 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 2 a+b=3i i=0; a=0; b=0 4 a+b=3i+3 1 a+b=3i 1 a+b=3i a+b=3i, i=n 5 E

  44. Complete ART 0: i = 0; a = 0; b = 0; 1: while( i != n ) { if (*) { 2: a = a+1; b = b+2; } else { 3: a = a+2; b = b+1; } 4: i = i+1; } 5: assert( a+b == 3*n ); 0 2 a+b=3i i=0; a=0; b=0 4 a+b=3i+3 1 a+b=3i 1 a+b=3i 3 a+b=3i a+b=3i, i=n 5 4 a+b=3i+3 E 1 a+b=3i

  45. Quantified Invariants 0: for( i=0; i<n; i++) { 1: a[i] = 0; } 2: for( i=0; i<n; i++) { 3: assert( a[i] == 0 ); }

  46. First Counterexample Path 0 0: for( i=0; i<n; i++) { 1: a[i] = 0; } 2: for( i=0; i<n; i++) { 3: assert( a[i] == 0 ); } 1 0 Track a[0]=0 2 3 E

  47. k-th Counterexample Path 0: for( i=0; i<n; i++) { 1: a[i] = 0; } 2: for( i=0; i<n; i++) { 3: assert( a[i] == 0 ); } Track a[k]=0

  48. Counterexample Path Program 0: for( i=0; i<n; i++) { 1: a[i] = 0; } 2: for( i=0; i<n; i++) { 3: assert( a[i] == 0 ); } 0 1 2 3 E

  49. Counterexample Path Invariants 8 k: 0·k<i ! a[k]=0 8 k: 0·k<i ! a[k]=0 0: for( i=0; i<n; i++) { 1: a[i] = 0; } 2: for( i=0; i<n; i++) { 3: assert( a[i] == 0 ); } 0 1 2 3 8 k: 0·k<n ! a[k]=0 8 k: 0·k<n ! a[k]=0 E

  50. Counterexample Path Invariants 8 k: 0·k<i ! a[k]=0 8 k: 0·k<i ! a[k]=0 0: for( i=0; i<n; i++) { 1: a[i] = 0; } 2: for( i=0; i<n; i++) { 3: assert( a[i] == 0 ); } 0 1 2 3 8 k: 0·k<n ! a[k]=0 8 k: 0·k<n ! a[k]=0 E Quantified invariants can be synthesized in the combined theory of linear arithmetic and uninterpreted functions (VMCAI 07).

More Related