1 / 43

Yogi – Part 2

Yogi – Part 2. Handling programs with pointers and procedure calls. Yogi ’s refinement. S k-2. T. S k-2. T. refine. S k-1 ∧¬ρ. S k-1. S k-1 ∧ρ. Suppose there is no test that extends the frontier. op. op. suitable predicate. S k. S k. Results in too many iterations!.

polly
Download Presentation

Yogi – Part 2

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. Yogi – Part 2 Handling programs with pointers and procedure calls

  2. Yogi’srefinement Sk-2 T Sk-2 T refine Sk-1∧¬ρ Sk-1 Sk-1∧ρ Suppose there is no test that extends the frontier op op suitable predicate Sk Sk Results in too many iterations! Candidates for suitable predicates Strongest postcondition (SP) along the path up to the frontier Weakest precondition (WP): Any formula separating the two above (e.g., an interpolant) Explodes in the presence of aliasing!

  3. WP and aliasing Sk-2 T Sk-1∧¬ρ Sk-1∧ρ ASSGN(i=j) *a<10 aliasing possibilities

  4. WP and aliasing Sk-2 T Sk-1∧¬ρ Sk-1∧ρ ASSGN(i=j) *a+*b<10 aliasing possibilities

  5. WP and aliasing (a≠&i ∧ b≠&i ∧ *a+*b<10) ∨ (a=&i ∧ b≠&i ∧ j+*b<10) ∨ (a≠&i ∧ b=&i ∧ *a+j<10) ∨ (a=&j ∧ b=&i∧ j+j<10) ¬((a≠&i ∧ b≠&i ∧ *a+*b<10) ∨ (a=&i ∧ b≠&i ∧ j+*b<10) ∨ (a≠&i ∧ b=&i ∧ *a+j<10) ∨ (a=&j ∧ b=&i∧ j+j<10)) ASSGN(i=j) *a+*b<10 In practice a global alias analysis required to prune the formula generated by WP • if () • p = &a; • else • p = &b; • *p = 3; • alias(*p) = {a, b}

  6. Deriving a suitable predicate Belongs to exactly one region a≠&i ∧ b≠&i ∧ *a+*b≥10 a≠&i ∧ b≠&i ∧ *a+*b<10 a=&i ∧ b≠&i ∧ j+*b<10 a=&i ∧ b≠&i ∧ j+*b≥10 a≠&i ∧ b=&i ∧ *a+j<10 a≠&i ∧ b=&i ∧ *a+j≥10 a=&i ∧ b=&i ∧ j+j<10 a=&i ∧ b=&i ∧ j+j≥10 ASSGN(i=j) *a+*b<10

  7. Deriving a suitable predicate a≠&i ∧ b≠&i ∧ *a+*b≥10 a≠&i ∧ b≠&i ∧ *a+*b<10 a=&i ∧ b≠&i ∧ j+*b<10 a=&i ∧ b≠&i ∧ j+*b≥10 a≠&i ∧ b=&i ∧ *a+j<10 a≠&i ∧ b=&i ∧ *a+j≥10 a=&i ∧ b=&i ∧ j+j<10 a=&i ∧ b=&i ∧ j+j≥10 ASSGN(i=j) *a+*b<10

  8. Refining with suitable predicate WPα WPα a ≠ &i ∨ b=&i ∨ j+*b<10 a=&i ∧ b≠&i ∧ j+*b≥10 ASSGN(i=j) *a+*b<10 No global alias analysis required! def

  9. Refining with suitable predicate WPα Sk-2 T Sk-2 T refine Sk-1∧¬ρ Sk-1 Sk-1∧ρ op op suitable predicate Sk Sk Theorem: is a suitable predicate for refinement

  10. Aliasing Example 0 p1 = malloc(); p1->lock = 0 struct DE { int lock; int y; }; void baz(DE *p, DE *p1, DE *p2) { 0: p1 = malloc(sizeof(DE)); p1->lock = 0; 1: p2 = malloc(sizeof(DE)); p2->lock = 0; 2: p->lock = 1; 3: if (p1->lock == 1 || p2->lock == 1) 4: error(); 5: p = p1; 6: p = p2; } 1 p2 = malloc(); p2->lock = 0 2 p->lock = 1 3 assume(!(p1->lock =1  p2->lock=1)) assume(p1->lock =1  p2->lock=1) 4 5 p = p1 6 p = p2 7

  11. Aliasing Example 0 struct DE { int lock; int y; }; void baz(DE *p, DE *p1, DE *p2) { 0: p1 = malloc(sizeof(DE)); p1->lock = 0; 1: p2 = malloc(sizeof(DE)); p2->lock = 0; 2: p->lock = 1; 3: if (p1->lock == 1 || p2->lock == 1) 4: error(); 5: p = p1; 6: p = p2; } 1 2 3 frontier 4 5 6 7

  12. Aliasing Example 0 struct DE { int lock; int y; }; void baz(DE *p, DE *p1, DE *p2) { 0: p1 = malloc(sizeof(DE)); p1->lock = 0; 1: p2 = malloc(sizeof(DE)); p2->lock = 0; 2: p->lock = 1; 3: if (p1->lock == 1 || p2->lock == 1) 4: error(); 5: p = p1; 6: p = p2; } 1 frontier 2 3: ρ 3: ¬ρ 5 4 6 7

  13. Aliasing Example 0 struct DE { int lock; int y; }; void baz(DE *p, DE *p1, DE *p2) { 0: p1 = malloc(sizeof(DE)); p1->lock = 0; 1: p2 = malloc(sizeof(DE)); p2->lock = 0; 2: p->lock = 1; 3: if (p1->lock == 1 || p2->lock == 1) 4: error(); 5: p = p1; 6: p = p2; } 1 2 : 2:¬ 3: ρ 3: ¬ρ 5 4 6 7

  14. Aliasing Example – Proof! 0 struct DE { int lock; int y; }; void baz(DE *p, DE *p1, DE *p2) { 0: p1 = malloc(sizeof(DE)); p1->lock = 0; 1: p2 = malloc(sizeof(DE)); p2->lock = 0; 2: p->lock = 1; 3: if (p1->lock == 1 || p2->lock == 1) 4: error(); 5: p = p1; 6: p = p2; } 1: μ 1: ¬μ 2 : 2:¬ 3: ρ 3: ¬ρ 5 4 6 7

  15. Generalized Example void foo(int *p, int *p1, int* p2, … , int*pn) { 0: p1 = malloc(sizeof(DE)); p1->lock = 0; 1: p2 = malloc(sizeof(DE)); p2->lock = 0; … pn= malloc(sizeof(DE)); pn->lock = 0; 2: *p1 = 0; *p2 = 0; … ; *pn = 0; 3: if (*p1 == 1 || … || *pn == 1) 4: error(); 5: p = p1; 6: p = p2; … p = pn; }

  16. Recap: programs with pointers • Refine using • Generalizes better than S • Handles explosion in aliasing better than

  17. Next… Handling programs with procedures…

  18. Recall Key ideas 0 Step 1: Try to generate a test that crosses the frontier • Perform symbolic simulation on the path until the frontier and generate a constraint • Conjoin with the condition needed to cross frontier • Is satisfiable? [YES] Step 2: run the test and extend the frontier 1 2 3 frontier 4 5 7 8 6 10 9

  19. Recall Key ideas 0 Step 1: Try to generate a test that crosses the frontier • Perform symbolic simulation on the path until the frontier and generate a constraint • Conjoin with the condition needed to cross frontier • Is satisfiable? [NO] Step 2: use to refine so that the frontier moves back! 1 2 frontier 3 4 4 5 7 8 6 10 9

  20. Handling procedures 0 How to deal with frontiers that have function calls on the frontier edge? 1 2 3 4 5 7 8 6 10 9

  21. Questions • How do we perform symbolic simulation over function call frontiers? • If frontier can be extended, how do we generate a test? • If frontier needs to be refined, what is ? • Can we reuse results?

  22. Answer I Call the intraprocedural analysis recursively Y - no: perform refinement - yes: generate test

  23. Questions • How do we perform symbolic simulation over function call frontiers? • If frontier can be extended, how do we generated a test? • If frontier needs to be refined, what is ? • Can we reuse results?

  24. Answer 2 If the result of the recursive call is a “yes”, use the corresponding test to extend the frontier Y

  25. Questions • How do we perform symbolic simulation over function call frontiers? • If frontier can be extended, how do we generated a test? • If frontier needs to be refined, what is ? • Can we reuse results?

  26. Answer 3 If the result of the recursive call is a “no”, use the corresponding proof to compute and refine! Y

  27. Questions • How do we perform symbolic simulation over function call frontiers? • If frontier can be extended, how do we generated a test? • If frontier needs to be refined, what is ? • Can we reuse results?

  28. Answer 4 Yes, we can reuse. Stores tests and proofs obtained at function frontiers as must and not-may summaries

  29. Query If we start procedure in a state satisfying precondition , and execution of completes, can we reach a state satisfying postcondition?

  30. Formalizing procedure summaries must summary • A must summary for a procedure f is of the form • can be obtained by executing from an initial state • A must summary can be used to answer “yes” to the query if≠ { } • A may summary for a procedure is of the form • cannot be obtained by executing starting in state • A may summary can be used to answer “no” to the query if

  31. Yogi: Compositional May-Must Analysis • May analysis = predicate abstraction (SLAM) • Must analysis = symbolic execution + tests (DART) • Compositional May-Must analysis: • Interprocedural analysis • Memoize and re-use may/must summaries • May analysis can use must summaries and vice-versa Yogi implements Compositional-May and Compositional-Mustanalysis with interactions between the two

  32. Example 1 (not-may summaries) void main(int i1,i2,i3) { 0: int x1,x2,x3; 1: x1 = g(i1); 2: x2 = g(i2); 3: x3 = g(i3); 4: if ((x1 < 0)||(x2 < 0)||(x3 < 0)) 5: error(); int g(inti) { 11: if (i > 0) 12: return i; 13: else 14: return -i; } • Yogi generates the query • Analysis of generates the not-may summary • The property is proved in main using this • not-may summary

  33. Example 2 (must summaries) void main(int i1,i2,i3) { 0: int x1,x2,x3; 1: x1 = f(i1); 2: x2 = f(i2); 3: x3 = f(i3); 4: if (x1 > 0) 5: if (x2 > 0) 6: if (x3 > 0) 7: error(); } int f(inti) { 11: if (i > 0) 12: return i; else 13: return h(i); // h(i) is a complex function // such as a hash function } • Yogi generates the query • Analysis of generates the must summary • Condition (i1 > 0) && (i2 > 0) && (i3 > 0) is generated, and corresponding test to reach error is generated

  34. Interplay between may and must void main() { 1: A(); 2: if () 3: B1(); 4: else 5: B2(); 6: C(); 7: if () 8: error(); } intmain() { 1: A(); 2: B(); 3: C(); 4: if () 5: error(); } not-may summary helps must-answer - assume has a not-may summary - useful for “efficiently” proving that is reachable! must summary helps not-may-answer - assume and B() have must summaries - useful for “efficiently” proving that is unreachable!

  35. Example 3 (interplay between may and must) void main(int j) { 1: inti = 0; 2: x = foo(i,j); 3: if (x == 1) 4: error(); } int foo(inti,j) { 11: if (j > 0) 12: return bar(i)+1; 13: else 14: return i+1; } • Assume bar is a complex function with a not-may summary • Yogi generates the query • Using this, analysis of generates the must summary • Yogi generates condition inmainfor test to reach error

  36. Must and not-may summaries • Let us formally state what the examples showed us…

  37. Interprocedural analysis Y not-may summary: perform refinement must summary : generate test and extend frontier

  38. Using must summary • Query: • Suppose we have • such that • Pick any point in • and thus extend test case • across the frontier

  39. Using not-may summary • Query • Suppose we have • such that • and • Useto refine

  40. Using not-may summary • Query • Suppose we have • such that • and • Useto refine

  41. Computing must summaries void foo(int a) { 0: i = 0; 1: c = 0; 2: while (i < 1000) { 3: c = c + i; 4: i = i + 1; } 5: if(a <= 0) return(1) else return(0) } test … Symbolic state at entry to the procedure is Symbolic state on exit from procedure is Generated must-summary is

  42. Computing not-may summaries • Query • Suppose we have a proof • that is unreachable from • Generate may-summary • where are initial regions that are reachable by tests, and 0: 0: 0: 1: μ 1: ¬μ 2 : 2:¬ 3: ρ 3: ¬ρ 4: 4:

  43. Interplay between and must summaries must must must must must must must must must

More Related