Modular Procedure Equivalence with Dynamic Heap Allocation Tim Wood - - PowerPoint PPT Presentation

modular procedure equivalence with dynamic heap allocation
SMART_READER_LITE
LIVE PREVIEW

Modular Procedure Equivalence with Dynamic Heap Allocation Tim Wood - - PowerPoint PPT Presentation

Modular Procedure Equivalence with Dynamic Heap Allocation Tim Wood 1 Shuvendu Lahiri 2 Sophia Drossopoulou 1 1 Imperial College London 2 Microsoft Research 12th April 2016 Introduction Subject Procedure equivalence for procedures that


slide-1
SLIDE 1

Modular Procedure Equivalence with Dynamic Heap Allocation

Tim Wood 1 Shuvendu Lahiri 2 Sophia Drossopoulou 1

1Imperial College London 2Microsoft Research

12th April 2016

slide-2
SLIDE 2

Introduction

Subject

Procedure equivalence for procedures that dynamically allocate heap memory

Overview

  • 1. What is procedure equivalence in this context?
  • 2. How can we modularly verify such procedure equivalence?

◮ How to relate the procedures. ◮ Some sound underapproximations that help.

  • 3. Current status of our verification tool.
slide-3
SLIDE 3

What we are trying to do

◮ Automatically verify equivalence of procedures

◮ unbounded dynamic heap memory allocation ◮ unbounded recursion (but not loops) ◮ memory-safe / no pointer arithmetic ◮ sequential

slide-4
SLIDE 4

What we are trying to do

◮ Automatically verify equivalence of procedures

◮ unbounded dynamic heap memory allocation ◮ unbounded recursion (but not loops) ◮ memory-safe / no pointer arithmetic ◮ sequential

◮ Use a permissive notion of equivalence that allows for

◮ differences in allocation order ◮ differences in garbage ◮ equivalent rearrangements of existing memory

slide-5
SLIDE 5

What we are trying to do

◮ Automatically verify equivalence of procedures

◮ unbounded dynamic heap memory allocation ◮ unbounded recursion (but not loops) ◮ memory-safe / no pointer arithmetic ◮ sequential

◮ Use a permissive notion of equivalence that allows for

◮ differences in allocation order ◮ differences in garbage ◮ equivalent rearrangements of existing memory

◮ Apply single program modular verification technology to

procedure equivalence verification

◮ take advantage of procedure contracts if present

slide-6
SLIDE 6

Outline

Introduction What is procedure equivalence? When are procedures that allocate memory equivalent? How do changes in allocation order affect equivalence? How does garbage affect equivalence? How does context affect equivalence? Equivalence and recursion. Verifying procedure equivalence Why is it difficult? Sound approximations - assuming isomorphic state is equal Equivalence and statement ordering Tool current abilities

slide-7
SLIDE 7

When are procedures equivalent?

◮ Symdiff1 says that procedures are equivalent iff they produce

equal final stores given equal initial stores

◮ We call this equi-equivalence

s1 equi-equivalent s2

def

⇐ ⇒ ∀φ1...4 : φ1 = φ2 ∧ φ1, s1

C φ3 ∧ φ2, s2 C φ4

= ⇒ φ3 = φ4

1Lahiri, Shuvendu K., et al. ”Symdiff: A language-agnostic semantic diff

tool for imperative programs.” CAV. 2012

slide-8
SLIDE 8

A note on termination

◮ Whether the procedures terminate under the same conditions

is important. Particularly if a transitive notion of equivalence is required

◮ Only going to talk about terminating programs

Related:

◮ Hawblitzel, Chris, et al. ”Towards modularly comparing

programs using automated theorem provers.” CADE-24 (2013)

◮ Elenbogen, Dima, et al. ”Proving mutual termination.”

Formal Methods in System Design 47.2 (2015)

slide-9
SLIDE 9

Example - identical procedures

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

r.v := new;

20 21

rl := new;

22

copy ’(t.l, rl);

23

r.v.l := rl.v;

24 25

rr := new;

26

copy ’(t.r, rr);

27

r.v.r := rr.v;

28 }

◮ Procedures recursively copy a tree ◮ Heap cell used to return result ◮ Recursive calls can allocate an unbounded amount of memory

slide-10
SLIDE 10

Example - identical procedures

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

r.v := new;

20 21

rl := new;

22

copy ’(t.l, rl);

23

r.v.l := rl.v;

