Date post: | 20-Jan-2016 |
Category: |
Documents |
Upload: | cornelia-montgomery |
View: | 217 times |
Download: | 0 times |
Spec#
K. Rustan M. LeinoPrincipal ResearcherMicrosoft Research, Redmond, WA, USA
14 Nov 2007ØredevMalmö, Sweden
CollaboratorsMike BarnettNikolaj BjørnerÁdám DarvasLeonardo de MouraManuel FähndrichBart JacobsFrancesco Logozzo
Ronald MiddelkoopPeter MüllerRalf SasseWolfram SchulteHerman VenterAngela Wallenburg
Microsoft ResearchTake risksAdvance state of the art, state of knowledgeOver time, have a significant impact on Microsoft productsFirst “customers”: early adopters
Want feedbackWhat seems useful to you?
Email me, [email protected]—better yet—the Spec# mailing list, see http://research.microsoft.com/specsharp
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
Research goalsBuild the best such system we can build todayExperiment with the system to get a feel for what it is like to useAdvance the state of the art
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 program verification (optional)
Program specifications– the academic view
{ P } S { Q }
If program S is started in a state satisfying the precondition P, then
the execution of S will not go wrong andif the execution terminates, it does so in a state satisfying the postcondition Q
If S starts in P, then it ends in Q
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
valueA character array.
startIndexThe starting position in value.
charCountThe number of characters append.
Return Value
A reference to this instance after the append operation has occurred.
Exceptions
Exception Type Condition
ArgumentNullException value is a null reference, and startIndex and charCount are not zero.
ArgumentOutOfRangeException charCount is less than zero.-or-startIndex is less than zero.-or-startIndex + charCount is less than the length of value.
Specifications: .NET today
Specifications 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;
Exception Type Condition
ArgumentNullException value is a null reference, and startIndex and charCount are not zero.
ArgumentOutOfRangeException charCount is less than zero.-or-startIndex is less than zero.-or-startIndex + charCount is less than the length of value.
Method specificationsA specification has three parts:
requires P; // preconditionmodifies x; // frame conditionensures Q; // postcondition
A specification is a contract between callers and implementions:
Caller must establish P before callImplementation can assume P on entry to method
Implementation must establish Q before returning, and must only modify x
Caller can assume Q holds upon return,and that only x was modified
Spec# demo
dict:
Multi-object invariants
:Chunker
:Dictionary
n: 84
Count: 21
:Chunker
dict:
n: 20
inv dict.Count ≤ n;
:Classroom
studentGrades:
inv studentGrades.Count ≤
20;
rep
inv dict.Count ≤ n;ow
ner
Spec# is superset of C#From C# to Spec#:
accept every C# programcompile 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 errorSupport for out-of-band contracts
C# compatibility
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);
}
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;
}
C# modeShow and tell
Backward compatibility
requires 0 <= startIndex otherwise
ArgumentOutOfRangeException;
Exception Type Condition
ArgumentNullException value is a null reference, and startIndex and charCount are not zero.
ArgumentOutOfRangeException charCount is less than zero.-or-startIndex is less than zero.-or-startIndex + charCount is less than the length of value.
type checking,
program
verification
precondition
s
throws
clauses
ExceptionsProgram errors
e.g., NullPointerException, ArrayBoundsException
Parameter validatione.g., ArgumentException
Unanticipated eventse.g., OutOfMemoryError, InternalCLRError
Anticipated conditionse.g., SocketClosedException
ExceptionsShow and tell
Inheriting contractsinterface 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){ … }
}
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
Chunker.NextChunk public string! NextChunk() modifies this.*; ensures result.Length <= ChunkSize; { string s; if (n + ChunkSize <= src.Length) { s = src.Substring(n, ChunkSize); } else { s = src.Substring(n); } n += s.Length; return s; }
(LET ((FORMULA ReallyLastGeneratedExit_correct (IMPLIES (LBLPOS |+25122| TRUE) (AND (LBLNEG |@28448| (OR (EQ (select2 $Heap@7 s@0 $ownerFrame) $PeerGroupPlaceholder) (OR (NOT (EQ (<: (select2 $Heap@7 (select2 $Heap@7 s@0 $ownerRef) $inv) (select2 $Heap@7 s@0 $ownerFrame)) |@true|)) (EQ (select2 $Heap@7 (select2 $Heap@7 s@0 $ownerRef) $localinv) ($BaseClass (select2 $Heap@7 s@0 $ownerFrame)))))) (IMPLIES (OR (EQ (select2 $Heap@7 s@0 $ownerFrame) $PeerGroupPlaceholder) (OR (NOT (EQ (<: (select2 $Heap@7 (select2 $Heap@7 s@0 $ownerRef) $inv) (select2 $Heap@7 s@0 $ownerFrame)) |@true|)) (EQ (select2 $Heap@7 (select2 $Heap@7 s@0 $ownerRef) $localinv) ($BaseClass (select2 $Heap@7 s@0 $ownerFrame))))) (AND (LBLNEG |@28511| (FORALL ($pc) (PATS ($typeof $pc) (select2 $Heap@7 $pc $localinv) (select2 $Heap@7 $pc $inv) (select2 $Heap@7 $pc $ownerFrame) (select2 $Heap@7 $pc $ownerRef)) (QID unknown.0:0) (SKOLEMID 19) (IMPLIES (AND (AND (NEQ $pc nullObject) (EQ (select2 $Heap@7 $pc $allocated) |@true|)) (AND (EQ (select2 $Heap@7 $pc $ownerRef) (select2 $Heap@7 s@0 $ownerRef)) (EQ (select2 $Heap@7 $pc $ownerFrame) (select2 $Heap@7 s@0 $ownerFrame)))) (AND (EQ (select2 $Heap@7 $pc $inv) ($typeof $pc)) (EQ (select2 $Heap@7 $pc $localinv) ($typeof $pc)))))) (IMPLIES (FORALL ($pc) (PATS ($typeof $pc) (select2 $Heap@7 $pc $localinv) (select2 $Heap@7 $pc $inv) (select2 $Heap@7 $pc $ownerFrame) (select2 $Heap@7 $pc $ownerRef)) (QID unknown.0:0) (SKOLEMID 19) (IMPLIES (AND (AND (NEQ $pc nullObject) (EQ (select2 $Heap@7 $pc $allocated) |@true|)) (AND (EQ (select2 $Heap@7 $pc $ownerRef) (select2 $Heap@7 s@0 $ownerRef)) (EQ (select2 $Heap@7 $pc $ownerFrame) (select2 $Heap@7 s@0 $ownerFrame)))) (AND (EQ (select2 $Heap@7 $pc $inv) ($typeof $pc)) (EQ (select2 $Heap@7 $pc $localinv) ($typeof $pc))))) (AND (LBLNEG |@28647| (<= ($StringLength s@0) (select2 $Heap@7 this Chunker.ChunkSize))) (IMPLIES (<= ($StringLength s@0) (select2 $Heap@7 this Chunker.ChunkSize)) TRUE)))))))) (FORMULA block4437_correct (IMPLIES (LBLPOS |+5747| TRUE) (IMPLIES TRUE (IMPLIES TRUE ReallyLastGeneratedExit_correct)))) (FORMULA block4590_correct (IMPLIES (LBLPOS |+5742| TRUE) (IMPLIES TRUE (IMPLIES TRUE block4437_correct)))) (FORMULA block4607-2-block4590_correct (IMPLIES (LBLPOS |+25365| TRUE) (IMPLIES (EQ $Heap@7 $Heap@6) (IMPLIES (EQ stack0s@1 stack0s@0) (IMPLIES (EQ stack0o@4 stack0o@3) block4590_correct))))) (FORMULA block4607_correct (IMPLIES (LBLPOS |+5573| TRUE) (IMPLIES TRUE (IMPLIES (EQ ($IsTokenForType stack0s@0 Chunker) |@true|) (IMPLIES (EQ stack0o@3 (TypeObject Chunker)) (AND (LBLNEG |@28246| (NEQ this nullObject)) (IMPLIES (NEQ this nullObject) (AND (LBLNEG |@28252| (EQ (select2 $Heap@5 this $localinv) System.Object)) (IMPLIES (EQ (select2 $Heap@5 this $localinv) System.Object) (AND (LBLNEG |@28263| (< 0 (select2 $Heap@5 this Chunker.ChunkSize))) (IMPLIES (< 0 (select2 $Heap@5 this Chunker.ChunkSize)) (AND (LBLNEG |@28274| (<= 0 (select2 $Heap@5 this Chunker.n))) (IMPLIES (<= 0 (select2 $Heap@5 this Chunker.n)) (AND (LBLNEG |@28285| (<= (select2 $Heap@5 this Chunker.n) ($StringLength (select2 $Heap@5 this Chunker.src)))) (IMPLIES (<= (select2 $Heap@5 this Chunker.n) ($StringLength (select2 $Heap@5 this Chunker.src))) (AND (LBLNEG |@28303| (FORALL ($p) (QID unknown.0:0) (SKOLEMID 55) (IMPLIES (AND (AND (NEQ $p nullObject) (EQ (select2 $Heap@5 $p $allocated) |@true|)) (AND (EQ (select2 $Heap@5 $p $ownerRef) this) (EQ (select2 $Heap@5 $p $ownerFrame) Chunker))) (AND (EQ (select2 $Heap@5 $p $inv) ($typeof $p)) (EQ (select2 $Heap@5 $p $localinv) ($typeof $p)))))) (IMPLIES (FORALL ($p) (QID unknown.0:0) (SKOLEMID 55) (IMPLIES (AND (AND (NEQ $p nullObject) (EQ (select2 $Heap@5 $p $allocated) |@true|)) (AND (EQ (select2 $Heap@5 $p $ownerRef) this) (EQ (select2 $Heap@5 $p $ownerFrame) Chunker))) (AND (EQ (select2 $Heap@5 $p $inv) ($typeof $p)) (EQ (select2 $Heap@5 $p $localinv) ($typeof $p))))) (IMPLIES (EQ $Heap@6 (store2 $Heap@5 this $localinv ($typeof this))) (IMPLIES (EQ (IsHeap $Heap@6) |@true|) (IMPLIES TRUE block4607-2-block4590_correct)))))))))))))))))))) (FORMULA true4471to4607_correct (IMPLIES (LBLPOS |+5569| TRUE) (IMPLIES TRUE (IMPLIES (EQ nullObject nullObject) (IMPLIES TRUE block4607_correct))))) (FORMULA true4505to4607_correct (IMPLIES (LBLPOS |+5733| TRUE) (IMPLIES TRUE (IMPLIES (NEQ ($As nullObject Microsoft.Contracts.ICheckedException) nullObject) (IMPLIES TRUE block4607_correct))))) (FORMULA block4556-2-block4590_correct (IMPLIES (LBLPOS |+25363| TRUE) (IMPLIES (EQ $Heap@7 $Heap@5) (IMPLIES (EQ stack0s@1 stack0s) (IMPLIES (EQ stack0o@4 nullObject) block4590_correct))))) (FORMULA block4556_correct (IMPLIES (LBLPOS |+5737| TRUE) (IMPLIES TRUE (IMPLIES TRUE block4556-2-block4590_correct)))) (FORMULA false4505to4556_correct (IMPLIES (LBLPOS |+5735| TRUE) (IMPLIES TRUE (IMPLIES (EQ ($As nullObject Microsoft.Contracts.ICheckedException) nullObject) (IMPLIES TRUE block4556_correct))))) (FORMULA block4505_correct (IMPLIES (LBLPOS |+5575| TRUE) (IMPLIES TRUE (IMPLIES TRUE (AND true4505to4607_correct false4505to4556_correct))))) (FORMULA false4471to4505_correct (IMPLIES (LBLPOS |+5571| TRUE) (IMPLIES TRUE (IMPLIES (NEQ nullObject nullObject) (IMPLIES TRUE block4505_correct))))) (FORMULA block4471_correct (IMPLIES (LBLPOS |+5554| TRUE) (IMPLIES TRUE (IMPLIES TRUE (AND true4471to4607_correct false4471to4505_correct))))) (FORMULA block4284_correct (IMPLIES (LBLPOS |+5401| TRUE) (IMPLIES TRUE (AND (LBLNEG |@27875| (NEQ this nullObject)) (IMPLIES (NEQ this nullObject) (IMPLIES (EQ stack0i@2 (select2 $Heap@4 this Chunker.n)) (AND (LBLNEG |@27893| (NEQ s@0 nullObject)) (IMPLIES (NEQ s@0 nullObject) (IMPLIES (EQ stack1i@5 ($StringLength s@0)) (IMPLIES (EQ stack0i@3 (+ stack0i@2 stack1i@5)) (AND (LBLNEG |@27916| (NEQ this nullObject)) (IMPLIES (NEQ this nullObject) (AND (LBLNEG |@27923| (OR (EQ (select2 $Heap@4 this $ownerFrame) $PeerGroupPlaceholder) (OR (NOT (EQ (<: (select2 $Heap@4 (select2 $Heap@4 this $ownerRef) $inv) (select2 $Heap@4 this $ownerFrame)) |@true|)) (EQ (select2 $Heap@4 (select2 $Heap@4 this $ownerRef) $localinv) ($BaseClass (select2 $Heap@4 this $ownerFrame)))))) (IMPLIES (OR (EQ (select2 $Heap@4 this $ownerFrame) $PeerGroupPlaceholder) (OR (NOT (EQ (<: (select2 $Heap@4 (select2 $Heap@4 this $ownerRef) $inv) (select2 $Heap@4 this $ownerFrame)) |@true|)) (EQ (select2 $Heap@4 (select2 $Heap@4 this $ownerRef) $localinv) ($BaseClass (select2 $Heap@4 this $ownerFrame))))) (IMPLIES (EQ $Heap@5 (store2 $Heap@4 this Chunker.n stack0i@3)) (AND (LBLNEG |@28007| (OR (NOT (AND (EQ (<: (select2 $Heap@5 this $inv) Chunker) |@true|) (NEQ (select2 $Heap@5 this $localinv) ($BaseClass Chunker)))) (< 0 (select2 $Heap@5 this Chunker.ChunkSize)))) (IMPLIES (OR (NOT (AND (EQ (<: (select2 $Heap@5 this $inv) Chunker) |@true|) (NEQ (select2 $Heap@5 this $localinv) ($BaseClass Chunker)))) (< 0 (select2 $Heap@5 this Chunker.ChunkSize))) (AND (LBLNEG |@28055| (OR (NOT (AND (EQ (<: (select2 $Heap@5 this $inv) Chunker) |@true|) (NEQ (select2 $Heap@5 this $localinv) ($BaseClass Chunker)))) (<= 0 (select2 $Heap@5 this Chunker.n)))) (IMPLIES (OR (NOT (AND (EQ (<: (select2 $Heap@5 this $inv) Chunker) |@true|) (NEQ (select2 $Heap@5 this $localinv) ($BaseClass Chunker)))) (<= 0 (select2 $Heap@5 this Chunker.n))) (AND (LBLNEG |@28103| (OR (NOT (AND (EQ (<: (select2 $Heap@5 this $inv) Chunker) |@true|) (NEQ (select2 $Heap@5 this $localinv) ($BaseClass Chunker)))) (<= (select2 $Heap@5 this Chunker.n) ($StringLength (select2 $Heap@5 this Chunker.src))))) (IMPLIES (OR (NOT (AND $Heap@5 this Chunker.n) ($StringLength (select2 $Heap@5 this Chunker.src)))) (IMPLIES (EQ (IsHeap $Heap@5) |@true|) (IMPLIES TRUE block4471_correct))))))))))))))))))))))) (FORMULA block4267-2-block4284_correct (IMPLIES (LBLPOS |+25361| TRUE) (IMPLIES (EQ stack2i@1 stack2i) (IMPLIES (EQ s@0 call4133formal@$result@0) (IMPLIES (EQ stack1i@4 stack1i@3) (IMPLIES (EQ $ActivityIndicator@2 $ActivityIndicator@1) (IMPLIES (EQ stack0o@2 stack0o@1) (IMPLIES (EQ $Heap@4 $Heap@3) block4284_correct)))))))) (FORMULA block4267_correct (IMPLIES (LBLPOS |+2908| TRUE) (IMPLIES TRUE (AND (LBLNEG |@26919| (NEQ this nullObject)) (IMPLIES (NEQ this nullObject) (IMPLIES (EQ stack0o@1 (select2 $Heap@1 this Chunker.src)) (AND (LBLNEG |@26937| (NEQ this nullObject)) (IMPLIES (NEQ this nullObject) (IMPLIES (EQ stack1i@3 (select2 $Heap@1 this Chunker.n)) (AND (LBLNEG |@26955| (NEQ stack0o@1 nullObject)) (IMPLIES (NEQ stack0o@1 nullObject) (IMPLIES (AND (EQ ($IsNotNull call4133formal@$result System.String) |@true|) (EQ (select2 $Heap call4133formal@$result $allocated) |@true|)) (AND (LBLNEG |@26962| (<= 0 stack1i@3)) (IMPLIES (<= 0 stack1i@3) (AND (LBLNEG |@26968| (<= stack1i@3 ($StringLength stack0o@1))) (IMPLIES (<= stack1i@3 ($StringLength stack0o@1)) (AND (LBLNEG |@26976| (FORALL ($pc) (PATS ($typeof $pc) (select2 $Heap@1 $pc $localinv) (select2 $Heap@1 $pc $inv) (select2 $Heap@1 $pc $ownerFrame) (select2 $Heap@1 $pc $ownerRef)) (QID unknown.0:0) (SKOLEMID 27) (IMPLIES (AND (AND (NEQ $pc nullObject) (EQ (select2 $Heap@1 $pc $allocated) |@true|)) (AND (EQ (select2 $Heap@1 $pc $ownerRef) (select2 $Heap@1 stack0o@1 $ownerRef)) (EQ (select2 $Heap@1 $pc $ownerFrame) (select2 $Heap@1 (IMPLIES TRUE block4233_correct))))))))))))) (FORMULA block4063_correct (IMPLIES (LBLPOS |+2515| TRUE) (IMPLIES TRUE (IMPLIES TRUE block4216_correct)))) (FORMULA entry_correct (IMPLIES (LBLPOS |+2512| TRUE) (IMPLIES (EQ (IsHeap $Heap) |@true|) (IMPLIES (AND (EQ ($IsNotNull this Chunker) |@true|) (EQ (select2 $Heap this $allocated) |@true|)) (IMPLIES (AND (EQ ($IsNotNull $result System.String) |@true|) (EQ (select2 $Heap $result $allocated) |@true|)) (IMPLIES (AND (EQ ($Is local2 System.Exception) |@true|) (EQ (select2 $Heap local2 $allocated) |@true|)) (IMPLIES (AND (EQ ($Is s System.String) |@true|) (EQ (select2 $Heap s $allocated) |@true|)) (IMPLIES (AND (EQ ($Is return.value System.String) |@true|) (EQ (select2 $Heap return.value $allocated) |@true|)) (IMPLIES (AND (EQ ($Is SS$Display.Return.Local System.String) |@true|) (EQ (select2 $Heap SS$Display.Return.Local $allocated) |@true|)) (IMPLIES (EQ $PurityAxiomsCanBeAssumed |@true|) (IMPLIES (EQ $BeingConstructed nullObject) (IMPLIES (OR (EQ (select2 $Heap this $ownerFrame) $PeerGroupPlaceholder) (OR (NOT (EQ (<: (select2 $Heap (select2 $Heap this $ownerRef) $inv) (select2 $Heap this $ownerFrame)) |@true|)) (EQ (select2 $Heap (select2 $Heap this $ownerRef) $localinv) ($BaseClass (select2 $Heap this $ownerFrame))))) (IMPLIES (FORALL ($pc) (PATS ($typeof $pc) (select2 $Heap $pc $localinv) (select2 $Heap $pc $inv) (select2 $Heap $pc $ownerFrame) (select2 $Heap $pc $ownerRef)) (QID unknown.0:0) (SKOLEMID 18) (IMPLIES (AND (AND (NEQ $pc nullObject) (EQ (select2 $Heap $pc $allocated) |@true|)) (AND (EQ (select2 $Heap $pc $ownerRef) (select2 $Heap this $ownerRef)) (EQ (select2 $Heap $pc $ownerFrame) (select2 $Heap this $ownerFrame)))) (AND (EQ (select2 $Heap $pc $inv) ($typeof $pc)) (EQ (select2 $Heap $pc $localinv) ($typeof $pc))))) (IMPLIES TRUE (IMPLIES TRUE block4063_correct)))))))))))))))) entry_correct)
Verification condition
Further challengesExtend structuring methodologiesImprove performance…
Download
Spec#
from here
Summary and conclusionsSpec# lets programmers work with contracts
type checkingrun-time checkingprogram verification
Hardest challenge: programming methodology that
fits common programming idioms andcan be handled well by automatic prover
EducationTry it out!
http://research.microsoft.com/specsharp