An introduction to separation logic James Brotherston Programming - - PowerPoint PPT Presentation

an introduction to separation logic
SMART_READER_LITE
LIVE PREVIEW

An introduction to separation logic James Brotherston Programming - - PowerPoint PPT Presentation

An introduction to separation logic James Brotherston Programming Principles, Logic and Verification Group Dept. of Computer Science University College London, UK J.Brotherston@ucl.ac.uk Oracle Labs, Brisbane, 4 December 2015 1/ 19


slide-1
SLIDE 1

An introduction to separation logic

James Brotherston

Programming Principles, Logic and Verification Group

  • Dept. of Computer Science

University College London, UK J.Brotherston@ucl.ac.uk

Oracle Labs, Brisbane, 4 December 2015

1/ 19

slide-2
SLIDE 2

Introduction

Verification of imperative programs is classically based on Hoare triples: {P} C {Q} where C is a program and P, Q are assertions in some logical language. These are read, roughly speaking, as for any state σ satisfying P, if C transforms state σ to σ′, then σ′ satisfies Q. (with some wriggle room allowing us to deal with faulting or non-termination in various ways.)

2/ 19

slide-3
SLIDE 3

Hoare-style verification

A Hoare-style program logic therefore relies on three main components:

  • 1. a language of programs, and an operational semantics

explaining how they transform states;

  • 2. a language of logical assertions, and a semantics explaining

how to read them as true or false in a particular state;

  • 3. a formal interpretation of Hoare triples, together with

(sound) proof rules for manipulating them. We’ll look at these informally first, then introduce a little more formal detail.

3/ 19

slide-4
SLIDE 4

Programs, informally

We consider a standard while language with pointers, memory (de)allocation and recursive procedures. E.g.: deltree(*x) { if x=nil then return; else { l,r := x.left,x.right; deltree(l); deltree(r); free(x); } }

4/ 19

slide-5
SLIDE 5

Assertions, informally

Our assertion language lets us describe heap data structures such as linked lists and trees. E.g., binary trees with root pointer x can be defined by: x = nil : emp ⇒ tree(x) x = nil : x → (y, z) ∗ tree(y) ∗ tree(z) ⇒ tree(x) where

  • emp denotes the empty heap;
  • x → (y, z) denotes a single pointer to a pair of data cells;
  • ∗ means “and separately in memory”.

5/ 19

slide-6
SLIDE 6

An example proof

deltree(*x) { if x=nil then return; else { l,r := x.left,x.right; deltree(l); deltree(r); free(x); } }

6/ 19

slide-7
SLIDE 7

An example proof

{tree(x)} deltree(*x) { if x=nil then return; else { l,r := x.left,x.right; deltree(l); deltree(r); free(x); } } {emp}

6/ 19

slide-8
SLIDE 8

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { l,r := x.left,x.right; deltree(l); deltree(r); free(x); } } {emp}

6/ 19

slide-9
SLIDE 9

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { {x → (y, z) ∗ tree(y) ∗ tree(z)} l,r := x.left,x.right; deltree(l); deltree(r); free(x); } } {emp}

6/ 19

slide-10
SLIDE 10

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { {x → (y, z) ∗ tree(y) ∗ tree(z)} l,r := x.left,x.right; {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l); deltree(r); free(x); } } {emp}

6/ 19

slide-11
SLIDE 11

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { {x → (y, z) ∗ tree(y) ∗ tree(z)} l,r := x.left,x.right; {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l); {x → (l, r) ∗ emp ∗ tree(r)} deltree(r); free(x); } } {emp}

6/ 19

slide-12
SLIDE 12

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { {x → (y, z) ∗ tree(y) ∗ tree(z)} l,r := x.left,x.right; {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l); {x → (l, r) ∗ emp ∗ tree(r)} deltree(r); {x → (l, r) ∗ emp ∗ emp} free(x); } } {emp}

6/ 19

slide-13
SLIDE 13

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { {x → (y, z) ∗ tree(y) ∗ tree(z)} l,r := x.left,x.right; {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l); {x → (l, r) ∗ emp ∗ tree(r)} deltree(r); {x → (l, r) ∗ emp ∗ emp} free(x); {emp ∗ emp ∗ emp} } } {emp}

