1 / 107

# Higher-Order Verification With Liquid Types - PowerPoint PPT Presentation

Higher-Order Verification With Liquid Types. Ranjit Jhala , UC San Diego (with Pat Rondon , Ming Kawaguchi). Part I. First-Order Verification. Part II. Higher-Order Verification. First-Order Verification. char* rev_copy ( char* a, int n){ i = 0; j = n – 1; b = malloc (n);

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Higher-Order Verification With Liquid Types ' - harry

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

RanjitJhala, UC San Diego

(with Pat Rondon, Ming Kawaguchi)

• First-Order Verification

• Part II

• Higher-Order Verification

char* rev_copy(char* a, int n){

i = 0;

j = n – 1;

b = malloc(n);

while(0<=j){

b[i] = a[j];

i++;

j--;

}

return b;

}

char* rev_copy(char* a, int n){

i = 0;

j = n – 1;

b = malloc(n);

while(0<=j){

b[i] = a[j];

i++;

j--;

}

return b;

}

• Access Within Array Bounds

char* rev_copy(char* a, int n){

i = 0;

j = n – 1;

b = malloc(n);

while(j>=0){

b[i] = a[j];

i++;

j--;

}

return b;

}

0:

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

1:

2:

assert(i<n);

assert(0<=i && i<n);

• Access Within Array Bounds

• How to prove assert never fails ?

• Invariants [Floyd-Hoare]

Invariants

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

true

• Predicate that is always true

• @ Program Location

i+j=n-1

i+j=n-1Æ0·j

• How to Prove Asserts?

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

?

?

?

• Let Xi= Invariant @ location i

?

X0

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

X1

?

• Properties of X0,X1,X2?

X2

?

X0

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

• X0= true

• Initial Values Arbitrary

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

true

X1

• i=0Æj=n-1 )X1

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

X1

X2

0·jÆX1)X2

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

X2

X2)i<n

0: i = 0;

j = n–1;

1: while (0<=j){

2: assert(i<n);

i = i+1;

j = j–1;

}

X1

X2

i=io+1Æj=jo-1Æ[io/i][jo/j]X2)X1

• Predicates X1, X2s.t.

• i=0Æj=n-1 )X1

0·jÆX1)X2

X2)i<n

…Æ[io/i][jo/j]X2)X1

• Predicates X1, X2s.t.

• Idea: Lazy Abstraction

• How to Infer Invariants?

• How to Solve forX1, X2?

• i=0Æj=n-1 )X1

0·jÆX1)X2

X2)i<n

…Æ[io/i][jo/j]X2)X1

• Tree of executions over atomic predicates

i+j=n-1

Nodes: X1, X2

0·j

Edges: X1)X2

Tree Root

Root X(i.e. non-RHS)

X0

true

Atoms: i+j=n-1,0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

X2)i<n

…[io/i][jo/j]X2)X1

Tree Edge

“Unrolled” Implication

X0

true

X1

Atoms: i+j=n-1,0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

X2)i<n

…[io/i][jo/j]X2)X1

Theorem Prover

X0

true

• i=0Æj=n-1Ætrue)

i+j=n-1

Valid

?

X1

Atoms: i+j=n-1,0·j

• i=0Æj=n-1ÆX0)X1

Theorem Prover

X0

true

• i=0Æj=n-1Ætrue)

0·j

?

X1

i+j=n-1

Invalid

Atoms: i+j=n-1,0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

X2)i<n

…[io/i][jo/j]X2)X1

X0

true

X1

i+j=n-1

Atoms: i+j=n-1,0·j

?

X2

i+j=n-1Æ0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

X2)i<n

…[io/i][jo/j]X2)X1

Theorem Prover

X0

true

0·jÆi+j=n-1)

i<n

X1

Valid

i+j=n-1

Atoms: i+j=n-1,0·j

X2

i+j=n-1Æ0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

i<n

X2)i<n

…[io/i][jo/j]X2)X1

X0

true

X1

i+j=n-1

Atoms: i+j=n-1,0·j

X2

i+j=n-1Æ0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

?

X1

i<n

i+j=n-1

X2)i<n

…[io/i][jo/j]X2)X1

X0

true

Proved Asserts…

…not so fast!

Fixpoint

Stop Unrolling

Inferred Invariants

X1

i+j=n-1

• Constraints Solved

