software verification with blast thomas a. henzinger, ranjit jhala, rupak majumdar, george necula,...
Post on 19-Dec-2015
215 views
TRANSCRIPT
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