Secrets of Software Model Checking Thomas Ball Sriram K. Rajamani Software Productivity Tools...

45
Secrets of Software Model Checking Thomas Ball Sriram K. Rajamani Software Productivity Tools Microsoft Research http://research.microsoft.com/slam/
  • date post

    20-Dec-2015
  • Category

    Documents

  • view

    219
  • download

    1

Transcript of Secrets of Software Model Checking Thomas Ball Sriram K. Rajamani Software Productivity Tools...

Secrets of Software Model Checking

Thomas BallSriram K. Rajamani

Software Productivity ToolsMicrosoft Research

http://research.microsoft.com/slam/

Outline

• Overview

• Status and Demo

• Secrets– Leaping loops– Fast predicate abstraction– Predicate generating genie

• Conclusions– more “secrets”

Source Code

TestingDevelopment

PreciseAPI Usage Rules

(SLIC)

Software Model Checking

Read forunderstanding

New API rules

Drive testingtools

Defects

100% pathcoverage

Rules

Static Driver VerifierStatic Driver Verifier

SLAM – Software Model Checking

• Counterexample-driven refinement for C – model = boolean programs– model creation (c2bp)– model checking (bebop)– model refinement (newton)

• SLAM toolkit– build on MSR program analysis infrastructure

prog. P’prog. P

SLIC rules

The SLAM Process

boolean program

pathpredicates

slic

c2bp

bebop

newton

SLIC

• Finite state language for stating rules– monitors behavior of C code– temporal safety properties (security automata)– familiar C syntax

• Suitable for expressing control-dominated properties – e.g. proper sequence of events– can encode data values inside state

State Machine for Locking

Unlocked Locked

Error

Rel Acq

Acq

Rel

state {

enum {Locked,Unlocked}

s = Unlocked;

}

KeAcquireSpinLock.entry {

if (s==Locked) abort;

else s = Locked;

}

KeReleaseSpinLock.entry {

if (s==Unlocked) abort;

else s = Unlocked;

}

Locking Rule in SLIC

do {KeAcquireSpinLock();

nPacketsOld = nPackets;

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

}} while (nPackets != nPacketsOld);

KeReleaseSpinLock();

ExampleDoes this code

obey the locking rule?

do {KeAcquireSpinLock();

if(*){

KeReleaseSpinLock();

}} while (*);

KeReleaseSpinLock();

ExampleModel checking boolean program

(bebop)

U

L

L

L

L

U

L

U

U

U

E

do {KeAcquireSpinLock();

nPacketsOld = nPackets;

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

}} while (nPackets != nPacketsOld);

KeReleaseSpinLock();

ExampleIs error path feasible

in C program?(newton)

U

L

L

L

U

U

U

E

nPackets = CnPacketsOld = C

nPackets = C+1

C+1 != C

do {KeAcquireSpinLock();

nPacketsOld = nPackets; b := true;

if(request){request = request->Next;KeReleaseSpinLock();nPackets++; b := b? false : *;

}} while (nPackets != nPacketsOld);// !b

KeReleaseSpinLock();

ExampleAdd new predicateto boolean program

(c2bp)

U

L

L

L

L

U

L

U

U

U

E

b : (nPacketsOld == nPackets)

do {KeAcquireSpinLock();

b := true;

if(*){

KeReleaseSpinLock();b := b? false : *;

}} while ( !b );

KeReleaseSpinLock();

b

b

b

b

ExampleModel checking

refined boolean program

(bebop)

b : (nPacketsOld == nPackets)

U

L

L

L

L

U

L

U

U

U

E

b

b

!b

Example

do {KeAcquireSpinLock();

b := true;

if(*){

KeReleaseSpinLock();b := b? false : *;

}} while ( !b );

KeReleaseSpinLock();

b : (nPacketsOld == nPackets)

b

b

b

b

U

L

L

L

L

U

L

U

U

b

b

!b

Model checking refined

