Software Verification With Liquid Types

Post on 22-Feb-2016

43 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Software Verification With Liquid Types. Ranjit Jhala , UC San Diego (with Pat Rondon , Ming Kawaguchi). Software Verification. i nt min_index ( int [] a){ r = 0; n = a.length ; for (i = 0; i < n; i++){ if (a[i] < a[r]) r = i; } return r; }. - PowerPoint PPT Presentation

Transcript

Software VerificationWith Liquid Types

Ranjit Jhala, UC San Diego(with Pat Rondon, Ming Kawaguchi)

int min_index(int [] a){ r = 0; n = a.length; for (i = 0; i < n; i++){

if (a[i] < a[r]) r = i; } return r;}

Software Verification

int min_index(int [] a){ r = 0; n = a.length; for (i = 0; i < n; i++){

if (a[i] < a[r]) r = i; } return r;}

Example: Memory Safety

Access In Array Bounds ?

int min_index(int [] a){ r = 0; n = a.length; for (i = 0; i < n; i++){

if (a[i] < a[r]) r = i; } return r;}

Example: Memory Safety

How to prove assert ?

assert (0<=r && r<n)

int min_index(int [] a){ r = 0; n = a.length; //@invariant: 0·iÆ 0·r Æ

r<nfor (i = 0; i < n; i++){

if (a[i] < a[r]) r = i; } return r;}

Example: Memory Safety

int min_index(int [] a){ r = 0; n = a.length; //@invariant: 0·iÆ 0·r Æ

r<nfor (i = 0; i < n; i++){

if (a[i] < a[r]) r = i; } return r;}

Invariants

By Man [Floyd-Hoare]Or Machine [Cousot-Cousot]

But, what of …

ClosuresCollections

PolymorphismData Structures …?

H-O Logics?Quantifiers?

Induction?

But, what of …

Automation

H-O Logics?Quantifiers?

Induction?A Solution: Types

Part I

Part II

Part III

Types and Invariants

Closures, Collections, Generics

Induction for Data Structures

Part ITypes and Invariants

Part IRefinement Types

[Zenger ’97, Owre-Rushby-Shankar ’98, Xi-Pfenning ’98]

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

min_index: a:int array -> int

min_index: {a:int array|0≺ a.len} -> {v:int|0≼ v≺ a.len}

Type

Refinement

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

min_index: {a:int array|0≺ a.len} -> {v:int|0≼ v≺ a.len}

“Requires”

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

min_index: {a:int array|0≺ a.len} -> {v:int|0≼ v≺ a.len}

“Ensures”

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

{r:int|0≼ r≺ a.len}->{i:int|0≼ i}->{v:int|0≼ v≺ a.len}

loop:

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

