Model checking C programs

Blast:
Software Model Checking
Tom Henzinger
Ranjit Jhala
Rupak Majumdar
Software Model Checking
Objective:
Automatic verification of flow-sensitive temporal properties of
C code using model checking.
Approach:
-Starting point: Counter-example driven abstraction refinement
(Microsoft SLAM project).
-Key improvement: Lazy Abstraction.
Software Model Checking
Tool:
BLAST (Berkeley Lazy Abstraction Software * Tool).
Applications:
-Linux and NT device drivers.
-If a bug is found, then BLAST produces a counter-example;
otherwise BLAST produces a succinct correctness certificate
(which can be used in proof-carrying code).
Ongoing Work:
-Race checking for multi-threaded code.
-Provide automatic suggestions for bug fixes.
A Brief History of Model Checking
1980s: Theory of finite-state model checking
[Clarke, Sifakis, et al.]
1990s: Finite-state model checking penetrates the hardware
industry [Intel, IBM, Motorola, Siemens, Lucent/Cadence]
Heuristics to combat state explosion [Mcmillan et al.]
Theory of infinite-state model checking
2000s: Infinite-state model checking penetrates the software
industry ?
Heuristics for automatic model extraction ?
The SLAM Abstract-Check-Refine Loop [Ball, Rajamani]
Code
Build Predicate Abstraction
New Predicates of Interest
Model Check Abstraction
Concretize Error Trajectory
Concrete Error
Trajectory
Abstract
Error
Trajectory
Correctness
Certificate
BLAST (The Berkeley Lazy Abstraction Software * Tool)
Code
Locally Refine
Build Predicate Abstraction
New Predicates of Interest
Integrated
Model Check Abstraction
Concretize Error Trajectory
Concrete Error
Trajectory
Refined Parts of
the Abstraction
Abstract
Error
Trajectory
Correctness
Certificate
Example
Example () {
1: do {
lock ();
old = new;
2:
if (*) {
3:
unlock ();
new ++;
}
4: } while (new != old);
5: unlock ();
?: return;
}
lock ()
U
L
unlock ()
unlock ()
lock ()
E
Safety specification
Control Flow Graph
1
lock ();
old = new
2
[T]
[T]
3
Example () {
1: do {
lock ();
old = new;
2:
if (*) {
3:
unlock ();
new ++;
}
4: } while (new != old);
5: unlock ();
?: return;
}
unlock ();
new++
[new != old]
4
[new == old]
5
unlock ()
lock ()
U
L
unlock ()
?
unlock ()
lock ()
E
Abstract Reachability
1
U
2
L
4
U
lock ();
old = new
[T]
3
L
unlock ();
new++
[new == old]
1
lock ();
old = new
5
2
[T]
lock ()
unlock ()
[T]
3
U
U
[new != old]
unlock ();
new++
L
unlock ()
4
[new == old]
?
E
unlock ()
lock ()
5
E
unlock ()
?
Concretize Error Trajectory
1
U
new+1 = new
2
L
new+1 = old
lock ();
old = new
[T]
3
L
unlock ();
new++
new+1 = old
4
U
new = old
[new == old]
1
lock ();
old = new
5
2
[T]
true
lock ()
unlock ()
[T]
3
U
U
[new != old]
unlock ();
new++
L
unlock ()
4
[new == old]
?
E
true
unlock ()
lock ()
5
E
unlock ()
?
Concretize Error Trajectory
1
U
new+1 = new
2
L
new+1 = old
new=old
is a relevant
predicate
lock ();
old = new
[T]
3
L
unlock ();
new++
new+1 = old
4
U
new = old
[new == old]
1
lock ();
old = new
5
2
[T]
true
lock ()
unlock ()
[T]
3
U
U
[new != old]
unlock ();
new++
L
unlock ()
4
[new == old]
?
E
true
unlock ()
lock ()
5
E
unlock ()
?
Refined Abstract Reachability
1
U
2
L, new = old
lock ();
old = new
[T]
L, new = old
3
unlock ();
new++
U, new  old
1
[new == old]
2
5
lock ();
old = new
[T]
[T]
3
[new != old]
unlock ();
new++
4
4
[new != old]
1
U, new  old
U
unlock ()
unlock ()
lock ()
E
?
L
unlock ()
[new == old]
5
lock ()
Complete Proof Tree
1
U
2
L, new = old
lock ();
old = new
[T]
L, new = old
3
unlock ();
new++
U, new  old
1
[new == old]
2
5
lock ();
old = new
[T]
[T]
3
[new != old]
unlock ();
new++
4
4
[T]
[new !=
old]
4
1
L, new = old
[new == old]
5
unlock ()
[new != old]
1
U, new  old
L, new = old
?
U, new = old
U
unlock ()
unlock ()
lock ()
E
?
L
unlock ()
[new == old]
5
lock ()
Incremental Programming
Example () {
0: if (*) {
6:
do {{
6:
do
got_lock
got_lock== 0;
0;
7:
if
(*)
{
7:
if (*) {
8:
lock();
8:
lock ();
got_lock
got_lock++;
++;
}};
9:
(got_lock) {{
9:
ifif (got_lock)
10:
unlock();
10:
unlock
();
}
};
11:
}
while
11:
} while (*)
(*);;
}};
1: do {
lock();
lock
();
old = new;
2:
if (*) {
3:
unlock();
unlock
();
new ++;
}
4: } while (new
( new!=
!=old);
old);
5: unlock ();
return;
?: return;
}
0
1
6
2
7
3
8
4
9
10
5
11
?
Incremental Model Checking
U
0
[T]
U
1
[T]
U
6
old
proof tree
refine only this part using
different predicates
E
Incremental Model Checking
U
0
[T]
U
1
[T]
U
6
reuse old
proof tree
1
U, got_lock  0
Experiments with BLAST
Program
Linux
Lock
3 states
Lines of
Code
DDK
IRP
22 states
Active
Preds
Total Time
(sec)
Pred. Disc. Proof Size
Time (sec) (bytes)
ide.c
18131
5
5
4.5
0.01
253
qpmouse.c
23539
2
2
0.5
0.01
179
aha152x.c
17736
2
2
20.93
0.03
tlan.c
16506
5
4
428.63
403.33
cdaudio.c
17798
85
45
1398
540
floppy.c
17386
62
37
2086
1565
93
44
395
17
54
40
64
5
48
35
256
165
37
34
10
0.38
[fixed]
Windows
Total
Preds
kbflter.c
12131
[fixed]
mouclass.c
17372
57
46
54
3.34
parport.c
61781
193
50
1980
519
156787
60129
7619
102967