boolean program(bebop)

SLAM 2002 Status• March

– Bill Gates review

• May– Windows committed to hire two people with model checking

background to support Static Driver Verifier (SDV)• Byron Cook (Prover, OGI)• Vladimir Levin (Bell Labs, FormalCheck)

• July– running SLAM on 100+ drivers, 20+ properties

• September 3– released SDV-1.00 to Windows

Demo

SLAM Secrets

– Leaping loops

– Fast predicate abstraction

– Predicate generating genie

Leaping Loops• Most loops fill/access arrays

– are a pain for counter-example-driven refinement – loop predicates usually are irrelevant

• Example: is foo called twice in a row?if (y==0) foo();for(i = 0; i<100; i++) if (a[i]) y=y+1;if (y==1) foo();

• Many infeasible paths to eliminate due to loop predicate i<100

Goal: eliminate irrelevant loop predicates

if (y==0) foo();

for(i = 0; i<100 ;i++) if (a[i]) y=y+1;

if (y==1) foo();

y==0

entry

foo()

y==1

foo()

i<100

a[i]

y=y+1

Control dependence graph

foo() foo()

y==0

entry

foo()

y==1

foo()

i<100

a[i]

y=y+1

y==0

entry

foo()

y==1

foo()

i<100

a[i]

y=y+1

if (y==0) foo();

for(i = 0; * ;i++) if (a[i]) y=y+1;

if (y==1) foo();

Results

• Without apriori loop abstraction– SLAM sometimes runs out of resources or

time– many refinements of irrelevant loops to find

feasible counterexample

• With abstraction– SLAM always has terminated– few false negatives

SLAM Secrets

– Leaping loops

– Fast predicate abstraction

– Predicate generating genie

c2bp: Predicate Abstraction for C Programs

Given• P : a C program• E = {e1,...,en}, ei pure boolean expression

Produce a boolean program B• same control-flow structure as P• only vars are 3-valued booleans {b1,...,bn}• properties true of B are true of P

Assignment ExampleStatement in P: Predicates in

E:y=y+1; {x==y}Weakest Precondition:wp(y=y+1, x==y) = x==y+1wp(y=y+1, x!=y) = x!=y+1

Strengthenings:S(x==y+1) = false

Boolean abstraction of y=y+1:b = b ? false : *;

S(x!=y+1) = x==y

Strengthening

S(e) is the best predicate over {e1,...,en} that implies e:

• a minterm m is a conjunction d1^...^dn

– di = ei or di = !ei

• S(e) = m, where m e • use decision procedures (theorem

prover) to check implication– O(2n) calls in worst-case

Fast Predicate Abstraction

• Predicate abstraction requires many calls to theorem prover to compute S(e)– for each minterm m over predicates in E

• does m imply e?

• Idea:– compute set of minterms m that imply e

directly via theorem prover data structures

Consider Equalities• Example

– E = { a==b, b==c, c==d, a==c }– S(a==d)

• Many unhelpful minterms– (a==b)^(c==d), etc

• Equality graph induced by E:

a b c da b c da b c d

(a==c)^(c==d)

Efficient Implementation of S(e)

• Graph representation of– equalities– uninterpreted function symbols– inequalities (x < c)

• Computation of good minterms via CFL-reachability query

Example Graph ClosureRules

*p*x *y==

x y==

* *x == y *x == *y

*p*x y==

x &y==

* *x == &y *x == y

Example

• E = { p==q, &q==x, **x<5 }

• S(*p<5)

p q==

&q x==

**x 5<

*p<

*p *q==

* *

q *x==

* *

*q **x==

*

The Rest of the Story

• For predicates not in theory (i.e., x<y+c), call theorem prover as before– limit size of minterms for efficiency

• Use Das/Dill refinement to deal with approximation introduced by heuristics– implemented by Satyaki Das, summer 2001

Results

• Before fast predicate abstraction– c2bp was bottleneck in SLAM process