6/ 19

slide-14
SLIDE 14

An example proof

{tree(x)} deltree(*x) { if x=nil then return; {emp} else { {x → (y, z) ∗ tree(y) ∗ tree(z)} l,r := x.left,x.right; {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l); {x → (l, r) ∗ emp ∗ tree(r)} deltree(r); {x → (l, r) ∗ emp ∗ emp} free(x); {emp ∗ emp ∗ emp} } {emp} } {emp}

6/ 19

slide-15
SLIDE 15

Frame property

Consider the following step in the previous example: {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l) {x → (l, r) ∗ emp ∗ tree(r)} Implicitly, this relies on a framing property, namely: {tree(l)} deltree(l) {emp} {x → (l, r) ∗ tree(l) ∗ tree(r)} deltree(l) {x → (l, r) ∗ emp ∗ tree(r)}

7/ 19

slide-16
SLIDE 16

Classical failure of frame rule

The so-called frame rule, {P} C {Q} {F ∧ P} C {F ∧ Q} is well known to fail in standard Hoare logic. E.g., {x = 0} x := 2 {x = 2} {y = 0 ∧ x = 0} x := 2 {y = 0 ∧ x = 2} is not valid (because y could alias x). As we’ll see, using the “separating conjunction” ∗ instead of ∧ will however give us a valid frame rule.

8/ 19

slide-17
SLIDE 17

Heap memory model

  • We assume an infinite set Val of values of which an infinite

subset Loc ⊂ Val are allocable locations; nil is a non-allocable value.

  • Stacks map variables to values, s : Var → Val.
  • Heaps map finitely many locations to values,

h : Loc ⇀fin Val. We write e for the empty heap (undefined

  • n all locations).
  • Heap composition h1 ◦ h2 is defined to be h1 ∪ h2 if their

domains are non-overlapping, and undefined otherwise.

  • A state is simply a stack paired with a heap, (s, h).

9/ 19

slide-18
SLIDE 18

Program semantics

  • A configuration is given by (C, s, h), where C is a program,

and (s, h) a (stack-heap) state.

  • C could be empty, in which case we call (C, s, h) final (and

usually just write s, h).

  • fault is a special configuration used to catch memory errors.
  • The small-step semantics of programs is then given by a

relation between configurations: (C, s, h) (C′, s′, h′)

10/ 19

slide-19
SLIDE 19

Semantics of assignment and (de)allocation

