• Aucun résultat trouvé

Temporary Read-Only Permissions for Separation Logic

N/A
N/A
Protected

Academic year: 2022

Partager "Temporary Read-Only Permissions for Separation Logic"

Copied!
60
0
0

Texte intégral

(1)

Temporary Read-Only Permissions for Separation Logic

Arthur Charguéraud François Pottier (talk delivered byArmaël Guéneau)

ESOP 2017 Uppsala, April 28, 2017

(2)

Separation Logic: to own, or not to own

The setting is basic (sequential) Separation Logic.

Separation Logic is aboutdisjointness, therefore aboutunique ownership.

A dichotomy arises:

To every memory cell, array, or user-defined data structure,

either we haveno access at all, or we havefull read-write access.

This is visible in the read and write axioms, which both need afull permission: set

{l,→v0}(setl v){λy.l,→v}

traditional read axiom

{l,→v}(getl){λy.[y=v]?l,→v}

(3)

Separation Logic: to own, or not to own

The setting is basic (sequential) Separation Logic.

Separation Logic is aboutdisjointness, therefore aboutunique ownership.

A dichotomy arises:

To every memory cell, array, or user-defined data structure,

either we haveno access at all, or we havefull read-write access.

This is visible in the read and write axioms, which both need afull permission:

set

{l,→v0}(setl v){λy.l,→v}

traditional read axiom

{l,→v}(getl){λy.[y=v]?l,→v}

(4)

The problem

Suppose we are implementing an abstract data type of mutable sequences.

