Tachio Terauchi Nagoya University

22
Relatively Complete Verification of Higher-Order Programs (via Automated Refinement Type Inference) Tachio Terauchi Nagoya University

description

Relatively Complete Verification of Higher-Order Programs (via Automated Refinement Type Inference). Tachio Terauchi Nagoya University. TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: A A A A A A A A A. Verifying higher-order functional programs. - PowerPoint PPT Presentation

Transcript of Tachio Terauchi Nagoya University

Page 1: Tachio  Terauchi Nagoya University

Relatively Complete Verification of Higher-Order Programs

(via Automated Refinement Type Inference)

Tachio TerauchiNagoya University

Page 2: Tachio  Terauchi Nagoya University

Verifying higher-order functional programs

let rec F x c = c x inand G x y = assert x+1 ¸ y; F (y+1) (G y) inand Main w = F (w+1) (G w)

Show : 8w:int. Main w is assertion safe

• Refinement types approach:• F : x:int -> c:({u|u ¸ x} -> *) -> *• G : x:int -> y:{u|x+1 ¸ y} -> *• Main: w:int -> *

Page 3: Tachio  Terauchi Nagoya University

Much recent work on automated inference• Liquid types [Rondon, Kawaguchi, Jhala PLDI’08]• Dependent type inference with interpolants [Unno,

Kobayashi PPDP’09]• Dependent types from counterexamples [Terauchi POPL’10]• Predicate abstraction and CEGAR for higher-order model

checking [Kobayashi, Sato, Unno PLDI’11]• HMC: Verifying functional programs using abstract

interpreters [Jhala, Majumdar, Rybalchenko CAV’11]• “?” [Jagannathan 2011]• Leverages advances in first-order program

verification: – predicate abstraction, interpolation, CEGAR, SMT solvers,

Test generation, etc.• “Model Checkers” for higher-order programs

Incomplete

Page 4: Tachio  Terauchi Nagoya University

Completeness and Incompleteness

• Def: Refinement type system is sound iff– If a program is typable then it is safe.

• Def: Refinement type system is complete iff– A program is typable iff it is safe.

• Existing refinement type systems are sound, but incomplete– Different from incompleteness of inference algorithms

Page 5: Tachio  Terauchi Nagoya University

Relative Completeness

• Higher-order program verification is undecidable– Because it contains 1st-order program verification

• Complete verification for 1st-ord programs– E.g., Hoare logic– Relative to expressive 1st-ord theory like PA

• Allow arbitrary PA formulas as refinement predicates? i.e., { u | µ } µ 2 PA– Sufficient for ord-1 programs– Not for general higher-order programs

Page 6: Tachio  Terauchi Nagoya University

Refinement types incompleteness in detail• Problem: Higher-order functions

• A typical relative completeness proof of Hoare logic– wpre(x = e, µ) = µ[x/e]– wpre(s1;s2, µ) = wpre(s1,wpre(s2, µ)) , …– Show the logic (PA) can express wpre(…)– Then, s is safe iff wpre(s,true) = true.

• What’s wpre(f x, µ) where f : int -> * and x : int? • Or wpre(g f, µ) with g : (int -> *) -> * and f : (int -

> *)?

Page 7: Tachio  Terauchi Nagoya University

Weakest pre. of higher-order terms

• Ideally: – wpre(f x, true) = “f x runs safe”– Ex. F f x = f x

• F : f:(int->*)->x:{ u : int | “f u runs safe” }->*– But, ref. pred. inference becomes higher-order

program verification!– To prevent circularity, we only allow 1st-ord formulas

• I don’t have relative completeness for all higer-order programs yet

• I will show: How to get relative completeness for a class that haven’t been covered previously

Page 8: Tachio  Terauchi Nagoya University

Closure Boudedness

• Def: Size of a closure is the number of base-type values captured in the closure

• Def: A program is closure-bounded if its evaluation only generates closures of bounded size

• Def: Closure pattern is a closure with base-type values abstracted– E.g., F (G ®) ® represent infinite number of

closures F (G 0) 0, F (G 0) 1, F (G 1) -1, …– In lambda, ¸x.(y (¸z.z ®) ®), etc.

• Lemma: Closure-bounded iff finite # of patterns

Page 9: Tachio  Terauchi Nagoya University

Contribution

• Relative completeness for closure-bounded programs

• High-level Idea : Environment Passing F c f = c f G x k = k x H x y = assert x · y; F (G y+1) (H y)Main w = F (G w+1) (H w)

Parametrize type of F with G ®, H ®

F : 8a1.8a2.c:(({u|µ1}->*)->*)->f:({u|µ2} ->*) ->*

Intersection types to handle different contexts

(this example needs none)

Show: 8w:int. Main w as safe

Page 10: Tachio  Terauchi Nagoya University

Details

• Naïve Approach :– Symbolically evaluate the program for n steps

and record closure patterns seen– Build type shapes from the patterns– Check if typable restricted to the type shapes– If not typable, increase n and repeat– (In parallel) check for unsafety

Page 11: Tachio  Terauchi Nagoya University

Symbolic Eval => Closure Patterns

• Patterns A := F | ® | F A– Ex.

• Evaluate from M with w : int• Patterns: F (G ®) ®, …

F c x = c xG x y = assert x+1 · y ; F (G y) (y+1) M w = F (G w) (w+1)

