Galois Transformers and Modular Abstract Interpreters Reusable - - PowerPoint PPT Presentation

galois transformers and modular abstract interpreters
SMART_READER_LITE
LIVE PREVIEW

Galois Transformers and Modular Abstract Interpreters Reusable - - PowerPoint PPT Presentation

Galois Transformers and Modular Abstract Interpreters Reusable Metatheory for Program Analysis David Darais Matthew Might David Van Horn University of Maryland University of Utah University of Maryland Program Analysis 2 Program


slide-1
SLIDE 1

Galois Transformers and 
 Modular Abstract Interpreters

Reusable Metatheory for Program Analysis

David Darais

University of Maryland

Matthew Might

University of Utah

David Van Horn

University of Maryland

slide-2
SLIDE 2

Program Analysis

2

slide-3
SLIDE 3

Program Analysis

  • Lots of choices when designing a program analysis

2

slide-4
SLIDE 4

Program Analysis

  • Lots of choices when designing a program analysis
  • Choices make tradeoffs between precision and performance

2

slide-5
SLIDE 5

Program Analysis

  • Lots of choices when designing a program analysis
  • Choices make tradeoffs between precision and performance
  • Implementations are brittle and difficult to change

2

slide-6
SLIDE 6

Program Analysis

  • Lots of choices when designing a program analysis
  • Choices make tradeoffs between precision and performance
  • Implementations are brittle and difficult to change
  • Galois Transformers:



 Reusable components for building program analyzers

2

slide-7
SLIDE 7

Program Analysis

  • Lots of choices when designing a program analysis
  • Choices make tradeoffs between precision and performance
  • Implementations are brittle and difficult to change
  • Galois Transformers:



 Reusable components for building program analyzers

  • Bonus:



 Variations in path/flow sensitivity of your analyzer for free

2

slide-8
SLIDE 8

Let's Design an Analysis

3

(in the paradigm of abstract interpretation)

slide-9
SLIDE 9

Let's Design an Analysis

4

Program

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-10
SLIDE 10

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Program

5

Let's Design an Analysis

Analysis Property

x/0

slide-11
SLIDE 11

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Program

x/0

Analysis Property

6

Let's Design an Analysis

Abstract Values

ℤ ⊑ {-,0,+}

slide-12
SLIDE 12

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Program

x/0

Analysis Property

ℤ ⊑ {-,0,+}

Abstract Values

Let's Design an Analysis

Implement

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

7

slide-13
SLIDE 13

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Program

x/0

Analysis Property

ℤ ⊑ {-,0,+}

Abstract Values

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

Implement

Let's Design an Analysis

Get Results

N ∈ {-,0,+} x ∈ {0,+} y ∈ {-,0,+}
 UNSAFE: {100/N}
 UNSAFE: {100/x}

8

slide-14
SLIDE 14

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Program

x/0

Analysis Property

ℤ ⊑ {-,0,+}

Abstract Values

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

Implement

N ∈ {-,0,+} x ∈ {0,+} y ∈ {-,0,+}
 UNSAFE: {100/N}
 UNSAFE: {100/x}

Get Results

⟦e⟧ ∈ ⟦analyze(e)⟧

9

Let's Design an Analysis

Prove Correct

slide-15
SLIDE 15

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

10

Get Results

Let's Design an Analysis

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}} N ∈ {-,0,+} x ∈ {0,+} y ∈ {-,0,+}
 UNSAFE: {100/N}
 UNSAFE: {100/x}

⟦e⟧ ∈ ⟦analyze(e)⟧

Prove Correct

slide-16
SLIDE 16

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Let's Design an Analysis

11

Flow-insensitive

results : 
 var ↦ !({-,0,+})

N ∈ {-,0,+} x ∈ {0,+} y ∈ {-,0,+}
 UNSAFE: {100/N}
 UNSAFE: {100/x}

slide-17
SLIDE 17

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Let's Design an Analysis

12

Flow-sensitive

results : 
 loc ↦ (var ↦ !({-,0,+}))

slide-18
SLIDE 18

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

4: x ∈ {0,+} 4.T: N ∈ {-,+} 5.F: x ∈ {0,+} N,y ∈ {-,0,+} UNSAFE: {100/x}

Let's Design an Analysis

13

Flow-sensitive

results : 
 loc ↦ (var ↦ !({-,0,+}))

slide-19
SLIDE 19

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

Let's Design an Analysis

14

Path-sensitive

