k. rustan m. leino microsoft research, redmond, wa, usa 19 july 2007 invited talk, cade-21 bremen,...

41
Designing verification conditions for software K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Upload: dominick-nicholson

Post on 02-Jan-2016

214 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Designing verification conditions for software

K. Rustan M. LeinoMicrosoft Research, Redmond, WA, USA

19 July 2007Invited talk, CADE-21Bremen, Germany

Page 2: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Recent collaboratorsMike BarnettNikolaj BjørnerEvan ChangErnie CohenÁdám DarvasLeo de MouraManuel FähndrichBart JacobsFrancesco Logozzo

Ronald MiddelkoopRosemary MonahanPeter MüllerRalf SasseWolfram SchulteJan SmansHerman VenterAngela WallenburgBurkhart Wolff

Page 3: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Software engineering problemProblem

Building and maintaining programs that are correct

ApproachSpecifications record design decisions

bridge intent and codeTools amplify human effort

manage detailsfind inconsistenciesensure quality

Page 4: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Grand Challenge of

Verified SoftwareHoare, 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]

Page 5: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Spec# programming systemSpec# language

Object-oriented .NET languageSuperset of C#, adding:

more typesspecifications (pre- and postconditions, etc.)

Usage rules (methodology)Checking:

Static type checkingRun-time checkingStatic verification (optional)

Page 6: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Static verificationSound modular verificationFocus on automation, not full functional correctness specificationsNo termination verificationNo verification of temporal properties

Page 7: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Spec# demo

Page 8: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

stati

c veri

fier

(Boogie

)

MSIL (“bytecode”)

SMT solver

V.C. generator

Inference engine

Translator

verification condition

“correct” or list of errors

Spec# compiler

Spec#

BoogiePL

Spec# verifier architecture

Page 9: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

BoogiePL – a verification tool bus C

HAVOC and VerifiedC

Eiffel …?Java

bytecode + BML

Spec#

Z3Simplif

yZap 2

SMT Lib

Fx7

Isabelle/HOL

…?

BoogiePL

abstract interpreter

predicate abstraction?

termination detector?

…?

Page 10: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Requirements of proverEUF, arithmetic, quantifiersCounterexamplesFast, for both valid and invalid formulas

Page 11: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Achieving goodSMT-solver performance

Non-chronological backtrackingAvoid “exponential splitting”Incremental matching

-- Leonardo de Moura, on Z3 for Boogie

Page 12: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

BoogiePL declarationstypeconstfunctionaxiomvarprocedureimplementation

Page 13: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

BoogiePL statementsx := Ea[ i ] := Ehavoc xassert Eassume E;call P()

ifwhilebreaklabel:goto A, B

Page 14: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

BoogiePL demo: DutchFlag

Page 15: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Example: source program

class C : object {int x;C( ) { … } virtual int M(int n) { … } static void Main() {

C c = new C( );c.x = 12;int y = c.M(5);

}}

Page 16: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Example: BoogiePL translation (0)

// class typesconst unique System.Object: name;const unique C: name;

axiom C <: System.Object;

function typeof(ref) returns (name);

// fieldstype field;const unique C.x: field;const unique allocated: field;

// the heapvar Heap: [ref, field] int;

class C: object {

int x;

Page 17: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Example: BoogiePL translation (1)

// 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;

procedure C.Main(); modifies Heap;

C() { … }

virtual int M(int n)

static void Main()

Page 18: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Example: BoogiePL translation (2)

// method implementations

implementation C.Main(){ var c: ref, y: int;

havoc c; assume c != null; assume Heap[c, allocated] ==

0; assume typeof(c) == C; Heap[c, allocated] := 1; call C..ctor(c);

assert c != null; Heap[c, C.x] := 12;

call y := C.M(c,

5);

}

C c = new C();c.x = 12;

int y = c.M(5);

Page 19: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Computing weakest preconditions0. Cut back edges1. Remove assignments2. (Recursively) apply wp (with some

form of memoization)

Page 20: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Modeling the memoryclass C { int f; object g; }var f: [ref] int;var g: [ref] ref;type Field; type Value;var Heap: [ref, Field] Value;function V2I(Value) returns (int);function I2V (int) returns (Value);axiom ( v: Value I2V(V2I(v)) == v);axiom ( i: int V2I(I2V(i)) == i);type Field ;var Heap: . [ref, Field ] ;For C:

select(Memory, Region, Offset, Length)store(Memory, Region, Offset, Length, Value)

x = c.f;

x := f [ c ];x = c.f;

x := V2I(Heap[ c, f ]);

x = c.f;

x := Heap[ c, f ];

Page 21: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Example:Chunker.NextChunk specificationpublic string NextChunk() modifies this.*; ensures result.Length <= ChunkSize;

Page 22: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Chunker.NextChunk translationprocedure Chunker.NextChunk(this: ref where $IsNotNull(this, Chunker)) returns ($result: ref where $IsNotNull($result, System.String)); // in-parameter: target object free requires $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 free ensures $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; free ensures (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 free requires $BeingConstructed == null; free ensures (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)); free ensures (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]);

free ensures (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]);

free ensures (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];

Page 23: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Working with quantifiersInstantiation via e-graph matchingA matching pattern (trigger) is a set of terms that together mention all the bound variables, and none of which is just a bound variable by itselfExamples:

(x { f(x) } 0 ≤ f(x))(x,y { g(x,y) } f(x) < g(x,y))

Page 24: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

More trigger examples(x,y { f(x), f(y) } x ≤ y f(x) ≤ f(y))(x { f(x) } x ≠ null f(x) ≤ f(next(x)))(x { f(next(x)) } x ≠ null f(x) ≤ f(next(x)))(x,y { f(x), f(y) } f(x) = f(y) x = y)(x { f(x) } f Inv(f(x)) = x)(x { f(x+1) } f(x) ≤ f(x+1))(x,y,z { x*(y+z) } x*(y+z) = x*y + x*z)(x,y { P(x,y) } x = y P(x,y) = 10)(x { P(x,x) } P(x,x) = 10)

Page 25: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Axiomatizing characteristics of source language

Introduce IsHeap(h) to mean“h is a well-formed heap”class C { T f; … }(h,o IsHeap(h) o ≠ null

h[o,f ] = null typeof(o) <: T )(h,o IsHeap(h) o ≠ null h[o,allocated]

h[o,f ] = null h[h[o,f ], allocated] )Since the heap uses the select/store axioms, it cannot be enforced by the BoogiePL type system

Page 26: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Discharging the IsHeap antecedent

The encoding needs to introduce assumptions that IsHeap holds

o.f = E;Heap[o,f ] := E; assume IsHeap(Heap);

IsHeap(Heap) is a free pre- and postcondition of every method

free requires IsHeap(Heap);modifies Heap;free ensures IsHeap(Heap);

Page 27: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Show and tell: Array types

Page 28: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Demo: Aggregate objects

Page 29: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Object states: a picture of the heap

Mutable

Consistent

Committed

c: Chunker

StringBuilder

ownershipsb

expose (c) { … }

Valid

Page 30: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Object states: a picture of the heap

Mutable

Committed

c: Chunker

StringBuilder

ownership

expose (c) { … }

sb

Consistent

Valid

Page 31: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Object states: a picture of the heap

Mutable

Committed

c: Chunker

StringBuilder

ownership

expose (c) { … }

sb

Consistent

Valid

Page 32: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Object states: a picture of the heap

Mutable

Committed

c: Chunker

StringBuilder

ownership

expose (c) { … }

sb

Consistent

Valid

Page 33: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Validityclass C { int x; int y; invariant x ≤ y; … }(h, o

IsHeap(h) x ≠ null h[o,allocated]

typeof(o) <: C Valid(o, h) h[o,x] ≤ h[o,y] )

Page 34: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Peer consistencyo is peer consistent in h

(h[o, owner] = Valid(h[o, owner]))

(p h[p, owner] = h[o, owner] Valid(p,h))

Peer consistency is the default precondition of all parameters of all methodsNeeds to be proved (all over!)

Page 35: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Frame conditionsvoid M( ) modifies this.x, this.y; { … }modifies Heap;ensures (o, f

Heap[o,f] = old(Heap)[o,f] (o = this f = x) (o = this f = y) old(Heap)[o, allocated]// or o is committed in old(Heap) old(Heap[o,owner]

Valid(Heap[o,owner], Heap)))

Page 36: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Type system for intermediate verification languageTypes find errors in translation

Some types are required by some provers (e.g., SMT Lib)

Page 37: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Type example (0)type R; // type representing recordstype Field ;function Get: . R Field ;function Set: . R Field R;axiom ( (r: R, f: Field , g: Field , x:

f = g Get(Set(r, f, x), g) = x ));axiom (, (r: R, f: Field , g: Field , x:

f g Get(Set(r, f, x), g) = Get(r, g) ));

Type error

Page 38: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Type example (1)class C {

int x; bool y; void M() modifies this.x, this.y;

{ … }const x: Field int;const y: Field bool;procedure M(this: ref);

modifies Heap;ensures ( (o: ref, f: Field

Heap[o,f] = old(Heap)[o,f] (o = this f = x) (o = this f = y) … )

Type errors

Page 39: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Are types worth the trouble?How complicated does the type

system need to be?parametric polymorphism?subtyping?type (disequality) constraints?guarded types?

How is it translated into provers with less advanced type systems?Performance penalty (ironically)Does it really help the prover that much?

[Meng & Paulson][Couchot & Lescuyer]

Page 40: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Other prover featuresLabeled subformulas

Useful for:pin-pointing location and type error, anddetermining execution traces leading to error

ModelsCan be used to print better error messages

Proving existentialsNeeded to prove that a function is well-definedMatching not up to the task (there is nothing to match against)

Page 41: K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany

Download

Spec# and

Boogie

from here

Summary and conclusionsSpec# system, Boogie, BoogiePLTo verify, use an intermediate language

Separates concernsPromotes sharing in verification community

Front ends for multiple languagesMultiple theorem proversShared benchmarks

Quantifiers are both crucial and convenientReduce the need for other theoriesTriggers are important

Need to be carefully designedInclude in competitions. SMT Comp?

What’s a good type system for prover input?Hardest part in designing VCs: programming methodology that

Fits common programming idioms andCan be handled well by automatic prover

Education

http://research.microsoft.com/specsharp