Predicate Abstraction for Software Verification Cormac Flanagan Shaz Qadeer Compaq Systems Research...
-
date post
21-Dec-2015 -
Category
Documents
-
view
221 -
download
0
Transcript of Predicate Abstraction for Software Verification Cormac Flanagan Shaz Qadeer Compaq Systems Research...
Predicate Abstraction for Software Verification
Cormac Flanagan
Shaz QadeerCompaq Systems Research Center
POPL02The Continuing Saga of Predicate Abstraction
Extended Static Checking
• Statically verify many correctness properties
• Type systems catch many errors
– e.g. “Cannot multiply a number and a string”• Would like to catch additional errors
– e.g. “Array index out of bounds at line 10”• And verify other correctness properties
– assertions– object invariants– lightweight method specifications
Checking loops with ESC/Java/*@ loop_invariant i >= 0; loop_invariant 0 <= spot; loop_invariant spot <= MAXDIRENTRY; loop_invariant (\forall int j; 0 <= j && j < i && bdisk[addr].dirEntries[j].inum != DIRENTRY_UNUSED ==>
bdisk[addr].dirEntries[j].name != name); loop_invariant (\forall int j; spot == MAXDIRENTRY && 0 <= j && j < i ==> bdisk[addr].dirEntries[j].inum != DIRENTRY_UNUSED);
loop_invariant spot == MAXDIRENTRY || bdisk[addr].dirEntries[spot].inum == DIRENTRY_UNUSED;
loop_invariant (\forall DirEntry t; t != de ==> t.name == \old(t.name)); loop_invariant (\forall DirEntry t; t != de ==> t.inum == \old(t.inum)); loop_invariant (\forall DirEntry t; t.inum == FS.DIRENTRY_UNUSED ||
(0 <= t.inum && t.inum < FS.IMAX));*/for (i = 0; i < cwd.inode.length; i++) { GetDirEntry(de, addr, i); if (de.inum != DIRENTRY_UNUSED && de.name == name) { return ERROR; } if (de.inum == DIRENTRY_UNUSED && spot == MAXDIRENTRY) { spot = i; }}
Loop invariants
C;
while e do B end
Set of reachable states at loop head is a loop invariant!
sp(C, p)p C
Concrete states
I0 I1 I2 In... ...
Abstract states
J0 J1 J2 Jn... ...
(Ik) = JkIk = (Jk)
Abstract interpretation
Cousot-Cousot 77
Predicate abstractionGraf-Saidi 97
Computing loop invariantsC;
while e do
X;
Y;
end
{ I0 = (sp(C, true)) }
{ J0 = ((I0) e) }
{ K0 = (sp(X, (J0))) }
{ L0 = (sp(Y, (K0))) }
Computing loop invariantsC;
while e do
X;
Y;
end
{ I1 = I0 L0 }
{ J1 = ((I1) e) }
{ K1 = (sp(X, (J1))) }
{ L1 = (sp(Y, (K1))) }
/*@ requires a!=null && b!=null && a.length==b.length ensures \result==a.length || b[\result] */int find(int[] a, boolean[] b) { int spot = a.length; for (int i=0; i < a.length; i++) { if (spot==a.length && a[i] != 0) spot = i; b[i] = (a[i] != 0); } return spot;}
Predicate abstraction example
Ten predicates:a != nullb != nulla.length == b.lengthspot == a.lengthb[spot]spot < i0 <= ii < a.lengthspot = ia[i] != 0
Computing loop invariantsC;
while e do
X;
Y;
end
{ I0 = (sp(C, true)) }
{ L0 = (sp(“X;Y”, (I0)e)) }
Computing loop invariantsC;
while e do
X;
Y;
end
{ I1 = I0 L0 }
{ L1 = (sp(“X;Y”, (I1)e)) }
/*@ requires a!=null && b!=null && a.length==b.length ensures \result==a.length || b[\result] */int find(int[] a, boolean[] b) { int spot = a.length; for (int i=0; i < a.length; i++) { if (spot==a.length && a[i] != 0) spot = i; b[i] = (a[i] != 0); } return spot;}
Predicate abstraction example
Seven predicates:a != nullb != nulla.length == b.lengthspot == a.lengthb[spot]spot < i0 <= ii < a.lengthspot = ia[i] != 0
Computing loop invariants
C;
while e do
X;
Y;
end
{ I0 = (sp(C, true)) }
H = havoc variables modified in X;Y
P0 = “C;H;assume (I0)e;X;Y”
{ L0 = (sp(P0, true)) }
Computing loop invariants
C;
while e do
X;
Y;
end
{ I1 = I0 L0 }
H = havoc variables modified in X;Y
P1 = “C;H;assume (I1)e;X;Y”
{ L1 = (sp(P1, true)) }
/*@ requires a!=null && b!=null && a.length==b.length ensures \result==a.length || b[\result] */int find(int[] a, boolean[] b) { int spot = a.length; for (int i=0; i < a.length; i++) { if (spot==a.length && a[i] != 0) spot = i; b[i] = (a[i] != 0); } return spot;}
Predicate abstraction example
Four predicates:a != nullb != nulla.length == b.lengthspot == a.lengthb[spot]spot < i0 <= ii < a.lengthspot = ia[i] != 0
/*@ requires a!=null && b!=null && a.length==b.length ensures ( int j; 0<=j && j<\result ==> !b[j]) */int find(int[] a, boolean[] b) { int spot = a.length; for (int i=0; i < a.length; i++) { if (spot==a.length && a[i] != 0) spot = i; b[i] = (a[i] != 0); } return spot;}
Predicate abstraction example
( int j; 0<=j && j<i && j<spot ==>!b[j])
Invariant needed:
First method:add predicate ( int j; 0<=j && j<i && j<spot ==> !b[j])
-quantified loop invariants
Better method:
add skolem constant int jadd predicates 0<=j, j<i, j<spot, !b[j]infer 0<=j && j<i && j<spot ==>!b[j] Magic: int j; 0<=j && j<i && j<spot ==>!b[j])
Heuristics for guessing predicates
for (int i = 0; i < a.length; i++) a[i] = null;
Loop targets: i, a[*]
First set of predicates: i <= \old(i), i >= \old(i)
skolem_constant int sc
Second set of predicates: 0 <= sc, sc < i, a[sc] != null
Inferred invariant:i >= 0 int sc; 0 <= sc sc < i a[sc] == null
Javafe
• front end to ESC/Java• annotated with lightweight specifications • 45KLOC, 2418 routines, 520 loops• no inference warnings in 326 routines• with inference warnings in 31 routines• several failing routines had array bound
violations – not caught with loop unrolling
Computing abstraction function
• Compute
– I0 = (sp(C, true))
– In+1 = In (sp(“C;H;assume (In)e;B”, true))
• Problem: Given F compute (F)
(F) = least boolean function G such that F (G)
C; {I?}while e do B end
Abstract state space• Predicates {a, b, c, d}• They generate an abstract space of size 24 = 16
F
ab
ab
ab
ab
cd
cd
cd
cd
State Space
(F)
Naïve method (slow!)• Is F a b c d satisfiable? No!
• Can compute (F) by asking 2n such queries
ab
ab
ab
ab
cd
cd
cd
cd
F
(F)X X X X
X
X
XX
X
X X
New method• F a b c d ? No!
ab
ab
ab
ab
cd
cd
cd
cd
F
(F)X X X X
X
X
XX
X
X X
• F a c d ? No!• F c d ? No! • Removed 1/4 of state space in 3 queries!
= (c d) (a c) (a b) ( c d)
Other methods
• Das-Dill-Park 99 (DDP)• Saidi-Shankar 99 (SS)
Experiments
Benchmark Number of predicates
FQ DDP SS
partition 4 27 28 41
sort(outer) 6 44 54 111
sort(inner) 7 37 32 40
find 8 111 110 129
create 15 358 1191 2012
0
100
200
300
400
500
600
700
800
900
1000
0 2 4 6 8 10 12 14 16Predicates per Loop
Queries
FQ
DDP
SS
Experiments (Javafe)
Related work• Inferring/computing loop invariants
– German-Wegbreit 75– Katz-Manna 76– Suzuki-Ishihata 77
• Predicate abstraction– Graf-Saidi 97– Bensalem-Lakhnech-Owre 98, Colon-Uribe 98– Saidi-Shankar 99, Das-Dill-Park 99– Ball-Majumdar-Millstein-Rajamani 2001– Henzinger-Jhala-Majumdar-Sutre 2002