Download presentation
Presentation is loading. Please wait.
1
Predicate Abstraction for Software Verification Shaz Qadeer Compaq Systems Research Center (joint work with Cormac Flanagan)
2
Systems software OS components –file system, buffer cache manager Abstract from low-level to high-level operations –tedious low-level programming detail Expected to work –with multiple concurrent clients –in the presence of crashes
3
Outline Background –verification condition –strongest postcondition –loop invariants Inferring loop invariants –predicate abstraction –universally-quantified invariants Frangipani Related work
4
Verification condition x := a; if (x < b) { x := b; } assert x = max(a,b); sp(P,true) x a x b Program P Check for validity:
5
Statement S x := e A ; B assume e A B while {I} e do B end Guarded command language (Dijkstra 76) Variables have arbitrary values in program’s initial state if e then A else B end (assume e ; A) (assume e ; B)
6
Strongest postcondition semantics sp(S,Q) y.(Q[x y] x=e[x y]) sp(B,sp(A,Q)) e Q sp(A,Q) sp(B,Q) Statement S x := e A ; B assume e A B Denote sp(S, true) by sp(S)
7
Checking loop invariants Given loop Need to check –Invariant holds on entry to loop sp( C ) I –Invariant holds at end of every iteration sp( C; H; assume I e; B) I where H = havoc variables modified in B C; {I} while e do B end
8
Desugaring loops S = “while {I} e do B end” H = havoc variables modified in B desugar(S) = assert I ; H ; assume I ; ( (assume e ; B; assert I; assume false) assume e)
9
Example assume 0 < a.length; i := 0; while (i < a.length) { a[i] := 0; i := i + 1; } assert a[0] = 0; { int j; 0 <= j j < i a[j] = 0, 0<=i}
10
Translation assume 0 < a.length; i := 0; assert int j; 0 <= j j < i a[j] = 0; assert 0 <= i; havoc a[*], i; assume int j; 0 <= j j < i a[j] = 0; assume 0 <= i; ( assume (i < a.length); a[i] := 0; i := i + 1; assert int j; 0 <= j j < i a[j] = 0; assert 0 <= i; assume false;) assume (i < a.length) assert a[0] = 0;
11
ESC/Java with loop invariants /*@ 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 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; }
12
Outline Background –verification condition –strongest postcondition –loop invariants Inferring loop invariants –predicate abstraction –universally-quantified invariants Frangipani Related work
13
Inferring loop invariants Could try –I 0 = sp( C ) –I n+1 = I n sp( C; H; assume I n e; B) I n is an invariant for first n iterations Problem: May not converge C; {I} while e do B end
14
Divergence State Space I0I0 I1I1 I2I2 InIn...
15
Predicate abstraction Invariant is boolean combination of predicates Split problem into two parts 1Find a suitable set of predicates 2Find the boolean combination of these predicates
16
Predicate abstraction (contd.) Predicates over program variables –a = expr1, b = expr2, c = expr3, d = expr4 : boolean expression over {a,b,c,d} formula over program variables : formula over program variables boolean expression over {a, b, c, d} (F) = least boolean function G over {a,b,c,d} such that F (G)
17
Abstract state space Predicates { a, b, c, d } They generate an abstract space of size 2 4 = 16 a b a b a b abab cdcd c d c d cdcd F (F) State Space
18
Inferring loop invariants Compute –I 0 = (sp( C )) –I n+1 = I n (sp( C; H; assume E (I n) ; B)) Converges yielding valid loop invariant –Best loop invariant for the given predicates
19
Method 1 (slow!) Is F a b c d satisfiable? No! Can compute (F) by asking 2 n such queries a b a b a b abab cdcd c d c d cdcd F (F) XXXX X X XX X XX
20
Method 2 (Das-Dill-Park 99) Order the variables: a < b < c < d a b c FaFa FabFab F a b c F a b (F) a b a b a b abab cdcd c d c d cdcd F XXXX X X XX X XX O(2 n+1 ) queries Sensitive to ordering
21
Method 3 (Shankar-Saidi 99) O(3 n ) queries No ordering required Queries of size 1: F a, F a, F b, etc. Number = n C 1 2 1 Queries of size 2: F a b, F a b, etc. Number = n C 2 2 2 Queries of size n:... Number = n C n 2 n....
22
New method F a b c d ? No! a b a b a b abab cdcd c d c d cdcd F (F) XXXX X X XX X XX 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)
23
Universally-quantified loop invariants /*@ 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 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; }
24
Inferring -quantified loop invariants assume 0 < a.length; i := 0; /*@ loop_invariant 0 <= i, int j; 0 <= j j < i a[j] = 0 */ while (i < a.length) { a[i] := 0; i := i + 1; } assert a[0] = 0;
25
Inferring -quantified loop invariants assume 0 < a.length; i := 0; /*@ loop_predicate 0 <= i, int j; 0 <= j j < i a[j] = 0 */ while (i < a.length) { a[i] := 0; i := i + 1; } assert a[0] = 0;
26
Inferring -quantified loop invariants assume 0 < a.length; i := 0; /*@ skolem_constant int j */ /*@ loop_predicate 0 <= i, 0 <= j, j < i, a[j] = 0 */ while (i < a.length) { a[i] := 0; i := i + 1; } assert a[0] = 0;
27
Inferring -quantified loop invariants I 0 = (sp(i := 0)) I n+1 = I n (sp(i := 0; havoc i, a[*]; assume I n i < a.length; a[i] := 0; i := i+1)) /*@ loop_predicate 0 <= i, 0 <= j, j < i, a[j] = 0 */ TFTF TFTTTTFFTTFT I0I0 TTTT I1I1
28
Inferring -quantified loop invariants /*@ loop_predicate 0 <= i, 0 <= j, j < i, a[j] = 0 */ TFTF TFTTTTFFTTFT TTTT I0I0 I1I1 0 i (0 j) (j < i) a[j] = 0 0 j j < i
29
Inferring -quantified loop invariants /*@ loop_predicate 0 <= i, 0 <= j, j < i, a[j] = 0 */ TFTF TFTTTTFFTTFT TTTT I0I0 I1I1 0 i int j; 0 j j < i a[j] = 0 int j; 0 j j < i
30
Outline Background –verification condition –strongest postcondition –loop invariants Inferring loop invariants –predicate abstraction –universally-quantified invariants Frangipani Related work
31
Frangipani Distributed file system (Thekkath, Mann, Lee 1997) Built on top of Petal virtual disk (Lee, Thekkath 1996) Implements the file abstraction from the virtual disk block abstraction Exports file and directory operations - create, delete, rename etc. - to clients
32
Verification Loop invariant inference built on top of ESC/Java (Detlefs, Leino, Nelson, Saxe 1998) ESC/Java uses automatic theorem prover Simplify (Nelson 81) Frangipani data structures and “create” modeled abstractly in Java Assume –single thread of execution –no crashes
33
... ibusy idisk bdisk bbusy F TT TT FFF FF F F Inode { int inum; int addr; int mode; int length; } Block { int addr; Entry[] entries; } Entry { String name; int inum; } addr Data structures on disk: Data structures in memory:... vArray vbusy TTFF T F vArray contains inodes distinct entries must contain distinct inodes itov: int int
34
/*@ invariant int i, j: vbusy[i] ((vArray[i].inum = j) (itov[j] = i)); invariant int i: ibusy[i] bbusy[idisk[i].addr]; invariant idisk bdisk; invariant int i: idisk[i] null idisk[i].inum = i;. */ /*@ requires vbusy[num] vArray[num].mode = DIR */ /*@ ensures \result = ERROR there is an entry with name s in directory vArray[num] */ int create(int num, String s) {. }
35
Main loop in “create” /*@ 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 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; }
36
Performance
37
Related work Inferring/computing loop invariants Predicate abstraction –Graf-Saidi 97 –Bensalem-Lakhnech-Owre 98, Colon-Uribe 98 –Saidi-Shankar 99, Das-Dill-Park 99 –Ball-Majumdar-Millstein-Rajamani 2001
38
Future Work Heuristics for generating predicates Multiple threads –locks, semaphores,... –thread-modular reasoning Linked lists, reachability Target C
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.