1 / 30

Verifying object-oriented software: Lessons and challenges

Verifying object-oriented software: Lessons and challenges. K. Rustan M. Leino Microsoft Research, Redmond. Invited talk, TACAS 2007 ETAPS, Braga, Portugal 28 March 2007. Collaborators. Rosemary Monahan Michaŀ Moskal Peter Müller Madan Musuvathi Dave Naumann Simon Ou

aquarius
Download Presentation

Verifying object-oriented software: Lessons and challenges

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. Verifying object-oriented software:Lessons and challenges K. Rustan M. Leino Microsoft Research, Redmond Invited talk, TACAS 2007ETAPS, Braga, Portugal28 March 2007

  2. Collaborators • Rosemary Monahan • MichaŀMoskal • Peter Müller • MadanMusuvathi • Dave Naumann • Simon Ou • ArndPoetzsch-Heffter • Wolfram Schulte • Herman Venter • Angela Wallenburg • … • Dave Detlefs • Cormac Flanagan • Rajeev Joshi • Gary Leavens • Mark Lillibridge • Todd Millstein • Greg Nelson • Jim Saxe • RaymieStata • Mike Barnett • Nikolaj Bjørner • Evan Chang • Ádám Darvas • Rob DeLine • Leo de Moura • Manuel Fähndrich • Diego Garbervetsky • Bart Jacobs • Francesco Logozzo

  3. 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]

  4. Spec# programming system • Spec# language • Object-oriented .NET language • More types • Specifications (pre- and postconditions, etc.) • Usage rules (methodology) • Checking: • Static type checking • Run-time checking • Static verification (optional)

  5. Static verification • sound modular verification • focus on automation, not full functional correctness specifications • no termination verification • no verification of temporal properties

  6. Spec# demo

  7. 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

  8. Lessons and challenges • Language design • Specifications • VC generation • Inference and decision procedures • Error messages

  9. Language design for verification • non-null types • control flow • if, loops, exceptions, gotos • by default, put base-constructor call last • include pre- and postconditions constructs • à la Gypsy, Eiffel • superset of full language is challenging

  10. Comparing against null publicvoid M( T? x ) { if (x == null) { … } else {int y = ((T!)x).f; … }}

  11. Comparing against null publicvoid M( T? x ) { if (x == null) { … } else {int y = ((!)x).f; … }}

  12. Comparing against null publicvoid M( T? x ) { if (x == null) { … } else {int y = x.f; … }} Spec# performs a data-flow analysis to allow this (similar to definite assignment)

  13. Non-null instance fields No! Is this code type safe? class C : B { T ! x;public C(T ! y) {base();this.x = y;this.P();} publicoverrideint M() { returnx.f; } } abstractclass B {public B() { this.M(); } publicabstractint M(); } null dereference

  14. Non-null instance fields Spec# allows x to beassigned before baseconstructor is called. class C : B { T ! x;public C(T ! y) {this.x = y;base(); this.P();} publicoverrideint M() { returnx.f; } }

  15. Specifications • specifying consistency of data (invariants) • organizing the heap (ownership, …) • abstraction and information hiding (model fields, pure methods, …) • frame conditions (modifies clauses) • support for useful programming idioms • Spec# has a numerous attributes—what is a small, usable set?

  16. x.M(); The heap x exposed mutable consistent committed valid

  17. Frame conditions modifiesp.x; modifies Heap; ensures (forall o: ref, f: field :: • Heap[o,f] == old(Heap)[o,f] •  (o == p  f == x) •   old(Heap)[o,allocated] •  old(Heap)[o,committed] • );

  18. VC generation • use an intermediate language • BoogiePL, Why [Filliâtre et al.] • a common verification toolbus • challenge: how to take advantage of special features/theories of the underlying provers? • loop invariants • simple inference helps • applying method frame conditions to loops • functions and quantifiers encode theories • extensible, convenient

  19. BoogiePL Spec# C Java+JML Eiffel … abstract interpreter BoogiePL predicate abstraction termination detector … Simplify Z3 CVC 3 SMT Lib Coq …

  20. Example: source program class C : object{int x; C() { … } virtualint M(int n) { … } staticvoid Main() { C c = new C();c.x = 12;int y = c.M(5); }}

  21. Example: BoogiePL translation (0) • class C • : object { • int x; // class types constuniqueSystem.Object: name; constuniqueC: name; axiom C <: System.Object; functiontypeof(o: ref) returns (t: name); // fields typefield; constuniqueC.x: <int>field; constuniqueallocated: <bool>field; // the heap var Heap: [ref, <α>field]α;

  22. Example: BoogiePL translation (1) C() { … } virtualint M(int n) staticvoid Main() // 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;

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

  24. Chunker.NextChunk specification publicstringNextChunk() modifiesthis.*; ensuresresult.Length <= ChunkSize;

  25. 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];

  26. Inference, decision procedures • most useful features in theorem prover: • functions and equality, boolean connectives, quantifiers, arithmetic, … • counterexamples • good performance • benchmarks • very different from, say, TTA (time-triggered architecture) protocols • wish: combine inference and theorem proving

  27. Achieving goodSMT-prover performance • non-chronological backtracking • avoid “exponential splitting” • incremental matching -- Leonardo de Moura, on Z3 for Boogie

  28. Combining inference and theorem proving • Abstraction • Computes fix-points • Arithmetic • Unique variables names • Functions, equality • Heap operations Spec# … BoogiePL Inference engine • Precision • Unique variables names • Functions, equality • Arithmetic • Heap operations • Quantifiers V.C. generator verification condition SMT solver

  29. Generating error messages • error location and execution trace to error can easily be reconstructed from simple/limited prover output • better: concrete values, more explanation • e.g., “an object allocated by method M and is later changed by the call to P might violate ownership invariant”

  30. Conclusions • Spec#, C, functional languages, dynamically typed languages, … • allow correctness features to drive language design • use intermediate language • separation of concern • let us share as a community (abstract interpretation, VC generation, multiple theorem provers, predicate abstraction, …) • theorem prover must be good with quantifiers • exciting prospect: combine abstract interpretation and SMT solving • mine counterexamples for more detailed error messages DownloadSpec# from here http://research.microsoft.com/specsharp

More Related