Atoms: i+j=n-1,0·j

X2

i+j=n-1Æ0·j

• i=0Æj=n-1ÆX0)X1

0·jÆX1)X2

X1

i<n

i+j=n-1

X2)i<n

…[io/i][jo/j]X2)X1

[popl 02]

Safety

Invariants

C Program

+

Asserts

Atoms

How to get good atoms?

e.g. i+j=n-1

e.g. i=0, j=n-1, 0·j

…Yields Counterexample “Path”

X0

true

i:=0

j:=n–1

X1

i=0 Æ j=n-1

0<=j?

Assert Holds

X2

i<n

i=0Æj=n-1Æ0·j

i:=i+1

j:=j-1

Not a fixpoint

X1

true

0<=j?

Assert Fails

X2

i<n

true

Atoms

Lazy Abstraction

[popl 02]

Safety

Invariants

C Program

+

Asserts

Atoms

Path

Counterexample

Analysis

Unsafe

Paths

“Counterexample Guided Abstraction Refinement”

[Kurshan 94, Clarke et al. 00, Ball & Rajamani 00]

Formula

Proof

Atoms

X0

i:=0

j:=n–1

i:=0

j:=n–1

X1

How to compute

good atoms from paths?

0<=j?

0<=j?

X2

i:=i+1

j:=j-1

i:=i+1

j:=j-1

Good Atoms

Relationships from past

Prove safety of future

X1

0<=j?

0<=j?

X2

i<n

Formula

Proof

Atoms

X0

Æi0 = 0

Æ j0 = n–1

i:=0

j:=n–1

Formula Unsatisfiable

iff

Assert Holds at Path End

X1

Rename

Variables

(SSA)

Æ 0·j0

0<=j?

Æ i1 = i0 + 1

Æ j1 = j0 - 1

X2

i:=i+1

j:=j-1

Æ 0·j1

X1

Negate Assert

0<=j?

Æ n·i1¸

X2

Formula Unsatisfiableiff Assert Holds

i<n

Formula

Proof

Atoms

X0

0·j1

Æi0=0

Æ j0=n–1

Æi0 = 0

Æ j0 = n–1

i:=0

j:=n–1

+

0·j0-1

X1

Æ 0·j0

j1=j0-1

Æ 0·j0

0<=j?

+

0·n-2

Æ i1 = i0 + 1

Æ j1 = j0 - 1

X2

j0=n-1

Æ i1=i0+1

Æ j1=j0-1

i:=i+1

j:=j-1

+

False

0·-1

Æ 0·j1

i0=0

X1

+

0<=j?

n·1

Æ i1¸n

Æ 0·j1

n·i1

X2

+

n·i0+1

Æ n·i1

i1=i0+1

i<n

Formula

Proof

Atoms

Good Atoms

Relationships from past

Prove safety of future

0·j1

+

0·j0-1

j1=j0-1

+

0·n-2

j0=n-1

+

False

i0=0

i+j=n-1

+

+

n·1

n·i1

+

n·i0+1

i1=i0+1

X0

i:=0

j:=n–1

X1

Atom = Craig Interpolant

Of Past, Future Formulas

0<=j?

0<=j?

X2

i:=i+1

j:=j-1

Extracted from proof

Of path unsatifiability

Inferred Good Atom

i+j=n-1

X1

0<=j?

X2

i<n

• How to verify safety ?

• Compute invariantsX1, X2...

• How to solve for X1, X2... ?

• Tree of executions over atoms

• How to find good atoms ?

• Interpolants of path formulas

Safety

Invariants

X0, X1

• Implications

• X0)X1

AI, PA, CEGAR,…

• First-Order (by Logic)

• Part II

Higher-Order Verification

Collections?

Closures?

Polymorphism?

Recursive Data?

• Idea: Logically Qualified Types

• Factor Invariant to Logic x Type

• Logic

• Describes Individual Data

• Type

• Quantifies over Structure

8i:0 ·i<table.length)-1· table[i]

Logic

Type

• factored into

table::{v:int|-1·v}array

8x:next*(root,x))-1·x.data

Logic

Type

• factored into

root::{v:int|-1·v}list

• Pre-Condition

’aarray

->int

-> ’a

x:’aarray

->{v:int|0·v<lenx}

-> ’a

• Post-Condition

• lo:int

• ->hi:{int|lo·v}