24 25

rr := new;

26

copy ’(t.r, rr);

27

r.v.r := rr.v;

28 }

◮ Equi-equivalence depends on the behaviour of the allocator ◮ With a non-deterministic allocator, these procedures are not

equi-equivalent

◮ If we assume a deterministic incrementing allocator, then

these procedures are equi-equivalent

1 2

  • 3. . . 3+n

3+n 1 2

  • 3. . . 3+n

3+n

slide-11
SLIDE 11

Example - allocation order

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

rl := new;

20

copy ’(t.l, rl);

21 22

rr := new;

23

copy ’(t.r, rr);

24 25

r.v := new;

26

r.v.l := rl.v;

27

r.v.r := rr.v;

28 }

slide-12
SLIDE 12

Example - allocation order

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

rl := new;

20

copy ’(t.l, rl);

21 22

rr := new;

23

copy ’(t.r, rr);

24 25

r.v := new;

26

r.v.l := rl.v;

27

r.v.r := rr.v;

28 }

◮ These procedures are not equi-equivalent with an

incrementing allocator

◮ The trees produced by copy’ are allocated at different

memory addresses than those produced by copy

1 2

  • 3. . . 3+n

3+n 1

  • 2. . . 2+n

2+n 3+n

slide-13
SLIDE 13

Use a weaker notion of equivalence

◮ Use a weaker equivalence, which requires stores are related by

some weaker relation ≈ rather than =, perhaps: s1 ≈ s2

def

⇐ ⇒ ∀φ1...4 : φ1 ≈ φ2 ∧ φ1, s1

C φ3 ∧ φ2, s2 C φ4

= ⇒ φ3 ≈ φ4

◮ what should ≈ be?

slide-14
SLIDE 14

Isomorphism

◮ Our programs do not look at the actual values of pointers ◮ Stores should be equivalent whenever they have the same

shape

◮ Suggestion: φ1 ≈ φ2 when

◮ ∃ a bijection between the allocated addresses in φ1 and φ2 ◮ the bijection preserves the shape of the stores

slide-15
SLIDE 15

Isomorphism

t 3 x 1 y 1 z 4 1 2 3 4 5 f g n

t 7 x 11 y 11 z 9 11 14 7 9 6 f g n

{1 → 11, 2 → 14, 3 → 7, 4 → 9, 5 → 6}

slide-16
SLIDE 16

Example - garbage

1 copy(t,r) 2 { 3

n := new;

4 5

if(t = null) return;

6 7

rl := new;

8

copy(t.l, rl);

9

n.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

n.r := rr.v;

14 15

r.v := n;

16 } 17 copy ’(t,r) 18 { 19 20 21

if(t = null) return;

22 23

rl := new;

24

copy ’(t.l, rl);

25 26

rr := new;

27

copy ’(t.r, rr);

28 29

r.v := new;

30

r.v.l := rl.v;

31

r.v.r := rr.v;

32 }

◮ copy creates extra unreachable garbage at the leaves

slide-17
SLIDE 17

Isomorphism

◮ Our programs do not resurrect stuff out of the garbage ◮ Stores could be equivalent whenever their reachable parts

have the same shape

◮ φ1 ≈ φ2 when

◮ ∃ a bijection between the reachable addresses in φ1 and φ2 ◮ the bijection preserves the shape of the reachable parts of the

stores

slide-18
SLIDE 18

Example - garbage

1 copy(t,r) 2 { 3

n := new;

4 5

if(t = null) return;

6 7

rl := new;

8

copy(t.l, rl);

9

n.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

n.r := rr.v;

14 15

r.v := n;

16 } 17 copy ’(t,r) 18 { 19 20 21

if(t = null) return;

22 23

rl := new;

24

copy ’(t.l, rl);

25 26

rr := new;

27

copy ’(t.r, rr);

28 29

r.v := new;

30

r.v.l := rl.v;

31

r.v.r := rr.v;

32 }

◮ copy creates extra unreachable garbage at the leaves ◮ This presents a couple of difficulties:

◮ The garbage is still reachable at the end of the procedure ◮ The stack variables differ

slide-19
SLIDE 19

Use a weaker notion of equivalence

◮ The caller cannot observe the stack frame of the callee ◮ So the final stores only need equivalent calling contexts

s1 ≈ s2

def

⇐ ⇒ ∀φ1...4 : φ1 ≈ φ2 ∧ φ1, s1