Page 12: Tachio  Terauchi Nagoya University

Patterns => Type shapes

• Types t := * | x:t -> t | {u|µ} | 8x.t | [A].t Æ [A].t• Type shapes = N £ types with µ erased

– E.g., (3, f:{u|_}->*)

• ord(A) = order of simple type of A • A => (v,t’) inductively on the order of A

– Ex. A = F : – Seen patterns: F (G ®) ®, F (H ® ®) ®, …– ty(F) = (0, [(G ®), ®].8a1.t1->®.s->* Æ [(H ® ®),

®].8a18a2.t2->®.s->*)– ty(®) = (0,s), ty(G ®) = (1,t1), ty(H ® ®) = (2, t2), …

Page 13: Tachio  Terauchi Nagoya University

Checking typability

• Shapes & patterns => derivation structure– For each F, have patterns A1, …, An for its args– Make type derivation per F, Ai– Ex. Patterns : F (G ®) (K ®) ® for F c f x = c f x

• Track concrete patterns: c: G a1, f: K a2, x: x, …, up to base-type parameter variables

• At function applications– Look up ty(...) for matching abstract patterns– Instantiate with captured base-type variables– Use “top” type to handle unmatched shapes

• Infer satisfying assignment for µ’s– If none found, fail

Page 14: Tachio  Terauchi Nagoya University

Summary of naïve approach

• Symbolically evaluate the program for n steps and record closure patterns seen

• Build type shapes from the patterns• Check if typable restricted to the type shapes• If not typable, increase n and repeat• (In parallel) check for unsafety

• Thm: This is rel. comp. for closure-bounded programs– Pf. Like that of Hoare logic. “Thread” weakest

precondition through the type derivation.• Cor: 1st-order program verification can be “lifted”

to closure-bounded higher-order program verification

Page 15: Tachio  Terauchi Nagoya University

Naïve approach

• Relatively complete but not very clever– Patterns sufficient but not always necessary– Fails for non-closure-bounded programs

• Better approach: – Try type inference w/o patterns– If type inference fails, then infer patterns– Repeat with the added patterns

– Also, just add candidate 8x.t, e[e’] and have type inf. alg. figure out the rest (i.e., rid patterns from type inference)

Page 16: Tachio  Terauchi Nagoya University

Check typability w/o patterns

• Leverage existing algorithms– Liquid types [Rondon, Kawaguchi, Jhala PLDI’08]– Dependent type inference with interpolants [Unno,

Kobayashi PPDP’09]– Dependent types from counterexamples [Terauchi

POPL’10]– Predicate abstraction and CEGAR for higher-order

model checking [Kobayashi, Sato, Unno PLDI’11]– HMC: Verifying functional programs using abstract

interpreters [Jhala, Majumdar, Rybalchenko CAV’11]

Page 17: Tachio  Terauchi Nagoya University

A) Use the symbolic evaluation as in naïve

B) Or use counterexample from type inference

[Terauchi POPL’10][Kobayashi, Sato, Unno PLDI’11]– Unwound program slice without recursion– Infer patterns that occur in slice via flow

analysis

If inference fails, infer patterns

Page 18: Tachio  Terauchi Nagoya University

Check typability with the added patterns• Like the naïve approach, but• Instead of using the patterns

– i.e., c : G w, …, and [(G ®), ®].8x.t1->®.s->*, …, etc.

• Use the built type shapes minus the patterns– c : 8x.{u | _} -> *, … – And how to instantiate them– Let backend type inference alg. resolve type

matching (as well as µ inference)• Implement as program translation

Page 19: Tachio  Terauchi Nagoya University

Program Translation

• Universal types 8x.t modeled by x:int -> t• Instantiations e[e’] modeled by e e’ F c f = c f G x k = k x H x y = assert x · y main w = F (G w) (H w)

F a1 a2 c f = c f G x k = k x H x y = assert x · y main w = F w (G w) w (H w) ty(F) = (nil,8a1.8a2.c:(({u|_}->*)->*)->f:({u|_} ->*) -

>*)ty(G ®) = ([w],…)ty(H ®) = ([w],…)

Multiple trans. when ty(…) has intersection types(none needed for this example)

Page 20: Tachio  Terauchi Nagoya University

Summary of translation approach

• Try type inference w/o patterns• If type inference fails, then infer patterns• Repeat with the added patterns

• Uses off-the-shelf refinement type inference algorithms

• Complete relative to– Underlying refinement type inference

• And pattern generation– Incomplete in practice (obviously)

Page 21: Tachio  Terauchi Nagoya University

Preliminary Experimental Results

• Depcegar [Terauchi POPL’10]P rogram T ime (ms) T -P GEN T -T P Multiple

up1direct 33 0.9% 91.7% Nd0up1 36 1.4% 88.2% Ndmax 64 1.2% 90.3% N

nonuni 295 0.7% 92.0% Yunbounded 346 0.9% 94.4% N

Page 22: Tachio  Terauchi Nagoya University

Conclusions

• Relatively complete verification framework for higher-order programs– Based on refinement types– Good for “model checking” like automation

• Frees the backend theorem prover/decision prover from directly reasoning about higher-order functions

– High-level : Environment passing– Theory : Rel. comp. for closure-bounded

programs– Practice: Iterative translation