An abstract predicates{SeqL represents theunique ownershipof a sequence.

Here is a typical specification of sequence concatenation:

{s1{SeqL1 ?s2{SeqL2} (append s1s2)

{λs3. s3{Seq(L1++L2) ?s1{SeqL1 ?s2{SeqL2}

Although correct, this style of specification can be criticized on several grounds:

I It is a bitnoisy.

I It requires the permissionss1{SeqL1 ?s2{SeqL2to be threaded through the proofofappend.

I It actuallydoes not guarantee thats1ands2are unmodifiedin memory.

I It requiress1ands2to bedistinctdata structures.— (next slide)

(5)

The problem

Suppose we are implementing an abstract data type of mutable sequences.

An abstract predicates{SeqL represents theunique ownershipof a sequence.

Here is a typical specification of sequence concatenation:

{s1{SeqL1 ?s2{SeqL2} (append s1s2)

{λs3. s3{Seq(L1++L2) ?s1{SeqL1 ?s2{SeqL2}

Although correct, this style of specification can be criticized on several grounds:

I It is a bitnoisy.

I It requires the permissionss1{SeqL1 ?s2{SeqL2to be threaded through the proofofappend.

I It actuallydoes not guarantee thats1ands2are unmodifiedin memory.

I It requiress1ands2to bedistinctdata structures.— (next slide)

(6)

The problem, focus: sharing is not permitted

This specification requiress1ands2to bedistinct(disjoint) data structures:

{s1{SeqL1 ?s2{SeqL2} (append s1s2)

{λs3. s3{Seq(L1++L2) ?s1{SeqL1 ?s2{SeqL2}

(append s s)requiress{SeqL ?s{SeqL, which the client cannot produce.

To allow(append s s), we must establishanother specification: {s{SeqL}

(append s s)

{λs3. s3{Seq(L++L) ?s{SeqL}

Duplicate workandincreased complicationfor us and for our clients.

(7)

The problem, focus: sharing is not permitted

This specification requiress1ands2to bedistinct(disjoint) data structures:

{s1{SeqL1 ?s2{SeqL2} (append s1s2)

{λs3. s3{Seq(L1++L2) ?s1{SeqL1 ?s2{SeqL2}

(append s s)requiress{SeqL ?s{SeqL, which the client cannot produce.

To allow(append s s), we must establishanother specification:

{s{SeqL} (append s s)

{λs3. s3{Seq(L++L) ?s{SeqL}

Duplicate workandincreased complicationfor us and for our clients.

(8)

Fractional permissions to the rescue...?

In (some) Concurrent SLs, sequence concatenation can be specified as follows:

∀π1, π2.{π1·(s1{SeqL1) ? π2·(s2{SeqL2)} (append s1s2)

{λs3. s3{Seq(L1++L2) ? π1·(s1{SeqL1)? π2·(s2{SeqL2)} Wescalean assertion by a fraction:π·H.

This addresses the main aspects of the problem,

I but is stillnoisy,

I might seem a bit frightening to non-experts,

I and still requires carefulsplitting, threading, and joiningof permissions.

I “Hiding” fractions (Heule et al, 2013) adds another layer of sophistication.

(9)

Fractional permissions to the rescue...?

In (some) Concurrent SLs, sequence concatenation can be specified as follows:

∀π1, π2.{π1·(s1{SeqL1) ? π2·(s2{SeqL2)} (append s1s2)

{λs3. s3{Seq(L1++L2) ? π1·(s1{SeqL1)? π2·(s2{SeqL2)} Wescalean assertion by a fraction:π·H.

This addresses the main aspects of the problem,

I but is stillnoisy,

I might seem a bit frightening to non-experts,

I and still requires carefulsplitting, threading, and joiningof permissions.

I “Hiding” fractions (Heule et al, 2013) adds another layer of sophistication.

(10)

In this paper

We propose a solution that is:

I not as powerfulas fractional permissions (or other share algebras),

I but significantlysimpler. (A design “sweet spot”?) Our contributions:

I introducing aread-only modality,const(in the paper: “RO”).

const(H)givestemporaryread-only access to the memory governed byH.

I findingsimple and sound reasoning rulesforconst.

I proposinga modelthat justifies these rules.

(11)

Some Intuition

Reasoning Rules

Model

Conclusion

(12)

Our solution

We would like the specification ofappendto look like this:

{const(s1{SeqL1) ?const(s2{SeqL2)} (append s1s2)

{λs3. s3{Seq(L1++L2)}

Compared with the earlier specification based on unique read-write permissions,

I this specification ismore concise,

I imposesfewer proof obligations,

I makes it clear thatthe data structures cannot be modifiedbyappend,

I anddoes not requires1ands2to be distinct.— (next slide)

I Furthermore, this specimpliesboth earlier specs.— (next slide)

(13)

Our solution

We would like the specification ofappendto look like this:

{const(s1{SeqL1) ?const(s2{SeqL2)} (append s1s2)

{λs3. s3{Seq(L1++L2)}

Compared with the earlier specification based on unique read-write permissions,

I this specification ismore concise,

I imposesfewer proof obligations,

I makes it clear thatthe data structures cannot be modifiedbyappend,

I anddoes not requires1ands2to be distinct.— (next slide)

I Furthermore, this specimpliesboth earlier specs.— (next slide)

(14)

The new spec subsumes both earlier specs

{const(s1{SeqL1) ?const(s2{SeqL2)} (appends1s2)

{λs3. s3{Seq(L1++L2)} new spec

{const(s{SeqL)} (appends s)

{λs3. s3{Seq(L++L)}

new spec (with sharing)

{s{SeqL} (appends s)

{λs3. s3{Seq(L++L)

?s{SeqL}

earlier spec (with sharing) {s1{SeqL1 ?s2{SeqL2}

(appends1s2)

{λs3. s3{Seq(L1++L2)

?s1{SeqL1 ?s2{SeqL2} earlier spec (without sharing)

(15)

The new spec subsumes both earlier specs

{const(s1{SeqL1) ?const(s2{SeqL2)} (appends1s2)

{λs3. s3{Seq(L1++L2)} new spec

{const(s{SeqL)} (appends s)

{λs3. s3{Seq(L++L)}

new spec (with sharing)

{s{SeqL} (appends s)

{λs3. s3{Seq(L++L)

?s{SeqL}

earlier spec (with sharing)

{s1{SeqL1 ?s2{SeqL2} (appends1s2)

{λs3. s3{Seq(L1++L2)

?s1{SeqL1 ?s2{SeqL2} earlier spec (without sharing)

(16)

The new spec subsumes both earlier specs

{const(s1{SeqL1) ?const(s2{SeqL2)} (appends1s2)

{λs3. s3{Seq(L1++L2)} new spec

{const(s{SeqL)} (appends s)

{λs3. s3{Seq(L++L)}

new spec (with sharing)

{s{SeqL} (appends s)

{λs3. s3{Seq(L++L)

?s{SeqL}

earlier spec (with sharing)

{s1{SeqL1 ?s2{SeqL2} (appends1s2)

{λs3. s3{Seq(L1++L2)

?s1{SeqL1 ?s2{SeqL2} earlier spec (without sharing)

(17)

The new spec subsumes both earlier specs

{const(s1{SeqL1) ?const(s2{SeqL2)} (appends1s2)

{λs3. s3{Seq(L1++L2)} new spec

{const(s{SeqL)} (appends s)

{λs3. s3{Seq(L++L)}

new spec (with sharing)

{s{SeqL} (appends s)

{λs3. s3{Seq(L++L)

?s{SeqL}

earlier spec (with sharing) {s1{SeqL1 ?s2{SeqL2}

(appends1s2)

{λs3. s3{Seq(L1++L2)

?s1{SeqL1 ?s2{SeqL2} earlier spec (without sharing)

(18)

Some Intuition

Reasoning Rules

Model

Conclusion

(19)

Assertions

The syntax of assertions is extended:

H := [P]|l,→v|H1?H2|H1∨∨H2| ∃∃x.H|const(H) Read-only access to a data structure entailsread-only access to its parts:

const(H1?H2) const(H1)?const(H2) (the reverse is false) Read-only access can beshared:

const(H) = const(H)?const(H) (A few more axioms, not shown).

(20)

A new read axiom

The traditional read axiom:

traditional read axiom

{l,→v}(getl){λy.[y=v]?l,→v} is replaced with a “smaller” axiom:

new read axiom

{const(l,→v)}(getl){λy.[y=v]} The traditional axiom can be derived from the new axiom.

(21)

A new frame rule

The traditional frame rule is subsumed by a new “read-only frame rule”:

frame rule

{H}t{Q} normal(H0) {H?H0}t{Q?H0}

read-only frame rule

{H?const(H0)}t{Q} normal(H0) {H?H0}t{Q?H0}

Upon entry into a code block,H0can betemporarily replacedwithconst(H0), and upon exit,H0magically re-appears.

The side conditionnormal(H0)means roughly thatH0has noconstcomponents. This means thatread-only permissions cannot be framed out.

Not a problem, as they are alwayspassed down, never returned. They never appear in postconditions.

(22)

A new frame rule

The traditional frame rule is subsumed by a new “read-only frame rule”:

frame rule

{H}t{Q} normal(H0) {H?H0}t{Q?H0}

read-only frame rule

{H?const(H0)}t{Q} normal(H0) {H?H0}t{Q?H0}

Upon entry into a code block,H0can betemporarily replacedwithconst(H0), and upon exit,H0magically re-appears.

The side conditionnormal(H0)means roughly thatH0has noconstcomponents.

This means thatread-only permissions cannot be framed out.

Not a problem, as they are alwayspassed down, never returned.

They never appear in postconditions.

(23)

Some Intuition

Reasoning Rules

Model

Conclusion

(24)

Interpretation of assertions

In a heap fragment, let every cell be coloredRWorRO.

Let separating conjunction require:

I disjointnessof the RW areas;

I disjointnessof one side’s RW area with the other side’s RO area;

I agreementon the content of the heap where the RO areas overlap.

If an assertionHdescribes a certain set of heaps, then:

I Letconst(H)describethe same heaps, colored entirely RO.

I Letnormal(H)mean that every heap inHis colored entirely RW.

(25)

Interpretation of triples

The meaning of the Hoare triple{H}t{Q}is a variant of the usual:

∀h1h2.

( h1+h2is defined H h1

)

⇒ ∃vh01.













h01+h2is defined t/bh1+h2c ⇓v/bh01+h2c (Q ?true)v h10

h01.r=h1.r













Roughly, “If part of the heap satisfiesH, thentruns safely and changes that part of the heap to satisfyQ, leaving the rest untouched.”

We make two changes:

I Q describesa purely RW partof the final heap.

I The RO part of the heap ispreserved, even thoughQ says nothing about it.

(26)

Interpretation of triples

The meaning of the Hoare triple{H}t{Q}is a variant of the usual:

∀h1h2.

( h1+h2is defined H h1

)

⇒ ∃vh01.













h01+h2is defined t/bh1+h2c ⇓v/bh01+h2c on-some-rw-frag(Q v)h01

h01.r=h1.r













Roughly, “If part of the heap satisfiesH, thentruns safely and changes that part of the heap to satisfyQ, leaving the rest untouched.”

We make two changes:

I Qdescribesa purely RW partof the final heap.

I The RO part of the heap ispreserved, even thoughQ says nothing about it.

(27)

Interpretation of triples

The meaning of the Hoare triple{H}t{Q}is a variant of the usual:

∀h1h2.

( h1+h2is defined H h1

)

⇒ ∃vh01.













h01+h2is defined t/bh1+h2c ⇓v/bh01+h2c on-some-rw-frag(Q v)h01 h01.r=h1.r













Roughly, “If part of the heap satisfiesH, thentruns safely and changes that part of the heap to satisfyQ, leaving the rest untouched.”

We make two changes:

I Qdescribesa purely RW partof the final heap.

I The RO part of the heap ispreserved, even thoughQ says nothing about it.

(28)

Soundness

Theorem

With respect to this interpretation of triples, every reasoning rule is sound.

Proof.

“Straightforward”. Machine-checked.

(29)

Some Intuition

Reasoning Rules

Model

Conclusion

(30)

What about concurrency?

Our proof is carried out in asequentialsetting.

I The proof uses big-step operational semantics.

What aboutstructured concurrency, i.e., parallel composition(e1||e2)?

I We believe thatconst permissions remain sound,

I but do not have a proof – a different proof technique is required.

I They allow read-only state to be shared between threads.

What aboutunstructured concurrency, i.e., threads and channels?

I One cannot allowconstpermissions to be sent along channels.

I More complex machinery is required: fractions, lifetimes, . . .

(31)

Conclusion

We propose:

I a simple extensionof Separation Logic with a read-only modality;

I a simple modelthat explains why this is sound.

A possible design sweet spot?

I not so easy to find, worth knowing about;

I applicable to PL design? (e.g., addingconstto Mezzo) Applications:

I moreconcise, moreaccurate, moregeneralspecifications;

I simplerproofs.

Pending implementation in CFML (Charguéraud).

(32)

Some Intuition

Reasoning Rules

Model

Conclusion

(33)

Temporary modifications are not forbidden

Repeating “s{SeqL” in the pre- and postcondition can be deceiving.

This doesnotforbid changes to theconcretedata structure in memory.

Here is a function that really just reads the data structure:

{s{SeqL}(length s){λy.s{SeqL ?[y=|L|]}

And a function that actually modifies the data structure:

{s{SeqL ?[|L| ≤n]}(resize s n){λ().s{SeqL}

(34)

Temporary modifications are not forbidden

Repeating “s{SeqL” in the pre- and postcondition can be deceiving.

This doesnotforbid changes to theconcretedata structure in memory.

Here is a function that really just reads the data structure:

{s{SeqL}(length s){λy.s{SeqL ?[y=|L|]} And a function that actually modifies the data structure:

{s{SeqL ?[|L| ≤n]}(resize s n){λ().s{SeqL}

(35)

Amnesia (1/2)

Supposepopulationhas this specification:

{const(h{HashTableM)}(population h){λy.[y=cardM]}

Suppose a hash table is a mutable record whosedatafield points to an array:

h{HashTableM:=

∃∃a.∃∃L.(h{{data=a;. . .}?a{ArrayL? . . .) Suppose there is an operationfooon hash tables:

letfoo h=

letd=h.datain – read the address of the array letp=population hin – callpopulation

. . .

If “const” is sugar for repeatingh{HashTableMin the pre and post, then the proof offooruns into a problem...

(36)

Amnesia (2/2)

Reasoning aboutfoomight go like this:

1 letfoo h=

2 {h{HashTableM} –foo’s precondition

3 {h{{data=a;. . .}?a{ArrayL? . . .} – by unfolding

4 letd=h.datain

5 {h{{data=a;. . .}?a{ArrayL? . . . ?[d=a]} – by reading

6 {h{HashTableM?[d=a]} – by folding

7 letp=population hin – wehaveto fold

8 {h{HashTableM?[d=a]?[p= #M]}

9 . . .

At line 8, the equationd=ais useless.

We haveforgottenwhatdrepresents, andlost the benefitof the read at line 4.

If “const” is sugar, the specification ofpopulationisweakerthan it seems.

If “const” is native, there is a way around this problem. (Details omitted.)

(37)

Our solution, facet 4: sharing is permitted

The top Hoare triple is the new spec ofappend, wheres1ands2are instantiated withs.

{ const(s{SeqL) ?const(s{SeqL) } (append s s)

{ λs3. s3{Seq(L++L) } { const(s{SeqL) } (append s s)

{ λs3. s3{Seq(L++L) }

consequence

The bottom triple states that, with read-only access tos,append s sispermitted.

(38)

Our solution, facet 4: sharing is permitted

The top Hoare triple is the new spec ofappend, wheres1ands2are instantiated withs.

{ const(s{SeqL) ?const(s{SeqL) } (append s s)

{ λs3. s3{Seq(L++L) } { const(s{SeqL) } (append s s)

{ λs3. s3{Seq(L++L) }

consequence

The bottom triple states that, with read-only access tos,append s sispermitted.

read-only permissions are

duplicable

(39)

Our solution, facet 5: the earlier specification can be derived

The Hoare triple at the top is the new spec ofappend.

{ const(s1{SeqL1) ?const(s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) }

{ const(s1{SeqL1 ?s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) } { s1{SeqL1 ?s2{SeqL2 } (append s1s2)

{ λs3. s3{Seq(L1++L2) ?s1{SeqL1?s2{SeqL2 }

read-only frame consequence

The triple at the bottom is the earlier spec ofappend.

(40)

Our solution, facet 5: the earlier specification can be derived

The Hoare triple at the top is the new spec ofappend.

{ const(s1{SeqL1) ?const(s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) }

{ const(s1{SeqL1 ?s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) } { s1{SeqL1 ?s2{SeqL2 } (append s1s2)

{ λs3. s3{Seq(L1++L2) ?s1{SeqL1?s2{SeqL2 }

read-only frame consequence

The triple at the bottom is the earlier spec ofappend.

permission becomes read-only

(41)

Our solution, facet 5: the earlier specification can be derived

The Hoare triple at the top is the new spec ofappend.

{ const(s1{SeqL1) ?const(s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) }

{ const(s1{SeqL1 ?s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) } { s1{SeqL1 ?s2{SeqL2 } (append s1s2)

{ λs3. s3{Seq(L1++L2) ?s1{SeqL1?s2{SeqL2 }

read-only frame consequence

The triple at the bottom is the earlier spec ofappend.

read-only permission

is split

(42)

Our solution, facet 5: the earlier specification can be derived

The Hoare triple at the top is the new spec ofappend.

{ const(s1{SeqL1) ?const(s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) }

{ const(s1{SeqL1 ?s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) } { s1{SeqL1 ?s2{SeqL2 } (append s1s2)

{ λs3. s3{Seq(L1++L2) ?s1{SeqL1?s2{SeqL2 }

read-only frame consequence

The triple at the bottom is the earlier spec ofappend.

appendis called

(43)

Our solution, facet 5: the earlier specification can be derived

The Hoare triple at the top is the new spec ofappend.

{ const(s1{SeqL1) ?const(s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) }

{ const(s1{SeqL1 ?s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) } { s1{SeqL1 ?s2{SeqL2 } (append s1s2)

{ λs3. s3{Seq(L1++L2) ?s1{SeqL1?s2{SeqL2 }

read-only frame consequence

The triple at the bottom is the earlier spec ofappend.

read-write permission

magically re-appears

(44)

Our solution, facet 5: the earlier specification can be derived

The Hoare triple at the top is the new spec ofappend.

{ const(s1{SeqL1) ?const(s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) }

{ const(s1{SeqL1 ?s2{SeqL2) } (append s1s2)

{ λs3. s3{Seq(L1++L2) } { s1{SeqL1 ?s2{SeqL2 } (append s1s2)

{ λs3. s3{Seq(L1++L2) ?s1{SeqL1?s2{SeqL2 }

read-only frame consequence

The triple at the bottom is the earlier spec ofappend.

no need to join read-only permissions

(45)

Assertions

The syntax of assertions is extended:

H := [P]|l,→v|H1?H2|H1∨∨H2| ∃∃x.H|const(H) Read-only access to a data structure entails read-only access to its parts:

const(H1?H2) const(H1)?const(H2) (the reverse is false) Read-only permissions are duplicable (therefore, no need to count them!):

const(H) = const(H)?const(H) Read-only permissions are generally well-behaved:

const([P]) = [P]

const(H1∨∨H2) = const(H1)∨∨const(H2) const(∃∃x.H) = ∃∃x.const(H)

const(const(H)) = const(H)

const(H) const(H0) ifH H0

(46)

Reasoning rules (structural)

read-only frame rule

{H?const(H0)}t{Q} normal(H0) {H?H0}t{Q?H0}

consequence

HH0 {H0}t{Q0} Q0Q {H}t{Q}

discard-pre {H}t{Q} {H?GC}t{Q}

discard-post {H}t{Q?GC}

{H}t{Q}

extract-prop P ⇒ {H}t{Q} {[P]?H}t{Q} extract-or

{H1}t{Q} {H2}t{Q} {H1∨∨H2}t{Q}

extract-exists

∀x. {H}t{Q} {∃∃x.H}t{Q}

(47)

Reasoning rules (syntax-directed)

val

{[ ]}v{λy.[y=v]}

if

n,0 ⇒ {H}t1{Q} n=0 ⇒ {H}t2{Q} {H}(ifnthent1elset2){Q} framed sequencing rule(let)

{H}t1{Q0} ∀x. {Q0x?H0}t2{Q} {H?H0}(letx=t1int2){Q}

app

v1=µf.λx.t {H}([v1/f] [v2/x]t){Q} {H}(v1v2){Q}

ref

{[ ]}(refv){λy.∃∃l. [y=l]?l,→v}

new read axiom(get)

{const(l,→v)}(getl){λy.[y=v]} set

{l,→v0}(setl v){λy.l,→v}

(48)

Memories & heaps – a simple model of access rights

Amemoryis a finite map of locations to values.

Aheaphis a pair of twodisjointmemoriesh.f andh.r.

I h.f represents the locations to which we havefull access;

I h.r represents the locations to which we haveread-only access.

Anassertion, orpermission, is a predicate over heaps (or: a set of heaps).

(49)

Heap composition & separating conjunction

The combination of two heaps:

h1+h2= (h1.f]h2.f,h1.r∪h2.r)

read-write read-only

is defined only if:

I the read-write componentsh1.f andh2.f aredisjoint;

I the read-only componentsh1.r andh2.ragreewhere they overlap;

I the read-write componenth1.f isdisjointwith the read-only componenth2.r, and vice-versa.

With this in mind,separating conjunctionis interpreted as usual: H1?H2=

λh. ∃h1h2. (h1+h2is defined) ∧ h=h1+h2 ∧ H1h1 ∧ H2h2

(50)

Heap composition & separating conjunction

The combination of two heaps:

h1+h2= (h1.f]h2.f,h1.r∪h2.r)

read-write read-only

is defined only if:

I the read-write componentsh1.f andh2.f aredisjoint;

I the read-only componentsh1.r andh2.ragreewhere they overlap;

I the read-write componenth1.f isdisjointwith the read-only componenth2.r, and vice-versa.

With this in mind,separating conjunctionis interpreted as usual: H1?H2=

λh. ∃h1h2. (h1+h2is defined) ∧ h=h1+h2 ∧ H1h1 ∧ H2h2

(51)

Heap composition & separating conjunction

The combination of two heaps:

h1+h2= (h1.f]h2.f,h1.r∪h2.r)

read-write read-only

is defined only if:

I the read-write componentsh1.f andh2.f aredisjoint;

I the read-only componentsh1.r andh2.ragreewhere they overlap;

I the read-write componenth1.f isdisjointwith the read-only componenth2.r, and vice-versa.

With this in mind,separating conjunctionis interpreted as usual: H1?H2=

λh. ∃h1h2. (h1+h2is defined) ∧ h=h1+h2 ∧ H1h1 ∧ H2h2

(52)

Heap composition & separating conjunction

The combination of two heaps:

h1+h2= (h1.f]h2.f,h1.r∪h2.r)

read-write read-only

is defined only if:

I the read-write componentsh1.f andh2.f aredisjoint;

I the read-only componentsh1.r andh2.ragreewhere they overlap;

I the read-write componenth1.f isdisjointwith the read-only componenth2.r, and vice-versa.

With this in mind,separating conjunctionis interpreted as usual: H1?H2=

λh. ∃h1h2. (h1+h2is defined) ∧ h=h1+h2 ∧ H1h1 ∧ H2h2

(53)

Heap composition & separating conjunction

The combination of two heaps:

h1+h2= (h1.f]h2.f,h1.r∪h2.r)

read-write read-only

is defined only if:

I the read-write componentsh1.f andh2.f aredisjoint;

I the read-only componentsh1.r andh2.ragreewhere they overlap;

I the read-write componenth1.f isdisjointwith the read-only componenth2.r, and vice-versa.

With this in mind,separating conjunctionis interpreted as usual:

H1?H2=

λh. ∃h1h2. (h1+h2is defined) ∧ h=h1+h2 ∧ H1h1 ∧ H2h2

(54)

The read-only modality

h h’

const(H)is interpreted as follows:

const(H) =

λh. (h.f=∅) ∧ ∃h0.(h.r=h0.f]h0.r)∧H h0

This means:

I we have write access tonothing.

I if we had write accessto certain locations for which we have read access, thenHwould hold.

(55)

The read-only modality

h h’

const(H)is interpreted as follows:

const(H) =

λh. (h.f=∅) ∧ ∃h0.(h.r=h0.f]h0.r)∧H h0 This means:

I we have write access tonothing.

I if we had write accessto certain locations for which we have read access, thenHwould hold.

(56)

The read-only modality

h h’

const(H)is interpreted as follows:

const(H) =

λh. (h.f=∅) ∧ ∃h0.(h.r=h0.f]h0.r)∧H h0 This means:

I we have write access tonothing.

I if we had write accessto certain locations for which we have read access, thenHwould hold.

(57)

The rest of the connectives

[P] = λh. (h.f=∅)∧ (h.r=∅)∧ P l,→v = λh. (h.f= (l7→v))∧(h.r=∅) H1∨∨H2 = λh. H1h ∨H2h

∃∃x.H = λh. ∃x.H h normal(H) = ∀h.H h ⇒ h.r=∅

(58)

Interpretation of triples

The meaning of the Hoare triple{H}t{Q}is as follows:

∀h1h2.

( h1+h2is defined H h1

)

⇒ ∃vh01.













h01+h2is defined t/bh1+h2c ⇓v/bh01+h2c h01.r=h1.r

on-some-rw-frag(Q v)h01













What’s nonstandard?

I The read-only part of the heap must bepreserved.

I The postcondition describes onlya read-write fragment of the final heap. on-some-rw-frag(H) =

λh.∃h1h2.(h1+h2is defined) ∧h=h1+h2 ∧h1.r=∅∧ H h1

(59)

Interpretation of triples

The meaning of the Hoare triple{H}t{Q}is as follows:

∀h1h2.

( h1+h2is defined H h1

)

⇒ ∃vh01.













h01+h2is defined t/bh1+h2c ⇓v/bh01+h2c h01.r=h1.r

on-some-rw-frag(Q v)h01













What’s nonstandard?

I The read-only part of the heap must bepreserved.

I The postcondition describes onlya read-write fragment of the final heap. on-some-rw-frag(H) =

λh.∃h1h2.(h1+h2is defined) ∧h=h1+h2 ∧h1.r=∅∧ H h1

(60)

Interpretation of triples

The meaning of the Hoare triple{H}t{Q}is as follows:

∀h1h2.

( h1+h2is defined H h1

)

⇒ ∃vh01.













h01+h2is defined t/bh1+h2c ⇓v/bh01+h2c h01.r=h1.r

on-some-rw-frag(Q v)h01













What’s nonstandard?

I The read-only part of the heap must bepreserved.

I The postcondition describes onlya read-write fragment of the final heap.

on-some-rw-frag(H) =

λh.∃h1h2.(h1+h2is defined) ∧h=h1+h2 ∧h1.r=∅∧ H h1

Références

Documents relatifs

We have presented a powerful Separation Logic with support for user-defined effects and effect handlers, both shallow and deep.. It is restricted to

To guarantee the soundness of our extension of Separation Logic with read-only permissions, we must enforce one key metatheoretical invariant, namely: a mem- ory location is

Cosmo: a concurrent separation logic for Multicore OCaml.. Glen Mével, Jacques-Henri Jourdan, François Pottier

They are known as “small axioms”, because they require minimum permission?. But are they as small as they

We believe that temporary read-only permissions sometimes help state more concise, accurate, useful specifications, and lead to simpler proofs. Possible future work : an

The essential result, which fails for separation logic as a whole, is that when considering the possible models of our list segment predicate, no case analysis on the

To this end it asso- ciates collections and iterators with access permissions, de- fines a simple state machine to capture the iterator usage pro- tocol, and tracks

This fragment consists at least of the rules that govern access to nonatomic locations and can be extended by allowing the use of concurrent data structures whose specification