Presentation is loading. Please wait.

Presentation is loading. Please wait.

Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Research, Redmond, WA, USA Microsoft Research faculty summit, Redmond,

Similar presentations


Presentation on theme: "Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Research, Redmond, WA, USA Microsoft Research faculty summit, Redmond,"— Presentation transcript:

1 Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Research, Redmond, WA, USA Microsoft Research faculty summit, Redmond, WA, USA, 17 July 2006 joint work with Mike Barnett, Robert DeLine, Manuel Fähndrich, Wolfram Schulte, Herman Venter, and interns Bor-Yuh Evan Chang, Ádám Darvas, Bart Jacobs, Daan Leijen, Angela Wallenburg, and visiting researchers Francesco Logozzo, Peter Müller, David A. Naumann, Arnd Poetzsch-Heffter

2 Software engineering problem Building and maintaining large systems that are correct

3 Approach Specifications record design decisions bridge intent and code Tools amplify human effort manage details find inconsistencies ensure quality Specifications record design decisions bridge intent and code Tools amplify human effort manage details find inconsistencies ensure quality

4 Research goals Build the best such system we can build today Experiment with the system to get a feel for what it is like to use Advance the state of the art Build the best such system we can build today Experiment with the system to get a feel for what it is like to use Advance the state of the art

5 Spec# Experimental mix of contracts and tool support Aimed at experienced developers who know the high cost of testing and maintenance Superset of C# non-null types pre- and postconditions object invariants Tool support more type checking compiler-emitted run-time checks static program verification Experimental mix of contracts and tool support Aimed at experienced developers who know the high cost of testing and maintenance Superset of C# non-null types pre- and postconditions object invariants Tool support more type checking compiler-emitted run-time checks static program verification C# contracts everywhere type checking static verification into the future run-time checks degree of checking, effort familiar

6 Spec# demo: Chunker

7 Some design issues 0.Non-null types 1.C# compatibility 2.Preconditions 3.Object invariants 4.Program verifier architecture 5.Verification-condition generation 0.Non-null types 1.C# compatibility 2.Preconditions 3.Object invariants 4.Program verifier architecture 5.Verification-condition generation

8 T x; The value of x is null or a reference to an object whose type is a subtype of T. T ! y; The value of y is a reference to an object whose type is a subtype of T, not null. T x; The value of x is null or a reference to an object whose type is a subtype of T. T ! y; The value of y is a reference to an object whose type is a subtype of T, not null. 0. Non-null types

9 Non-null escape hatch: cast object o; string s; … string! a = (string!)o; string! b = (!)s; object o; string s; … string! a = (string!)o; string! b = (!)s;

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

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

12 Non-null instance fields class C : B { T ! x; public C(T ! y) :base() { this.x = y; } public override int M() { return x.f; } } class C : B { T ! x; public C(T ! y) :base() { this.x = y; } public override int M() { return x.f; } } Is this code type safe? No! abstract class B { public B() { this.M(); } public abstract int M(); } null dereference

13 Non-null instance fields class C : B { T ! x; public C(T ! y) { this.x = y; base(); } public override int M() { return x.f; } } class C : B { T ! x; public C(T ! y) { this.x = y; base(); } public override int M() { return x.f; } } Spec# allows x to be assigned before base constructor is called.