C φ3 ∧ φ2, s2 C φ4

= ⇒ φctx

3

≈ φctx

4

slide-20
SLIDE 20

Context Isomorphism

t 3 x 1 y 1 z 4 1 2 3 4 5 f g n

t 7 x 11 y 11 z 9 11 14 7 9 6 g f n

Pointer from t distinguishes objects 2 and 3

slide-21
SLIDE 21

Context Isomorphism

t 3 x 1 y 1 z 4 1 2 3 4 5 f g n

t 7 x 11 y 11 z 9 11 14 7 9 6 g f n

In caller context no way to distinguish objects 2 and 3

slide-22
SLIDE 22

Context Isomorphism

t 3 x 1 y 1 z 4 1 2 3 4 5 f g n

t 7 x 11 y 11 z 9 11 14 7 9 6 g f n t 3 x 1 y 1 z 4 1 2 3 4 5 f g n m

t 7 x 11 y 11 z 9 11 14 7 9 6 g f n m

Suppose there was an extra pointer m in the calling context

slide-23
SLIDE 23

Context Isomorphism

t 3 x 1 y 1 z 4 1 2 3 4 5 f g n

t 7 x 11 y 11 z 9 11 14 7 9 6 g f n t 3 x 1 y 1 z 4 1 2 3 4 5 f g n m

t 7 x 11 y 11 z 9 11 14 7 9 6 g f n m

Now pointer 4.m distinguishes objects 2 and 3

slide-24
SLIDE 24

Example - context

1 noop(x) 2

requires ...

3 { 4 5 6 7 } 8 swap(x) 9

requires ...

10 { 11

t := x.f;

12

x.f := x.g;

13

x.g := t;

14 }

◮ These procedures could be equivalent when a precondition is

taken into account

◮ e.g. requires x.f==x.g

◮ Preconditions may need to talk about the shape of the calling

context

◮ Need a way to write about the calling context shape. ◮ It is always sound to assume a worst case calling context that

can distinguish any two existing objects.

slide-25
SLIDE 25

Use a weaker notion of equivalence

◮ The procedures are equivalent given some precondition

s1 ≈pre s2

def

⇐ ⇒ ∀φ1...4 : φ1 ∈ pre ∧ φ2 ∈ pre ∧ φ1 ≈ φ2 ∧ φ1, s1

C φ3 ∧ φ2, s2 C φ4

= ⇒ φctx

3

≈ φctx

4

slide-26
SLIDE 26

Modularity and recursion

◮ We want to reason modularly (for scalability) ◮ When can we use the knowledge that two procedures are

equivalent?

slide-27
SLIDE 27

Example - modularity

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

rl := new;

20

copy ’(t.l, rl);

21 22

rr := new;

23

copy ’(t.r, rr);

24 25

r.v := new;

26

r.v.l := rl.v;

27

r.v.r := rr.v;

28 }

◮ Calls on lines 8 and 20 are equivalent in some way

slide-28
SLIDE 28

Example - modularity

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

rl := new;

20

copy ’(t.l, rl);

21 22

rr := new;

23

copy ’(t.r, rr);

24 25

r.v := new;

26

r.v.l := rl.v;

27

r.v.r := rr.v;

28 }

◮ Calls on lines 8 and 20 are equivalent in some way ◮ Their prestores are not fully isomorphic

◮ one more object is reachable in copy

slide-29
SLIDE 29

Example - modularity

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

rl := new;

20

copy ’(t.l, rl);

21 22

rr := new;

23

copy ’(t.r, rr);

24 25

r.v := new;

26

r.v.l := rl.v;

27

r.v.r := rr.v;

28 }

◮ parts reachable from the initial callee stackframe are

isomorphic

◮ so the calls will have isomorphic effects

slide-30
SLIDE 30

Example - modularity

1 copy(t,r) 2 { 3

if(t = null) return;

4 5

r.v := new;

6 7

rl := new;

8

copy(t.l, rl);

9

r.v.l := rl.v;

10 11

rr := new;

12

copy(t.r, rr);

13

r.v.r := rr.v;

14 } 15 copy ’(t,r) 16 { 17

if(t = null) return;

18 19

rl := new;

20

copy ’(t.l, rl);

21 22

rr := new;

23

copy ’(t.r, rr);

24 25

r.v := new;

26

r.v.l := rl.v;

27

r.v.r := rr.v;

28 }