{r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

loop:

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

{r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}“Requires”

loop:

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

{r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len} “Ensures”

loop:

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Part IRefinement Types

1. Type-checking2. Refine-checking3. Refine-Inference

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop : r:int -> i:int -> int

Assume

1

loop : … r : int i : int

Prove output is int

r “subtype-of” int⊢

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop : r:int -> i:int -> int

Assume

1

loop : … r : int i : int

Prove output is int

r <: int⊢

loop : r:int -> i:int -> int

Assume

12

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0loop : … r : int i : int

Prove index is int⊢ i <: int

loop : r:int -> i:int -> int

Assume

1

3

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

2

loop : … i : int r : int r': int i': int

Prove input is int⊢ r' <: int

loop : r:int -> i:int -> int

Assume

loop r' i' <: int

Prove output is int

1

3 4

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

2

loop : … i : int r : int r': int i': int

loop : r:int -> i:int -> int

Assume Prove input is int

1

3 4

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

2

5

loop : … i : int r : int r': int i': int

⊢0 <: int

Part IRefinement Types

1. Type-checking2. Refine-checking3. Refine-Inference

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop{r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺

a.len}

min_index{a:0≺ a.len}->{v:0≼ v≺ a.len}

r :0≼ r≺ a.leni :0≼ i

Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

3 4

2

5

[i≽ a.len]

r :0≼ r≺ a.leni :0≼ i [i≽ a.len]

Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured⊢ {v=r} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

r :0≼ r≺ a.leni :0≼ i [i≽ a.len]

Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured⊢ {v=r} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured⊢ {v=r} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

0≼ r≺ a.len⋀ 0≼ i⋀ i≽ a.len

Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured

{v=r} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

0≼ r≺ a.len⋀ 0≼ i⋀ i≽ a.len ⋀

Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

0≼ r≺ a.len⋀ 0≼ i⋀ i≽ a.len ⋀ ⇒v=r 0≼ v≺ a.len

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

v=r 0≼ v≺ a.len⋀ 0≼ r≺ a.len⋀ 0≼ i⋀ i≽ a.lenIs Valid?Yes. ⇒

Assume

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

r :0≼ r≺ a.leni :0≼ i [i≺ a.len]

Prove index in bounds⊢{v=i} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

1

3 4

2

5

[i≺ a.len]

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

⇒v=i 0≼ v≺ a.len

⋀ 0≼ r≺ a.len⋀ 0≼ i⋀ i≺ a.lenIs Valid?Yes.

2

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove input as required⊢{v=r'} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

1

3 4

2

5

Assume

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0r :0≼ r≺ a.leni :0≼ i [i≺ a.len]i':i'=i+1

Prove input as required⊢{v=r'} <: {0≼ v≺ a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

3

r':r'=i ∨ r'=r

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

3

⇒v=r' 0≼ v≺ a.len

⋀Is Valid?Yes!

0≼ r≺ a.len⋀ 0≼ i⋀ i≺ a.len⋀ r'=i ∨ r'=r⋀ i'=i+1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured⊢{0≼ v≺a.len}<: {0≼ v≺a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

1

3 4

2

5

Trivial.

Assume

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

a :0 ≺ a.lenProve input as required⊢ {v=0}<: {0≼ v≺a.len}

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

1

3 4

2

5

⇒⋀

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

v=0 0≼ v≺a.len

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

5

Is Valid?Indeed.

0 ≺ a.len

Part IRefinement Types

1. Type-checking2. Refine-checking3. Refine-Inference

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop{r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺

a.len}

min_index{a:0≺ a.len}->{v:0≼ v≺ a.len}

loop{r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺

a.len}

min_index{a:0≺ a.len}->{v:0≼ v≺ a.len}

Writing Types is Hard Work!

Automatic Refinement Inference

Writing Types is Hard Work!

loop: ???

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

loop: ???

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

loop : r:int -> i:int -> int

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

loop : {r:int|?} -> {i:int|?} ->

{v:int|?}

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

Types + X for unknown refinements

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]Type Checking, but with Templates

r : Xr

i : Xi

[i≽ a.len]Assume

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured

3 4

2

5

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

⊢ {v=r} <:

{Xout}

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

⋀ Xr ⋀ Xi ⋀ i≽ a.lenIs Valid? ⇒ v=r Xout

“It is too soon to say. ”

1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

3 4

2

5

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

Xr ⋀ Xi ⋀ i≽ a.len ⋀ v=r ⇒ XoutConstraint 1

Assume

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove index in bounds

⊢{v=i} <: {0≼ v≺ a.len}

1

3 4

2

5

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

r : Xr

i : Xi

[i≺ a.len]

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

2

Xr ⋀ Xi ⋀i≺ a.len ⋀ v=i ⇒ 0≼ v≺ a.lenConstraint 2

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove input as required⊢{v:v=r'} <: {r:int|Xr}

1

3 4

2

5

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

Assume r :Xr

i :Xi

[i≺ a.len]r':r'=i ∨ r'=ri':i'=i+1

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

loop: {r:0≼ r≺ a.len}->{i:0≼ i}->{v:0≼ v≺ a.len}

Constraint 3

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ v=r' Xr[v/r ]⇒

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove output is ensured

1

3 4

2

5

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

Constraint 4

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout Xout⇒

let min_index a = let rec loop r i = if i >= a.length then r

else let r' = a[i] < a[r] ?

i : r let i' = i + 1 loop r' i' loop 0 0

Prove input as required

1

3 4

2

5

loop :{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

Constraint 5 0≺ a.len ⋀ v=0 Xr[v/r ]⇒

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]Type Checking, but with Templates

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

0≺ a.len ⋀ v=0 ⇒ Xr[v/r ]

1

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ v=r' ⇒ Xr[v/r ]

Xr ⋀ Xi ⋀i≺ a.len ⋀ v=i ⇒ 0≼ v≺ a.lenXr ⋀ Xi ⋀ i≽ a.len ⋀ v=r ⇒ Xout

2345

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout 4

⋀Xi ⋀ P ⇒ X

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout 4

⋀Xi ⋀ P ⇒ X

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout 4

⋀Xi ⋀ P ⇒ X

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

0≺ a.len ⋀ v=0 ⇒ Xr[v/r ]

1

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ v=r' ⇒ Xr[v/r ]

Xr ⋀ Xi ⋀ i≽ a.len ⋀ v=r ⇒ Xout

2345

Xr ⋀ Xi ⋀i≺ a.len ⋀ v=i ⇒ 0≼ v≺ a.len⋀Xi ⋀ P ⇒ Q

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

0≺ a.len ⋀ v=0 ⇒ Xr[v/r ]

1

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ v=r' ⇒ Xr[v/r ]

Xr ⋀ Xi ⋀ i≽ a.len ⋀ v=r ⇒ Xout

2345

Xr ⋀ Xi ⋀i≺ a.len ⋀ v=i ⇒ 0≼ v≺ a.len⋀Xi ⋀ P ⇒ Q

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

0≺ a.len ⋀ v=0 ⇒ Xr[v/r ]

1

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ Xout ⇒ Xout

Xr ⋀ Xi ⋀ i≺ a.len ⋀ (r'=i∨ r'=r) ⋀ v=r' ⇒ Xr[v/r ]

Xr ⋀ Xi ⋀ i≽ a.len ⋀ v=r ⇒ Xout

2345

Xr ⋀ Xi ⋀i≺ a.len ⋀ v=i ⇒ 0≼ v≺ a.len⋀Xi ⋀ P ⇒ Q

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]

⋀Xi ⋀ P ⇒ Q⋀Xi ⋀ P ⇒ X (Post*)

(Safe)

Automatic Refinement Inference

1. Templates2. Constraints 3. Fixpoint [MC/AI]⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

“Horn Clauses”

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

“Positive Implications”

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

“Non-Linear Implications”

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

1. Reduce to simple “first-order” program Reuse any abs-interpreter, model-checker e.g. Interproc, SLAM, BLAST, ARMC [CAV 11]

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

2. Monomial Predicate Abstraction (“Houdini”) Input : Candidates Q = {q1…qn} Output : X ↦ ⋀qj satisfying constraints

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

2. Monomial Predicate Abstraction (“Houdini”) Input : Q = {⋆≼ v, v≼ ⋆, v≺ ⋆, v≺ ⋆.len} ⋆ = any variable or constant

Automatic Refinement Inference

Fixpoint Solution ⋀Xi ⋀ P ⇒ X⋀Xi ⋀ P ⇒ Q

2. Monomial Predicate Abstraction (“Houdini”) Input : Q = {⋆≼ v, v≼ ⋆, v≺ ⋆, v≺ ⋆.len} Output : Xr = 0≼ v ⋀ v≺ a.len

Xi = 0≼ v Xout = 0≼ v ⋀ v≺ a.len

2. Monomial Predicate Abstraction (“Houdini”) Input : Q = {⋆≼ v, v≼ ⋆, v≺ ⋆, v≺ ⋆.len} Output : Xr = 0≼ v ⋀ v≺ a.len

Xi = 0≼ v Xout = 0≼ v ⋀ v≺ a.len

Automatic Refinement Inference

Plug Solution In Template

loop:{r:int|Xr} -> {i:int|Xi} -> {v:int|Xout}

2. Monomial Predicate Abstraction (“Houdini”) Input : Q = {⋆≼ v, v≼ ⋆, v≺ ⋆, v≺ ⋆.len} Output : Xr = 0≼ v ⋀ v≺ a.len

Xi = 0≼ v Xout = 0≼ v ⋀ v≺ a.len

Automatic Refinement Inference

Plug Solution In Template

loop:{r:int|0≼r≺a.len}->{i:int|0≼ i}->{v:int|0≼

v≺a.len}

Automatic Refinement Inference

loop:{r:int|0≼r≺a.len}->{i:int|0≼ i}->{v:int|0≼

v≺a.len}Inferred Refinement Type

Automatic Refinement Inference

loop:{r:int|0≼r≺a.len}->{i:int|0≼ i}->{v:int|0≼

v≺a.len}Liquid Type of loop

RecapProgram

Templates

Constraints

AI, MC, PA …

{i:int|Xi} -> {v:int|Xo}

⋀Xi ⋀ P ⇒ X

Part I

Part II

Part III

Liquid Types

Closures, Collections, Generics

Induction for Data Structures

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Closures / Higher-Order Functions

let rec ffor l u f = if l < u then f l; ffor (l+1) u f

let rec ffor l u f =

if l < u then ( f l; ffor (l+1) u f )

Type of f

int ! unit

let rec ffor l u f =

if l < u then ( f l; ffor (l+1) u f )

Template of f

{v:int|X1}!unit

let rec ffor l u f =

if l < u then ( f l; ffor (l+1) u f )

Template of f

{v:int|X1}!unit

Check: input l as required by f

let rec ffor l u f =

if l < u then ( f l; ffor (l+1) u f )

Template of f

{v:int|X1}!unit

l≺ u ⊢ {v:int|v=l} <: {v:int|X1}

l≺ u Æ v=l ) X1

Solution X1 = l≼ v Æ v≺ u

Reduces to

let rec ffor l u f =

if l < u then ( f l; ffor (l+1) u f )

Template of f

{v:int|X1}!unitSolution

X1 = l≼ v Æ v≺ u

Liquid Type of f

{v:int|l≼ v Æ v≺ u} ! unit

Closures / Higher-Order Functions

let rec ffor l u f = if l < u then f l; ffor (l+1) u f

Liquid Type of ffor

l:int!u:int!({v:int|l≼v≺u}!unit)!unit

Liquid Type of f

{v:int|l≼ v Æ v≺ u} ! unit

let rec ffor l u f = if l < u then f l; ffor (l+1) u f let min_index a = let r = ref 0 ffor 0 a.len (fun i

-> if a.(i) < a.(!r) then r := i ); !r

Min-Index Revisited

Liquid Type of fforl:int!u:int!({v:int|l≼v≺u}!unit)!unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of ffor 0u:int!({v:int|0≼v≺u}!unit)!unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of ffor 0 a.len

({v:int|0 ≼ v≺ a.len}!unit)!unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of ffor 0 a.len

({v:int|0 ≼ v≺ a.len}!unit)!unit

Template of (fun i ->...)

{v:int|Xi} ! unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of ffor 0 a.len

({v:int|0 ≼ v≺ a.len}!unit)!unit

Template of (fun i ->...)

{v:int|Xi} ! unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!rCheck: input (fun i... ) as required by

ffor

Liquid Type of ffor 0 a.len

({v:int|0 ≼ v≺ a.len}!unit)!unit

Template of (fun i ->...)

{v:int|Xi} ! unit

{Xi}!unit <:{0≼v≺a.len}!unit

Check: input (fun i... ) as required by ffor

{0≼v≺a.len}

unit{Xi} unit{Xi}!unit <:{0≼v≺a.len}!unit

{0≼v≺a.len} <:

{Xi}unit <: unit

Trivial

Function Subtyping Splits Into

Function Subtyping Splits Into

{Xi}!unit <:{0≼v≺a.len}!unit

0≼v≺ a.len ) Xi