14 Other non-null issues Comparing a field against null if (this.f != null) { // … this.f.M(…); } Static fields static T g = new T(); Arrays T![ ] a = new T![100]; Generics List myList = new List (); Comparing a field against null if (this.f != null) { // … this.f.M(…); } Static fields static T g = new T(); Arrays T![ ] a = new T![100]; Generics List myList = new List ();

15 Spec# is superset of C# From C# to Spec#: accept every C# program compile it to have the same behavior Consequences Possible null dereference is just a warning Must initialize non-null fields before calling base constructor is an error Support for out-of-band contracts Spec# is superset of C# From C# to Spec#: accept every C# program compile it to have the same behavior Consequences Possible null dereference is just a warning Must initialize non-null fields before calling base constructor is an error Support for out-of-band contracts 1. C# compatibility

16 From Spec# to C# or: Leveraging wiz-bang features of Visual Studio 2005 class B : A { string! src; public B(string! source, int x) requires 0 <= x; { this.src = source; base(x); }

17 From Spec# to C# or: Leveraging wiz-bang features of Visual Studio 2005 class B : A { string! src; public B(string! source, int x) //^ requires 0 <= x; { this.src = source; base(x); }

18 From Spec# to C# or: Leveraging wiz-bang features of Visual Studio 2005 class B : A { string/*!*/ src; public B(string/*!*/ source, int x) //^ requires 0 <= x; { this.src = source; base(x); }

19 From Spec# to C# or: Leveraging wiz-bang features of Visual Studio 2005 class B : A { string/*!*/ src; public B(string/*!*/ source, int x) //^ requires 0 <= x; : base(x) { this.src = source; //^ base; }

20 2. Preconditions

21 StringBuilder.Append Method (Char[ ], Int32, Int32) Appends the string representation of a specified subarray of Unicode characters to the end of this instance. public StringBuilder Append(char[] value, int startIndex, int charCount); Parameters value A character array. startIndex The starting position in value. charCount The number of characters append. Return Value A reference to this instance after the append operation has occurred. Exceptions Contracts today Exception TypeCondition ArgumentNullExceptionvalue is a null reference, and startIndex and charCount are not zero. ArgumentOutOfRangeExceptioncharCount is less than zero. -or- startIndex is less than zero. -or- startIndex + charCount is less than the length of value.

22 Contract in Spec# public StringBuilder Append(char[ ] value, int startIndex, int charCount ); requires value == null ==> startIndex == 0 && charCount == 0; requires 0 <= startIndex; requires 0 <= charCount; requires value == null || startIndex + charCount <= value.Length; public StringBuilder Append(char[ ] value, int startIndex, int charCount ); requires value == null ==> startIndex == 0 && charCount == 0; requires 0 <= startIndex; requires 0 <= charCount; requires value == null || startIndex + charCount <= value.Length; Exception TypeCondition ArgumentNullExceptionvalue is a null reference, and startIndex and charCount are not zero. ArgumentOutOfRangeExceptioncharCount is less than zero. -or- startIndex is less than zero. -or- startIndex + charCount is less than the length of value.

23 Otherwise clauses public StringBuilder Append(char[ ] value, int startIndex, int charCount ); requires value == null ==> startIndex == 0 && charCount == 0 otherwise ArgumentNullException; requires 0 <= startIndex otherwise ArgumentOutOfRangeException; … public StringBuilder Append(char[ ] value, int startIndex, int charCount ); requires value == null ==> startIndex == 0 && charCount == 0 otherwise ArgumentNullException; requires 0 <= startIndex otherwise ArgumentOutOfRangeException; … Exception TypeCondition ArgumentNullExceptionvalue is a null reference, and startIndex and charCount are not zero. ArgumentOutOfRangeExceptioncharCount is less than zero. -or- startIndex is less than zero. -or- startIndex + charCount is less than the length of value.

24 Inheriting contracts interface J { void M(int x); requires P; } class A { public abstract void M(int x); requires Q; } class B : A, J { public override void M(int x) { … } } interface J { void M(int x); requires P; } class A { public abstract void M(int x); requires Q; } class B : A, J { public override void M(int x) { … } }

25 3. Object invariants

26 When do object invariants hold? class C { private int x; private int y; invariant x < y; public C() { x = 0; y = 1; } public void M() { int t = 100 / (y – x); x = x + 1; P(t); y = y + 1; } … } class C { private int x; private int y; invariant x < y; public C() { x = 0; y = 1; } public void M() { int t = 100 / (y – x); x = x + 1; P(t); y = y + 1; } … } invariant assumed to hold on entry to method invariant checked to hold on exit from method invariant checked to hold at end of constructor invariant may be temporarily broken here invariant is restored here what if P calls back into M?

27 Object states Mutable Object invariant may not hold Field updates allowed Valid Object invariant holds Field updates not allowed Mutable Object invariant may not hold Field updates allowed Valid Object invariant holds Field updates not allowed

28 Valid vs. mutable objects class C { private int x; private int y; invariant x < y; public void M() requires this.inv == Valid; { expose (this) { int t = 100 / (y – x); x = x + 1; P(t); y = y + 1; } } … } class C { private int x; private int y; invariant x < y; public void M() requires this.inv == Valid; { expose (this) { int t = 100 / (y – x); x = x + 1; P(t); y = y + 1; } } … } represent explicitly that invariant holds (without revealing what the invariant is) change this.inv from Valid to Mutable check invariant; then, change this.inv from Mutable to Valid field updates allowed only on Mutable objects

29 Summary of object invariants invariant … inv : { Mutable, Valid } expose updates of o.f require o.inv = Mutable ( o o.inv = Mutable Inv (o)) invariant … inv : { Mutable, Valid } expose updates of o.f require o.inv = Mutable ( o o.inv = Mutable Inv (o))

30 4. Spec# verifier architecture V.C. generator automatic theorem prover verification condition Spec# correct or list of errors Spec# compiler MSIL (bytecode) bytecode translator Boogie PL inference engine Spec# program verifier (aka Boogie)

31 BoogiePL Intermediate language theory part imperative part Semantics of Spec# is encoded in BoogiePL Can be used for other program-verification tasks, like verifying other source languages Intermediate language theory part imperative part Semantics of Spec# is encoded in BoogiePL Can be used for other program-verification tasks, like verifying other source languages

32 Example BoogiePL (0) var $Heap: [ref,name]any where IsHeap($Heap); function IsHeap(h: [ref,name]any) returns (bool); const Chunker: name; axiom Chunker <: System.Object; const Chunker.n: name; function DeclType(field: name) returns (class: name); axiom DeclType(Chunker.n) = Chunker; const $allocated: name; axiom ( h: [ref,name]any, o: ref, f: name IsHeap(h) h[o, $allocated] h[h[o, f],$allocated]); const $inv: name; axiom ( $oi: ref, $h: [ref,name]any IsHeap($h) $h[$oi, $inv] <: Chunker 0 < $h[$oi, Chunker.ChunkSize] 0 $h[$oi, Chunker.n] $h[$oi, Chunker.n] $Length($h[$oi, Chunker.src])); var $Heap: [ref,name]any where IsHeap($Heap); function IsHeap(h: [ref,name]any) returns (bool); const Chunker: name; axiom Chunker <: System.Object; const Chunker.n: name; function DeclType(field: name) returns (class: name); axiom DeclType(Chunker.n) = Chunker; const $allocated: name; axiom ( h: [ref,name]any, o: ref, f: name IsHeap(h) h[o, $allocated] h[h[o, f],$allocated]); const $inv: name; axiom ( $oi: ref, $h: [ref,name]any IsHeap($h) $h[$oi, $inv] <: Chunker 0 < $h[$oi, Chunker.ChunkSize] 0 $h[$oi, Chunker.n] $h[$oi, Chunker.n] $Length($h[$oi, Chunker.src]));

33 Example BoogiePL (1) procedure Chunker.NextChunk(this: ref) returns ($result: ref); requires $Heap[this, $inv] = Chunker; requires $Heap[this, $ownerFrame] = $PeerGroupPlaceholder ¬($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]); free requires $Heap[this, $allocated] = true $IsNotNull(this, Chunker); modifies $Heap; ensures $Length($result) $Heap[this, Chunker.ChunkSize]; ensures ( $pc: ref $pc null $Heap[$pc, $allocated] = true $Heap[$pc, $ownerRef] = $Heap[$result, $ownerRef] $Heap[$pc, $ownerFrame] = $Heap[$result, $ownerFrame] ($Heap[$pc, $ownerFrame] = $PeerGroupPlaceholder ¬($Heap[$Heap[$pc, $ownerRef], $inv] <: $Heap[$pc, $ownerFrame])) $Heap[$pc, $inv] = $typeof($pc)); free ensures $Heap[$result, $allocated] = true $IsNotNull($result, System.String); free ensures ( $o: ref $o null ¬old($Heap)[$o, $allocated] $Heap[$o, $allocated] $Heap[$o, $inv] = $typeof($o)); ensures ( $o: ref $o null old($Heap)[$o, $allocated] = true old($Heap)[$Heap[$o, $ownerRef], $allocated] = true old($Heap)[$o, $ownerRef] = $Heap[$o, $ownerRef] old($Heap)[$o, $ownerFrame] = $Heap[$o, $ownerFrame]); free ensures ( $o: ref, $f: name $f $inv $o null old($Heap)[$o, $allocated] = true (old($Heap)[$o, $ownerFrame] = $PeerGroupPlaceholder ¬(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame])) (¬IsStaticField($f) ¬IsDirectlyModifiableField($f)) old($Heap)[$o, $f] = $Heap[$o, $f]); free ensures ( $o: ref old($Heap)[$o, $inv] = $Heap[$o, $inv] old($Heap)[$o, $allocated] true); free ensures ( $o: ref old($Heap)[$o, $allocated] $Heap[$o, $allocated]); procedure Chunker.NextChunk(this: ref) returns ($result: ref); requires $Heap[this, $inv] = Chunker; requires $Heap[this, $ownerFrame] = $PeerGroupPlaceholder ¬($Heap[$Heap[this, $ownerRef], $inv] <: $Heap[this, $ownerFrame]); free requires $Heap[this, $allocated] = true $IsNotNull(this, Chunker); modifies $Heap; ensures $Length($result) $Heap[this, Chunker.ChunkSize]; ensures ( $pc: ref $pc null $Heap[$pc, $allocated] = true $Heap[$pc, $ownerRef] = $Heap[$result, $ownerRef] $Heap[$pc, $ownerFrame] = $Heap[$result, $ownerFrame] ($Heap[$pc, $ownerFrame] = $PeerGroupPlaceholder ¬($Heap[$Heap[$pc, $ownerRef], $inv] <: $Heap[$pc, $ownerFrame])) $Heap[$pc, $inv] = $typeof($pc)); free ensures $Heap[$result, $allocated] = true $IsNotNull($result, System.String); free ensures ( $o: ref $o null ¬old($Heap)[$o, $allocated] $Heap[$o, $allocated] $Heap[$o, $inv] = $typeof($o)); ensures ( $o: ref $o null old($Heap)[$o, $allocated] = true old($Heap)[$Heap[$o, $ownerRef], $allocated] = true old($Heap)[$o, $ownerRef] = $Heap[$o, $ownerRef] old($Heap)[$o, $ownerFrame] = $Heap[$o, $ownerFrame]); free ensures ( $o: ref, $f: name $f $inv $o null old($Heap)[$o, $allocated] = true (old($Heap)[$o, $ownerFrame] = $PeerGroupPlaceholder ¬(old($Heap)[old($Heap)[$o, $ownerRef], $inv] <: old($Heap)[$o, $ownerFrame])) (¬IsStaticField($f) ¬IsDirectlyModifiableField($f)) old($Heap)[$o, $f] = $Heap[$o, $f]); free ensures ( $o: ref old($Heap)[$o, $inv] = $Heap[$o, $inv] old($Heap)[$o, $allocated] true); free ensures ( $o: ref old($Heap)[$o, $allocated] $Heap[$o, $allocated]);