◮ parts reachable from the initial callee stackframe are

isomorphic

◮ so the calls will have isomorphic effects ◮ in the caller context, the parts of the stores reachable from

the call parameters are isomorphic φ8 ≈(t.l,rl),(t.l,rl) φ20

slide-31
SLIDE 31

Outline for section 3

Introduction What is procedure equivalence? When are procedures that allocate memory equivalent?

Is a procedure equivalent with itself?

How do changes in allocation order affect equivalence?

A weaker notion of equivalence.

How does garbage affect equivalence? How does context affect equivalence? Equivalence and recursion. Verifying procedure equivalence Why is it difficult? Sound approximations - assuming isomorphic state is equal Equivalence and statement ordering Tool current abilities

slide-32
SLIDE 32

Overview

◮ Similar approach as Symdiff

1 F_G ’(t,r) 2

requires ...

3 { 4

heap_start := heap; // save initial heap

5

inline F;

6

heap_F := heap; // save final heap

7 8

havoc heap; // non - deterministic value

9

assume iso(ctx ,t,r,heap_start ,heap); // restore an iso heap

10

inline G;

11

heap_G := heap; // save final heap

12 13

assert iso(ctx ,heap_F ,heap_G); // not heap_F == heap_G

14 }

slide-33
SLIDE 33

Problem

◮ the solver is often unable to find the bijection ◮ need a better approach

Recall:

◮ φ1 ≈ φ2 when

◮ ∃ a bijection between the reachable addresses in φ1 and φ2 ◮ the bijection preserves the shape of the reachable parts of the

stores

slide-34
SLIDE 34

Sound approximations that may help

Can we make the problem easier?

◮ are there sound (under)approximations of the problem?

◮ we prove the approximations are sound by hand (meta-proof)

◮ can we prove equivalence without needing to actually produce

the bijection?

slide-35
SLIDE 35

Observation - statements closed under ≈

When executing statements twice from isomorphic states, we reach isomorphic states ∀s, φ1...4 : φ1, s

C φ3 ∧ φ2, s C φ4 ∧ φ1 ≈ φ2

= ⇒ φ3 ≈ φ4

◮ can think of this as the programs not being sensitive to the

actual values of pointers

slide-36
SLIDE 36

Only consider equal initial stores

◮ when statements s1, s2 are equivalent for equal initial stores,

they are equivalent for isomorphic initial stores

  • ∀φ1...4 : φ1=φ2 ∧ φ1, s1

C φ3 ∧ φ2, s2 C φ4 =

⇒ φctx

3

≈ φctx

4

  • =

  • ∀φ1...4 : φ1≈φ2 ∧ φ1, s1

C φ3 ∧ φ2, s2 C φ4 =

⇒ φctx

3

≈ φctx

4

  • ◮ so the identity bijection can be the initial isomorphism
slide-37
SLIDE 37

Overview

1 F_G ’(t,r) 2

requires ...

3 { 4

heap_start := heap; // save initial heap

5

inline F;

6

heap_F := heap; // save final heap

7 8

havoc heap; // non - deterministic value

9

assume iso(ctx ,t,r,heap_start ,heap); // restore an iso heap

10

assume heap = heap_start ; // restore the equal iso heap

11

inline G;

12

heap_G := heap; // save final heap

13 14

assert iso(ctx ,heap_F ,heap_G); // not heap_F == heap_G

15 }

slide-38
SLIDE 38

Can apply isomorphism if it exists

◮ Where an isomorphism exists it can be applied. ◮ Helps avoid needing to materialize the bijection

◮ if we know there must be a bijection ◮ we assume it to be the identity

slide-39
SLIDE 39

Can apply isomorphism if it exists

◮ Where an isomorphism exists it can be applied. ◮ Helps avoid needing to materialize the bijection

◮ if we know there must be a bijection ◮ we assume it to be the identity

◮ This corresponds to assumptions of the form

assume φi ≈ φj = ⇒ φi ≈id φj

slide-40
SLIDE 40

Can apply isomorphism if it exists

◮ Where an isomorphism exists it can be applied. ◮ Helps avoid needing to materialize the bijection

◮ if we know there must be a bijection ◮ we assume it to be the identity

◮ This corresponds to assumptions of the form

assume φi ≈ φj = ⇒ φi ≈id φj

intuition

a lucky allocator that always allocates memory in just the right way

slide-41
SLIDE 41

Can apply isomorphism if it exists

