Advanced programming tools at Microsoft K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 16...

Post on 26-Mar-2015

216 views 0 download

Tags:

Transcript of Advanced programming tools at Microsoft K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 16...

Advanced programming tools at Microsoft

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

16 May 2005Distinguished lecture, York UniversityToronto, ON, Canada

Software engineering problem

Building and maintaining large systems that are correct

Approach

• Specifications record design decisions– bridge intent and code

• Tools amplify human effort– manage details– find inconsistencies– ensure quality

Design decisions– examples and trends

procedural abstractionint x;assert(x < a.Length);

finite-state protocolsmark-ups

pre- and postconditions, andobject invariants

More powerful techniques—a selection

0. PREfix1. SLAM2. SpecStrings3. Spec#

0. PREfix

• Detects common errors in C/C++– incorrect usage of null pointers, memory

allocation, uninitialized variables, library idioms, ...

• Performs symbolic execution– detailed C semantics– paths simulated in detail, not all paths

simulated– interprocedural, procedures summarized

by small subset of their paths

[Bush, Pincus, Sielaff, et al.]

PREfix example

int abs(int x) {int y;if (0 <= x) {

y = x;}return y;

}possible use of

uninitialized variable

PREfix virtues

• Expensive to run– whole-program analysis

• Reduces effects of spurious warnings– filters and prioritizes output, uses

heuristics

• Effective at finding errors– 1/8 of bugs fixed in Windows Server 2003

found by PREfix (and PREfast)

• Widely deployed

The PREfast revolution

• PREfast – framework for authoring analyses (walks AST)

• PREfix runs centrally after check-ins,PREfast can run on developer desktops before check-ins

• Name recognition, plug-ins

[Weise, et al.]

On the road to embracing static analysis:

PREfix milestonePREfix and PREfast have openedeyes of developers and managementto power of compile-time checking

1. Niche: device drivers

• bugs can have severe effects• relatively small code base (usually ≤

50 KLOC)• crash-freedom specified by finite-state

API protocols• correctness mostly

depends on flow ofcontrol, not data

Acquire()

Acquire()Release()

Release()

SLAM

• Software model checking– predicate abstraction– model checking (state exploration)– counterexample-driven predicate

refinement

[Ball, Rajamani, et al.]

error message

Predicate abstraction and refinement

C program

predicates

boolean program

modelchecker

correct

concrete trace

feasible?

abstract trace

no yes

predicateabstraction

predicaterefinement

SLAM example

do {KeAcquireSpinLock();

nPacketsOld = nPackets;

if (request) {request = request->Next;KeReleaseSpinLock();nPackets++;

}} while (nPackets != nPacketsOld);

KeReleaseSpinLock();

Acquire()

Acquire()Release()

Release()

SLAM example

do {assert ¬P; P := true; // KeAcquireSpinLock();

if ( * ) {

assert P; P := false; // KeReleaseSpinLock();

}} while ( * );

assert P; P := false; // KeReleaseSpinLock();

Predicates:

• P: spin lock held

SLAM example

do {assert ¬P; P := true;

if ( * ) {

assert P; P := false;

}} while ( * );

assert P; P := false;

error path in abstract program

Predicates:

• P: spin lock held

SLAM example

do {KeAcquireSpinLock();

nPacketsOld = nPackets;

if (request) {request = request->Next;KeReleaseSpinLock();nPackets++;

}} while (nPackets != nPacketsOld);

KeReleaseSpinLock();

error path in abstract program

infeasible path in concrete program

Predicates:

• P: spin lock held

SLAM example

do {KeAcquireSpinLock();

nPacketsOld = nPackets;

if (request) {request = request->Next;KeReleaseSpinLock();nPackets++;

}} while (nPackets != nPacketsOld);

KeReleaseSpinLock();

error path in abstract program

Predicates:

• P: spin lock held

• Q: nPackets == nPacketsOld

infeasible path in concrete program

SLAM example

do { assert ¬P; P := true;

Q := true; // nPacketsOld = nPackets;

if ( * ) {

assert P; P := false;Q := if Q then false else * end; // nPackets++;

}} while (¬ Q); // nPackets != nPacketsOld

assert P; P := false;

Predicates:

• P: spin lock held

• Q: nPackets == nPacketsOld

no error path in abstract program;hence, concrete program is correct

SLAM at Microsoft• finite-state API protocols specified by

experts• applied to 100s of Windows drivers,

for 10s of rules, found 60+ errors• Static Driver Verifier

– transferred to WindowsDriver Quality group

– to be released in DDK

On the road to embracing static analysis:

SLAM milestoneSLAM showcases specifications and powerful checking

2. SpecStrings

• company-wide effort to annotate C/C++ APIs

