1 / 32

M odel-based reasoning meets code verification

M odel-based reasoning meets code verification. Michael Butler 21 May 2014 WG 2.3 Meeting 55, Orlando. Talk is about. Distinguish algorithm from its implementation Use of patterns / ghost elements for Verification of algorithm wrt its spec independently from its implementation

fritz-hood
Download Presentation

M odel-based reasoning meets code verification

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. Model-based reasoning meetscode verification Michael Butler 21 May 2014 WG 2.3 Meeting 55, Orlando

  2. Talk is about • Distinguish algorithm from its implementation • Use of patterns / ghost elements for • Verification of algorithm wrt its spec independently from its implementation • Verification of implementation wrt algorithm • Mechanised verification by linking existing verification systems • Dafny & Event-B/Rodin

  3. Model of a transition system SETS STATE CONSTANTSinit, tr, inv, reach tr∈ STATE ↔ STATE// transition relation inv ⊆ STATE // states satisfying invariant init⊆ inv // initial states (satisfy inv) reach = tr*[init] // set of reachable states

  4. Algorithm Specification IF reach ⊆inv THEN result := SAFE ELSE result := UNSAFE END

  5. Representing the transition system in Dafny class STATE {}; method initStatesreturns ( res: seq<STATE> ) ensures res == initial states of system; methodget_successors( s:STATE ) returns ( succ: seq<STATE> ) ensuressucc== “all successors of s” methodcheck_inv(s: STATE) returns( ok:bool ) ensures ok == “s satisfies invariant”

  6. Implementation of algorithm methodCheckReach() returns( pass: bool ) { var safe : seq<STATE>:= initStates() ; var err: seq<STATE>:= [] ; vari:= 0 ; while ( i < |safe| && err == []) { varj := 0; s1 := safe[i]; succ:= get_successors(s1); while ( j < |succ| && err == [] ) { var s2 := succ[j]; if ( s2 !in safe && s2 !in err ) { if( check_inv(s2) ) {safe := safe + [s2]; } else{ err := err + [s2]; } } ; j := j + 1; } ; i := i + 1; } ; if ( err == [] ) { pass := true; } else { pass := false; } }

  7. Search algorithm pattern • FindOk: ∃x∈S •P(x) or • NoFind: ∀x∈S• ¬P(x) Search xor FindOk NoFind StartFind StartFind Fail(i) FindOk Pass(i) NoFind some i all i

  8. Could merge to form a (less abstract) sequential algorithm StartFind; for iin S do Fail(i) [] Pass(i) ; exit od; if exit then FindOkelse NoFindfi

  9. Alternatively refine to parallel model FindOk • Partition S so that search is farmed out to multiple processors p ∈ P • This is a simple refinement step in Event-B StartFind FindOk Pass(p,i) some i:S[p] some p:P

  10. What’s in a refinement pattern? • Determining the refined events is relatively easy once we decide on the appropriate abstract program structure to use • But determining the right gluing invariants can be difficult • Patterns: from a certain specification structure • determine refined events • gluing invariants • convergence variants

  11. “All Condition” Pattern CondAll≙ when ∀i∈ S •Cond(i) then action end Search Fail: Cond(i) ≙ ¬Property(i)

  12. Refinement of CondAll Step ≙ anyiwhere Cond(i) ∧ s ∉ oStep then oStep := oStep ∪ {i} end CondAll≙ when oStep = S then action end CondAll alli:S Step(i) CondAll i ∈ oStep iff Step(i) event has occurred invariant ∀i∈ oStep • Cond(i)

  13. “Some Condition” Pattern CondSome≙ when ∃i . i∈ S ∧ Cond(i) then action end CondSome≙ any iwhere i∈ S Cond(i) then action(i) end

  14. Refinement of CondSome Step ≙ anyiwhere Cond(i) ∧ s ∉ oStep then oStep := oStep ∪ {i} end CondSome≙ any iwhere i∈ oStep then action(i) end CondSome somei:S Step(i) CondSome invariant ∀i∈ oStep• Cond(i)

  15. Refinement invariants for search • Invariant: oPass ⊆ S∩P • Invariant: oFail ⊆ S \ P Search xor FindOk NoFind StartFind StartFind Fail(i) FindOk Pass(i) NoFind some i all i

  16. Convergence variant for search • Variant:S \ ( oPass ∪ oFail ) • Invariant: finite(S) Search xor FindOk NoFind StartFind StartFind Fail(i) FindOk Pass(i) NoFind some i all i

  17. Event-B spec of reachability Pass ≙ WHEN reach ⊆inv THEN result := SAFE END Fail ≙ ANY e WHERE e ∈ reach e ∉inv THEN result := UNSAFE error_state := e END • reachis a ghost constant and it needs to be removed in the implementation • Refine the model to one that computes the reachable states step-by-step

  18. Guards for reachability events • Fail: ∃s∈reach •¬Inv(s) or • Pass: ∀s∈reach • Inv(s) Reach xor Fail Pass Start Start Ok(s) Fail Error(s) Pass Some s All s

  19. Invariants for reachability refinement • Invariant: oSafe⊆ reach ∩ inv • Invariant: oError ⊆ reach \ inv Reach xor Fail Pass Start Start Safe(s) Fail Error(s) Pass Some s All s

  20. Spec of Safe event EventSafe // add a new successor state that satisfies invariant to oSafe ANY s WHERE s ∈ reach s ∈ inv s ∉ oSafe THEN oSafe := oSafe∪ {s} END

  21. Convergence of Safe and Error events • Variant: S \ ( oSafe ∪oFail ) • Invariant: finite(S)

  22. Refining the Fail event AbstractFail ≙ ANY e WHERE e ∈ reach e ∉inv THEN result := FAIL error_state := e END Refined Fail ≙ ANY e WHERE e ∈oError THEN result := FAIL error_state := e END Invariant: oError ⊆ reach ∖ inv Prove guard strengthening refined guard = e ∈oError ⇒ “invariant” e ∈reach ∖ inv = abstract guard

  23. Refining the Pass event Abstract Pass ≙ WHEN reach ⊆inv THEN result := OK END Refined Pass ≙ WHEN oSafe = reach THEN result := OK END Invariant: oSafe ⊆ reach ∩ inv Prove guard strengthening oSafe= reach ⇒ “invariant” reach ⊆ reach ∩ inv ⇒ “set theory” reach ⊆ inv

  24. The specter of reach remains • Fail events do not refer to reach so no further refinement required • Pass events still do refer to reach, so further refinement required • Refine the guard of the Safe(s) event: s ∈ reach ⇐ “reach is a fixed point” ∃s1 • s1∈ reach ∧ s1↦s∈tr ⇐“oSafe ⊆ reach” ∃s1 • s1∈ oSafe ∧ s1↦s∈tr

  25. Add new parameter to Safe event EventSafe ANY s, s1 WHERE s1 ∈ oSafe s1↦s∈tr s ∈ inv s ∉ oSafe THEN oSafe := oSafe∪ {s} END

  26. Extra parameter gives nested iteration Pass Pass all s1 alls alls Safe(s) Pass Safe(s1,s) Pass

  27. Further refinement: tracking the explored states • A state is explored if it is in safe and all its successors are reached • Invariant: tr[ explored ] ⊆ ( oSafe ∪ oError ) • Introduce new event: EventMark_explored ANY s WHERE s ∈ rac s ∉ explored tr[{s}] ⊆ ( oSafe ∪ oError) THEN explored:= explored∪ {s} END

  28. Refining the Pass event Pass ≙ WHEN oSafe = reach THEN result := OK END Refined Pass ≙ WHEN explored = oSafe oError = {} THEN result := OK END Invariant: tr[ explored ] ⊆ ( oSafe ∪ oError ) Prove guard strengthening explored = oSafe ∧ oError = {} ⇒ “invariant” tr[ oSafe ] ⊆ oSafe ⇒“reach is least fixed point” reach ⊆ oSafe

  29. What to verify in Dafny? • Verify that the Dafny code is a correct refinement of the final Event-B model • Event-B variables become ghost variables in Dafny • Gluing invariants in Dafny: invariant oSafe == seqElems(safe); invariant oError == seqElems(err); invariant explored == seqElems(safe[0..i]); • Embed the events into the Dafny code

  30. Embed events in the Dafny methodCheckReach() returns( pass: bool ) { … Init while ( i < |safe| && err == []) { varj := 0; s1 := safe[i]; succ:= get_successors(s1); while ( j < |succ| && err == [] ) { var s2 := succ[j]; if ( s2 !in safe && s2 !in err ) { if( check_inv(s2) ) {safe := safe + [s2]; Safe(s1,s2); }; else{ err := err + [s2]; Error(s2); } } ; j := j + 1; } ; Mark_Explored ; i := i + 1; } ; if ( err == [] ) { pass := true; Pass ; } else { pass := false; Fail ;} }

  31. Ghost busters • Guarded event: when G then A end == (assume G) ; A • Eliminating guards with assertions (assert G) ; (assume G) ; A ⊑ A • Once guards are removed, ghost variables no longer influence the program so can be eliminated

  32. Concluding • Correctness of algorithm is proved independently of Dafny (with help from patterns) • At Dafny level we prove that the code is a correct implementation of the algorithm • Avoided any duplication in proof except for Dafny variants • NB: proposed “embeddding” method for proving Dafny refines the algorithm only works if code is deterministic

More Related