Predicate Abstraction for Software Verification Cormac Flanagan Shaz Qadeer Compaq Systems Research...

Post on 21-Dec-2015

221 views 0 download

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