34 Example BoogiePL (2) implementation Chunker.NextChunk(this: ref) returns ($result: ref) { var temp0: ref, local4: ref, stack0i: int, stack1i: int, stack1o: ref, stack0b: bool, stack0o: ref, stack2i: int, s: ref, return.value: ref, SS$Display.Return.Local: ref; entry: // … // ----- load field ----- Chunker.ssc(14,7) assert this null; stack1o := $Heap[this, Chunker.src]; // … // ----- binary operator ----- Chunker.ssc(14,7) stack0b := stack0i > stack1i; // ----- branch ----- Chunker.ssc(14,7) goto true5814to5848, false5814to5831; true5814to5848: assume stack0b = true; … implementation Chunker.NextChunk(this: ref) returns ($result: ref) { var temp0: ref, local4: ref, stack0i: int, stack1i: int, stack1o: ref, stack0b: bool, stack0o: ref, stack2i: int, s: ref, return.value: ref, SS$Display.Return.Local: ref; entry: // … // ----- load field ----- Chunker.ssc(14,7) assert this null; stack1o := $Heap[this, Chunker.src]; // … // ----- binary operator ----- Chunker.ssc(14,7) stack0b := stack0i > stack1i; // ----- branch ----- Chunker.ssc(14,7) goto true5814to5848, false5814to5831; true5814to5848: assume stack0b = true; …

35 Example BoogiePL (3) // ----- call ----- Chunker.ssc(17,9) assert stack0o null; call s := System.String.Substring$System.Int32(stack0o, stack1i); // … // ----- store field ----- Chunker.ssc(19,7) assert this null; assert ¬($Heap[this, $inv] <: Chunker); $Heap[this, Chunker.n] := stack0i; // … // ----- return $result := stack0o; return; } // ----- call ----- Chunker.ssc(17,9) assert stack0o null; call s := System.String.Substring$System.Int32(stack0o, stack1i); // … // ----- store field ----- Chunker.ssc(19,7) assert this null; assert ¬($Heap[this, $inv] <: Chunker); $Heap[this, Chunker.n] := stack0i; // … // ----- return $result := stack0o; return; }

36 5. Verification conditions Automatic theorem prover can be hidden from programmer generates counterexamples Interactive theorem prover requires gurus not limited by built-in decision procedures Automatic theorem prover can be hidden from programmer generates counterexamples Interactive theorem prover requires gurus not limited by built-in decision procedures

37 Performance considerations Generate verification conditions that the theorem prover can handle quickly Efficient encodings of axioms Efficient weakest preconditions Generate verification conditions that the theorem prover can handle quickly Efficient encodings of axioms Efficient weakest preconditions

38 Initial verifier experience Pilot production project it changes how you think Several smaller (300-1500 lines) case studies Parts of Spec# program verifier External academic use Pilot production project it changes how you think Several smaller (300-1500 lines) case studies Parts of Spec# program verifier External academic use

39 download Spec# from here Conclusions Because of tool support, were ready for programming at the next level of rigor Current work Specification/programming/verification methodology Performance Technology transfer Engineering effort Technology sharing Teaching Case studies BoogiePL as common intermediate logic Because of tool support, were ready for programming at the next level of rigor Current work Specification/programming/verification methodology Performance Technology transfer Engineering effort Technology sharing Teaching Case studies BoogiePL as common intermediate logic http://research.microsoft.com/~leino http://research.microsoft.com/specsharp


Download ppt "Spec# K. Rustan M. Leino Senior Researcher Programming Languages and Methods Microsoft Research, Redmond, WA, USA Microsoft Research faculty summit, Redmond,"

Similar presentations


Ads by Google