◮ This corresponds to assumptions of the form

assume φi ≈ φj = ⇒ φi ≈id φj

◮ But suppose:

φ1 ≈ φ2 ∧ φ1 ≈ φ3 ∧ φ2 ≈id φ3 The assumption tell us φ1 ≈id φ2 ∧ φ1 ≈id φ3 So it must be that φ2 ≈id φ3 But this contradicts (unsound)

slide-42
SLIDE 42

Can apply isomorphism if it exists

◮ This corresponds to assumptions of the form

assume φi ≈ φj = ⇒ φi ≈id φj

◮ But suppose:

φ1 ≈ φ2 ∧ φ1 ≈ φ3 ∧ φ2 ≈id φ3 The assumption tell us φ1 ≈id φ2 ∧ φ1 ≈id φ3 So it must be that φ2 ≈id φ3 But this contradicts (unsound)

◮ Solution: add extra constraints to prevent contradictory

assumptions being used (affects completeness)

slide-43
SLIDE 43

Assume equivalent procedures have identical effects

◮ Problem: after isomorphic calls to equivalent procedures

◮ we know that the effects are isomorphic, but ◮ we don’t know what the bijection between the effects is

slide-44
SLIDE 44

Assume equivalent procedures have identical effects

◮ Problem: after isomorphic calls to equivalent procedures

◮ we know that the effects are isomorphic, but ◮ we don’t know what the bijection between the effects is

◮ recall: it is sound to assume that the relevant parts of the

pre-states are related by ≈id

slide-45
SLIDE 45

Assume equivalent procedures have identical effects

◮ Problem: after isomorphic calls to equivalent procedures

◮ we know that the effects are isomorphic, but ◮ we don’t know what the bijection between the effects is

◮ recall: it is sound to assume that the relevant parts of the

pre-states are related by ≈id

◮ idea: can we also assume that the effects are equal?

slide-46
SLIDE 46

Assume equivalent procedures have identical effects

◮ Problem: after isomorphic calls to equivalent procedures

◮ we know that the effects are isomorphic, but ◮ we don’t know what the bijection between the effects is

◮ recall: it is sound to assume that the relevant parts of the

pre-states are related by ≈id

◮ idea: can we also assume that the effects are equal? ◮ No, not directly:

◮ equivalent procedures may allocate different garbage

slide-47
SLIDE 47

1 copy(t,r) { 2

n := new;

3 4

if(t = null) return;

5 6

rl := new;

7

copy(t.l, rl);

8

n.l := rl.v;

9 10

rr := new;

11

copy(t.r, rr);

12

n.r := rr.v;

13 14

r.v := n;

15 } 16 copy ’(t,r) { 17 18 19

if(t = null) return;

20 21

rl := new;

22

copy ’(t.l, rl);

23 24

rr := new;

25

copy ’(t.r, rr);

26 27

r.v := new;

28

r.v.l := rl.v;

29

r.v.r := rr.v;

30 } 31 copy ’’(t,r) { 32 33 34

if(t = null) return;

35 36

rl := new;

37

copy(t.l, rl);

38 39

rr := new;

40

copy(t.r, rr);

41 42

r.v := new;

43

r.v.l := rl.v;

44

r.v.r := rr.v;

45 }

copy ≈ copy’ ⇐ ⇒ copy ≈ copy’’

slide-48
SLIDE 48

1 copy(t,r) { 2

n := new;

3 4

if(t = null) return;

5 6

rl := new;

7

copy(t.l, rl);

8

n.l := rl.v;

9 10

rr := new;

11

copy(t.r, rr);

12

n.r := rr.v;

13 14

r.v := n;

15 } 16 copy ’(t,r) { 17 18 19

if(t = null) return;

20 21

rl := new;

22

copy ’(t.l, rl);

23 24

rr := new;

25

copy ’(t.r, rr);

26 27

r.v := new;

28

r.v.l := rl.v;

29

r.v.r := rr.v;

30 } 31 copy ’’(t,r) { 32 33 34

if(t = null) return;

35 36

rl := new;

37

copy(t.l, rl);

38 39

rr := new;

40

copy(t.r, rr);

41 42

r.v := new;

43

r.v.l := rl.v;

44

r.v.r := rr.v;

45 }

◮ Isomorphic calls of a procedure allocate the same garbage ◮ So it is sound to assume that isomorphic calls of a procedure

have equal effects