0≼v≺ a.len ) Xi

Solution Xi = 0≼v≺ a.len

Solution Xi = 0≼v≺ a.lenTemplate of (fun i ->...)

{v:int|Xi} ! unit

Solution Xi = 0≼v≺ a.lenLiquid Type of (fun i ->...)

{v:int | 0≼v≺ a.len} ! unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of r{v:int | 0≼v≺ a.len} ref

Liquid Type of (fun i ->...)

{v:int | 0≼v≺ a.len} ! unit

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of r{v:int | 0≼v≺ a.len} ref

Access Safe

let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i)

!r

Liquid Type of r{v:int | 0≼v≺ a.len} ref

Liquid Type of min_indexa:int array ! {v:int | 0≼v≺ a.len}

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Collections (e.g. Lists)

Type of rangel:int ! u:int ! int list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Collections (e.g. Lists)

Template of rangel:int ! u:int ! {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Template of rangel:int ! u:int ! {v:int|Xout} list

Template of “then”: {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” and “tail” as required

Template of “then”: {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” and “tail” as requiredl≺ u ⊢ “head” <: {v:int|Xout}

Template of “then”: {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” and “tail” as requiredl≺ u ⊢ “head” <: {v:int|Xout}l≺ u ⊢ “tail” <: {v:int|Xout} list

Template of “then”: {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” and “tail” as requiredl≺ u ⊢ “head” <: {v:int|Xout}

let rec range l u = if l < u then l :: (range (l+1) u)

else []

l≺ u Æ v=l ) Xout

Reduces To(1)

Check: “head” and “tail” as requiredl≺ u ⊢ {v:int|v=l} <: {v:int|Xout}

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” and “tail” as requiredl≺ u ⊢ “tail” <: {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” and “tail” as requiredl≺ u ⊢ {Xout[l+1/l]} list <: {Xout }

list By List-Subtyping, Reduces Tol≺ u ⊢ {Xout[l+1/l]} <: {Xout

}

Check: “head” and “tail” as requiredl≺ u ⊢ {Xout[l+1/l]} list <: {Xout }

list Reduces To(2)l≺ u Æ Xout[l+1/l] ) Xout

(2)(1)

Solution Xout = l≼v≺ ul≺ u Æ v=l ) Xout

l≺ u Æ Xout[l+1/l] ) Xout

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Collections (e.g. Lists)

Template of rangel:int ! u:int ! {v:int|Xout} list

Solution Xout = l≼v≺ u

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Collections (e.g. Lists)

Liquid Type of rangel:int!u:int!{v:int|l≼v≺ u} list

Solution Xout = l≼v≺ u

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

let rec range l u = if l < u then l :: (range (l+1) u) else []

Generics/Polymorphism

let rec range l u = if l < u then l :: (range (l+1) u) else [] let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r)

0 indices

Generics/Polymorphism

Instance Typea = intb = int

Generic Type of fold_left(a ! b! a) ! a ! b list ! a

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Generic Type of fold_left(a ! b! a) ! a ! b list ! a

Instance Templatea = {v:int| Xa }b = {v:int| Xb }

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Instance Template of fold_left({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Instance Templatea = {v:int| Xa }b = {v:int| Xb }

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Template of r{v:int | Xa }

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Template of i{v:int | Xb }

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Template of min_indexa:int array ! {v:int | Xa }

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Check: args as required

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Check: args as required

1

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Check: args as required

12

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indicesInstance Template of fold_left

({Xa}!{Xb}!{Xa})!{Xa}!{Xb}list!{Xa}

Check: args as required

123

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Constraints

123

r:int!i:int!{v=i ∨ v=r} <: {Xa}!{Xb}!{Xa}

{v:int | v=0} <: {v:int | Xa}

{v:int | 0≼ v≺ a.len} list <: {v:int | Xb}

list

123

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Subtyping Reduces To Implications

123

r:int!i:int!{v=i ∨ v=r} <: {Xa}!{Xb}!{Xa}

{v:int | v=0} <: {v:int | Xa}

{v:int | 0≼ v≺ a.len} list <: {v:int | Xb}

list

Xa[r/v]Æ Xb[i/v]Æ (v=i ∨ v=r) ) Xav=0 ) Xa

0≼ v≺ a.len ) Xb