(x := E, s, h) (s[x → [ [E] ]s], h) [ [E] ]s ∈ dom(h) (x := E.f, s, h) (s[x → h([ [E] ]s).f], h) [ [E] ]s ∈ dom(h) (E.f := E′, s, h) (s, h[[ [E] ]s.f → [ [E′] ]s]) ℓ ∈ Loc \ dom(h) v ∈ Val (E := new(), s, h) (s[x → ℓ], h[ℓ → v]) [ [E] ]s = ℓ ∈ dom(h) (free(E), s, h) (s, (h ↾ (dom(h) \ {ℓ})) C ≡ x := E.f | E.f := E′ | free(E) [ [E] ]s / ∈ dom(h) (C, s, h) fault

11/ 19

slide-20
SLIDE 20

Symbolic-heap assertions

  • Terms t are either variables x, y, z . . . or the constant nil.
  • Pure formulas π and spatial formulas F are given by:

π ::= t = t | t = t F ::= emp | x → t | Pt | F ∗ F (where P a predicate symbol, t a tuple of terms).

  • A symbolic heap is ∃x. Π : F, for Π a set of pure formulas.
  • The predicate symbols might come from a hard-coded set,
  • r might be user-defined.

12/ 19

slide-21
SLIDE 21

Semantics of assertions

We define the forcing relation s, h | = A:

s, h | =Φ t1 = (=)t2 ⇔ s(t1) = (=)s(t2) s, h | =Φ emp ⇔ h = e s, h | =Φ x → t ⇔ dom(h) = {s(x)} and h(s(x)) = s(t) s, h | =Φ Pt ⇔ (s(t), h) ∈ [ [P] ] s, h | =Φ F1 ∗ F2 ⇔ ∃h1, h2. h = h1 ◦ h2 and s, h1 | =Φ F1 and s, h2 | =Φ F2 s, h | =Φ ∃z. Π : F ⇔ ∃v ∈ Val|z|. s[z → v], h | =Φ π for all π ∈ Π and s[z → v], h | =Φ F

The semantics [ [P] ] of inductive predicate P has a standard construction (but outside the scope of this talk).

13/ 19

slide-22
SLIDE 22

Interpretation of Hoare triples

Our interpretation of Hoare triples is almost standard, except we take a fault-avoiding interpretation: Definition {P} C {Q} is valid if, whenever s, h | = P,

  • 1. (C, s, h) ∗ fault (i.e. is memory-safe), and
  • 2. if (C, s, h) ∗ (ǫ, s, h), then s, h |

= Q. If we are interested in total correctness, simply replace the memory-safety condition above by (safe) termination: everything still works!

14/ 19

slide-23
SLIDE 23

Axioms and proof rules for triples

{emp} x := E {x = E[x′/x] : emp} {E.f → } E.f := E′ {E.f → E′} {E.f → t} x := E.f {x = t[x′/x] : E.f → t[x′/x]} {emp} x := new() {x → x′} {E → } free(E) {emp} {P} C1 {R} {R} C2 {Q} {P} C1; C2 {Q} {B : P} C1 {Q} {¬B : P} C2 {Q} {P} if B then C1 else C2 {Q}

(Note that E.f → E′ is a shorthand for E → (. . . , E′, . . .) where E′ occurs at the fth position in the tuple.)

15/ 19

slide-24
SLIDE 24

The frame rule

The general frame rule of separation logic can be stated as follows: {P} C {Q} {F ∗ P} C {F ∗ Q} subject to the obvious sanity condition: C does not modify any variable mentioned in the “frame” F. This rule is exactly what is needed to carry out proofs like the

  • ne we saw before for deltree.

16/ 19

slide-25
SLIDE 25

Soundness of frame rule

Soundness of the frame rule depends on the following two facts about the programming language: Lemma (Safety monotonicity) If (C, s, h) ∗ fault then (C, s, h ◦ h′) ∗ fault (for any h′ such that h ◦ h′ is defined). Lemma (Frame property) Suppose (C, s, h1 ◦ h2) ∗ s, h, and that (C, s, h1) ∗ fault. Then there exists h′ such that (C, s, h1) ∗ s, h′, and, moreover, h = h′ ◦ h2. Together, these lemmas imply the locality of all commands. N.B.: this is an operational fact about the programming language, and nothing at all to do with logic!

17/ 19

slide-26
SLIDE 26

Closing remarks

  • What we call separation logic is really a combination of
  • programming language,
  • assertion language
  • and rules for Hoare triples.
  • The power of separation logic comes from compositionality:

proofs of sub-programs can be combined into proofs of whole programs.

  • Compositionality depends on the frame rule:

{P} C {Q} {F ∗ P} C {F ∗ Q}

  • And the soundness of the frame rule is essentially a

reflection of the locality of commands.

18/ 19

slide-27
SLIDE 27

Further reading

  • S. Ishtiaq and P. O’Hearn.

BI as an assertion language for mutable data structures. In Proc. POPL-28. ACM, 2001. (Winner of Most Influential POPL Paper 2001 award.) J.C. Reynolds. Separation logic: A logic for shared mutable data structures. In Proc. LICS-17. IEEE, 2002.

  • H. Yang and P. O’Hearn.

A semantic basis for local reasoning. In Proc. FoSSaCS-5. Springer. 2002.

  • C. Calcagno, D. Distefano, P. O’Hearn and H. Yang.

Compositional shape analysis by means of bi-abduction. In Journal of the ACM 58(6). ACM, 2011. Original version in Proc. POPL-36. ACM, 2009.

19/ 19