• ->({v:int|lo·v<hi}->unit)

• -> unit

• int

• ->int

• ->(int->unit)

• -> unit

• Logic

• Describes Individual Data

• Theorem Prover

• Type System

• Type

• Quantifies over Structure

“Map-Reduce”

• map :: (e -> (k, v) list)

• -> elist

• -> (k, v)list

• group :: (k, v)list

• -> (k, v list)table

• reduce :: (v-> v-> v)

• -> (k, vlist)table

• -> (k, v) table

2. (Group) Points by Center

K-Means via Map-Reduce

• Base Types

• Collections

• Closures

• Polymorphism

• Recursive Data

• Template of f

• {v:int|X1}!unit

let rec ffor l u f =

if l < u then (

f l;

ffor (l+1) u f

)

Solution

X1 = l·vÆv<u

lFlows Into Input of f

{v:int|v=l}<:{v:int|X1}

• l<u|-

Liquid Type of f

{v:int|l·vÆv<u}!unit

Reduces to

l<u Æ v=l)X1

• Base Types

• Collections

• Closures

• Polymorphism

• Recursive Data

let nearest dist ctra x =

let da = Array.map (dist x) ctra in

[min_index da, (x, 1)]

(’a !’b)!x:’aarray!{v:’barray|lenx=lenv}

Type of Output

int*’b*intlist

Template of Output

{v:int|X1}*’b*{v:int|X2}list

Solution

X1 = 0·v<lenctra

X2 = 0<v

Liquid Type of

da:{lenv=lenctra}

|-{0·v<lenda} *’b* {v=1}list <: {X1} *’b* {X2}list

da{v:’b array|lenv=lenctra}

min_indexda{v:int|0·vÆv<lenda}

x:’aarray!{v:int|0·vÆv<lenx}

Reduces To

Liquid Type of Output

{v:int|0·v<lenctra}*’b*{v:int|0<v}list

lenda=lenctraÆ0·v<lenda)X1

lenda=lenctraÆv=1)X2

• Base Types

• Collections

• Closures

• Polymorphism

• Recursive Data

let min_index a =

let min = ref 0 in

ffor 0 (Array.length a) (fun i ->

if a.(i) < a.(!min) then min:=i

); !min

{Xi}

unit

unit

{Xi}!unit<:{0·v<lena}!unit

{0·v<lena}

Solution

Xi = 0·v<lena

Reduces To

Template of (fun i ->...)

{v:int|Xi}!unit

0·v<lena )Xi

{0·v<lena}<:{Xi}

unit<:unit

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

{v:int|0·v<lena} !unit

Liquid Type of ffor

l:int!u:int!({v:int|l·v<u}!unit)!unit

Liquid Type of ffor 0 (len a)

({v:int|0· v<len a}!unit)!unit

Liquid Type of ffor 0

u:int!({v:int|0·v<u}!unit)!unit

• Base Types

• Collections

• Closures

• Polymorphism

• Recursive Data

|> List.iter(fun (i,(x,sz))->ctra.(i)<-divxsz)

Type of mapreduce

(’a!’b*’c list)!...!’b*’clist

Template of mapreduce

(’a! {X1}*’a*{X2}list)!...!{X1}*’a*{X2}list

Liquid Type of (nearest dist ya)

’a! {0·v<lenctra}*’a*{0<v}list

Reduces To

0·v<lenctra ) X1

0<v ) X2

Type Instantiation

’a with’a

’b withint

’c with’a*int

Template Instantiation

’a with’a

’b with{v:int|X1}

’c with’a*{v:int|X2}

Solution

X1=0·v<lenctra

X2=0<v

’a! {0· v<lenctra}*’a*{0<v}list

<:

’a! {X1}*’a*{X2}list

Liquid Type of mapreduceOutput

{0·v<lenctra}*’a*{0<v}list

Polymorphism = “Meta Invariants”

• foldl::(a->b->a)->a->blist->a

Polymorphism = “Meta Invariants”

• foldl::(a->b->a)->a->blist->a

• Initial Value Satisfies a

Polymorphism = “Meta Invariants”

• foldl::(a->b->a)->a->blist->a

• Each “Iteration” Preserves a

Polymorphism = “Meta Invariants”

• foldl::(a->b->a)->a->blist->a

• Hence, Output Satisfiesa

Polymorphism = “Meta Invariants”