slide-49
SLIDE 49

1 copy(t,r) { 2

n := new;

3 4

if(t = null) return;

5 6

rl := new;

7

copy(t.l, rl);

8

n.l := rl.v;

9 10

rr := new;

11

copy(t.r, rr);

12

n.r := rr.v;

13 14

r.v := n;

15 } 16 copy ’(t,r) { 17 18 19

if(t = null) return;

20 21

rl := new;

22

copy ’(t.l, rl);

23 24

rr := new;

25

copy ’(t.r, rr);

26 27

r.v := new;

28

r.v.l := rl.v;

29

r.v.r := rr.v;

30 } 31 copy ’’(t,r) { 32 33 34

if(t = null) return;

35 36

rl := new;

37

copy(t.l, rl);

38 39

rr := new;

40

copy(t.r, rr);

41 42

r.v := new;

43

r.v.l := rl.v;

44

r.v.r := rr.v;

45 }

assume φ7 ≈(t.l,rl),(t.l,rl) φ37 = ⇒ φ7 ≈(t.l,rl),(t.l,rl)

id

φ37 ∧ diff(φ7, φ8) = diff(φ37, φ38)

slide-50
SLIDE 50

Isomorphism doesn’t always follow statement ordering

1 copy(t,r) { 2

n := new;

3 4

if(t = null) return;

5 6

rl := new;

7

copy(t.l, rl);

8

n.l := rl.v;

9 10

rr := new;

11

copy(t.r, rr);

12

n.r := rr.v;

13 14

r.v := n;

15 } 16 copy ’(t,r) { 17 18 19

if(t = null) return;

20 21

rr := new;

22

copy(t.r, rr);

23 24

rl := new;

25

copy(t.l, rl);

26 27

r.v := new;

28

r.v.l := rl.v;

29

r.v.r := rr.v;

30 }

◮ copy copies the left nodes first ◮ copy’ copies the right nodes first ◮ φ7 ≈(t.l,rl),(t.l,rl) φ25 and φ11 ≈(t.r,rr),(t.r,rr) φ22

slide-51
SLIDE 51

Mutual Summaries2 (ish)

From our Boogie encoding:

1

function Copy_succ(h1:Heap ,t:Ref ,r:Ref ,h2:Heap):bool;

2

function Copy ’_succ(h1:Heap ,t:Ref ,r:Ref ,h2:Heap):bool;

Uninterpreted functions as free postconditions represent procedure calls

3

procedure Copy(r:Ref ,t:Ref)

4

...

5

free ensures Copy_succ(old(h),r,t,h);

6

axiom (∀h1 ,h2 ,h3 ,h4:Heap , t_1 ,r_1 ,t_2 ,r_2:Ref :: ...

7

Copy_succ(h1 ,t_1 ,r_1 ,h3)

8

∧ Copy ’_succ(h2 ,t_2 ,r_2 ,h4)

9

∧ Call#Iso(h1 ,t_1 ,r_1 ,h2 ,t_2 ,r_2)

10 =

11

Heap#SameDiff(h1 ,h3 ,h2 ,h4)

12

∧ ...

13

∧ Call#Eq(h1 ,t_1 ,r_1 ,h2 ,t_2 ,r_2));

axioms are like global assumptions

2Hawblitzel, Chris, et al. ”Towards modularly comparing programs using

automated theorem provers.” Automated Deduction–CADE-24 (2013)

slide-52
SLIDE 52

Tool current abilities

1

CopyList(x,r) {

2

if(x!=null ∧ r!=null){

3 4 5 6

rn := new ();

7

CopyList(x.n, rn);

8 9

t := new ();

10

t.n := rn.v;

11

r.v := t;

12 13

}

14 } 15 CopyList ’(x,r) { 16

if(x!=null) {

17

t := new ();

18 19

if(y!=null) {

20

rn := new ();

21

CopyList ’(x.n, rn);

22 23 24

r.v := t;

25

t.n := rn.v;

26

}

27

}

28 }

◮ We can verify equivalence of some programs involving lists

slide-53
SLIDE 53

Unresolved Challenges

◮ Verify programs involving trees or more complex structures

causes solver timeouts

◮ Difficulty is deciding if there is an isomorphism

◮ want to design triggers that instantiate quantifiers more

precisely (which heap addresses/fields are relevant to determining isomorphism)

◮ invent more axioms about which sequences of operations

preserve isomorphism