123

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Solution Xa , Xb = 0≼ v≺ a.len

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Solution Xa , Xb = 0≼ v≺ a.lenTemplates

r : {v:int|Xa}i : {v:int|Xb}

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Solution Xa , Xb = 0≼ v≺ a.lenLiquid Types

r : {v:int| 0≼ v≺ a.len}i : {v:int| 0≼ v≺ a.len}

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Solution Xa , Xb = 0≼ v≺ a.lenLiquid Types

r : {v:int| 0≼ v≺ a.len}i : {v:int| 0≼ v≺ a.len}

Safe

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Solution Xa , Xb = 0≼ v≺ a.lenTemplate of min_index

a:int array ! {v:int | Xa }

let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r )

0 indices

Solution Xa , Xb = 0≼ v≺ a.lenLiquid Type of min_index

a:int array ! {v:int | 0≼v≺ a.len}

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Data (Structure) Properties

Piggyback Predicates On Types

[] ::

{x:int|0<x} listint list0<x Describes all elementsx:int

Representation

[] ::

0<xx:int

Type Unfolding

[] ::

0<hh:int

[] ::

0<xx:int

Head TailEmptyPositive Property holds recursivelyList of positive integers

[] ::

0<x Describes all elementsx:int

x<v v Describes tail elements

Representation

