View
215
Download
0
Tags:
Embed Size (px)
Citation preview
Higher-Order VerificationWith Liquid Types
Ranjit Jhala, UC San Diego(with Pat Rondon, Ming Kawaguchi)
Part IFirst-Order Verification
Part IIHigher-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;}
First-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;}
Example: Memory Safety
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;}
assert (0<=i && i<n);
0:
1: 2:
How to prove assert never fails ?
assert (i<n);
0: i = 0; j = n–1; 1: while (0<=j){ 2: assert(i<n); i = i+1; j = j–1; }Access Within Array Bounds
How to prove asserts?Invariants [Floyd-Hoare]
Invariants
Predicate that is always true@ Program Location
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
true
i+j=n-1
i+j=n-1 Æ 0·j
Invariant Proves Assert
How to Prove Asserts?How to Find Invariants?
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
?
What are Invariants ?
??
What are Invariants ?
Let Xi = Invariant @ location i
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
?
What are Invariants ?
??
X0
X1
X2Properties of X0,X1,X2?
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
What are Invariants ?
X0
Initial Values ArbitraryX0= true
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
What are Invariants ?
i=0 Æ j=n-1 )
X1
true
X1
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
What are Invariants ?
0·j Æ X1 ) X2
X1X2
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
What are Invariants ?
X2 ) i<n
X2
0: i = 0; j = n–1; 1: while (0<=j){
2: assert(i<n);
i = i+1; j = j–1; }
What are Invariants ?
i=io+1 Æ j=jo-1 Æ [io/i][jo/j]X2 )
X1
X1X2
What are Invariants ?
… Æ [io/i][jo/j]X2 ) X1
Predicates X1, X2 s.t.
i=0 Æ j=n-1 ) X1
0·j Æ X1 ) X2
X2 ) i<n
What are Invariants ?
… Æ [io/i][jo/j]X2 ) X1
Predicates X1, X2 s.t.i=0 Æ j=n-1 ) X1
0·j Æ X1 ) X2
X2 ) i<n
How to Infer Invariants? How to Solve for X1, X2? Idea: Lazy Abstraction
Idea: Lazy AbstractionTree of executions over atomic predicates
i+j=n-10·j
Nodes: X1, X2
Edges: X1 ) X2
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
Lazy Predicate Abstraction
X0 trueTree Root Root X (i.e. non-RHS)
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·j
Lazy Predicate Abstraction
X0 true
X1
Tree Edge“Unrolled” Implication
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·j
Lazy Predicate Abstraction
X0 true
X1
Theorem Prover
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·j
?i=0 Æ j=n-1Ætrue
)i+j=n-1
Valid
Lazy Predicate Abstraction
X0 true
X1i+j=n-1
Theorem Prover
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·j
i=0 Æ j=n-1Ætrue
)0·j
Invalid
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
?
Lazy Predicate Abstraction
X0 true
X1i+j=n-1
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·jX2 i+j=n-1 Æ 0·j?
Lazy Predicate Abstraction
X0 true
X1i+j=n-1
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·jX2 i+j=n-1 Æ 0·j
i<n
Theorem Prover0·j Æ i+j=n-1 )i<n
Valid
Lazy Predicate Abstraction
X0 true
X1i+j=n-1
X2
X1 i<n?
i+j=n-1 Æ 0·j
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·j
i+j=n-1
Lazy Predicate Abstraction
X0 true
X1i+j=n-1
X2
X1 i<n
i+j=n-1 Æ 0·j
… [io/i][jo/j]X2 ) X1
0·j Æ X1 ) X2
X2 ) i<n
i=0 Æ j=n-1Æ X0 )
X1
Atoms: i+j=n-1, 0·j
i+j=n-1
FixpointStop UnrollingInferred InvariantsProved Asserts…Constraints Solved
…not so fast!
C Program+
Asserts
Lazy Abstraction[popl 02]
Atoms
Safety Invariants
How to get good atoms?e.g. i+j=n-1
If we have bad atoms...e.g. i=0, j=n-1, 0·j
X2 i<n
X0true
X1i=0 Æ j=n-1
X2
X1
i<ni=0 Æ j=n-1 Æ 0·j
true
true
…Yields Counterexample “Path”Abstraction With Bad Atoms...
Assert Holds
Not a fixpoint
Assert Fails
i:=0j:=n–1
0<=j?
i:=i+1j:=j-1
0<=j?
Bad atoms yield counterexample paths
C Program+
Asserts
Lazy Abstraction[popl 02]
Atoms Path
Safety Invariants
CounterexampleAnalysis
UnsafePaths
“Counterexample Guided Abstraction Refinement”[Kurshan 94, Clarke et al. 00, Ball & Rajamani 00]
Path Atoms
X2
i<n
X0
X1
X2
X1
i:=0j:=n–1
0<=j?
i:=i+1j:=j-1
0<=j?
Path AtomsFormula Proof
Good AtomsRelationships from pastProve safety of future
i:=0j:=n–1
0<=j?
i:=i+1j:=j-1
0<=j?
How to computegood atoms from paths?
Path AtomsFormula Proof
Æ i0 = 0
Æ j0 = n–1Æ 0 · j0
Æ i1 = i0 + 1
Æ j1 = j0 - 1Æ n · i1 ¸
Æ 0 · j1
Negate Assert
RenameVariables
(SSA)
Formula Unsatisfiable iff Assert Holds
X2
i<n
X0
X1
X2
X1
i:=0j:=n–1
0<=j?
i:=i+1j:=j-1
0<=j?
Path AtomsFormula Proof
Æ i0=0
Æ j0=n–1
Æ 0·j0
Æ i1=i0+1
Æ j1=j0-1
Æ n·i1
Æ 0·j1
Æ i0 = 0
Æ j0 = n–1Æ 0 · j0
Æ i1 = i0 + 1
Æ j1 = j0 - 1Æ i1 ¸ n
Æ 0 · j1
0·j1
j1=j0-1
j0=n-1
n·i1
i1=i0+1
i0=0
0·j0-1
0·n-2
0·-1
n·i0+1
n·1
False
X2
i<n
X0
X1
X2
X1
i:=0j:=n–1
0<=j?
i:=i+1j:=j-1
0<=j?
+
+
+
+
+
Path AtomsFormula Proof
0·j1
j1=j0-1
j0=n-1
n·i1
i1=i0+1
i0=0
0·j0-1
0·n-2
n·i0+1
n·1
False
+
+
+
+
+
Good AtomsRelationships from pastProve safety of future+ i+j=n-1
Atom = Craig InterpolantOf Past, Future FormulasExtracted from proof
Of path unsatifiabilityInferred Good Atomi+j=n-1X2
i<n
X0
X1
X2
X1
0<=j?
i:=0j:=n–1
0<=j?
i:=i+1j:=j-1
0<=j?
RecapHow to verify safety ?Compute invariants X1, X2 ...
How to solve for X1, X2 ... ?Tree of executions over atoms
How to find good atoms ?Interpolants of path formulas
RecapSafety
Invariants
Implications
AI, PA, CEGAR,…
X0 , X1
X0 ) X1
Part IFirst-Order (by Logic)
Part IIHigher-Order Verification
Key Problem: Invariants for…
Collections?Closures?
Polymorphism?Recursive Data?
Idea: Logically Qualified TypesFactor Invariant to Logic x Type
Idea: Liquid Types
LogicDescribes Individual Data
TypeQuantifies over Structure
factored into
8i: 0 ·i<table.length )-1· table[i]
table :: {v:int|-1 · v} array
Type Logic
factored into
8x: next*(root,x) )-1 · x.data
root :: {v:int|-1 · v} list
Type Logic
Pre-Condition x:’a array
-> {v:int|0·v< len x}-> ’a
Functions: Array.get
Post-Condition
’a array
-> int-> ’a
int-> int-> (int-> unit) -> unit
Higher-Order: ffor
lo:int-> hi:{int|lo·v}-> ({v:int|lo·v<hi}->
unit) -> unit
LogicDescribes Individual Data
TypeQuantifies over Structure
Theorem ProverReasoning about Individual Data
Type SystemQuantified Reasoning about Structure
Demo“Map-Reduce”
“Map-Reduce”map :: (e -> (k, v) list) -> e list -> (k, v) list
group :: (k, v) list -> (k, v list)
tablereduce :: (v -> v -> v) -> (k, v list)
table -> (k, v) table
K-Means Clustering
0. Choose K Centers Arbitrarily
1. (Map) Points to Nearest Center
2. (Group) Points by Center
3. (Reduce) Centroids into New Centers
Repeat 1,2,3 Until Convergence
DemoK-Means via Map-Reduce
Base TypesCollections
ClosuresPolymorphismRecursive Data
let rec ffor l u f =
if l < u then ( f l; ffor (l+1) u f )
Type of f
int ! unitTemplate of f
{v:int|X1}!unit
Liquid Type of f
{v:int|l·v Æ v<u} ! unit
l Flows Into Input of f {v:int|v=l} <: {v:int|X1}
l<u |-
l<u Æ v=l ) X1
Solution X1 = l·v Æ v<u
Reduces to
Base TypesCollections
ClosuresPolymorphismRecursive Data
let nearest dist ctra x = let da = Array.map (dist x) ctra in
[min_index da, (x, 1)]Type of Output
int * ’b * int listTemplate of Output
{v:int | X1} * ’b * {v:int | X2} list
(’a !’b)!x:’a array!{v:’b array|len x = len v}
Liquid Type of
x:’a array!{v:int| 0·v Æ v < len x}
min_index da {v:int| 0·v Æ v < len da}da {v:’b array| len v = len ctra}
len da = len ctra Æ 0·v<len da ) X1
len da = len ctra Æ v=1 ) X2
da:{len v = len ctra}|-{ 0·v<len da} * ’b * {v=1} list <: {X1} * ’b * {X2}
list
Reduces To
Solution X1 = 0·v < len ctra X2 = 0 < v
Liquid Type of Output{v:int|0·v<len ctra}*’b*{v:int|0<v}
list
Base TypesCollections
ClosuresPolymorphismRecursive 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
Liquid Type of ffor 0 (len a)
({v:int|0· v < len a} ! unit)! unit
Template of (fun i ->...)
{v:int|Xi} ! unit
{Xi}!unit <: {0·v<len a}!unit{0·v<len a} unit{Xi} unit
{0·v<len a} <: {Xi}
Reduces To
unit <: unit0· v < len a ) Xi
Solution Xi = 0·v< len a
Liquid Type of (fun i ->...) {v:int|0·v<len a} ! unit
Liquid Type of fforl:int!u:int!({v:int|l·v<u}!unit)!unit
Liquid Type of ffor 0u:int!({v:int|0·v< u} ! unit)! unit
Base TypesCollections
ClosuresPolymorphismRecursive Data
mapreduce (nearest dist ctra) (centroid plus) xs
|> List.iter (fun (i,(x,sz)) -> ctra.(i)<- div x
sz) Type of mapreduce(’a !’b * ’c list) !...! ’b * ’c list
Template of mapreduce(’a ! {X1} * ’a * {X2} list)!...! {X1} * ’a * {X2} list
Type Instantiation ’a with ’a ’b with int
’c with ’a * int
Template Instantiation ’a with ’a
’b with {v:int|X1}
’c with ’a * {v:int|X2}
Liquid Type of (nearest dist ya)’a ! {0 · v < len ctra} * ’a * {0<v} list’a ! {0 · v < len ctra} * ’a * {0<v} list
<:’a ! {X1} * ’a * {X2} list
Solution X1 = 0 · v < len ctra X2 = 0 < v
Reduces To0 · v < len ctra ) X1
0 < v ) X2
Liquid Type of mapreduce Output {0 · v < len ctra} * ’a * {0 < v} list
Polymorphism = “Meta” Invariants
Polymorphism = “Meta Invariants”
foldl :: (a->b-> a)-> a-> b list-> a
Polymorphism = “Meta Invariants”
foldl :: (a->b-> a)-> a-> b list-> a
Initial Value Satisfies a
Polymorphism = “Meta Invariants”
foldl :: (a->b-> a)-> a-> b list-> a
Each “Iteration” Preserves a
Polymorphism = “Meta Invariants”
foldl :: (a->b-> a)-> a-> b list-> a
Hence, Output Satisfies a
Polymorphism = “Meta Invariants”
foldl :: (a->b-> a)-> a-> b list-> a
At callsite instantiate a for invariantAnalysis oblivious to iterated structure
Base TypesCollections
ClosuresPolymorphismRecursive Data
Recursive Data Structures
Data (Structure) Invariants
Piggyback Predicates On Types
[] ::
{x:int|0<x} listint list0<x Describes all elementsx:int
Representation
[] ::
0<x
x:int
Type Unfolding
[] ::
0<h
h:int
[] ::
0<x
x: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) Invariants
[] ::
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) Invariants
[] ::
x:intFold
h:int
[] ::
x:int
::
l:sorted list h:int t:sorted
list & {h<x}
list
Generalize
tl
let l = h::t in
x<Vx<V
h<x
Quantifier Generalization
Demoisort
Recursive Data Structures
Piggyback Predicates On Types
(Data) Structure Invariants
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 Invariants
l:’a list
l:’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 Invariants
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)
Demomsortb
Recursive Data StructuresPiggyback Measures
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
Automatic Liquid Type InferenceBy Predicate Abstraction
0<x
[] ::
x:int
x<v
Automatic Liquid Type 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<x, x<v, ...
Part IFirst-Order (by Logic)
Part IIHigher-Order (by Types)
Take Home LessonsWhy are HO Programs difficult?Complex “invariants”
How to represent invariants? Factor into liquid type
How to compute liquid type?AbsInt/Predicate Abstraction/…
“Back-End” LogicConstraint Solving
Rich Decidable Logics Qualifier 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…
http://goto.ucsd.edu/liquidsource, papers, demo, etc.
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 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
Recursive Rebalance
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