Typing Local Control and State Using Flow Analysis

![• • Java. Script [Anderson ’ 05, Heidegger ‘ 09] LISP [Reynolds ’ • • Java. Script [Anderson ’ 05, Heidegger ‘ 09] LISP [Reynolds ’](https://slidetodoc.com/presentation_image_h2/9dd9581f55d2f39372b118da0c0e5595/image-2.jpg)








![var slice = function (arr, start, stop) { var result = []; for (var var slice = function (arr, start, stop) { var result = []; for (var](https://slidetodoc.com/presentation_image_h2/9dd9581f55d2f39372b118da0c0e5595/image-11.jpg)





![Soundness [Preservation]. s c i t eman If e : T and e e’, Soundness [Preservation]. s c i t eman If e : T and e e’,](https://slidetodoc.com/presentation_image_h2/9dd9581f55d2f39372b118da0c0e5595/image-17.jpg)












![Soundness [Preservation] If e : T and e e’, e’ : T [Progress] If Soundness [Preservation] If e : T and e e’, e’ : T [Progress] If](https://slidetodoc.com/presentation_image_h2/9dd9581f55d2f39372b118da0c0e5595/image-30.jpg)






![[Type Pres. ] If e : T and e e’, e’ : T [Type [Type Pres. ] If e : T and e e’, e’ : T [Type](https://slidetodoc.com/presentation_image_h2/9dd9581f55d2f39372b118da0c0e5595/image-37.jpg)


- Slides: 39
Typing Local Control and State Using Flow Analysis Arjun Guha, Claudiu Saftoiu, and Shriram Krishnamurthi
• • Java. Script [Anderson ’ 05, Heidegger ‘ 09] LISP [Reynolds ’ 68, Cartwright ’ 75] Ruby [Furr ’ 09] Scheme [Tobin-Hochstadt ‘ 06] Smalltalk [Suzuki ’ 80] Thorn [Bloom ’ 09] etc. why add types? 2
why we want types for Java. Script documentation verifying security-critical code Caja FBJS 3
untyped code in the wild 4
Union of the two function from. Origin(p) { if (typeof p === "object") { return Math. sqrt(p. x * p. x + p. y * p. y); } else { return Math. abs(p); Object with numeric } x and y fields } Number 5
T = Num | Bool | String | Undef | T T | Any | T … T-> T Explicit | {field: T, …} type annotations (primarily on functions) 6
p: {x: Num, y: Num} Num function from. Origin(p) { if (typeof p === "object") { return Math. sqrt(p. x * p. x + p. y * p. y); } else { return Math. abs(p); p: } {x: Num, y: } Num} p: Num 7
Control Operators if, ? : while, for, do, for in switch, continue, break, label: &&, ||, throw, try catch finally 8
function serialize(val) { switch (typeof val) { case "undefined": case "function": return false; case "boolean": return val ? "true" : "false"; case "number": return "" + val; case "string": return val; } where is case "object"? Any String Bool if (val === null) { return "null"; } var fields = [ ]; for (var p in val) { var v = serialize(val[p]); if (typeof v === "string") { fields. push(p + ": " + v); } } return "{ " + fields. join(", ") + " }"; } 9
function serialize(val) { switch (typeof val) { case "undefined": case "function": return false; case "boolean": return val ? "true" : "false"; case "number": return "" + val; case "string": return val; } implicit case "object" Any String Bool if (val === null) { return "null"; } var fields = [ ]; for (var p in val) { var v = serialize(val[p]); if (typeof v === "string") { fields. push(p + ": " + v); } } return "{ " + fields. join(", ") + " }"; } 10
var slice = function (arr, start, stop) { var result = []; for (var i = 0; i <= stop - start; i++) { result[i] = arr[start + i]; } return result; } slice([5, 7, 11, 13], 0, 2) [5, 7, 11] slice([5, 7, 11, 13], 2) arity mismatch error? 11
arr: Array<a> start: Num stop: Num Undef var slice = function (arr, start, stop) { if (typeof stop === "undefined") { stop = arr. length – 1; stop: Undef } stop: Num var result = []; for (var i = 0; i <= stop - start; i++) { result[i] = arr[start + i]; stop: Num } return result; } slice([5, 7, 11, 13], 0, 2) [5, 7, 11] slice([5, 7, 11, 13], 2) [11, 13] 12
Checks For LOC undefined/null instanceof typeof field-presence Total Checks JS Gadgets ADsafe Python stdlib Ruby stdlib Django Rails 617, 766 2, 000 313, 938 190, 002 91, 999 294, 807 3, 298 0 1, 686 538 868 712 17 45 613 1, 730 647 764 474 40 381 N/A 4 N/A unknown 504 171 348 719 3, 789 95 3, 184 2, 439 1, 867 2, 195 pervasive runtime checks in various scripting languages 13
Moral “Scripting language” programmers use state and non-trivial control flow to refine types 14
A TYPE SYSTEM FOR JAVASCRIPT 15
16
Soundness [Preservation]. s c i t eman If e : T and e e’, This s a ) 0 s e’ : T 1 d 0 e 2 e P n s O is i O h t C E g ( n " i t [Progress] ip r c S Prov a J f o e c n If e : T, e Esstrue… e "Th but • e is a value, or • e’. enot e’ very useful! 17
This is not typeable! function from. Origin(p) { /* {x: Num, y: Num} Num -> Num */ if (typeof p === "object") { return Math. sqrt(p. x * p. x + p. y * p. y); } else { return Math. abs(p); } } 18
function from. Origin(p) { /* {x: Num, y: Num} Num -> Num */ if (typeof p === "object") { var pt = cast p …; return Math. sqrt(pt. x * pt. x + pt. y * pt. y); } else { var pf = cast p …; return Math. abs(pf); } } 19
Casting is an operation between types But Java. Script (and Scheme, Python, …) have only tags Tag = "number" | "string" | … | {field: T, …} "object" | T … -> T "function" 20
function from. Origin(p) { /* {x: Num, y: Num} Num -> Num */ if (typeof p === "object") { var pt = cast p …; return Math. sqrt(pt. x * pt. x + pt. y * pt. y); } else { var pf = cast p …; return Math. abs(pf); } } Should really be called tagof… 21
function from. Origin(p) { /* {x: Num, y: Num} Num -> Num */ if (typeof p === "object") { var pt = tagcheck(set("object"), p); return Math. sqrt(pt. x * pt. x + pt. y * pt. y); } else { var pf = tagcheck(set("number"), p); return Math. abs(pf); } } 22
Introducing tagcheck R e Set of tags An expression Reduce e to value v Let t be the typeof (i. e. , the tag of) v If t is in R, return v; else error (tagerr) 23
runtime : Type 2 Tag static : 2 Tag Type 24
static : 2 Tag Type Given a set of tags… …and a type… …pick out the parts of the type that correspond to the tags static(set("string", "bool"), Str Num Bool) = Str Bool static(set("object"), {x: Num, y: Num} Num)) = {x: Num, y: Num} 25
Determine static type, identify presumed run-time tags, narrow type based on these two… …that’s the resulting static type 26
static(set("string"), Num Str set("string") Num Str) Str 27
function from. Origin(p) { /* {x: Num, y: Num} Num -> Num */ if (typeof p === "object") { var pt = tagcheck(set("object"), p); return Math. sqrt(pt. x * pt. x + pt. y * pt. y); } else { var pf = tagcheck(set("number"), p); return Math. abs(pf); } } 28
tagcheck Failure Modes tag set R is inconsistent with the type S actual run-time tag is simply not contained in R resulting type T is inconsistent with the context’s needs 29
Soundness [Preservation] If e : T and e e’, e’ : T [Progress] If e : T, • e is a value, or • e’. e e’, or • e = E[tagerr ] 30
1. How to prevent programs from resulting in the new run-time error (tagerr)? 2. Who’s going to write tagchecks? 31
FLOW ANALYSIS 1. Value sets are about tags, not values 2. Only inside procedures; halts at calls 3. Intermediate representation (CPS, ANF, SSA, …) 32
p = {"object", "number"} p = runtime({ x: Num, y: Num } Num) t 1 = typeof p p = {"object", "number"} t 2 = t 1 === "object" function from. Origin(p) { /* {x: Num, y: Num } Num -> Num */ var t 1 = typeof p; var t 2 = (t 1 === "object"); if (t 2) { var t 3 = p. x; var t 4 = p. x; p = {"object"} var t 5 = t 3 * t 4; var t 6 = p. y; var t 7 = p. y; t 1 = typeof p var t 8 = t 6 * t 7; t 2 = true var t 9 = t 5 + t 8; return Math. sqrt(t 9); p = {"number"} } else { t 1 = typeof p return Math. abs(p); } t 2 = false 33 }
function from. Origin(p) { /* {x: Num, y: Num } Num -> Num */ var t 1 = typeof p; var t 2 = (t 1 === "object"); if (t 2) { var t 3 var t 5 var t 6 var t 8 var t 9 return } else { p = {"object"} t 1 = typeof p t 2 = true p = {"number"} t 1 = typeof p = p. x; var t 4 = p. x; = t 3 * t 4; = p. y; var t 7 = p. y; = t 6 * t 7; = t 5 + t 8; Math. sqrt(t 9); return Math. abs(p); t 2 = false } } 34
p = {"object"} t 1 = typeof p t 2 = true p = {"number"} t 1 = typeof p t 2 = false function from. Origin(p) { /* {x: Num, y: Num } Num -> Num */ var t 1 = typeof p; var t 2 = (t 1 === "object"); if (t 2) { var pt = tagcheck(set("object"), p); var t 3 = pt. x; var t 4 = pt. x; var t 5 = t 3 * t 4; var t 6 = pt. y; var t 7 = pt. y; var t 8 = t 6 * t 7; var t 9 = t 5 + t 8; return Math. sqrt(t 9); } else { var pf = tagcheck(set("number"), p); return Math. abs(pf); } } 35
p = runtime({ x: Num, y: Num } Num) = {"object", "number"} function from. Origin(p) { /* { x: Num, y: Num } Num -> Num */. . . } actual arguments ignored by flows from. Origin(500) from. Origin({ x : 20, y: 900 }) from. Origin("invalid argument") therefore, invalid arguments ignored too! 36
[Type Pres. ] If e : T and e e’, e’ : T [Type Prog. ] If e : T, • e is a value, or • e’. e e’, or • e = E[tagerr] [Flow Soundness] If e : ok and e e’, • e’ : ok, or • e is a βv redex (func(x) : T … { return e })(v) tagof(v) runtime(T) Combined Soundness for Types and Flows 37
Our Recipe Simple type checker (not quite enough) Add tagcheck (breaks progress) Simple flow analysis (w/ preservation broken) “Types on the outside, flows on the inside” The composition is sound The performance is great (seconds on netbook) 38
Verifying Web Sandboxes Types as Documentation for Java. Script programs Typing Objects (in progress) Typing Local Control and State (ESOP 2011) Java. Script Semantics (ECOOP 2010) 39