[] ::x<v

x:int

Type Unfolding

[] ::

h:int

[] ::x<v

x:int

Head TailEmptyElements larger than head Property holds recursively

List of sorted integers

h<v

Push Edge Predicate Into NodeRename Variable

h<x

Piggyback Predicates On Types

Data (Structure) Properties

[] ::

x:intUnfold

::

h:int

[] ::

x:int

l:sorted list h:int t:sorted

list & {h<x}

list

Instantiate

tl

match l with

h::t

x<Vx<V

h<x

Quantifier Instantiation

Piggyback Predicates On Types

Data (Structure) Properties

[] ::

x:intFold

h:int

[] ::

x:int

::

l:sorted list h:int t:sorted

list & {h<x}

listGeneralize

tllet l = h::t in

x<Vx<V

h<x

Quantifier Generalization

Another Example: Trees

Leaf

Node

x:int

x<VV<x

Node

Leaf

Node

x:int

Leaf

Node

x:int

Node

Leaf

x<VV<x x<VV<x

r<VV<r

Another Example: Trees

r:int

Unfold

< RHS nodesLHS nodes < root

Node

Leaf

Node

x:int

Leaf

Node

x:int

Node

Leaf

x<VV<x x<VV<x

r<xx<r

Another Example: Trees

r:int