• After fast predicate abstraction– bebop is the bottleneck, as it should be

SLAM Secrets

– Leaping loops

– Fast predicate abstraction

– Predicate generating genie

The Predicate Generating Genie

• Fantasy:– if a genie gave SLAM just the right set of predicates, it

could terminate in one iteration

• Reality:– for a restricted subset of C, find enough predicates so

that SLAM terminates in just one iteration– if program not in restricted subset, find predicates and

then iterate to get remaining predicates

Restricted C Language of Equalities

• v1 = v2

• v = c // c Z

• if (*) stmt1 else stmt2

• v1 = fun(v2, …)

• return v

• abortif(v1 v2) // relop

“Simple” Example

bar(int c, int d) int p,q; p = c; q = d; foo(p,q)

foo(int a, int b) abortif(a b)

main() int x,y,z; x = 2; x = 3; y = 5; y = pick(3); z = x; bar(z,y);

pick(int s) int v; if (*) v = s; else v = 4; return v

Value Flow Graph

2

3

x z

s v

4

5

y

c p a

d q b

bar(int c, int d) int p,q; p = c; q = d; foo(p,q)

foo(int a, int b) abortif(a b)

main() int x,y,z; x = 2; x = 3; y = 5; y = pick(3); z = x; bar(z,y);

pick(int s) int v; if (*) v = s; else v = 4; return v

The Idea

• If we knew the final values of a and b (e.g., “3” and “5”) we could decide a b

• Walk back in the graph from a– for each edge “u v”

• add predicate “u == v”

• Do the same for b

Theory and Practice

2

3

4

5

x z

s v

c

y

p

d

a

q b

p==ac==pz==cx==z 2==x3==x

Let’s try it on the a branch …

Theory and Practice

p==a // bad scopec==pz==c // bad scopex==z 2==x3==x

Let’s try it on the a branch …

2

3

4

5

x z

s v

c

y

p

d

a

q b

Scoping Things Out

There is no scope in which “z == c” is a valid predicate.

But this predicate is necessary!

Solution: link all ground terms to c

bar(int c, int d) int p,q; p = c; q = d; foo(p,q)

main() int x,y,z; x = 2; x = 3; y = 5; y = pick(3); z = x; bar(z,y);

Constraint Propagation

2

3

4

5

x z

s v

c

y

p

d

a

q b

Concentrating just onzc, conceptuallyadd 3c and 2c,thus adding “3==c”and “2==c”

Why does it work?

If we know “z==2” or “z==3”

We can easily prove “c==2” or “c==3” at the call-site

And “c==2 & z==2” implies “c==z”

bar(int c, int d) int p,q; p = c; q = d; foo(p,q)

main() int x,y,z; x = 2; x = 3; y = 5; y = pick(3); z = x; bar(z,y);

Forward Pointer

• Speeding Up Dataflow Analysis Using Flow-Insensitive Pointer AnalysisStephen Adam, Thomas Ball, Manuvir Das, Sorin Lerner,

Sriram K. Rajamani, Mark Seigle, and Westley Weimer

• SAS talk on Thursday morning

Result

Floppy driver (3 iterations instead of 25) 6500 lines, simple spec 21 global predicates 741 local predicates 72 max local in scope

Other Technical “Secrets”

• Program slicing– implementation underway– valuable for getting rid of code that is totally irrelevant

to property under consideration

• Incremental abstraction/model checking– abstraction implemented

• Boolean program minimization– implementation underway

Conclusion:SLAM’s “Secret” to Success

• Specific problem• Safety properties• Shoulders & synergies• Separation of concerns• Summer interns & visitors

– Sagar Chaki, Todd Millstein, Rupak Majumdar (2000)– Satyaki Das, Wes Weimer, Robby (2001)– Jakob Lichtenberg, Mayur Naik (2002)– Giorgio Delzanno, Andreas Podelski, Stefan Schwoon