1 / 66

Predicate -t ransformer –based Verification (LN Chapter 2)

This chapter explores predicate transformer-based verification, focusing on Hoare logic, specifying programs using Hoare triples, assignments, loops, and the use of weakest preconditions (wp) and weakest liberal preconditions (wlp) transformers. The goal is to understand how to mechanically verify a real program.

jhoffman
Télécharger la présentation

Predicate -t ransformer –based Verification (LN Chapter 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. Predicate-transformer–based Verification(LN Chapter 2) WishnuPrasetya wishnu@cs.uu.nl www.cs.uu.nl/docs/vakken/pv

  2. Plan • Hoare logic • Verification using predicate transformers • Verification with “Guarded Command Language” (GCL) • Objects and exceptions • Should at end give an answer to “how to mechanically verify a real program”.

  3. Specifying programs • We can use “Hoare triples” : • total and partial correctness interpretation. { true } plusOne(x) body{ return = x+1 } { #S>0 } max(S) body{ return  S /\ (x: xS : return≥x) }

  4. Hoare Logic • Provides a set of “inference rules” to prove the validity of Hoare triples. Example: • Note : LN uses the notation ⊢ OP OP , { P } S { Q } ------------------------------------------------ { O } S { Q }

  5. The logic’s general idea: break it down! { P } S1 { Q } , { Q } S2 { R } --------------------------------------------------------- { P } S1 ; S2 { R } { P /\ g } S1 { Q } , { P /\ g } S2 { Q } ---------------------------------------------------------- { P } ifgthenS1 else S2{ Q }

  6. Assignment • Eventually, everything boils down to “assignments” • An assignment is correct if ..... • Note: this assumes that the assignment only changes the value of x (it does not silently affect other variables) PQ[e/x]--------------------------------------- { P } x:=e { Q }

  7. Loop • A loop is correct if you can find an “invariant” : • E.g. a trivial loop: P I { g /\ I } S { I } I /\ g  Q ---------------------------------------- { P } whilegdo S { Q } { k=1000 } while k>0 do k := k-1 { k=0 }

  8. Few more examples { y=0 /\ k=0 } while k<10 do { y := y+2 ; k++ }{ y = 20 } { y=0 /\ k=10 } while k ≠ 0 do { y := y+2 ; k-- }{ y = 20 }

  9. Few more examples Home work: { s=false /\ k=0 } while k<#b do { s = s \/ b[k] ; k = k + 1 } { s = (∃i: 0≤i<#b : b[i]) }

  10. Proving termination (of loop) • Extend the previous rule to:P I { g /\ I } S { I } I /\ g  Q { I /\ g } C:=m ; S { m<C } // m decreasing I /\ g  m> 0 // m bounded below ---------------------------------------- { P } whilegdo S { Q }

  11. Example { x0 /\ y0 } whilex+y>0 do { if x>0 then { x-- ; y := y+100 } else y-- } { x=0 /\ y=0 }

  12. Home work { x>1 } while x>0 do { if x>1 then x := x - 2 else x := x + 1 } { true }

  13. Hoare logic cannot be directly automated • Problem: • Let’s now look at “predicate transformer-based verification”. A predicate transformer is a function of type : Statement  Predicate  Predicate { P } S1 { Q } , { Q } S2 { R } --------------------------------------------------------- { P } S1 ; S2 { R }

  14. Forward and backward transformer • cp S P (forward) : transform a given pre-condition P to a post-condition. • cpS Q (backward) : transform a given post-condition Q to a pre-condition. • Do they produce valid (sound) pre/post conditions? Yes if : { P } S { cp S P } { cp S Q } S { Q }

  15. Forward and backward transformer • Sound and complete if : { P } S { Q }  cp S P  Q { P } S { Q }  P  cp S Q

  16. WP and WLP transformer • wpS Q : the weakest pre-condtion so that S terminates in Q. • wlp S Q : the weakest pre-condition so that S, if it terminates, will terminate in Q.wlp = weakest liberal pre-conidtion. • Though, we will see later, that we may have to drop the completeness property of wp/wlp,but we will still call them wp/wlp.

  17. Guarded Command Language (GCL) • Simple language to start • Expressive enough to encode larger languages • So that you can keep your logic-core simple • Constructs • assignment, seq, while, if-then-else • varx in S , uninitialized local-var. • asserte , assumee • try-catch • program decl, program call • primitive types, arrays

  18. wlp • wlp skip Q = Q • wlp (x:=e) Q = Q[e/x] • wlp (S1 ; S2) Q = wlp S1 (wlp S2 Q)We don’t need to propose our own intermediate predicate! • Example, prove: { xy }tmp:= x ; x:=y ; y:=tmp{ xy }

  19. wlp • wlp (asserte) Q = e /\ Q • wlp (assumee) Q = eQ • wlp (S [] T) Q = (wlp SQ) /\ (wlpT Q) • With respect to Hoare triples these two are equivalent (any Hoare triple satisfied by one is satisfied by the other) : ifgthen S1else S2 (assumeg ; S1 ) [] (assume g ; S2 )

  20. wlp • So, it follows:wlp (ifgthen S1else S2) Q = (g wlpS1Q) /\ (g  wlpS2Q) • Note : it is equivalent to (g /\wlpS1Q) \/ (g /\ wlpS2Q)

  21. WLP-based verification • Any program S that does not contain a loop or recursion can be equivalently decomposed into linear “program paths”. • Example : Can be decomposed to: • assume g ; x:=e1 ; assume h ; y := e3 • assume g ; x:=e1 ; assume ¬h ; y := e4 • assume ¬g ; x:=e2 ; assume h ; y := e3 • assume ¬g ; x:=e2 ; assume ¬h ; y := e4 ifgthen x:=e1else x := e2 ;ifhthen y:=e3else y := e4

  22. WLP-based verification • {P} S {Q} is valid ≡ forall program path 𝜎 of S: {P} 𝜎 {Q} is valid. • E.g. to verify : • This approach of verification is also called “symbolic execution”, because it as if we symbolically execute each control path in the target program. { P } ifgthen x:=e1else x := e2 ;ifhthen y:=e3else y := e4 { Q } 1. { P } assume g ; x:=e1 ; assume h ; y := e3 { Q } 2. { P } assume g ; x:=e1 ; assume ¬h ; y := e4 { Q } 3. { P } assume ¬g ; x:=e2 ; assume h ; y := e3 { Q } 4. { P } assume ¬g ; x:=e2 ; assume ¬h ; y := e4 { Q } Each is reducible to pred. logic formula. We can automate this!

  23. Unfeasible path • Consider as an example of program path (recall that the “assumes” came originally from branch-guards) : • A program path can turn out to be unfeasible if no actual execution can trigger it. This happens if one of its branch-guard is unfeasible towards the path pre-condition (P above) : • Condition g above is unfeasible if C1 is unsatisfiable • Condition h is unsatisfiable if C2 in unsatisfiable • Verifying an unfeasible path is waste of effort, but checking if a path in unfeasible also takes effort (above, you need to check C1 and C2). { P } assume g ; x:=x+1 ; assume h ; y := x { y>z } C1 = P /\ g C2 = P /\ g /\ h[x+1/x]

  24. Backward vs forward symbolic execution • Consider the verification of: • Using wlp (backward) we obtain: 2>y. • The validity of the program follows from the validity of x=y /\ y=0 ⇒ 2>y { x=y /\ y=0} x:=x+1 ; x:=2 { x>y } x=y /\ y=0 ⇒ 2>y wlp-based verification

  25. Backward vs forward symbolic execution • Forward symbolic execution: we execute a program, taking a formula as its input : • The Hoare triple on the left is valid if and only if the formula f on the right is valid. Introducing x0 and y0 to represent the initial symbolic value of x and y. 0 1 2 3 { x=y /\ y=0} x:=x+1 ; x:=2 { x>y } x0=y0 /\ y0=0 /\ x1 = x0+1 /\ x2=2 ⇒ x2>y2 f

  26. Backward vs forward transformation • Backward execution yields: x=y /\ y=0 ⇒ 2>y. • Forward execution yields:x0=y0 /\ y0=0 /\ x1 = x0+1 /\ x2=2 ⇒ x2>y2 • Backward transformation: • yields more succinct formulas. • Forward transformation • The direction is more intuitive • The intermediate formulas also produce conditions that correspond to the feasibility of each branch-guard (orange and blue boxes above), so you can immediately check the guard feasibility. Note we can also check this via wlp; it is just that we need more staging in the corresponding symbolic execution.

  27. Can we prove the soundness and completeness of the wlptransformer ? • Yes, e.g. wrt a denotational semantic. I will just give a sketch of how to do this. • Consider the following semantical domains: • State : the space of all possible program states. • val : the space of all possible values of program variables • Note: Chapter 1 and 2 propose two different representations of states. They are both usable, as they both support state query and update.

  28. The semantic of expressions and predicates • ℰ : expr ⟶ (State ⟶ val) • ℰ : Pred ⟶ (State ⟶ bool) // overloading ℰ • e.g. ℰ⟦x>y⟧ = (s. s x > s y) • Note that P:State → bool can equivalently be seen as a set of all the states on which P is true: “P as a set”= { s | s   /\ Ps } • Predicate operators translate to set operators, e.g. /\, \/ to   , negation to complement wrt . • This ordering: “PQ is valid” translates to P  Q

  29. The semantic of statements • 𝒮 : stmt ⟶ (State ⟶ State) • Alternatively: 𝒮 : stmt ⟶ (State ⟶ Pow(State)) to allow non-determinism.where Pow(State) is the domain of all subsets of State. On this domain, we have: ∩ ∪ ⊆ ⊇

  30. The semantic of statements(deterministic) • 𝒮 ⟦skip⟧ = (𝜆s. s) • 𝒮 ⟦ x := e ⟧ = (𝜆s. update s x (ℰ ⟦ e ⟧ s) ) • 𝒮 ⟦ S1 ; S2 ⟧ = (𝜆s. 𝒮 ⟦ S2 ⟧ (𝒮 ⟦ S1 ⟧ s))

  31. Semantic of Hoare Triple(deterministic) • ℋ : Hoare-triple ⟶ boolℋ( {P} S {Q} ) = ∀s: ℰ⟦P⟧ s : ℰ⟦Q⟧ (𝒮⟦S⟧ s) • wlp is sound and complete if: {P} S {Q} if and only if P ⇒ wlp S Q is valid • In comes down to proving that: for all state s, and post-cond Q: ℰ⟦Q⟧ (𝒮⟦S⟧s) if and only if ℰ⟦ wlp S Q ⟧ s • Can be proven inductively over the stucture of S.

  32. Dealing with loop • Unfortunately, no general way to calculate wlp of loops. • For annotated loop, let’s “define” :wlp(inv I while g do S) Q = I , provided • I /\ g  Q • I /\ g  wlpS I

  33. What if there is no I annotated ? • Heuristics to construct invarints e.g. based on the form of the post-condition → not in scope. • Dynamically infer invariants → not in scope. • Non-heuristic approaches, simple; can be used as starting points. • Fix point based • Unfolding

  34. wlp as fix point loop • Note this first: whilegdo S  if g then { S ; whilegdo S } else skip • let W = wlploopQ. = (g /\ wlp S (wlploop Q)) \/ (g /\ Q) • We are looking for the “weakest” solution of W = F(W) W F(W)

  35. The domain of state predicates, Pow(∑) • Suppose ∑ (set of all states) = { s,t,u }. The domain Pow(∑), ordered by ⊆ : { s,t,u } top ( ⟙ ) ... corresponds to “true” related by ⊆ {s,t} {t,u} {s,u} {t} {u} {s} ∅ bottom ( ⟘ ) .... corresponds to “false” X∪Y (union) acts as the least upper bound of X and Y X ∩ Y (intersection) acts asthe greatest lower bound of X and Y

  36. Some bit of fix point theory • (A,) where  is a p.o., is a complete lattice, if every subset X  A has a supremum and infimum. • Supremum = least upper bound = join /\ X  X • Infimum = greatest lower bound = meet \/ X  X • So, we will also have the supremum and infimum of the whole A, often called top ⊤ andbottom ⊥. • Let f : AA. An x such that x = f(x) is a fix point of f. • Knaster-Tarski. Let (A,) be a complete lattice. If f : AA is monotonic over , and P is the set of all its fix points, then P is non-empty, and (P, ) is a complete lattice. • (thus, both  P and  P are also in P).

  37. Some bit of fix point theory • The domain (pow(∑), ) is a complete lattice. • ∑ = top • ∅ = bottom • A∪B : least upper bound (/\) • A ∩ B : greatest lower bound (\/) • So, if F defined before is monotonic within this domain, then it has a greatest fix-point. • Is F monotonic ? • Is wlp monotonic ?

  38. Some bit of fix point theory • Consider now f : pow(∑)  pow(∑). It is -continuous if for all decreasing chain X0⊇ X1 ⊇ X2 ... : f ( X0  X1  ... ) = f(X0)  f(X1)  ... • If f is -continuous, it is also monotonic. • Is wlp -continuous ?

  39. FP iteration • Define: • f 0(X) = X , • f k+1(X) = f ( f k(X)) • Suppose f is -continuous. Consider the series f 0 (∑) , f 1(∑) , f 2(∑) ... Corollaries: • f is also monotonic. • The series is a decreasing chain. • 𝛼 = f 0(∑)  f 1(∑)  f 2(∑)  ... is a fix point of f. • 𝛼 is the greatest fix point of f.

  40. FP iteration • How to compute{ f k (∑) | k0 } ? • compute f 0, f 1, f 2, ... but notice you only need to keep track of the last. • X := ∑ ;while X  f(X) doX := f(X) • Will give the greatest FP, if it terminates. • For wlp : • W := true ;while W  F(W) doW := F(W)where F(W) = (g /\ wlpS W) \/ (g /\ Q)

  41. Example 1 • Q is y=0 • W0 = true • W1 = (y>0 /\ wlp S W0) \/ ((y>0) /\ y=0) = (y>0 /\ true) \/ (y=0) = y0 • W2 = (y>0 /\ y-10) \/ ((y>0) /\ y=0) = y 1 \/ y=0 = y0 • W2 = W1 while y>0 do { y := y−1 } { y=0 }

  42. Example 2 • Q is d -- c,d are boolvars • W0 = true • W1 = (y>0 /\ wlp S W0) \/ ((y>0) /\ d) = (y>0 /\ true) \/ (y0 /\ d) • W2 = (y>0 /\ wlp S W1) \/ (y0 /\ d)= (y>0 /\ y>1) \/ (y=1 /\ d) \/ (y0 /\ d) • W3 = (y>2 ) \/ (y=2 /\ d) \/ (y=1 /\ d) \/ (y0 /\ d) • does not terminate  while y>0 do { y := y−1 } { d }

  43. Example 3 • Q is d -- c,d are boolvars • W0 = true • W1 = (y>0 /\ wlp S W0) \/ ((y>0) /\ d) = (y>0 /\ d) \/ (y0 /\ d) = d • W2 = (y>0 /\ wlp S W1) \/ (y0 /\ d)= (y>0 /\ d) \/ (y0 /\ d) = d • W2 = W1 while y>0 do { assertd ; y := y−1 } { d }

  44. Finite unfolding • Define[while]0 (g,S) = assertg[while]k+1 (g,S) = ifg then { S ; [while]k (g,S) }else skipwhile0 (g,S) = assume gwhile k+1 (g,S) = ifg then { S ; whilek (g,S) }else skip • Iterate at most k-times. • Iterate at most k times, then miracle.

  45. Replacing while with [while]k • wlp ([while]2 (y>0 , y := y−1)) (y=0) = ( y=2 \/ y=1 \/ y=0 ) • Works if P says y is exactly that (0,1,2). • Does not work if P is e.g. y=3 or y≥0 • Such unfolding produces sound wlp, but incomplete. { P } while y>0 do { y := y−1 } { y=0 }

  46. Replacing while with whilek • wlp (while2 (y>0 , y := y−1)) (y=0 /\ b) = y>2 \/ (y=2/\b) \/ (y=1/\b) \/ (y=0/\b) • P : y=0 \/ y=1 ... works • P : y≥0 ... “works” as well • This unfolding yields wlp which is complete but unsound. So, if P ⇒ W, W is the above wlp, is valid, we don’t know if the original specification is also valid. However, if P ⇒ W is invalid, then so is the orig. spec.

  47. Verification of OO programs • GCL is not OO, but we can encode OO constructs in it. We’ll need few additional ingredients : • local variables • simultant assignment • program call • array • object • method

  48. Local variable • wlp(varx in x:=1 ; y := y+xend) (x=y) Rename loc-vars to fresh-vars, to avoid captures:wlp(varx’ in x’:=1 ; y := y+x’ end) (x=y) • Let’s try another example :wlp(varx’ inassume x’>0 ; y := y+x’ end) (x=y) • Note that if x’ is fresh we can alternatively treat this as:assume x’>0 ; y := y+x’

  49. Simultant assignment • For example: x,y := y , x+y{ x=y }wlp (x,y := e1,e2) Q = Q[e1,e2 / x,y] • Compare it with : (x=y) [y/x] [x+y/y] • But e.g. this is not allowed: x,x := e1, e2

  50. Program and program call • Syntax: Pr(x, y | r) body • x,yare input parameters  passed by value • ris an output parameter. • Syntax of program call: a := Pr(e1,e2)Example : • inc(x | r) { r := x+1 } • x := inc(x) • y := inc(x)

More Related