K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 1 Summer School on Logic and Theorem-Proving in Programming.

Slides:



Advertisements
Similar presentations
Advanced programming tools at Microsoft
Advertisements

Joint work with Mike Barnett, Robert DeLine, Manuel Fahndrich, and Wolfram Schulte Verifying invariants in object-oriented programs K. Rustan M. Leino.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 18 Program Correctness To treat programming.
Extended Static Checking for Java Cormac Flanagan K. Rustan M. Leino Mark Lillibridge Greg Nelson James B. Saxe Raymie Stata Compaq SRC 18 June 2002 PLDI02,
Demand-driven inference of loop invariants in a theorem prover
Checking correctness properties of object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 4 EEF summer school on Specification,
Object Invariants in Specification and Verification K. Rustan M. Leino Microsoft Research, Redmond, WA Joint work with: Mike Barnett, Ádám Darvas, Manuel.
Writing specifications for object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 21 Jan 2005 Invited talk, AIOOL 2005 Paris,
1 Towards a Verifying Compiler: The Spec# Approach Wolfram Schulte Microsoft Research Formal Methods 2006 Joint work with Rustan Leino, Mike Barnett, Manuel.
Technologies for finding errors in object-oriented software K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 3 Summer school on Formal Models.
Technologies for finding errors in object-oriented software K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 1 Summer school on Formal Models.
Technologies for finding errors in object-oriented software K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 0 Summer school on Formal Models.
Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Research, Redmond, WA, USA Microsoft Research faculty summit, Redmond,
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Challenges in increasing tool support for programming K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 23 Sep 2004 ICTAC Guiyang, Guizhou, PRC joint.
Using SMT solvers for program analysis Shaz Qadeer Research in Software Engineering Microsoft Research.
Automated Software Verification with a Permission-Based Logic 20 th June 2014, Zürich Malte Schwerhoff, ETH Zürich.
Rigorous Software Development CSCI-GA Instructor: Thomas Wies Spring 2012 Lecture 11.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA, USA 3 December 2008 U. Lugano Lugano, Switzerland.
Leonardo de Moura Microsoft Research. Verification/Analysis tools need some form of Symbolic Reasoning.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 0 International Summer School Marktoberdorf Marktoberdorf,
ECI 2007: Specification and Verification of Object-Oriented Programs Lecture 2 Courtesy: K. Rustan M. Leino and Wolfram Schulte.
Lecture 2 Towards a Verifying Compiler: Logic of Object oriented Programs Wolfram Schulte Microsoft Research Formal Methods 2006 Objects, references, heaps,
Leonardo de Moura and Nikolaj Bjørner Microsoft Research.
Using and Building an Automatic Program Verifier K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Lecture 1 LASER.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 4 International Summer School Marktoberdorf Marktoberdorf,
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 0 Summer School on Logic and Theorem-Proving in Programming.
ECI 2007: Specification and Verification of Object- Oriented Programs Lecture 1.
Building a program verifier K. Rustan M. Leino Microsoft Research, Redmond, WA 10 May 2006 Guest lecture, Shaz Qadeer’s cse599f, Formal Verification of.
K. Rustan M. Leino Microsoft Research, Redmond NUI Maynooth Maynooth, Ireland 8 June 2007.
K. Rustan M. Leino Microsoft Research, Redmond Invited talk, TACAS 2007 ETAPS, Braga, Portugal 28 March 2007.
Using and Building an Automatic Program Verifier K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Lecture 4 LASER.
Well-cooked Spaghetti: Weakest-Precondition of Unstructured Programs Mike Barnett and Rustan Leino Microsoft Research Redmond, WA, USA.
Using and Building an Automatic Program Verifier K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Lecture 5 LASER.
Using and Building an Automatic Program Verifier K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Lecture 3 LASER.
K. Rustan M. Leino Microsoft Research, Redmond, WA 10 Oct 2007 IFIP WG 2.3 meeting Santa Fe, NM.
Using data groups to specify and check side effects K. Rustan M. Leino Microsoft Research Arnd Poetzsch-Heffter Universität Kaiserslautern Yunhong Zhou.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Caltech Pasadena, CA 12 November 2009.
Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Corporation Joint work with: Mike Barnett, Robert DeLine, Manuel.
K. Rustan M. Leino RiSE, Microsoft Research, Redmond joint work with Peter Müller and Jan Smans Lecture 0 1 September 2009 FOSAD 2009, Bertinoro, Italy.
K. Rustan M. Leino RiSE, Joint work with: Peter Müller (ETH Zurich) Jan Smans (KU Leuven) Special thanks to Mike Barnett VMCAI, Madrid, Spain, 18 January.
K. Rustan M. Leino RiSE, Microsoft Research 1 Dec 2008 Invited talk, working group meeting COST Action IC0701, Formal Verification of Object-Oriented Software.
K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 19 July 2007 Invited talk, CADE-21 Bremen, Germany.
Using and Building an Automatic Program Verifier K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Lecture 3 Marktoberdorf.
Program Verification K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond University of Washington CSE P January.
Rustan Leino RiSE, Microsoft Research, Redmond MIT 5 June 2009 Joint work with: Peter Müller, ETH Zurich Jan Smans, KU Leuven.
A Universe-Type-Based Verification Technique for Mutable Static Fields and Methods Alexander J Summers Sophia Drossopoulou Imperial College London Peter.
Using and Building an Automatic Program Verifier K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Lecture 0 Marktoberdorf.
K. Rustan M. Leino Principal Researcher Microsoft Research, Redmond, WA, USA 14 Nov 2007 Øredev Malmö, Sweden.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 3 International Summer School Marktoberdorf Marktoberdorf,
Specifying and verifying programs in Spec# K. Rustan M. Leino Microsoft Research, Redmond, WA, USA Invited talk, PSI 2006 Novosibirsk, Russia 27 June 2006.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 2 International Summer School Marktoberdorf Marktoberdorf,
K. Rustan M. Leino RiSE, Microsoft Research, Redmond joint work with Peter Müller and Jan Smans Lecture 1 2 September 2009 FOSAD 2009, Bertinoro, Italy.
K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 15 Nov 2007 Chalmers Göteborg, Sweden.
1 Verification of object-oriented programs with invariants Mike Barnett, Robert DeLine, Manuel Fahndrich, K. Rustan M. Leino, Wolfram Schulte ECOOP 2003.
ESOP 2010, Paphos, Cyprus, 22 March 2010 K. Rustan M. Leino (RiSE group, Microsoft Research) Peter Müller (ETH Zurich) Jan Smans (KU Leuven)
K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 8 Nov 2007 Invited talk, ASE 2007 Atlanta, GA.
Reasoning about object structures with Spec# K. Rustan M. Leino Microsoft Research, Redmond, WA Joint work with: Mike Barnett, Ádám Darvas, Manuel Fähndrich,
George Edwards Computer Science Department Center for Systems and Software Engineering University of Southern California
Leonardo de Moura and Nikolaj Bjørner Microsoft Research
Dafny An automatic program verifier for functional correctness
Specification techniques for verifying object-oriented software
Auto-active verification
Weakest Precondition of Unstructured Programs
Using and Building an Automatic Program Verifier
Program Verification via an Intermediate Verification Language
Auto-active verification
Hoare-style program verification
Dafny An automatic program verifier for functional correctness
Auto-active verification
Presentation transcript:

K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 1 Summer School on Logic and Theorem-Proving in Programming Languages Eugene, OR 29 July 2008

Verification condition (logical formula) Source language Intermediate verification language

while E invariant J do S end =assert J; havoc x; assume J; (assume E; S; assert J; assume false  assume ¬ E ) where x denotes the assignment targets of S “fast forward” to an arbitrary iteration of the loop check that the loop invariant holds initially check that the loop invariant is maintained by the loop body

The meaning of source statement S is given by Tr[[ S ]] Tr : source-statement  command When defined, the meaning of a source expression E is given by Tr[[ E ]] Tr : source-expression  expression In a context permitted to read set of locations R, source expression E is defined when Df R [[ E ]] holds Df R : source-expression  boolean expression If R is the universal set, drop the subscript R

Tr[[ x := E ]] = assert Df[[ E ]]; x := Tr[[ E ]] Df R [[ E / F ]] = Df R [[ E ]]  Df R [[ F ]]  Tr[[ F ]] ≠ 0 Df R [[ E.x ]] = Df R [[ E ]]  Tr[[ E ]] ≠ null  ( Tr[[ E ]], x )  R Df R [[ E && F ]] = Df R [[ E ]]  (Tr[[ E ]]  Df R [[ F ]])

monitor m { var …; invariant …; } acquire m release m