Push Edge Predicates

Invariant: Binary Search Trees

Demoisort,bst

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Piggyback Predicates On Types

(Data) Structure Properties

measure len =| [] -> 0 | x::xs -> 1 + len xs

Representation: List Length

Representation: List Length

8l,x,xs. len([]) = 0 len(x::xs) = 1+len(xs)

Piggyback Predicates On Types

(Data) Structure Properties

l:’a listl:’a listh:’at:’a listlen(l)=1+len(t)

Instantiate

match l with

h::t

Quantifier Instantiation

8l,x,xs. len([]) = 0 len(x::xs) = 1+len(xs)

Piggyback Predicates On Types

(Data) Structure Properties

h:’at:’a list

Quantifier Generalization

8l,x,xs. len([]) = 0 len(x::xs) = 1+len(xs)

Generalize

let l = h::t in h:’at:’a listl:’a listlen(l)=1+len(t)

Demolistlen, msortb

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Leaf

l r

l = Left subtreer = Right subtree

treeHeight

H l = Left subtree’s heightH r = Right subtree’s height

measure H =

| Leaf = 0| Node(x,l,r) = 1 + max (H l) (H r)

Height Balanced Tree

|Hl–Hr|<2

Node

Height difference bounded at each node

Demoeval

Refinement Type InferenceBy Predicate Abstraction

0<x

[] ::

x:int

x<v

Automatic Inference

Predicates Determine InvariantLet X1, X2, ... = Unknown Predicates

Complex Subtyping Between data types

X1

X2

Reduces To Simple Implications Between X1, X2, ...

Solved by Predicate AbstractionOver atoms 0<⋆, ⋆<v, ...

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Program (ML) Verified Safety PropertiesList-based Sorting Sorted, Outputs Permutation of Input

Finite Map Balance, BST, Implements a SetRed-Black Trees Balance, BST, Color

Stablesort SortedExtensible Vectors Balance, Bounds Checking, …

Binary Heaps Heap, Returns Min, Implements SetSplay Heaps BST, Returns Min, Implements Set

Malloc Used and Free Lists Are AccurateBDDs Variable Order

Union Find AcyclicityBitvector Unification Acyclicity

Finite Maps (ML)5: ‘cat’

3: ‘cow’ 8: ‘tic’

1: ‘doc’ 4: ‘hog’ 7: ‘ant’ 9: ‘emu’From Ocaml Standard Library

Implemented as AVL TreesRotate/Rebalance on Insert/Delete