• standard annotation language (SAL) for describing assumptions about parameters

• limited checking by PREfast plug-in– can catch some null problems and buffer

overruns

[Das, Fähndrich, et al.]

SpecString example

void * memcpy(pre notnullpre writableTo(pre byteCount(num)) post readableTo(pre byteCount(num)) void * dest,

pre notnull pre readableTo(pre byteCount(num))void * src,

size_t num);

SpecStrings at Microsoft

• emphasizes importance of interfaces• better documentation• improves checking

– fewer spurious warnings– can detect errors from violations of

stated intent

On the road to embracing static analysis:

SpecStrings milestoneWith SpecStrings, developers become used to source-code annotations that go beyond what compiler requires

3. Into the future

• managed code (C#, …)• involve developers more intimately

– capture design decisions earlier– let developers take control of their code

• reach beyond checking limits of current tools

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

C#contracts

everywhere

type checking

static verification

into the future

run-time checks

degree of checking,effort

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 today

Spec# specificationsPrecondition• Callers are expected to establish

precondition before invoking method• Implementations can assume

precondition holds on entry

Postcondition• Implementations are expected to

establish postcondition on exit• Callers can assume postcondition

upon return from method invocation

public StringBuilder Append( char[ ] value, int startIndex, int charCount);

requires value != null || (startIndex == 0 && charCount == 0); requires 0 <= startIndex && 0 <= charCount; requires startIndex + charCount <= value.Length;

ensures result == this;

Object invariantsreadonly int rows;readonly int columns;readonly double[,] m;

readonly int numInitialVars;readonly int numSlackVars;readonly int rhsColumn;

readonly ArrayList<object> dims;readonly int[] basisColumns;readonly int[] inBasis;bool constructionDone = false;

invariant rows == m.GetLength(0);invariant 1 <= columns && columns == m.GetLength(1);invariant 0 <= numInitialVars;invariant 0 <= numSlackVars && numSlackVars <= rows;invariant numInitialVars + numSlackVars + 1 == columns;invariant rhsColumn == columns - 1;invariant dims.Count == numInitialVars;invariant basisColumns.Length == rows;invariant inBasis.Length == numInitialVars + numSlackVars;

Spec# demo

Spec# verifier architecture

V.C. generator

automatictheorem prover

verification condition

Spec#

“correct” or list of errors

Spec# compiler

MSIL (“bytecode”)

translator

Boogie PL

inference engine

Spec# static program verifier, akaBoogi

e

Analyzing verification conditions• Automatic theorem prover

– can be hidden from programmer– generates counterexamples

• Interactive theorem prover– requires gurus– not limited by built-in decision

procedures

Generating verification conditions

int AbsX(Robot c)requires c ≠ null;ensures 0 ≤ result;

{if (0 ≤ c.x) {

a := c.x;} else {

a := −c.x;}return a;

}

Weakest preconditions

0 ≤ result

0 ≤ a

c ≠ null 0 ≤ −sel(c,x)

c ≠ null 0 ≤ sel(c,x)

c ≠ null (0 ≤ sel(c,x) c ≠ null 0 ≤ sel(c,x)) (¬(0 ≤ sel(c,x)) c ≠ null 0 ≤ −sel(c,x))

c ≠ null c ≠ null (0 ≤ sel(c,x) c ≠ null 0 ≤ sel(c,x)) (¬(0 ≤ sel(c,x)) c ≠ null 0 ≤ −sel(c,x))

the programming languageis the software engineer'sprimary thinking and working tool

What’s in a language

Designing more rigor into the language

• Type system– impose coarse-grained restrictions– easy to understand and use– sound efficient checking

• General specifications– enforce by mix of dynamic and static

checking– don’t worry about completeness or

decidability

• Develop good defaults

non-null types

requires Pre;modifies Frame;ensures Post;

Examples

requires this.inv = Valid;modifies this.*;ensures true;

Enforcing specifications

• Run-time checking– may leave out expensive checks, if not

required for soundness• example: modifies clauses

• Static verification– requires more effort from the user

• example: modifies clauses

– modular checking a necessity

type checking

static verification

run-time checks

degree of checking,effort

Migration problems

• To the new language– how does the language compare to

existing ones?

• From (!) the new language– development organizations may have

process requirements

C#contracts

everywhere

into the future

download Spec#from here

Conclusions• Trend toward more rigorous languages and checking• Desire to contribute customized specifications• Tool support is crucial• Despite significant advances in the use of static

analyses, we need more experience before we’d expect users to take on more detailed verification tasks

• Some areas where more research will help– language design– program semantics– specification techniques– inference algorithms– decision procedures– methodology

http://research.microsoft.com/specsharp