1 / 34

Specifying and verifying software

Specifying and verifying software. K. Rustan M. Leino Microsoft Research, Redmond, WA, USA. 8 Nov 2007 Invited talk, ASE 2007 Atlanta, GA. Collaborators most relevant to this talk. Mike Barnett Nikolaj Bjørner Leonardo de Moura Manuel F ä hndrich Bart Jacobs Ronald Middelkoop

genica
Download Presentation

Specifying and verifying software

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. Specifying and verifying software K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 8 Nov 2007Invited talk, ASE 2007Atlanta, GA

  2. Collaborators most relevant to this talk • Mike Barnett • Nikolaj Bjørner • Leonardo de Moura • Manuel Fähndrich • Bart Jacobs • Ronald Middelkoop • Michał Moskal • Peter Müller • Ralf Sasse • Wolfram Schulte • Jan Smans • Herman Venter • Angela Wallenburg

  3. Software engineering problem • Problem • Building and maintaining programs that are correct • Approach • Specifications record design decisions • bridge intent and code • Tools amplify human effort • manage details • find inconsistencies • ensure quality

  4. Grand Challenge ofVerified Software • Hoare, Joshi, Leavens, Misra, Naumann, Shankar, Woodcock, et al. • “We envision a world in which computer programs are always the most reliable component of any system or device that contains them” [Hoare & Misra]

  5. Spec# programming system • Spec# language • Object-oriented .NET language • Superset of C#, adding: • more types • specifications (pre- and postconditions, etc.) • Usage rules (methodology) • Checking: • Static type checking • Run-time checking • Static verification (optional)

  6. Static verification • Sound modular verification • Focus on automation, not full functional correctness specifications • No termination verification • No verification of temporal properties

  7. Spec# demo

  8. Spec# verifier architecture Spec# Spec# compiler MSIL (“bytecode”) Translator BoogiePL Inference engine static verifier (Boogie) V.C. generator verification condition SMT solver “correct” or list of errors

  9. BoogiePL – a verification tool bus Spec# C HAVOC and VerifiedC (vcc) Java bytecode + BML Eiffel …? abstract interpreter predicate abstraction? BoogiePL termination detector? …? Z3 Simplify Zap 2 SMT Lib Fx7 Isabelle/HOL …?

  10. Challenges 0: specifications 1: specifications Spec# C 3: translation 4: translation BoogiePL 2: BoogiePL overview 5:V.C. generation Z3

  11. 0: Specifications in Spec# • Multi-variable invariants • Multi-object invariants

  12. Multi-variable invaraints • Demo

  13. Multi-object invariants :Chunker :Chunker :Classroom n: 84 n: 20 invstudentGrades.Count ≤ 20; invdict.Count ≤ n; invdict.Count ≤ n; rep dict: dict: studentGrades: owner :Dictionary Count: 21

  14. 1: Specifications in vcc • Based on dynamic frames [YannisKassios, FM 2006] class C {int x; int y; Dictionary d; …frame f  { x, y, d, … }  d.fr;predicate Valid reads f  x ≤ y  d.Valid  … ;method M()requires Valid;modifies f;ensures Valid;}

  15. 2: Overview of BoogiePL • Top-level declarations • Statements

  16. BoogiePL declarations • type T; • const x: T; • function f(A, B) returns (T); • axiom E; • var y: T; • procedure P(a: A, b: B) returns (x: T, y: U); requires pre; modifies w; ensures Q; • implementation P(a: A, b: B) returns (x: T, y: U) { … }

  17. BoogiePL statements • x := E • a[ i ] := E • havoc x • assert E • assume E • ; • call P() • if • while • break • label: • goto A, B

  18. BoogiePL demo F

  19. BoogiePL demo Queue frame :Queue head: tail: … :Node :Node :Node :Node next: next: next:

  20. 3: Defining OO semantics by translation into BoogiePL class C : object{int x; C() { … } virtualint M(int n) { … } staticvoid Main() { C c = new C();c.x = 12;int y = c.M(5); }} Example source program

  21. // class types constuniqueSystem.Object: name; constuniqueC: name; axiom C <: System.Object; functiontypeof(ref) returns(name); // fields typeField; constuniqueC.x: Field; constuniqueallocated: Field; // the heap var Heap: [ref, Field] int; Example: BoogiePL translation (0) class C : object { int x;

  22. // method declarations procedure C..ctor(this: ref); requires this != null&&typeof(this) <: C; modifies Heap; procedure C.M(this: ref, n: int)returns(result: int); requires this != null&&typeof(this) <: C; modifies Heap; procedureC.Main(); modifies Heap; Example: BoogiePL translation (1) C() { … } virtualint M(int n) staticvoid Main()

  23. // method implementations implementationC.Main() { var c: ref, y: int; havoc c; assume c != null; assume Heap[c, allocated] == 0; assumetypeof(c) == C; Heap[c, allocated] := 1; call C..ctor(c); assert c != null; Heap[c, C.x] := 12; call y := C.M(c, 5); } Example: BoogiePL translation (2) c.x = 12; C c = new C(); int y = c.M(5);

  24. The type of the heap • type Field;var Heap: [ref, Field] int; • type Field;varHeapInt: [ref, Field] int;varHeapBool: [ref, Field] bool;… • type Field;type Value;var Heap: [ref, Field] Value; and conversion functions between Value and other types • type Field ;var Heap: .[ref, Field ] ;

  25. Translation in more detail:Chunker.NextChunk specification publicstringNextChunk() modifiesthis.*; ensuresresult.Length <= ChunkSize;

  26. Chunker.NextChunk translation procedureChunker.NextChunk(this: refwhere $IsNotNull(this, Chunker)) returns ($result: refwhere $IsNotNull($result, System.String)); // in-parameter: target object freerequires $Heap[this, $allocated]; requires ($Heap[this, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]) || $Heap[$Heap[this, $ownerRef], $localinv] == $BaseClass($Heap[this, $ownerFrame])) && (forall $pc: ref :: $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[this, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[this, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc)); // out-parameter: return value freeensures $Heap[$result, $allocated]; ensures ($Heap[$result, $ownerFrame] == $PeerGroupPlaceholder || !($Heap[$Heap[$result, $ownerRef], $inv] <: $Heap[$result, $ownerFrame]) || $Heap[$Heap[$result, $ownerRef], $localinv] == $BaseClass($Heap[$result, $ownerFrame])) && (forall $pc: ref :: $pc != null && $Heap[$pc, $allocated] && $Heap[$pc, $ownerRef] == $Heap[$result, $ownerRef] && $Heap[$pc, $ownerFrame] == $Heap[$result, $ownerFrame] ==> $Heap[$pc, $inv] == $typeof($pc) && $Heap[$pc, $localinv] == $typeof($pc)); // user-declared postconditions ensures $StringLength($result) <= $Heap[this, Chunker.ChunkSize]; // frame condition modifies $Heap; freeensures (forall $o: ref, $f: name :: { $Heap[$o, $f] } $f != $inv && $f != $localinv && $f != $FirstConsistentOwner && (!IsStaticField($f) || !IsDirectlyModifiableField($f)) && $o != null && old($Heap)[$o, $allocated] && (old($Heap)[$o, $ownerFrame] == $PeerGroupPlaceholder || !(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame]) || old($Heap)[old($Heap)[$o, $ownerRef], $localinv] == $BaseClass(old($Heap)[$o, $ownerFrame])) && old($o != this || !(Chunker <: DeclType($f)) || !$IncludedInModifiesStar($f)) && old($o != this || $f != $exposeVersion) ==> old($Heap)[$o, $f] == $Heap[$o, $f]); // boilerplate freerequires $BeingConstructed == null; freeensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } $o != null && !old($Heap)[$o, $allocated] && $Heap[$o, $allocated] ==> $Heap[$o, $inv] == $typeof($o) && $Heap[$o, $localinv] == $typeof($o)); freeensures (forall $o: ref :: { $Heap[$o, $FirstConsistentOwner] } old($Heap)[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] == $Heap[old($Heap)[$o, $FirstConsistentOwner], $exposeVersion] ==> old($Heap)[$o, $FirstConsistentOwner] == $Heap[$o, $FirstConsistentOwner]); freeensures (forall $o: ref :: { $Heap[$o, $localinv] } { $Heap[$o, $inv] } old($Heap)[$o, $allocated] ==> old($Heap)[$o, $inv] == $Heap[$o, $inv] && old($Heap)[$o, $localinv] == $Heap[$o, $localinv]); freeensures (forall $o: ref :: { $Heap[$o, $allocated] } old($Heap)[$o, $allocated] ==> $Heap[$o, $allocated]) && (forall $ot: ref :: { $Heap[$ot, $ownerFrame] } { $Heap[$ot, $ownerRef] } old($Heap)[$ot, $allocated] && old($Heap)[$ot, $ownerFrame] != $PeerGroupPlaceholder ==> old($Heap)[$ot, $ownerRef] == $Heap[$ot, $ownerRef] && old($Heap)[$ot, $ownerFrame] == $Heap[$ot, $ownerFrame]) && old($Heap)[$BeingConstructed, $NonNullFieldsAreInitialized] == $Heap[$BeingConstructed, $NonNullFieldsAreInitialized];

  27. 4: Defining C semantics by translation into BoogiePL • A pointer in C can go to any byte location in a segment • A pointer is a (segment, offset) pair • base(ptr) gives the segment • offset(ptr) gives the offset within the segment • Each segment has a fixed length • length(seg)

  28. Modeling memory • Consider the translation of: *p = k; m = *p; • typePtr; type Segment;function base(Ptr) returns (Segment);function offset(Ptr) returns (int); • varMem: [Segment, int] int; • assert 0 ≤ offset(p);assertoffset(p) + 4 ≤ length(base(p));Mem[base(p), offset(p)] := B3(k);Mem[base(p), offset(p)+1] := B2(k);Mem[base(p), offset(p)+2] := B1(k); Mem[base(p), offset(p)+3] := B0(k); • assert 0 ≤ offset(p);assertoffset(p) + 4 ≤ length(base(p));m := Word( Mem[base(p), offset(p)+3],Mem[base(p), offset(p)+2],Mem[base(p), offset(p)+1],Mem[base(p), offset(p)]);

  29. Alternative memory model • Define custom functions to access memory • typeMType; typePtr;typeByteSeq;function rd(MType, Ptr, int) returns (ByteSeq);functionwr(MType, Ptr, int, ByteSeq) returns (Mtype); • axiom ( m: MType, p: Ptr, q: Ptr,plen: int, qlen: int, val: ByteSeq  base(p) = base(q)  offset(p) = offset(q)  0 < plen  plen = qlen rd(wr(m,p,plen,val), q, qlen) = val); • axiom ( m: MType, p: Ptr, q: Ptr,plen: int, qlen: int, val: ByteSeq  base(p)  base(q)  offset(p) + plen ≤ offset(q)  offset(q) + qlen ≤ offset(p) rd(wr(m,p,plen,val), q, qlen) = rd(m, q, qlen)); • axiom …

  30. 5: Verification-condition generation • Use of quantifiers • Matching triggers, available already in BoogiePL • Reducing redundancy • Paths across conditional statements • But also splitting VCs into smaller ones • wp versus sp

  31. Weakest-precondition versus strongest-postcondition • { P } S { Q } • Started in a state satisfying P, • no execution of S will go wrong, and • every terminating execution of S will end in a state satisfying Q • P  wp(S, Q) • or perhaps: sp(P, S)  Q ?

  32. wp versus sp • wp(x := E, Q) = Q[E/x] • wp(S;T, Q) =wp(S, wp(T, Q)) • wp(assume E, Q) = E  Q • wp(assert E, Q) = E  Q • sp(P, x := E) =(y P[y/x]  x = E[y/x]) • sp(P, S;T) = sp(sp(P, S), T) • sp(P, assume E) = E  P • sp(P, assert E) = E  Pbut one would also like to check that E actually holds in P

  33. Further challenges • Prove more programs • Extend structuring methodologies • Improve performance • Raise level of abstraction, e.g.: • Alloy • Meta programming • B method

  34. Summary and conclusions • Verification for Spec#, C, and BoogiePL • To verify, use an intermediate language • Separates concerns • Promotes sharing in verification community • Front ends for multiple languages • Multiple theorem provers • Shared benchmarks • Build your own verifier using Boogie • Hardest part in designing VCs: programming methodology that • Fits common programming idioms and • Can be handled well by automatic prover • Education • Teach using Spec# • Teach verification using BoogiePL • http://research.microsoft.com/specsharp DownloadSpec# and Boogiefrom here

More Related