Verified InvariantsBinary Search Ordered

Height BalancedKeys Implement Set

Binary Decision Diagrams (ML)X1

X2 X2

X3

X4 X4

1

Graph-Based Boolean Formulas [Bryant 86]

X1ÛX2 Ù X3ÛX4 Efficient Formula Manipulation

Memoizing Results on SubformulasVerified Invariant

Variables Ordered Along Each Path

Vec: Extensible Arrays (317 LOC)

“Python-style” extensible arrays for Ocamlfind, insert, delete, join

etc.

Efficiency via balanced trees

Balanced

Height difference between siblings ≤ 2

Dsolve found balance violation

Debugging via Inference

Using Dsolve we found

Where imbalance occurred

(specific path conditions)

How imbalance occurred

(left tree off by up to 4)

Leading to test and fix

Part I

Part II

Part III

Refinement Types

Closures, Collections, Generics

Induction for Data Structures

Take Home LessonsWhy is Verification difficult?Complex “Invariants”

How to represent invariants? Factor into liquid type

How to infer liquid type?Subtyping + Predicate Abstraction

“Back-End” LogicConstraint Solving

Rich Decidable Logics Predicate Discovery…

Much Work Remains…

“Front-End” TypesDestructive Update

ConcurrencyObjects & Classes

Dynamic Languages…

Much Work Remains…

User InterfaceThe smarter your analysis,

the harder to tell why it fails!

Much Work Remains…

DetailsOcaml (Pure functional)[PLDI 08] “Liquid Types”

[PLDI 09] “Type-based Data-Structure Verification”

Constraint Solving [CAV 11] “Hindley-Milner-Cousots”

C (Pointers/Arithmetic, Aliasing, Mutation)[POPL 10] “Low-level Liquid Types”

POPL Lightning Talk/DemoOcaml (Pure functional)[PLDI 08] “Liquid Types”

[PLDI 09] “Type-based Data-Structure Verification”

Constraint Solving [CAV 11] “Hindley-Milner-Cousots”

C (Pointers/Arithmetic, Aliasing, Mutation)[POPL 10] “Low-level Liquid Types”

Patrick Rondon (PhD ’12)Demo + Lightning Talk

http://goto.ucsd.edu/liquidsource, papers, demo, etc.

Program Lines DMLAnnot.

LiquidAnnot.

LiquidTime(s)

dotprod 7 3 0 0.3bsearch 24 3 0 0.5queens 30 7 0 0.7

insersort 33 12 0 0.9tower 36 8 1 3.3

matmult 43 10 0 1.8heapsort 84 11 0 0.5

fft 107 13 1 9.1simplex 118 33 0 7.7

gauss 142 22 1 3.1Total 632 125 3 27.9

Evaluation: Array Bounds Checking

Evaluation: Array Bounds Checking

DML @ 20% LOCvs.

Liquid @ 0.5% LOC

The end

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Template of “then”-expression{v:int|Xout} list

Check: “head” and “tail” as requiredl≺ u ⊢ “head” <: {v:int|Xout}l≺ u ⊢ “tail” <: {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “head” as requiredl≺ u ⊢ {v:int|v=l} <: {v:int|Xout}

l≺ u Æ v=l ) Xout

Reduces To1

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required

Template of rangel:int ! u:int ! {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required

Template of range (l+1)u:int ! {v:int| Xout [l+1/l]} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required

Template of range (l+1) u{v:int| Xout [l+1/l][u/u]} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required

Template of range (l+1) u{v:int| Xout [l+1/l]} list

{Xout [l+1/l]} list <: then-“tail”

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required{Xout [l+1/l]} list <: then-“tail”

Template of “then”-expression{v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required{Xout [l+1/l]} list <: {Xout } list

Template of “then”-expression{v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required{Xout [l+1/l]} list <: {Xout } list

Template of rangel:int ! u:int ! {v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required{Xout [l+1/l]} list <: {Xout } list

Template of “then”-expression{v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required{Xout [l+1/l]} list <: {Xout } list

Template of “then”-expression{v:int|Xout} list

let rec range l u = if l < u then l :: (range (l+1) u)

else []

Check: “tail” as required{Xout [l+1/l]} list <: {Xout } list

Template of “then”-expression{v:int|Xout} list

top related