results : 
 loc ↦ !(var ↦ !({-,0,+}))

slide-20
SLIDE 20

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

Let's Design an Analysis

15

Path-sensitive

results : 
 loc ↦ !(var ↦ !({-,0,+}))

slide-21
SLIDE 21

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

16

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Let's Design an Analysis

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

?

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-22
SLIDE 22

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

16

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Let's Design an Analysis

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

✗ ✗ ?

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-23
SLIDE 23

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

17

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Let's Design an Analysis

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ .. 4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

safe_fun.js

?

slide-24
SLIDE 24

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

17

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Let's Design an Analysis

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

✗ ✗

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

safe_fun.js

?

slide-25
SLIDE 25

Problems Worth Solving

  • How to change path/flow sensitivity without

redesigning from scratch?

  • How to reuse machinery between analyzers for

different languages?

  • How to translate proofs between different analysis

designs?

18

slide-26
SLIDE 26

19

Solution

Monad
 Transformers Galois
 Connections Galoiѕ
 Transformerѕ Compositional
 interpreters Compositional
 abstractions Compositional
 abstract interpreters

+ =

slide-27
SLIDE 27

Galoiѕ Transformerѕ

  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

20

slide-28
SLIDE 28

Galoiѕ Transformerѕ

  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

21

slide-29
SLIDE 29

A Monad

  • A module with:
  • a type operator "
  • a semicolon operator


(bind)

  • effect operation
  • "(t):
  • "A computation that performs

some effects, then returns t"

22

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p get
  • p put(e)
  • p fail
  • p ...
slide-30
SLIDE 30

N ∈ {-,0,+} x ∈ {0,+} y ∈ {-,0,+}
 UNSAFE: {100/N}
 UNSAFE: {100/x}

Analysis Property

x/0

Abstract Domain

ℤ ⊑ {-,0,+}

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Program Implement

23

A Monadic Interpreter

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ .. 0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-31
SLIDE 31

A Monadic Interpreter

24

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-32
SLIDE 32

A Monadic Interpreter

24

value := ℤ ∪ # ρ ∈ env := var ↦ value ⟦_⟧ : atom → "(value)
 chooseBool : value♯ → "♯(#)

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-33
SLIDE 33

A Monadic Interpreter

24

value := ℤ ∪ # ρ ∈ env := var ↦ value ⟦_⟧ : atom → "(value)
 chooseBool : value♯ → "♯(#) type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-34
SLIDE 34

A Monadic Interpreter

24

value := ℤ ∪ # ρ ∈ env := var ↦ value ⟦_⟧ : atom → "(value)
 chooseBool : value♯ → "♯(#) type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

step : exp → "(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯ ρ ← getEnv putEnv(ρ[x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯ case v of True → return(e₁) False → return(e₂) _ → fail

slide-35
SLIDE 35

A Monadic Interpreter

25

value := ℤ ∪ # ρ ∈ env := var ↦ value ⟦_⟧ : atom → "(value)
 chooseBool : value♯ → "♯(#)

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

step : exp → "(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯ ρ ← getEnv putEnv(ρ[x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯ case v of True → return(e₁) False → return(e₂) _ → fail

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-36
SLIDE 36

A Monadic Interpreter

26

value := ℤ ∪ # ρ ∈ env := var ↦ value ⟦_⟧ : atom → "(value)
 chooseBool : value♯ → "♯(#)

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

step : exp → "(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯ ρ ← getEnv putEnv(ρ[x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯ case v of True → return(e₁) False → return(e₂) _ → fail

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-37
SLIDE 37

Abstractify

27

value := ℤ ∪ # ρ ∈ env := var ↦ value ⟦_⟧ : atom → "(value)
 chooseBool : value♯ → "♯(#)

step : exp → "(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯ ρ ← getEnv putEnv(ρ[x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯ case v of True → return(e₁) False → return(e₂) _ → fail

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-38
SLIDE 38

Abstractify

28

