310 likes | 420 Views
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!.
E N D
Certified Correctness for Higher-order Programs Nikhil Swamy Microsoft Research, Redmond
Many recent successes for semi-automated verifiers Spec# Why3 Boogie VeriFast Vampire Simplify CVC4
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) { .. })
Higher-order verifiers ~interactive proof assistants Agda NuPRL… Very expressive logics! :-) Impoverished programming languages Pure total functions only :-(
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
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
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)
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 | …
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
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
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
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?
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
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
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
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
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
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
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
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
Src.fst • F* • typechecker • Type-checker • in F* Z3 Theorem: If src.fsttypechecks then it does not go wrong.
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
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
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)
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* • …
http://research.microsoft.com/fstar/ CERTIFIED Try it out … happy to help you get started!