# Typing Local Control and

Λογισμικό & κατασκευή λογ/κού

4 Νοε 2013 (πριν από 4 χρόνια και 8 μήνες)

74 εμφανίσεις

Typing Local Control and
State Using Flow Analysis

Arjun Guha, Claudiu Saftoiu, and
Shriram Krishnamurthi

1

2

JavaScript [Anderson ’05, Heidegger ‘09
]

LISP [Reynolds ’68, Cartwright ’75]

Ruby [
Furr

’09
]

Scheme
[Tobin
-

‘06
]

Smalltalk [Suzuki ’80
]

Thorn [Bloom ’09]

etc.

why we want types for JavaScript

3

verifying security
-
critical
code

documentation

Caja

FBJS

untyped

code in the wild

4

function
fromOrigin
(p) {

if (
typeof

p === "object") {

return
Math.sqrt
(
p.x

*
p.x

+
p.y

*
p.y
);

} else {

return Math.abs(p);

}

}

5

Object with numeric

x

and
y

fields

Number

Union of the two

T =
Num
|
B
ool

|
String |
Undef

| T

T | Any

| T

T
-
>
T

| {field: T, …}

6

Explicit

type

annotations

(primarily on

functions)

function
fromOrigin
(p) {

if (
typeof

p === "object
"
) {

return
Math.sqrt
(
p.x

*
p.x

+
p.y

*
p.y
);

} else {

return Math.abs(p);

}

}

7

p:

{x: Num, y: Num}

p:
Num

p: {x:
N
um, y: Num}

Control Operators

if
,
?:

while
,
for
,
do
,
for in

switch
,
continue
,
break
,
label:

&&
,
||
,
throw
,
try catch finally

8

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
(", ") +

" }";

}

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
;

}

9

Any

String

Bool

where is
case
"
object"
?

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
;

}

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

Any

䉯潬

implicit

case "object"

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)

11

a
rity

mismatch
error?

var

slice = function (
arr
, start, stop) {

if (
typeof

stop === "undefined") {

stop =
arr.length

1;

}

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)

[11, 13]

12

stop:
Undef

stop:
Num

stop:
Num

㨠䅲牡礼愾

Checks For

JS

Python
stdlib

Ruby
stdlib

Django

Rails

LOC

617,766

2,000

313,938

190,002

91,999

294,807

undefined/null

3,298

0

1,686

538

868

712

instanceof

17

45

613

1,730

647

764

typeof

474

40

381

N/A

4

N/A

field
-
presence

unknown

unknown

504

171

348

719

Total Checks

3,789

95

3,184

2,439

1,867

2,195

13

pervasive runtime checks in
various scripting languages

Moral

“Scripting language”
programmers

use state and

non
-
trivial control flow

to refine types

14

A T
YPE

S
YSTEM

FOR

J
AVA
S
CRIPT

15

16

Soundness

[
Preservation
]

If
e

: T and
e

e’
,

e’

: T

[
Progress
]

If
e

: T,

e

is a value, or

e’

.
e

e’

17

This

is

true…

but

not very useful
!