• foldl::(a->b->a)->a->blist->a

At callsite instantiate a for invariant

Analysis oblivious to iterated structure

• Base Types

• Collections

• Closures

• Polymorphism

• Recursive Data

• Piggyback Predicates On Types

[]

::

{x:int|0<x}list

intlist

x:int

Describes all elements

0<x

[]

[]

[]

::

::

::

x:int

x:int

h:int

0<x

0<x

0<h

Empty

Tail

List of positive integers

Positive

Property holds recursively

vDescribes tail elements

x<v

[]

::

x:int

Describes all elements

0<x

h<v

x<v

x<v

[]

[]

[]

::

::

::

x:int

x:int

h:int

h<x

Empty

Tail

Push Edge Predicate Into Node

Rename Variable

List of sorted integers

Property holds recursively

• Piggyback Predicates On Types

x<V

x<V

Unfold

l

t

h<x

::

[]

[]

::

::

matchlwithh::t

l:sortedlist

h:int

t:sortedlist

& {h<x}list

x:int

x:int

h:int

Instantiate

• Piggyback Predicates On Types

x<V

x<V

Fold

l

t

h<x

::

[]

[]

::

::

letl=h::tin

l:sortedlist

h:int

t:sortedlist

& {h<x}list

x:int

x:int

h:int

Generalize

isort

• Piggyback Predicates On Types

measure len=

|[] -> 0

|x::xs -> 1+lenxs

8l,x,xs.

len([]) = 0

len(x::xs) = 1+len(xs)

• Piggyback Predicates On Types

8l,x,xs.

len([]) = 0

len(x::xs) = 1+len(xs)

l:’a list

h:’a

t:’a list

len(l)=1+len(t)

matchlwithh::t

l:’a list

Instantiate

• Piggyback Predicates On Types

8l,x,xs.

len([]) = 0

len(x::xs) = 1+len(xs)

letl=h::tin

h:’a

t:’a list

l:’a list

len(l)=1+len(t)

h:’a

t:’a list

Generalize

msortb

Piggyback Measures

Height

tree

r

l

Node

|Hl–Hr|<2

Leaf

measure H =

|Leaf= 0

|Node(x,l,r) = 1+max(Hl)(Hr)

• H l= Left subtree’s height

• H r= Right subtree’s height

• l = Left subtree

• r = Right subtree

Height difference bounded at each node

eval

• Automatic LiquidType Inference

• By Predicate Abstraction

Complex Subtyping

Between data types

X2

x<v

[]

::

x:int

Reduces To Simple Implications

Between X1, X2,...

X1

0<x

Let X1, X2, ... = Unknown Predicates

• Predicates Determine Invariant

Solved by Predicate Abstraction

Over atoms 0<x,x<v,...

• First-Order (by Logic)

• Part II

Higher-Order (by Types)

• Why are HO Programs difficult?

• Complex “invariants”

• How to represent invariants?

• Factor into liquidtype

• How to compute liquidtype?

• AbsInt/Predicate Abstraction/…

“Back-End” Logic

Constraint Solving

Rich Decidable Logics

Qualifier Discovery…

“Front-End” Types

Destructive Update

Concurrency

Objects & Classes

Dynamic Languages…

User Interface

the harder to tell why it fails!

• source, papers, demo, etc.

5: ‘cat’

3: ‘cow’

8: ‘tic’

• From Ocaml Standard Library

1: ‘doc’

4: ‘hog’

7: ‘ant’

9: ‘emu’

• Verified Invariants

• Binary Search Ordered

• Height Balanced

• Keys Implement Set

• Implemented as AVL Trees

• Rotate/Rebalance on Insert/Delete

X1

X2

X2

• Graph-Based Boolean Formulas [Bryant 86]

X3

X4

X4

1

• Efficient Formula Manipulation

• Memoizing Results on Subformulas

• Verified Invariant

• Variables Ordered Along Each Path

X1ÛX2 Ù X3ÛX4

Vec: Extensible Arrays (317 LOC)

“Python-style” extensible arrays for Ocaml

find, insert, delete, join etc.

Efficiency via balanced trees

Balanced

Height difference between siblings ≤ 2

Dsolve found balance violation

fatal off-by-one error

Using Dsolve we found

Where imbalance occurred

(specific path conditions)

How imbalance occurred

(left tree off by up to 4)