value♯ := !({-,0,+}) ∪ !(#) ρ ∈ env♯ := var ↦ value♯ ⟦_⟧♯ : atom → "♯(value♯)
 chooseBool : value♯ → "♯(#) type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

step : exp → "♯(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯♯ ρ ← getEnv putEnv(ρ[x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯♯ case v of True → return(e₁) False → return(e₂) _ → fail

slide-39
SLIDE 39

Abstractify

29

value♯ := !({-,0,+}) ∪ !(#) ρ ∈ env♯ := var ↦ value♯ ⟦_⟧♯ : atom → "♯(value♯)
 chooseBool : value♯ → "♯(#)

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

step : exp → "♯(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯♯ ρ ← getEnv putEnv(ρ ⊔ [x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯♯ case v of True → return(e₁) False → return(e₂) _ → fail

type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-40
SLIDE 40

Abstractify

31

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

value♯ := !({-,0,+}) ∪ !(#) ρ ∈ env♯ := var ↦ value♯ ⟦_⟧♯ : atom → "♯(value♯)
 chooseBool : value♯ → "♯(#) type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

step : exp → "♯(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯♯ ρ ← getEnv putEnv(ρ ⊔ [x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯♯ b ← chooseBool(v) case b of True → return(e₁) False → return(e₂) step : exp → "♯(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯♯ ρ ← getEnv putEnv(ρ ⊔ [x↦v])⊔ return(SKIP)

slide-41
SLIDE 41

Abstractify

33

type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

step : exp → "♯(exp)♯ step(x := æ) := do v ← ⟦æ⟧♯♯ ρ ← getEnv putEnv(ρ ⊔ [x↦v])⊔ return(SKIP) step(IF(æ){e₁}{e₂}):= do v ← ⟦æ⟧♯♯ b ← chooseBool(v) case b of True → return(e₁) False → return(e₂)

value♯ := !({-,0,+}) ∪ !(#) ρ ∈ env♯ := var ↦ value♯ ⟦_⟧♯ : atom → "♯(value♯)
 chooseBool : value♯ → "♯(#)

slide-42
SLIDE 42

Monadic Abs. Interpreters

  • Start with a concrete monadic interpreter
  • Abstract value space (value♯,⟦_⟧♯)
  • Join results when updating env♯ (_⊔_)
  • Branch nondeterministically (chooseBool)

34

slide-43
SLIDE 43

Why Monads

  • A monadic interpreter can be simpler than a

state machine or constraint system

  • Two effects, State[$] and Nondet
  • Encode arbitrary small-step state machine relations
  • Don't commit to a single implementation of "♯
  • Different choices for "♯ yield different analyses

35

slide-44
SLIDE 44

Galoiѕ Transformerѕ

  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

36

slide-45
SLIDE 45

Galoiѕ Transformerѕ

  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

37

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
slide-46
SLIDE 46

Galoiѕ Transformerѕ

  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

38

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
slide-47
SLIDE 47

Why Monads

  • A monadic interpreter can be simpler than a

state machine or constraint system

  • Two effects, State[$] and Nondet
  • Encode arbitrary small-step state machine relations
  • Don't commit to a single implementation of "♯
  • Different choices for "♯ yield different analyses

39

slide-48
SLIDE 48

Monad Transformers

41

State[$] Nondet

get : "($)
 put : $ → "(1) fail : ∀ A. "(A) _⊞_ : ∀ A. "(A)×"(A) → "(A)

slide-49
SLIDE 49

Monad Transformers

42

StateT[$] NondetT

slide-50
SLIDE 50

Monad Transformers

44

StateT[$]

effects "

NondetT

slide-51
SLIDE 51

StateT[$](")
 
 effects + state

Monad Transformers

45

=

" StateT[$] effects

NondetT

slide-52
SLIDE 52

NondetT(")
 
 effects + nondet NondetT

Monad Transformers

46

StateT[$]

effects "

=

slide-53
SLIDE 53

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

Monad Transformers

47

slide-54
SLIDE 54

Monad Transformers

48

ID

=

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-55
SLIDE 55

Monad Transformers

49

ID NondetT

=

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-56
SLIDE 56

Monad Transformers

50

ID StateT[env] NondetT

=

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-57
SLIDE 57

Monad Transformers

51

ID StateT[env♯] NondetT

=

type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂
slide-58
SLIDE 58

Monad Transformers

53

ID StateT[env♯] NondetT

=

type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

Path-sensitive

slide-59
SLIDE 59

NondetT StateT[env♯]

Monad Transformers

54

ID

=

type "♯(t)

  • p x ← e₁ ; e₂
  • p return(e)
  • p getEnv
  • p putEnv(e)
  • p fail/e₁⊞e₂

Flow-insensitive

slide-60
SLIDE 60

StateT[env♯] NondetT

Flow-insensitive

Monad Transformers

56

StateT[env♯] NondetT

Path-sensitive

slide-61
SLIDE 61

StateT[env♯] NondetT

Flow-insensitive

StateT[env♯] NondetT

Path-sensitive

Monad Transformers

57

FlowT[env♯]

⊒ ⊒

Flow-sensitive

slide-62
SLIDE 62

!(exp) × env♯ exp ↦ !(env♯)

StateT[env♯] NondetT

Flow-insensitive

StateT[env♯] NondetT

Path-sensitive

Monad Transformers

58

FlowT[env♯]

⊒ ⊒

Flow-sensitive

exp ↦ env♯

slide-63
SLIDE 63

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

!(exp) × env♯ exp ↦ !(env♯)

Flow-insensitive Path-sensitive Flow-sensitive

exp ↦ env♯

Monad Transformers

59

4: x ∈ {0,+} 4.T: N ∈ {-,+} 5.F: x ∈ {0,+} N,y ∈ {-,0,+} UNSAFE: {100/x} N ∈ {-,0,+} x ∈ {0,+} y ∈ {-,0,+}
 UNSAFE: {100/N}
 UNSAFE: {100/x}

slide-64
SLIDE 64

Building Monads

  • Construct a monad using StateT[$], FlowT[$]

and NondetT

  • Order matters, yielding different analyses
  • Rapidly prototype precision performance tradeoffs

60

slide-65
SLIDE 65

Why Transformers

  • Semantics independent building blocks for writing

interpreters—also apply to abstract interpreters!

  • Reuse of analysis machinery
  • Different abs. interpreters use the same transformers
  • Variations in analysis
  • Different transformer stacks fit into the same interpreter

61

slide-66
SLIDE 66
  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

62

Galoiѕ Transformerѕ

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
slide-67
SLIDE 67
  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

63

Galoiѕ Transformerѕ

FlowT[$]

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
slide-68
SLIDE 68
  • What's a Monad?
  • What are Transformers?
  • What are Galois Connections?

64

FlowT[$]

Galoiѕ Transformerѕ

type "(t)

  • p x ← e₁ ; e₂
  • p return(e)
slide-69
SLIDE 69

Galois Connections

  • Compositional framework for proving correctness
  • We build two sets of GCs alongside transformers
  • Code: Enables execution of monadic analyzers
  • Proofs: Large number of proofs built automatically
  • (See the paper)

65

slide-70
SLIDE 70

Galois Transformers

  • GTs = Monad Transformers + Galois connections
  • Galois connections are necessary for execution

and proof of correctness for abstract interpreter

66

FlowT[env♯] StateT[env♯] NondetT

slide-71
SLIDE 71

Putting it All Together

  • You design a monadic abstract interpreter
  • Instantiate with monad transformers
  • Change underlying monad to change results
  • Galois connections synthesized for free:
  • Code: Execution engine for running the analysis
  • Proofs: Large part of correctness argument

67

slide-72
SLIDE 72

Implementation

  • Haskell package: cabal install maam
  • Galois Transformers are implemented as a

semantics independent library

  • Haskell's support for monadic programming was

helpful, but not necessary

68

slide-73
SLIDE 73

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

69

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Let's Design an Analysis

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

✓ ✓

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE ? 0: int x y; // global state 1: void safe_fun(int N) { 2: if (N≠0) {x := 0;} 3: else {x := 1;} 4: if (N≠0) {y := 100/N;} 5: else {y := 100/x;}}

slide-74
SLIDE 74

Program Analysis Property

x/0

Abstract Values

ℤ ⊑ {-,0,+}

Implement

70

Get Results Prove Correct

⟦e⟧ ∈ ⟦analyze(e)⟧

Let's Design an Analysis

analyze : exp → results analyze(x := æ) := .. x .. æ .. analyze(IF(æ){e₁}{e₂}) := .. æ .. e₁ .. e₂ ..

✓ ✓

4: N∈{-,+},x∈{0} 4: N∈{0},x∈{+} N∈{-,+},y∈{-,0,+} N∈{0},y∈{0,+} SAFE

safe_fun.js

?

slide-75
SLIDE 75

Future Work

  • Benchmark interaction between flow sensitivity and other

design choices, like context or object sensitivity

  • Explore uses of NondetT and FlowT[$] outside analysis
  • Other methods for executing monadic abstract

interpreters; might relate to pushdown analysis

  • Steps toward modular verified abstract interpreters in Coq
  • r Agda using Galois Transformer proof framework
  • First step, mechanizing Galois connections
  • Draft: Mechanically Verified Calculational Abstract Interpretation


(w/Van Horn)

71 David Darais — GTs+MAIs — OOPSLA2015