function
fromOrigin
(p) {

/* {x: Num, y: Num}

-
㸠乵>

if (
typeof

p === "object
"
) {

return
Math.sqrt
(
p.x

*
p.x

+
p.y

*
p.y
);

} else {

return Math.abs(p);

}

}

18

This is
not

typeable
!

19

function
fromOrigin
(p) {

/* {x: Num, y: Num}

-
㸠乵>

"
⤠)

††

pt = cast p …;

return
Math.sqrt
(
pt.x

*
pt.x

+
pt.y

*
pt.y
);

} else {

var

pf

= cast p …;

return Math.abs(
pf
);

}

}

Casting

Casting is an operation between
types

But JavaScript (and Scheme, Python, …)

have only
tags

Tag = "number
"

| "string" | …

| {field: T, …}

"object
"

| T

-
> T

"
function"

20

Should really be

called
tagof

21

function
fromOrigin
(p) {

/* {x: Num, y: Num}

-
㸠乵>

"
⤠)

††

pt = cast p …;

return
Math.sqrt
(
pt.x

*
pt.x

+
pt.y

*
pt.y
);

} else {

var

pf

= cast p …;

return Math.abs(
pf
);

}

}

function
fromOrigin
(p) {

/* {x: Num, y: Num}

-
㸠乵>

"
⤠)

††

⡳整⠢潢橥捴
"
⤬⁰⤻

††

䵡瑨⹳煲M
(

var

pf

=
tagcheck
(set("number"), p);

return Math.abs(
pf
);

}

}

22

Introducing
tagcheck

tagcheck

R

e

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

Set of
tags

An

expression

24

runtime
: Type

2
Tag

static
:
2
Tag

Type

static
:
2
Tag

Type

Type

25

static
:
2
Tag

Type

Type

static
(set("string
"
,
"
bool
"
),

Str

䉯潬
)

䉯潬

static
(set("object"),

{x: Num, y: Num}

Given a set
of tags…

…and a
type…

…pick out the parts

of the type that
correspond to the tags

26

Determine

static type,

i
dentify
presumed
run
-
time
tags,

…t
hat’s the
resulting
static type

narrow type
based on
these two…

27

Num


set("string
"
)

Str

static
(set("string"),

Num

)

function
fromOrigin
(p) {

/* {x: Num, y: Num}

-
㸠乵>

††

⡳整⠢潢橥捴
"
⤬⁰⤻

††

䵡瑨⹳煲M
(

var

pf

=
tagcheck
(set("number"), p);

return Math.abs(
pf
);

}

}

28

tagcheck

Failure Modes

29

tag set
R

is
inconsistent with
the type
S

resulting type
T

is

inconsistent with

the context’s needs

actual run
-
time tag
is simply not

contained in
R

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

31

1.
How to prevent programs from resulting in
the new run
-
time error (
tagerr
)?

2.
Who’s going to write
tagcheck
s
?

F
LOW

A
NALYSIS

1.
tags
, not
values

2.
Only inside procedures; halts at calls

3.
Intermediate representation (CPS, ANF,
SSA, …)

32

function
fromOrigin
(p) {

/* {x: Num, y: Num }

-

var

t1 =
typeof

p;

var

t2 = (t1 === "object");

if (t2) {

var

t3 =
p.x
;
var

t4 =
p.x
;

var

t5 = t3 * t4;

var

t6 =
p.y
;
var

t7 =
p.y
;

var

t8 = t6 * t7;

var

t9 = t5 + t8;

return
Math.sqrt
(t9);

} else {

return Math.abs(p);

}

}

33

p = {"object"}

t1 =
typeof

p

t2 = true

p = {"number"}

t1 =
typeof

p

t2 = false

p = runtime(
{ x:
Num
, y:
Num

}

)

p = {"object", "number"}

t1 =
typeof

p

t2 = t1 === "object"

function
fromOrigin
(p) {

/* {x: Num, y: Num }

-

var

t1 =
typeof

p;

var

t2 = (t1 === "object");

if (t2) {

var

t3 =
p.x
;
var

t4 =
p.x
;

var

t5 = t3 * t4;

var

t6 =
p.y
;
var

t7 =
p.y
;

var

t8 = t6 * t7;

var

t9 = t5 + t8;

return
Math.sqrt
(t9);

} else {

return Math.abs(p);

}

}

34

p = {"object"}

t1 =
typeof

p

t2 = true

p = {"number"}

t1 =
typeof

p

t2 = false

35

p = {"object"}

t1 =
typeof

p

t2 = true

p = {"number"}

t1 =
typeof

p

t2 = false

function
fromOrigin
(p) {

/* {x: Num, y: Num }

-

var

t1 =
typeof

p;

var

t2 = (t1 === "object");

if (t2) {

var

pt

=
tagcheck
(set("object"),
p
);

var

t3 =
pt.x
;
var

t4 =
pt.x
;

var

t5 = t3 * t4;

var

t6 =
pt.y
;
var

t7 =
pt.y
;

var

t8 = t6 * t7;

var

t9 = t5 + t8;

return
Math.sqrt
(t9);

} else {

var

pf

=
tagcheck
(set
("number"),
p);

return
Math.abs
(
pf
);

}

}

function
fromOrigin
(p) {

/* { x:
Num
, y:
Num

}

Num

-
>
Num

*/

...

}

fromOrigin
(500)

fromOrigin
({ x : 20, y: 900 })

fromOrigin
("invalid argument")

36

actual arguments ignored by
flows

therefore, invalid arguments
ignored too!

p = runtime(
{ x:
Num
, y:
Num

}

)

㴠笢潢橥捴∬•湵浢敲≽

[
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
]

37

[
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

Our Recipe

Simple type checker (not quite enough)

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

39

JavaScript Semantics (ECOOP 2010)

Typing Local Control and State (ESOP 2011)

Typing Objects (in progress)

Verifying Web Sandboxes

Types as Documentation
for JavaScript programs