Download presentation
Presentation is loading. Please wait.
Published byJoanna Daigh Modified over 10 years ago
1
Lecture #21 Software Model Checking: predicate abstraction Thomas Ball Testing, Verification and Measurement Microsoft Research
2
Lecture #22 Today Formalizing SLAM Predicate abstraction of programs with procedures and pointers Symbolic model checking of boolean programs
3
Lecture #23 unreachable States Reachability reachable init unsafe
4
Lecture #24 Safe Forward Invariants is a safe forward invariant if –init –F( ) – safe F( ) init unsafe
5
Lecture #25 Abstraction = Overapproximation of Behavior x<10 x<5 Concrete State Space Abstract State Space x=1 or x=2
6
Lecture #26 Abstraction = Overapproximation of Behavior F( ) init unsafe ## F#(#)F#(#)
7
Lecture #27 Counterexample-driven Refinement E := {}; loop F # := predAbs(F,E) if unsafe lfp(F #, init) then return SUCCESS else find min k s.t. unsafe F # k (init) if unsafe F k (init) then return FAILURE else find E’ s.t. unsafe G # k (init) where G # = predAbs(F,E’) E := E E’ forever
8
Lecture #28 C- Types ::= void | bool | int | ref Expressionse::=c | x | e 1 op e 2 | &x | *x LExpression l ::= x | *x Declarationd::= x 1,x 2,…,x n Statementss::=skip | goto L 1,L 2 …L n | L: s | assume(e) | l = e | l = f (e 1,e 2,…,e n ) |return x |s 1 ; s 2 ;… ; s n Procedures p ::= f (x 1 : 1,x 2 : 2,…,x n : n ) Programg ::= d 1 d 2 … d n p 1 p 2 … p n
9
Lecture #29 C-- Types ::= void | bool | int Expressionse::=c | x | e 1 op e 2 LExpression l ::= x Declarationd::= x 1,x 2,…,x n Statementss::=skip | goto L 1,L 2 …L n | L: s | assume(e) | l = e |f (e 1,e 2,…,e n ) |return |s 1 ; s 2 ;… ; s n Procedures p ::= f (x 1 : 1,x 2 : 2,…,x n : n ) Programg ::= d 1 d 2 … d n p 1 p 2 … p n
10
Lecture #210 BP Types ::= void | bool Expressionse::=c | x | e 1 op e 2 LExpression l ::= x Declarationd::= x 1,x 2,…,x n Statementss::=skip | goto L 1,L 2 …L n | L: s | assume(e) | l = e |f (e 1,e 2,…,e n ) |return |s 1 ; s 2 ;… ; s n Procedures p ::= f (x 1 : 1,x 2 : 2,…,x n : n ) Programg ::= d 1 d 2 … d n p 1 p 2 … p n
11
Lecture #211 What is Hard? Abstracting –from a language with pointers (C) –to one without pointers (boolean programs) All side effects need to be modeled by copying (as in dataflow)
12
Lecture #212 What stayed fixed? Boolean program model Basic tool flow Repercussions: –model side-effects by value-result –finite depth precision on the heap is all boolean programs can do
13
Lecture #213 Syntactic sugar if (e) { S1; } else { S2; } S3; goto L1, L2; L1: assume(e); S1; goto L3; L2: assume(!e); S2; goto L3; L3: S3;
14
Lecture #214 Example, in C void cmp (int a, int b) { if (a == b) g = 0; else g = 1; } int g; main(int x, int y){ cmp(x, y); if (!g) { if (x != y) assert(0); }
15
Lecture #215 void cmp(int a, int b) { goto L1, L2; L1: assume(a==b); g = 0; return; L2: assume(a!=b); g = 1; return; } int g; main(int x, int y){ cmp(x, y); assume(!g); assume(x != y) assert(0); } Example, in C--
16
Lecture #216 c2bp: Predicate Abstraction for C Programs Given P : a C program F = {e 1,...,e n } –each e i a pure boolean expression –each e i represents set of states for which e i is true Produce a boolean program B(P,F) same control-flow structure as P boolean vars {b 1,...,b n } to match {e 1,...,e n } properties true of B(P,F) are true of P
17
Lecture #217 Assumptions Given P : a C program F = {e 1,...,e n } –each e i a pure boolean expression –each e i represents set of states for which e i is true Assume: each e i uses either: –only globals (global predicate) –local variables from some procedure (local predicate for that procedure) Mixed predicates: –predicates using both local variables and global variables –complicate “return” processing –covered in advanced topics
18
Lecture #218 C2bp Algorithm Performs modular abstraction –abstracts each procedure in isolation Within each procedure, abstracts each statement in isolation –no control-flow analysis –no need for loop invariants
19
Lecture #219 void cmp (int a, int b) { goto L1, L2 L1: assume(a==b); g = 0; return; L2: assume(a!=b); g = 1; return; } int g; main(int x, int y){ cmp(x, y); assume(!g); assume(x != y) assert(0); } Preds: {x==y} {g==0} {a==b}
20
Lecture #220 void cmp (int a, int b) { goto L1, L2 L1: assume(a==b); g = 0; return; L2: assume(a!=b); g = 1; return; } int g; main(int x, int y){ cmp(x, y); assume(!g); assume(x != y) assert(0); } decl {g==0} ; main( {x==y} ) { } void cmp ( {a==b} ) { } Preds: {x==y} {g==0} {a==b}
21
Lecture #221 void cmp (int a, int b) { goto L1, L2 L1: assume(a==b); g = 0; return; L2: assume(a!=b); g = 1; return; } int g; main(int x, int y){ cmp(x, y); assume(!g); assume(x != y) assert(0); } decl {g==0} ; main( {x==y} ) { cmp( {x==y} ); assume( {g==0} ); assume( !{x==y} ); assert(0); } void cmp ( {a==b} ) { goto L1, L2; L1: assume( {a==b} ); {g==0} = T; return; L2: assume( !{a==b} ); {g==0} = F; return; } Preds: {x==y} {g==0} {a==b}
22
Lecture #222 C-- Types ::= void | bool | int Expressionse::=c | x | e 1 op e 2 LExpression l ::= x Declarationd::= x 1,x 2,…,x n Statementss::=skip | goto L 1,L 2 …L n | L: s | assume(e) | l = e | f (e 1,e 2,…,e n ) | return | s 1 ; s 2 ;… ; s n Procedures p ::= f (x 1 : 1,x 2 : 2,…,x n : n ) Programg ::= d 1 d 2 … d n p 1 p 2 … p n
23
Lecture #223 Statement y=y+1 and F={ y<4, y<5 } –{y<4}, {y<5} = ((!{y<5} || !{y<4}) ? F : *), {y<4} ; WP(x=e,Q) = Q[x -> e] WP(y=y+1, y<5)= (y y+1] = (y+1<5) = (y<4) Abstracting Assigns via WP
24
Lecture #224 WP Problem WP(s, e i ) not always expressible via { e 1,...,e n } Example –F = { x==0, x==1, x<5 } –WP( x=x+1, x<5 ) = x<4 –Best possible: x==0 || x==1
25
Lecture #225 Abstracting Expressions via F F = { e 1,...,e n } Implies F (e) –best boolean function over F that implies e ImpliedBy F (e) –best boolean function over F implied by e –ImpliedBy F (e) = !Implies F (!e)
26
Lecture #226 Implies F (e) and ImpliedBy F (e) e Implies F (e) ImpliedBy F (e)
27
Lecture #227 Computing Implies F (e) minterm m = d 1 &&... && d n –where d i = e i or d i = !e i Implies F (e) –disjunction of all minterms that imply e Naïve approach –generate all 2 n possible minterms –for each minterm m, use decision procedure to check validity of each implication m e Many optimizations possible
28
Lecture #228 Abstracting Assignments if Implies F (WP(s, e i )) is true before s then –e i is true after s if Implies F (WP(s, !e i )) is true before s then –e i is false after s {e i } = Implies F (WP(s, e i )) ?true : Implies F (WP(s, !e i )) ? false : *;
29
Lecture #229 Assignment Example Statement in P: Predicates in E: y = y+1; {x==y} Weakest Precondition: WP(y=y+1, x==y) = x==y+1 Implies F ( x==y+1 ) = false Implies F ( x!=y+1 ) = x==y Abstraction of assignment in B: {x==y} = {x==y} ? false : *;
30
Lecture #230 Abstracting Assumes WP( assume(e), Q) = e Q assume(e) is abstracted to: assume( ImpliedBy F (e) ) Example: F = {x==2, x<5} assume(x < 2) is abstracted to: assume( {x<5} && !{x==2} )
31
Lecture #231 Abstracting Procedures Each predicate in F is annotated as being either global or local to a particular procedure Procedures abstracted in two passes: –a signature is produced for each procedure in isolation –procedure calls are abstracted given the callees’ signatures
32
Lecture #232 Abstracting a procedure call Procedure call –a sequence of assignments from actuals to formals –see assignment abstraction Procedure return –NOP for C-- with assumption that all predicates mention either only globals or only locals –with pointers and with mixed predicates: Most complicated part of c2bp Covered in the advanced topics section
33
Lecture #233 void cmp (int a, int b) { Goto L1, L2 L1: assume(a==b); g = 0; return; L2: assume(a!=b); g = 1; return; } int g; main(int x, int y){ cmp(x, y); assume(!g); assume(x != y) assert(0); } decl {g==0} ; main( {x==y} ) { cmp( {x==y} ); assume( {g==0} ); assume( !{x==y} ); assert(0); } void cmp ( {a==b} ) { Goto L1, L2 L1: assume( {a==b} ); {g==0} = T; return; L2: assume( !{a==b} ); {g==0} = F; return; } {x==y} {g==0} {a==b}
34
Lecture #234 Precision For program P and E = {e 1,...,e n }, there exist two “ideal” abstractions: –Boolean(P,E) : most precise abstraction –Cartesian(P,E) : less precise abtraction, where each boolean variable is updated independently –[See Ball-Podelski-Rajamani, TACAS 00] Theory: –with an “ideal” theorem prover, c2bp can compute Cartesian(P,E) Practice: –c2bp computes a less precise abstraction than Cartesian(P,E) –we use Das/Dill’s technique to incrementally improve precision –with an “ideal” theorem prover, the combination of c2bp + Das/Dill can compute Boolean(P,E)
35
Lecture #235 Types ::= void | bool | int | ref Expressionse::=c | x | e 1 op e 2 | &x | *x LExpression l ::= x | *x Declarationd::= x 1,x 2,…,x n Statementss::=skip | goto L 1,L 2 …L n | L: s | assume(e) | l = e | l = f (e 1,e 2,…,e n ) |return x |s 1 ; s 2 ;… ; s n Procedures p ::= f (x 1 : 1,x 2 : 2,…,x n : n ) Programg ::= d 1 d 2 … d n p 1 p 2 … p n C-
36
Lecture #236 Two Problems Extending SLAM tools for pointers Dealing with imprecision of alias analysis
37
Lecture #237 Pointers and SLAM With pointers, C supports call by reference –Strictly speaking, C supports only call by value –With pointers and the address-of operator, one can simulate call-by-reference Boolean programs support only call-by-value-result –SLAM mimics call-by-reference with call-by-value-result Extra complications: –address operator (&) in C –multiple levels of pointer dereference in C
38
Lecture #238 Assignments + Pointers Weakest Precondition: WP( *p=3, x==5 ) = x==5 What if *p and x alias? We use Das’s pointer analysis [PLDI 2000] to prune disjuncts representing infeasible alias scenarios. Correct Weakest Precondition: (p==&x and 3==5) or (p!=&x and x==5) Statement in P:Predicates in E: *p = 3 {x==5}
39
Lecture #239 Abstracting Procedure Return Need to account for –lhs of procedure call –mixed predicates –side-effects of procedure Boolean programs support only call-by- value-result –C2bp models all side-effects using return processing
40
Lecture #240 Abstracting Procedure Returns Let a be an actual at call-site P(…) –pre(a) = the value of a before transition to P Let f be a formal of a procedure P –pre(f) = the value of f upon entry to P
41
Lecture #241 int R (int f) { int r = f+1; f = 0; return r; } WP(x=r, x==2) = r==2 Q() { int x = 1; x = R(x) } pre(f) == pre(x) x = r {x==1} {x==2} {f==pre(f)} {r==pre(f)+1} predicatecall/return relationcall/return assign {x==2} = s & {x==1}; } bool R ( {f==pre(f)} ) { {r==pre(f)+1} = {f==pre(f)}; {f==pre(f)} = *; return {r==pre(f)+1}; } WP(f=x, f==pre(f) ) = x==pre(f) f = x x==pre(f) is true at the call to R pre(f)==pre(x) and pre(x)==1 and r==pre(f)+1 implies r==2 Q() { {x==1},{x==2} = T,F; s = R(T); {x==1}s
42
Lecture #242 {x==1}, {x==2} = *, s & {x==1}; } int R (int f) { int r = f+1; f = 0; return r; } WP(x=r, x==2) = r==2 Q() { int x = 1; x = R(x) } {x==1} {x==2} {f==pre(f)} {r==pre(f)+1} predicatecall/return relationcall/return assign bool R ( {f==pre(f)} ) { {r==pre(f)+1} = {f==pre(f)}; {f==pre(f)} = *; return {r==pre(f)+1}; } WP(f=x, f==pre(f) ) = x==pre(f) x==pre(f) is true at the call to R pre(f)==pre(x) and pre(x)==1 and r==pre(f)+1 implies r==2 Q() { {x==1},{x==2} = T,F; s = R(T); {x==1}s f = x x = r pre(f) == pre(x)
43
Lecture #243 Extending Pre-states Suppose formal parameter is a pointer –eg. P(int *f) pre( *f ) –value of *f upon entry to P –can’t change during P * pre( f ) –value of dereference of pre( f ) –can change during P
44
Lecture #244 int R (int *a) { *a = *a+1; } Q() { int x = 1; R(&x); } pre(a) = &x {x==1} {x==2} predicatecall/return relationcall/return assign {x==2} = s & {x==1}; } bool R ( {a==pre(a)}, {*pre(a)==pre(*a)} ) { {*pre(a)==pre(*a)+1} = {*pre(a)==pre(*a)} ; return {*pre(a)==pre(*a)+1}; } a = &x Q() { {x==1},{x==2} = T,F; s = R(T,T); {a==pre(a)} {*pre(a)==pre(*a)} {*pre(a)=pre(*a)+1} pre(x)==1 and pre(*a)==pre(x) and *pre(a)==pre(*a)+1 and pre(a)==&x implies x==2 {x==1 } s
45
Lecture #245 Reachability in Boolean Programs Algorithm based on CFL reachability –[Sharir-Pnueli 81] [Reps-Sagiv-Horwitz 95] “path edge” of procedure P – –“if P’s entry is reachable in state d1 then statement s2 of P is reachable in state d2” “summary edge” of procedure P – –“if P calls Q from state d1 then Q returns to P in state d2”
46
Lecture #246 Symbolic CFL reachability Partition path edges by their “target” PE(v) = { | } What is for boolean programs? A bit-vector! What is PE(v)? A set of bit-vectors Use a BDD (attached to v) to represent PE(v)
47
Lecture #247 Binary Decision Diagrams Canonical representation of –boolean functions –set of (fixed-length) bitvectors –binary relations over finite domains Efficient algorithms for common dataflow operations –transfer function –join/meet –subsumption test void cmp ( e2 ) { [5]Goto L1, L2 [6]L1: assume( e2 ); [7] gz = T; goto L3; [8]L2: assume( !e2 ); [9]gz = F; goto L3 [10] L3: return; } e2=e2’ & gz’=e2’ BDD at line [10] of cmp: Read: “cmp leaves e2 unchanged and sets gz to have the same final value as e2”
48
Lecture #248 gz=gz’& e=e’ e=e’& gz’=e’ e=e’ & gz’=1 & e’=1 gz=gz’& e2=e2’ gz=gz’& e2=e2’& e2’=T e2=e2’& gz’=e2’ decl gz ; main( e ) { [1] equal( e ); [2] assume( gz ); [3] assume( !e ); [4] assert(F); } void cmp ( e2 ) { [5]Goto L1, L2 [6]L1: assume( e2 ); [7] gz = T; goto L3; [8]L2: assume( !e2 ); [9]gz = F; goto L3 [10] L3: return; } gz=gz’& e2=e2’& e2’=F e2=e2’& e2’=T & gz’=T e2=e2’& e2’=F & gz’=F e2=e
49
Lecture #249 Reachability Summary Explicit representation of CFG Implicit representation of path edges and summary edges Generation of hierarchical error traces Complexity: O(E * 2 O(N) ) E is the size of the CFG N is the max. number of variables in scope
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.