monitor m { var mx, my; invariant mx ≤ my; } introduce variable Locks Df R [[ mx ]] = m  Locks Tr[[ mx := E ]] = assert m  Locks; assert Df R [[ E ]]; mx := Tr[[ E ]] Tr[[ acquire m ]] = assert m  Locks; Locks := Locks  {m}; havoc mx, my; assume mx ≤ my Tr[[ release m ]] = assert m  Locks; assert mx ≤ my; Locks := Locks – {m}

Tr[[ acquire m ]] = assert m  Locks  max(Locks) < m; Locks := Locks  {m}; havoc mx, my; assume mx ≤ my

class C { var x: int; var y: C; … } Idea: c.x is modeled as Heap[c, x] Details: var Heap const x const y

class C { var x: int; var y: C; … } Idea: c.x is modeled as Heap[c, x] Details: type Ref type Field var Heap: Ref  Field  ? const x: Field const y: Field

class C { var x: int; var y: C; … } Idea: c.x is modeled as Heap[c, x] Details: type Ref; type Field  ; var Heap: . Ref  Field    ; const x: Field int; const y: Field Ref; Heap[c, x] has type int

class C { var x: int; var y: C; … } Translation into Boogie: type Ref; type Field  ; type HeapType =  [ Ref, Field  ]  ; var Heap: HeapType; const unique C.x: Field int; const unique C.y: Field Ref;

introduce: const null: Ref; Df R [[ E.x ]] = Df R [[ E ]]  Tr[[ E ]] ≠ null  ( Tr[[ E ]], x )  R Tr[[ E.x := F ]] = assert Df[[ E ]]  Df[[ F ]]  Tr[[ E ]] ≠ null; Heap[ Tr[[ E ]], x ] := Tr[[ F ]]

introduce: const unique alloc: Field bool; Tr[[ c := new C ]] = havoc c; assume c ≠ null  ¬ Heap[c, alloc]; Heap[c, alloc] := true

introduce: const unique alloc: Field bool; Tr[[ c := new C ]] = havoc c; assume c ≠ null  ¬ Heap[c, alloc]; assume dtype(c) = C; assume Heap[c, x] = 0  Heap[c, y] = null; Heap[c, alloc] := true dynamic type information initial field values

Df R [[ fresh(S) ]] = Df R [[ S ]] Tr[[ fresh(S) ]] = (  o  o  Tr[[ S ]]  o = null  ¬ old(Heap)[o, alloc])

introduce: axiom (  h: HeapType, o: Ref, f: Field Ref  o ≠ null  h[o, alloc]  h[o, f] = null  h[ h[o,f], alloc ] );

introduce: function IsHeap(HeapType) returns (bool); introduce: axiom (  h: HeapType, o: Ref, f: Field Ref  IsHeap(h)  o ≠ null  h[o, alloc]  h[o, f] = null  h[ h[o,f], alloc ] ); introduce: assume IsHeap(Heap) after each Heap update; for example: Tr[[ E.x := F ]] = assert …; Heap[…] := …; assume IsHeap(Heap)

method M(x: X) returns (y: Y) { Stmt } procedure M(this: Ref, x: Ref) returns (y: Ref); requires this ≠ null; implementation M(this: Ref, x: Ref) returns (y: Ref) { Tr[[ Stmt ]] }

method M(x: X) returns (y: Y) requires P; ensures Q; { Stmt } procedure M(this: Ref, x: Ref) returns (y: Ref); requires Df[[ P ]]  Tr[[ P ]]; ensures Df[[ Q ]]  Tr[[ Q ]];

method M(x: X) returns (y: Y) modifies S; { Stmt } procedure M(this: Ref, x: Ref) returns (y: Ref); requires Df[[ S ]]; modifies Heap; ensures (  o: Ref, f: Field   o ≠ null  old(Heap)[o,alloc]  Heap[o,f] = old(Heap)[o,f]  (o,f)  old( Tr[[ S ]] ) );

method M(x: X) returns (y: Y) modifies this.*, x.s, this.p.t; { Stmt } procedure M(this: Ref, x: Ref) returns (y: Ref); requires Df[[ S ]]; modifies Heap; ensures (  o: Ref, f: Field   o ≠ null  old(Heap)[o,alloc]  Heap[o,f] = old(Heap)[o,f]  o = this  (o = x  f = s)  (o = old(Heap)[this,p]  f = t));

