Technologies for finding errors in object-oriented software K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 1 Summer school on Formal Models of Software 2 Sep 2003, Tunis, Tunisia
Review: Tool architecture Source program Verification condition Counterexample context Warning messages Automatic theorem prover Post processor Sugared command Primitive command Passive command Translator Focus today
Commands and their possible outcomes Normal termination – terminates normally in some state Erroneous termination – goes wrong, crashes the computer Non-termination – diverges, fails to terminates, results in infinite recursion Miraculous termination – fails to start, blocks (partial/miraculous commands) you breach contract, demon wins demon breaches contract, you win!
Commands C::=w := E |assert P |assume P |var w in C end |C 0 ; C 1 |C 0 [] C 1
Semantics Hoare logic – {P} C {R} says that if command C is started in (a state satisfying) P, then: C does not go wrong, and if C terminates normally, then it terminates in (a state satisfying) R Weakest preconditions – for a given C and R, the weakest P satisfying {P} C {R} – written wp(C, R) or simply C.R
Command semantics assignment evaluate E and change value of w to E (w := E).R R[w := E] (x := x + 1).(x 10)x+1 10x < 10 (x := 15).(x 10)15 10false (y := x + 3*y).(x 10) x 10 (x,y := y,x).(x < y)y < x replace w by E in R
Command semantics assert if P holds, do nothing, else go wrong (assert P).R P R (assert x < 10).(0 x)0 x < 10 (assert x = y*y).(0 x)x = y*y 0 xx = y*y (assert false).(x 10)false logical AND, conjunction
Command semantics assume logical implication logical NOT, negation logical OR, disjunction if P holds, do nothing, else block (assume P).R P R P R (assume x < 10).(0 x)10 x 0 x0 x (assume x = y*y).(0 x)x = y*y 0 xtrue (assume false).(x 10)true
introduce w with an arbitrary initial value, then do C (var w in C end).R (w C.R) (var y in y := x end).(0 x)(y (y := x).(0 x))(y 0 x)0 x (var y in x := y end).(0 x)(y (x := y).(0 x))(y 0 y)false Command semantics local variable provided w does not occur free in R
do C 0, then C 1 (C 0 ; C 1 ).R C 0.(C 1.R) (x := x+1 ; assert x y).(0 < x)(x := x+1).( (assert x y).(0 < x) )(x := x+1).(0 < x y) 0 < x+1 y0 x < y (assume 0 y+z ; x := y).(0 x)(assume 0 y+z).( (x:=y).(0 x) )(assume 0 y+z).(0 y)0 y+z 0 y-y z -y 00 z Command semantics sequential composition
do either C 0 or C 1 (the demon chooses which) (C 0 [] C 1 ).R C 0.R C 1.R (x := x+1 [] x := x + 2).(x 10)(x := x+1). (x 10) (x := x+2).(x 10)x 9 x 8 x 8 (assume false [] x := y).(0 x)(assume false).(0 x) (x:=y).(0 x)true 0 y0 y Command semantics choice composition
Convenient shorthands skip = assert true = assume true wrong = assert false magic = assume false P C = assume P; C if P then C 0 else C 1 end = P C 0 [] P C 1 havoc w = var win w := wend
Change such that change w such that P = havoc w ; assume P change x such that y = x+1havoc x ; assume y = x+1x := y-1 change x such that y < xx := y+1 [] x := y+2 [] … change x such that x = x+1havoc x ; assume falsemagic change r such that r*r = yy < 0 magic []0 y r := y []0 y r := -y
Specification statement w:[P, Q] =requires P modifies w ensures Q =assert P ; var w 0 in w 0 := w ; change w such that Q end x:[true, x 0 =x+1]x := x-1 r:[0 y, r*r = y]assert 0 y ; (r := y [] r := -y) x:[0 x, x 2 x 0 < (x+1) 2 ] ? x,y,z,n:[1xy1z2n, x n +y n =z n ] ?
Variables with internal structure: maps x := a[i] = x := select(a, i) a[i] := E = a := store(a, i, E) where (m,i,j,v i j select(store(m, i, v), i) = v select(store(m, i, v), j) = select(m, j))
Example: maps (a[5] := 12 ; a[7] := 14 ; x := a[5]).(x=12) =(a[5] := 12 ; a[7] := 14).(select(a, 5) = 12) =(a[5] := 12).(select(store(a, 7, 14), 5) = 12) =select(store(store(a, 5, 12), 7, 14), 5) = 12 ={ select/store axiom, since 7 5 } select(store(a, 5, 12), 5) = 12 ={ select/store axiom, since 5 = 5 } 12 = 12 =true
Refinement B C = (R B.R C.R ) change x such that y < x x := y+4 assert x < 10 skip skip assume x < 10 wrong C C magic command B is refined by command C C is better than B anyone who requests B would be happy with C
Compositions are monotonic with respect to refinement if B C then: – var w in B end var w in C end – A;B A;C – B;D C;D – A [] B A [] C var x in... change x such that y < x... end var x in... x := y+4... end
Commands form a lattice Commands form a semi-lattice under ordering, with meet operation [], top element magic, and bottom element wrong A lattice theorem: B C 0 B C 1 B C 0 [] C 1 Corollary: C 0 [] C 1 C 0
Example application of lattice theorem Let B = x:[true, x = |x 0 | ]. Then: B assume 0 x = C 0 B assume x 0 ; x := -x = C 1 B assume x = -3 ; x := 3 = C 2 B magic = C 3 Therefore: B C 0 [] C 1 [] C 2 [] C 3
Procedures proc P(x,y,z) returns (r,s,t) spec S call to P: a,b,c := P(E 0, E 1, E 2 ) = var x,y,z,r,s,t in x := E 0 ; y := E 1 ; z := E 2 ; S ; a,b,c := r,s,t end
Example: procedure proc Add(x) returns (r) specrequires 0 x modifies k ensures k = k 0 +x r = k 0 a := Add(k+25) = var x,r in x := k+25 ; k:[0 x, k = k 0 +x r = k 0 ] ; a := r end
Procedure implementations proc P(x,y,z) returns (r,s,t) spec S impl P(x,y,z) returns (r,s,t) is C Proof obligation: S C Let C 0,..., C m- 1 be the declared implementations of P. Then, the language implementation of a call to P can replace S by: C 0 []... [] C m- 1
Exercise Redefine (in terms of the commands we've seen) the specification statement so that the postcondition mentions x,x instead of x 0,x Example: – old form: x:[0 x, x*x x 0 < (x+1)*(x+1)] – new form: x:[0 x, x*x x < (x+1)*(x+1)]
Exercise Define while {inv J} B do w: S end where: – B is the loop guard – S is the loop body – J is the loop invariant – w is the list of assignment targets in S in terms of the commands we've seen.
Loop (answer to exercise) while {inv J} B do w: S end = assert J ; change w such that J ; if B then S ; assert J ; magic else skip end
Summary Language is built up from 6 primitive commands Semantics can be given by weakest preconditions Partial (miraculous) commands are important and very useful select/store handle map variables Procedures are names for specifications Procedure implementations are hints for compiler