1 / 31

Certified Correctness for Higher-order Programs

Certified Correctness for Higher-order Programs. Nikhil Swamy Microsoft Research, Redmond. Many recent successes for semi-automated verifiers. Spec#. Why3. Boogie. VeriFast. V ampire. Simplify. CVC4. But, modern languages are pervasively higher-order!.

zahir-ellis
Download Presentation

Certified Correctness for Higher-order Programs

An Image/Link below is provided (as is) to download presentation 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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Certified Correctness for Higher-order Programs Nikhil Swamy Microsoft Research, Redmond

  2. Many recent successes for semi-automated verifiers Spec# Why3 Boogie VeriFast Vampire Simplify CVC4

  3. But, modern languages are pervasively higher-order! Delegates, lambdas, LINQ, RX, … delegate B Func<A,B>(A arg) foreach (var i in L) {…} Lambdas everywhere! JavaScript: Higher-order state everywhere! + AJAX, Event handlers, jQuery, DOM,… Element.addEventListener(ev, function(node){…}) $('li').each(function(index) { .. })

  4. Higher-order verifiers ~interactive proof assistants Agda NuPRL… Very expressive logics! :-) Impoverished programming languages Pure total functions only :-(

  5. Enter F* … http://research.microsoft.com/fstar An ML-like language with an SMT-based dependent type system Fournet Chen Strub Dagand Schlesinger Weinberger Livshits Bhargavan BorgstromChughFredriksonGuha Yang Jeannin Swamy

  6. Term language is core-ML, in a syntax resembling F#/Caml-light valf: x:int -> y:int{y = x + 1} letf x = x + 1 valhd: xs:list'a{xs<>[]} -> 'a lethd = function | x::_ -> x | _ -> raiseNot_found valcounter: unit -> Writer x:int{x >= 0} letcounter = letc = ref 0 in fun () -> c := !c + 1; !c valcompose: (x:'b -> DST 'c (WP_f x)) -> (y:'a -> DST 'b (WF_g y)) -> z:'a -> DST 'c (WP_f . WP_g z) letcompose f g x = f (g x) Type language allows expressing precise, functional properties

  7. valf: x:int -> y:int{y=x+1} letf x = x + 1 F* source Type-checker + Compiler Z3 Type-checker itself in F* Preserve types in .NET (PLDI ’10) class C<‘a::int => *> JS verification by translation to F* (PLDI ’13) rDCIL Interop with C#, VB.NET, F#,… Run on Azure, Windows Phone 7 Java Script Coq rDCIL Type-Checker Z3 Fully abstract compiler to JS (POPL ’13) Self-certified core type-checker (POPL ’12) C#, F#,… rDCIL .NET Virtual Machine F* source: core-ML with dependent refinement types uses SMT solvers to discharge proof obligations (ESOP ‘10, ICFP’11)

  8. int:S int->bool:S nat:S Kinds (>=):int => int => E list:S=> S S S => S (=):'a:S=> 'a => 'a => E E int => S => S array:int=>S=>S int => int => E Types t 0:int fun x->e : int->bool 0:zero fun x->e : int->bool list int int, bool, … int -> bool … array 17 float sz:nat -> init:'a -> array sz'a sz:int -> init:'a -> array sz'a zero = x:int{x = 0} nat = x:int{x >= 0} Expressions e Values v 0, 1, 2,… true, false, … funx -> e let x = e in e' match v with D x -> e ref v | v1 := v2 | !v | …

  9. The four base-kinds/universes of F* {S, E, A, P} P <: E S <: E A <: E E universe All terms, including ghost terms S universe Arbitrary Effectful computation P universe Constructive logic core , total functions A universe Affine types for controlling effects

  10. http://rise4fun.com/FStar/tutorial/guide http://rise4fun.com/FStar/plplY http://rise4fun.com/FStar/FCE http://rise4fun.com/FStar/8Ky http://rise4fun.com/FStar/tutorial/jsStar

  11. Reasoning about effects in monadic F*

  12. Reads and writes the heap Post-condition: Relates pre-heap, result and post-heap heap => 'a => heap => E h = h' on all ref cells except {r1, r2}, and any newly allocated ref cells Pre-condition is a heap predicate (heap => E) Permission to read and write r1, r2 val swap: r1:ref 'a -> r2:ref 'a -> Writer unit (Requires λh. Perm r1 h /\ Perm r2 h) (Ensures λh () h'. Perm r1 h' /\ Perm r2 h' /\ h'[r1]=h[r2] /\ h'[r2]=h[r1]) (Modifies {r1,r2}) let swap r1 r2 = let tmp = !r1 in r1 := !r2; r2 := tmp

  13. Closures and local state letevens () = leti = ref 0 in fun() -> i := !i + 1; 2*!i letevens' () = leti = ref 0 in letj = ref 0 in fun() -> i := !i + 1; j := !j + 1; !i + !j Can we give both the same spec, hiding local state from the client?

  14. Idea: pack the closure with invariant on its local state, hiding the representation from the client Pkg (Perm i) {i} (fun () -> i:=!i+1; 2*!i) : evens_t 'Inv instantiated to Perm i typeevens_t = | Pkg: 'Inv:heap=>E -> fp:refset -> (unit -> Writer int (Requires λh. 'Inv (h|fp)) (Ensures λh i h'.i%2=0/\ 'Inv (h'|fp)) (Modifies fp)) -> evens_t 'Inv is a pre- and post-condition of the closure fp={i}footprint of the local state (h|fp) is the fragment of the heap h whose domain is the set fpof refs Closure returns an even number

  15. letevens () = leti = ref 0 in Pkg (Perm i) {i} (fun() -> i := !i + 1; 2*!i) letevens' () = leti = ref 0 in letj = ref 0 in Pkg (λh. Perm i h /\ Perm j h /\ h[i]=h[j]) {i,j} (fun() -> i := !i + 1; j := !j + 1; !i + !j) The closure owns permission to {i,j}; iand j always hold the same value Both return evens_t … almost there

  16. Return evens_t Ensures that the invariant of evens_t holds on the footprint And that the footprint is fresh valevens, evens’: unit -> Writer evens_t (Requires λh.True) (Ensures λhv h'. Pkg.Inv v (h'| Pkg.fp v) /\ Fresh h (Pkg.fp v)) (Modifies {}) evens_tis a strong sum Can project the existentially bound variables Pkg.Inv: evens_t => heap => E projects the first component of a Pkg value, i.e., the invariant Pkg.fp: evens_t -> refset projects the second component of a Pkg value, i.e., the footprint

  17. To date: nearly 50,000 lines of verified F* code JavaScript source code (browser extensions) Verified library for JavaScript runtime support Solutions to VSTTE ‘11 competition with heavy use of local state PLDI ‘13

  18. But, what does it mean to verify a program in F*, formally?

  19. F* in Coq(simplified) Deep embedding of syntax of F* in Coq Inductive Tipe:= | Tarrow : name -> Tipe -> Tipe -> Tipe | … with Expr:= | Elam : name -> Tipe -> Expr -> Expr | … . Inductive Typing : Env -> Config -> Tipe -> Type := | WFVar: g:Env -> x:name -> t:Tipe -> In g (x,t) –> Typing g (Eval (Var x)) t … Inductive Steps : Config -> Config := | … F* typing relation as an inductive type in Coq 8 mutually recursive judgments, ~65 rules F* op. semantics

  20. Metatheory of F* in Coq(simplified) Theorem Preservation: forallG e e’ t, Typing G e t -> Steps e e’ -> Typing G e’ t. Theorem Progress: forallG e t, Typing G e t -> Value e \/ (exists e’. Steps e e’) Well-typed F* programs do not contain failing assertions

  21. More Metatheory of F* (proved manually) Theorem (Correspondence of the P universe): Terms in F*’s logical core of constructive proofs can be embedded in Coq, and the embedding is a forward simulation Corollary: F*’s logical core of constructive proofs is strongly normalizing E universe P universe A universe Suniverse

  22. But, what about the type checker implementation?

  23. Self-Certification Src.fst • F* checker • programmed • in F# • F* checker • in F* Z3 Theorem? If src.fsttype checks then it does not go wrong. Coq Bootstrap certification

  24. Src.fst • F* • typechecker • Type-checker • in F* Z3 Theorem: If src.fsttypechecks then it does not go wrong.

  25. Correspondence theorem Definitions.fst (F*) type Tipe = .. type Typing = … … Definitions.v (Coq) Inductive Tipe := .. Inductive Typing := … … Kernel type checker: 5,200 lines of F* code organized into 11 modules • check_expr: • G:Env -> e:Expr -> t:Tipe • -> Partial (Typing G e t) Metatheory.v (Coq) Theorem Preservation: … Theorem Progress: … check_expr’s result (if any) is a valid typing derivation F* Coq

  26. Theorem: forallG e t v, Steps (check_expr (embed G) (embed e) (embed t)) (Evalue v) -> Typing G e t Correspondence theorem Definitions.fst (F*) type Tipe = .. type Typing = … … Definitions.v (Coq) Inductive Tipe := .. Inductive Typing := … … Prettyprint as Coq term Typing derivation for check_expr Typing derivation for check_expr • check_expr: • G:Env -> e:Expr -> t:Tipe • -> Partial (Typing G e t) 7.3GB Coq term Took 24 machine-days to check Metatheory.v (Coq) Theorem Preservation: … Theorem Progress: … check_expr’s result (if any) is a valid typing derivation F* Coq

  27. What next? • More bootstrapping • Always elaborating into core F* is expensive • Certify higher-level checkers once and for al • Meta F* in F* • Prove syntactic soundness of F* in F* • (See tutorial on STLC for flavor)

  28. What next? • JavaScript, TypeScript, and friends • Verification of JS/TS source • Fully abstract embedding of Safe TS in JS • Relational F* • A logic for hyperproperties encoded in F* • …

  29. http://research.microsoft.com/fstar/ CERTIFIED Try it out … happy to help you get started!

More Related