method M(x: X) returns (y: Y) { Stmt } procedure M(this: Ref, x: Ref) returns (y: Ref); requires IsHeap(Heap); requires this ≠ null  Heap[this, alloc]; requires x = null  Heap[x, alloc]; ensures IsHeap(Heap); ensures y = null  Heap[y, alloc]; ensures (  o: Ref  old(Heap)[o,alloc]  Heap[o,alloc]);

The source language offers no way to violate these conditions procedure M(this: Ref, x: Ref) returns (y: Ref); free requires IsHeap(Heap); free requires this ≠ null  Heap[this, alloc]; free requires x = null  Heap[x, alloc]; free ensures IsHeap(Heap); free ensures y = null  Heap[y, alloc]; free ensures (  o: Ref  old(Heap)[o,alloc]  Heap[o,alloc]);

method M(x: X) returns (y: Y) requires P; modifies S; ensures Q; { Stmt } procedure M(this: Ref, x: Ref) returns (y: Ref); free requires IsHeap(Heap); free requires this ≠ null  Heap[this, alloc]; free requires x = null  Heap[x, alloc]; requires Df[[ P ]]  Tr[[ P ]]; requires Df[[ S ]]; modifies Heap; ensures Df[[ Q ]]  Tr[[ Q ]]; ensures (  o: Ref, f: Field   o ≠ null  old(Heap)[o,alloc]  Heap[o,f] = old(Heap)[o,f]  (o,f)  old( Tr[[ S ]] )); free ensures IsHeap(Heap); free ensures y = null  Heap[y, alloc]; free ensures (  o: Ref  old(Heap)[o,alloc]  Heap[o,alloc]);

procedure 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[$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[$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, $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];

Chunker.{ssc,dll,bpl} F.bpl

Program ::= Class* Class ::= class C { Field* Method* Function* } S, T ::= var x; x := E; x := new C; E.f := F; assert E; S T if (E) { S } else { T } while (E) invariant J; { S } call a,b,c := E.M(F, G);

class Chunker { var src: String; var n: int; method Init(source: String) requires source ≠ null; modifies {this}; { this.src := source; this.n := 0; } In Spec#:c = new Chunker(source); In Dafny:c := new Chunker; call c.Init(source); In Spec#:c = new Chunker(source); In Dafny:c := new Chunker; call c.Init(source); For simplicity, in Dafny, modifies clauses are done at the object granularity, not the (object,field) granularity. In Spec#: this.* In Dafny: {this} For simplicity, in Dafny, modifies clauses are done at the object granularity, not the (object,field) granularity. In Spec#: this.* In Dafny: {this}

method NextChunk() returns (s: String) modifies {this}; ensures s ≠ null; { if (this.n + 5 ≤ s.Length) { call s := this.src.Substring( this.n, this.n + 5); } else { call s := this.src.Substring( this.n, s.Length); } this.n := this.n + s.Length; } correctness relies on: this.src ≠ null  0 ≤ this.n ≤ this.src.Length correctness relies on: this.src ≠ null  0 ≤ this.n ≤ this.src.Length

Chunker0.dfy

function Valid() returns (bool) { this.src ≠ null  0 ≤ this.n  this.n ≤ this.src.Length } method Init(…) … ensures this.Valid(); method NextChunk(…) … requires this.Valid(); ensures this.Valid();

function F( ) returns (T) { E } function #F(HeapType, Ref) returns (T); Tr[[ o.F( ) ]] = #F(Heap, o) axiom (  h: HeapType, this: Ref  #F(h, this) = Tr[[ E ]]);

Bad!Bad! function F( ) returns (int) { F( ) + 1 } function #F(HeapType, Ref) returns (int); axiom (  h: HeapType, this: Ref  #F(h, this) = #F(h, this) + 1);

function F(p: T) returns (U) reads R; { E } procedure CheckWellDefined_F (this: Ref, p: T) returns (result: U) { assert Df R [[ E ]]; } Df R [[ O.M(E) ]] = Df R [[ O ]]  Tr[[ O ]] ≠ null  Df R [[ E ]]  S[ Tr[[ O ]] / this, Tr[[ E ]] / p ]  R where M has reads clause S can allow  if M returns bool and occurs in a positive position in the definition of a bool function

Chunker1.dfy

Demo: Queue.dfy :Queue:Queue :Node:Node:Node:Node:Node:Node:Node:Node head tail

Design semantics in terms of an intermediate language! Research problems: how to specify programs typing for intermediate language and provers faster/better/more decision procedures Links: These slides: Boogie language reference manual and other papers: Spec#, Boogie, Dafny download: