320 likes | 450 Vues
Specifying and verifying software. K. Rustan M. Leino Microsoft Research, Redmond, WA, USA. 15 Nov 2007 Chalmers G öteborg, Sweden. Collaborators most relevant to this talk. Mike Barnett Nikolaj Bjørner Leonardo de Moura Manuel F ä hndrich Bart Jacobs Ronald Middelkoop Michał Moskal.
E N D
Specifying and verifying software K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 15 Nov 2007ChalmersGöteborg, Sweden
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
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
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]
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)
Static verification • Sound modular verification • Focus on automation, not full functional correctness specifications • No termination verification • No verification of temporal properties
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
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 …?
Challenges 0: specifications 1: specifications Spec# C 3: translation 4: translation BoogiePL 2: BoogiePL overview 5:V.C. generation Z3
0: Specifications in Spec# • Multi-variable invariants • Multi-object invariants
Multi-variable invaraints • Demo
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
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;}
2: Overview of BoogiePL • Top-level declarations • Statements
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) { … }
BoogiePL statements • x := E • a[ i ] := E • havoc x • assert E • assume E • ; • call P() • if • while • break • label: • goto A, B
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
// 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;
// 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()
// 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);
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 ] ;
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)
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)]);
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 …
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
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 ?
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
Galois and wp, wlp, sp • f(x) ≤ y ≡ x ≤ g(y) • sp(S, P) Q ≡ P wlp(S, Q) • ? ≡ P wp(S, Q)
Further challenges • Prove more programs • Extend structuring methodologies • Improve performance • Raise level of abstraction, e.g.: • Alloy • Meta programming • B method
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