software verification with blast
DESCRIPTION
Software Verification with Blast. Thomas A. Henzinger, Ranjit Jhala, Rupak Majumdar, George Necula, Grégoire Sutre, Wes Weimer UC Berkeley. Motivation. Verification of systems code Locking disciplines Interface specifications Essential for correct operation High rate of bugs - PowerPoint PPT PresentationTRANSCRIPT
Software Verification Software Verification with Blastwith Blast
Thomas A. Henzinger, Ranjit Jhala, Rupak Majumdar,George Necula, Grégoire Sutre, Wes Weimer
UC Berkeley
2
MotivationMotivation
Verification of systems codeLocking disciplinesInterface specifications
Essential for correct operationHigh rate of bugs
Temporal propertiesRequire path-sensitive analysisSwamped by false positives
Really hard to check
3
Model CheckingModel Checking
Doesn’t scale to low level implementations
Can only model check “abstractions”
Requires human intervention …
Abstract – Check – Refine LoopMicrosoft SLAM Project[Clarke et. al. 00], [Saidi 00]
4
Abstract-Check-Refine LoopAbstract-Check-Refine Loop
Abstract
Explanation
YES (Trace)
BUG
Feasible
???
Check
Refine
NO
SAFE
Seed Abstraction
Program
Abstraction
InfeasibleWhy infeasible ?
Is model unsafe ?
5
Model Checking 101Model Checking 101
ERROR STATES
Init
SYSTEM’S STATE SPACE
Keep searching successors until …Hit error states: report “bug” !Add no new successors: report “safe”Could take a long time …
6
Model Checking & AbstractionModel Checking & Abstraction
Problem: Far too many states Iterations don’t terminate !Solution: Abstract …
ERROR STATES
Init
7
ERROR STATES
Init
Model Checking & AbstractionModel Checking & Abstraction
Problem: Abstraction too coarseSolution: Refine abstraction
Make boxes smaller
8
ERROR STATES
Init
Model Checking & AbstractionModel Checking & Abstraction
Problem: Abstraction too coarseSolution: Refine abstraction
Make boxes smaller
9
Abstract Only Where RequiredAbstract Only Where Required
ERROR STATES
Abstraction is very expensive Why abstract regions that are never visited ?
Init
Reachable States
On-the-fly abstraction: driven by the search
10
Refine Only Where RequiredRefine Only Where Required
Why be precise everywhere ?Don’t refine error-free regions
ERROR STATES
Init
ERROR FREE
11
Refine Only Where RequiredRefine Only Where Required
Why be precise everywhere ?Don’t refine error-free regions
Different precision for different regions Local Refinement : driven by the search
ERROR STATES
Init
ERROR FREE
12
How to improve How to improve
Abstract only where requiredReachable state space is very sparseConstruct the abstraction on-the-fly
Use greater precision only where requiredDifferent precisions/abstractions for different regionsRefine locally
Reuse work from earlier phasesBatch-oriented ) lose work from previous runsIntegrate the three phases
Exploit control flow structure
13
ExampleExample
Q: Is Error Reachable ?
Example ( ) {1: if (*) { 7: do { got_lock = 0;8: if (*) {9: lock(); got_lock ++; }10: if (got_lock) {11: unlock(); }12: } while (*) ; }2: do { lock(); old = new;3: if (*) {4: unlock(); new ++; }5: } while ( new != old);6: unlock (); return;}
unlock() lock()
lock()
unlock()
14
Example ( ) {1: if (*) { 7: do { got_lock = 0;8: if (*) {9: lock(); got_lock ++; }10: if (got_lock) {11: unlock(); }12: } while (*) ; }2: do { lock(); old = new;3: if (*) {4: unlock(); new ++; }5: } while ( new != old);6: unlock (); return;}
Example:CFAExample:CFA1
3
lock();
old = new
2 7
[>][>]
4
5
[>]
[>]
unlock()
new++
6
[new==old]
[new!=old]
retunlock()
15
Example ( ) {1: if (*) { 7: do { got_lock = 0;8: if (*) {9: lock(); got_lock ++; }10: if (got_lock) {11: unlock(); }12: } while (*) ; }2: do { lock(); old = new;3: if (*) {4: unlock(); new ++; }5: } while ( new != old);6: unlock (); return;}
Example:CFAExample:CFA
8
10
9
12
11
7
1
3
2
4
5
6
ret
got_lock=0
[>]
[>]
lock();
got_lock++
[got_lock == 0]
[got_lock != 0]
unlock()
[>] [>]
16
Example:CFAExample:CFA
Q: Is Error Reachable ?
Example ( ) {1: if (*) { 7: do { got_lock = 0;8: if (*) {9: lock(); got_lock ++; }10: if (got_lock) {11: unlock(); }12: } while (*) ; }2: do { lock(); old = new;3: if (*) {4: unlock(); new ++; }5: } while ( new != old);6: unlock (); return;}
8
10
9
12
11
7
1
3
2
4
5
6
retunlock() lock()
lock()
unlock()
17
Step 1: SearchStep 1: Search
Set of predicates:
LOCK=0, LOCK=1
1 LOCK=0
2 LOCK=0
4 LOCK=1
6 LOCK=0
[>]
lock();
old = new
[>]
unlock()
new++
[new==old]
unlock()
8
10
9
12
11
7
1
3
2
4
5
6
ret
5 LOCK=0
3 LOCK=1
Err LOCK=0
18
Q: When can:
Step 2:Step 2: Analyze CounterexampleAnalyze Counterexample
1 LOCK=0
2 LOCK=0
3 LOCK=1
4 LOCK=1
5 LOCK=0
6 LOCK=0
Err LOCK=0
8
10
9
12
11
7
1
3
2
4
5
6
ret
n Errops
States that can = wp( >,ops)
States at node n = Rn
) check:
Rn Æ wp( >,ops) = ? ?
19
Step 2:Step 2: Analyze CounterexampleAnalyze Counterexample
1 LOCK=0
2 LOCK=0
3 LOCK=1
4 LOCK=1
5 LOCK=0
6 LOCK=0
Err LOCK=0
lock();
old = new
[>]
unlock();
new++
[new==old]
unlock()
LOCK=0
LOCK=0
LOCK=0 Æ new = old
LOCK=0 Æ new+1 = new
LOCK=1 Æ new+1 = old
LOCK=1 Æ new +1 = old
8
10
9
12
11
7
1
3
2
4
5
6
ret
Rn Æ wp (>,ops) = ? ?
20
Step 2:Step 2: Analyze CounterexampleAnalyze Counterexample
1 LOCK=0
2 LOCK=0
3 LOCK=1
4 LOCK=1
5 LOCK=0
6 LOCK=0
Err LOCK=0
lock();
old = new
[>]
unlock();
new++
[new==old]
unlock()
LOCK=0
LOCK=0
LOCK=0 Æ new = old
LOCK=0 Æ new+1 = new
LOCK=1 Æ new+1 = old
LOCK=1 Æ new +1 = old
8
10
9
12
11
7
1
3
2
4
5
6
ret
Track the predicate:
new = old
21
Step 3: Resume searchStep 3: Resume search1LOCK=0
2LOCK=0
4LOCK=1 Æ new = old
lock();
old = new
[>]
unlock()
new++
[new==old]
? 6[new!=old]
2
LOCK=0 Æ : new = old µ LOCK =0
Set of predicates:
LOCK=0, LOCK=1
New predicate:
new = old,
8
10
9
12
11
7
1
3
2
4
5
6
ret
5LOCK=0 Æ : new = old
3LOCK=1 Æ new = old
22
Step 3: Resume searchStep 3: Resume search1LOCK=0
2LOCK=0
3LOCK=1 Æ new = old
4LOCK=1 Æ new = old
5LOCK=0 Æ : new = old
? 6 2
LOCK=0 Æ : new = old
[>]
5LOCK=1 Æ new=old
6
[new==old][new!=old]
1
?unlock()
8
10
9
12
11
7
1
3
2
4
5
6
ret
Set of predicates:
LOCK=0, LOCK=1
New predicate:
new = old
retLOCK=0Æ new=old
23
Example ( ) {1: if (*) { 7: do { got_lock = 0;8: if (*) {9: lock(); got_lock ++; }10: if (got_lock) {11: unlock(); }12: } while (*) ; }2: do { lock(); old = new;3: if (*) {4: unlock(); new ++; }5: } while ( new != old);6: unlock (); return;}
Example:CFAExample:CFA
8
10
9
12
11
7
1
3
2
4
5
6
ret
got_lock=0
[>]
[>]
lock();
got_lock++
[got_lock == 0]
[got_lock != 0]
unlock()
[>] [>]
24
Step 4: Search Right BranchStep 4: Search Right Branch1 LOCK=0
[>]
2LOCK=0 7 LOCK=0
[>]
Err
8
10
9
12
11
7
1
3
2
4
5
6
ret
Set of predicates:
LOCK=0, LOCK=1
New predicate: (from trace)
got_lock = 0
25
Leaves Covered (Reuse work)Leaves Covered (Reuse work)1 LOCK=0
2LOCK=0 7 LOCK=0
222
LOCK=0 Æ …
COVERED !
Leaves covered:
Avoid repeating search when paths merge
8
10
9
12
11
7
1
3
2
4
5
6
ret
27
Reachability TreeReachability Tree1LOCK=0
2LOCK=0
3LOCK=1 Æ new = old
4LOCK=1 Æ new = old
5LOCK=0 Æ : new = old
? 6 2
5LOCK=1 Æ new=old
6 1
?
retLOCK=0Æ new=old
8
12
7
10
10
11
1211
9
LOCK=0
12
82
LOCK=0 Æ got_lock=0
LOCK=1 Æ got_lock!=0
LOCK=0 Æ got_lock=0
LOCK=0 Æ got_lock=0
?
?
28
InvariantsInvariants1LOCK=0
2LOCK=0
3LOCK=1 Æ new = old
4LOCK=1 Æ new = old
5LOCK=0 Æ : new = old
? 6 2
5LOCK=1 Æ new=old
6 1
?
retLOCK=0Æ new=old
Regions in the tree are invariants:
Invariant Inv (n) for node n =
Disjunction of all node-n regions in the tree
Inv (5) is:
LOCK=0 Æ : new = old Ç LOCK=1 Æ new=old
Inv (6) is:
LOCK=1 Æ new=old
29
Proof GenerationProof Generation1
3
2
4
5
6
ret
LOCK=0 Æ : new = oldÇ
LOCK=1 Æ new=old [new==old]
[new!=old]
Use the invariants from the tree
Verification Conditions for correctness
1. Pre ) Inv (1)
2. Inv (e) = false for error node e
3. Post (Inv (j), cjk ) ) Inv (k)
These can be formalized as in PCC
1. Inv (1) contains Pre as disjunct
2. Error node not in tree
30
Proof Generation IIProof Generation II1
3
2
4
5
6
ret
LOCK=0 Æ : new = oldÇ
LOCK=1 Æ new=old [new==old]
[new!=old]
Prove : Post ( Inv (i) , cij ) ) Inv (j)
Use the tree to break the proof:
Post(AÇ B, c) ) D Ç E
becomes:
Post (A,c) ) D and Post (B,c) ) E
Example: Post (Inv (5), new==old) ) Inv (6)
LOCK=1 Æ new=old
Post (LOCK=0 Æ : new=old, new==old) ) LOCK=1Æ new=old
Post(LOCK=1 Æ new=old, new==old) ) LOCK=1 Æ new=old
31
Proof Generation IIProof Generation II1
3
2
4
5
6
ret
LOCK=0 Æ : new = oldÇ
LOCK=1 Æ new=old [new==old]
[new!=old]
Prove : Post ( Inv (i) , cij ) ) Inv (j)
Use the tree to break the proof:
Post(AÇ B, c) ) D Ç E
becomes:
Post (A,c) ) D and Post (B,c) ) E
But these were computed in the forward search!
Example: Post (Inv (5), new==old) ) Inv (6)
LOCK=1 Æ new=old
false ) LOCK=1Æ new=old
LOCK=1 Æ new=old) LOCK=1 Æ new=old
33
BLASTBLAST
LAZY
ABSTRACTION
Berkeley Lazy Abstraction Software verification Tool10K Lines of OcamlAnalyze Linux/Windows Device Drivers
CIL
(C ! CFA)
REGION
STRUCTURE
BDD Engine
(Boolean ops)
Simplify
(Post#)
Vampyre
(focus)
Proof Gen
(PCC)
34
MPR3
CallDriver
MPRcompletion
synch
not pending returned
SKIP2
IPCCallDriver
Skip returnchild status
DC
Completerequest
returnnot Pend
PPCprop
completion
CallDriver
N/A
no propcompletion
CallDriver
start NP
returnPending
NP
MPR1
MPRcompletion
SKIP2
IPCCallDriver
CallDriver
DC
Completerequest
PPCprop
completion
CallDriver
N?A
no propcompletion
CallDriver
start P Mark Pending
IRP accessible N/A
synch
SKIP1CallDriver
SKIP1Skip
MPR2 MPR1
NP
MPR3
CallDrivernot pending returned
MPR2
synch
From the SLAM project
35
ExperimentsExperiments
Windows Drivers (IRP Spec – 22 states)
Program Lines Predicates Time Proof
floppy.c 17386 62 37 35 min
17386 93 44 21 min 60K
parport.c 61781 193 50 33 min 103K
mouclass.c 17352 57 46 1 min
cdaudio.c 17798 85 45 23 min 156K
kbfiltr.c 12131 54 40 1 min
12131 12 8 10 sec 7K
36
Experiments Experiments : Linux Locking: Linux Locking
Program Lines Predicates Time Proof
ide.c 18131 5 5 4 sec 253
aironet.c 18152 17 11 4 min
aha152x.c 17736 2 2 20 sec
tlan.c 16505 5 4 7 min 405
37
Why Abstract Lazily ?Why Abstract Lazily ?
Reach set is very sparseAbstract on-the-flyOnly the reachable regionRequires very fast post#
Exploit Control-Flow StructureFree partitioning of state spacePartition preds: different abstractionsRefine locally: don’t repeat old work
38
Problems/Future workProblems/Future work
Engineering IssuesProgram analysis Partitioning by partial evaluation
Theory of counterexample driven refinement
for all linear and branching time logics
44
“BLAST! This is why I hate flying!”- Jedi Master Obi-Wan Kenobi in Episode II: Attack of the
Clones, 2002