• Aucun résultat trouvé

Temporary Read-Only Permissions for Separation Logic Making Separation Logic’s Small Axioms Smaller Arthur Charguéraud François Pottier Gallium seminar Paris, April 10, 2017

N/A
N/A
Protected

Academic year: 2022

Partager "Temporary Read-Only Permissions for Separation Logic Making Separation Logic’s Small Axioms Smaller Arthur Charguéraud François Pottier Gallium seminar Paris, April 10, 2017"

Copied!
49
0
0

Texte intégral

(1)

Temporary Read-Only Permissions for Separation Logic

Making Separation Logic’s Small Axioms

Smaller

Arthur Charguéraud François Pottier

Gallium seminar Paris, April 10, 2017

(2)

Separation Logic: to own, or not to own

Separation Logic (Reynolds, 2002) is aboutdisjointnessof heap fragments.

I what “we” own, versus what “others” own.

Therefore, it is aboutunique ownership. A dichotomy arises:

I Of every memory cell,eitherwe have ownership,orwe don’t.

I If we do, then we canread and writethis cell.

I If we don’t, then we canneither write nor even readthis cell.

From memory cells (and arrays), this dichotomy extends to data structures:

To a (user-defined) data structure,

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

(3)

Separation Logic’s read and write axioms

The reasoning rule for writing a cell requires (and returns) a full permission:

set

{l,→v0}(setl v){λy.l,→v} So does the reasoning rule for reading a cell:

traditional read axiom

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

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

But are they as small as they could be?

Isn’t it excessive for reading to require a full permission?

Are there adverse consequences of working with such coarse permissions?

(4)

Separation Logic’s read and write axioms

The reasoning rule for writing a cell requires (and returns) a full permission:

set

{l,→v0}(setl v){λy.l,→v} So does the reasoning rule for reading a cell:

traditional read axiom

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

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

terminology:

“permission” = “assertion”

But are they as small as they could be?

Isn’t it excessive for reading to require a full permission?

Are there adverse consequences of working with such coarse permissions?

(5)

Separation Logic’s read and write axioms

The reasoning rule for writing a cell requires (and returns) a full permission:

set

{l,→v0}(setl v){λy.l,→v} So does the reasoning rule for reading a cell:

traditional read axiom

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

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

But are they as small as they could be?

Isn’t it excessive for reading to require a full permission?

Are there adverse consequences of working with such coarse permissions?

(6)

The problem

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

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 throughout the proofofappend.

I It actuallydoes not guarantee thats1ands2are unmodified.— (next slide)

I It requiress1ands2to bedistinctdata structures.— (slide after next)

(7)

The problem

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

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 throughout the proofofappend.

I It actuallydoes not guarantee thats1ands2are unmodified.— (next slide)

I It requiress1ands2to bedistinctdata structures.— (slide after next)

(8)

The problem, facet 3: 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}

(9)

The problem, facet 3: 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}

(10)

The problem, facet 4: sharing is not permitted

The specification ofappendrequiress1ands2to bedistinctdata structures:

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

{λs3. s3{Seq(L1++L2) ?s1{SeqL1 ?s2{SeqL2} Indeed,s{SeqL ?s{SeqLis equivalent tofalse.

As a result, to allow sharing, we must establishanother specification: {s{SeqL}

(append s s)

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

Duplicate workfor us.Increased complicationand/or duplicate work for the user.

(11)

The problem, facet 4: sharing is not permitted

The specification ofappendrequiress1ands2to bedistinctdata structures:

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

{λs3. s3{Seq(L1++L2) ?s1{SeqL1 ?s2{SeqL2} Indeed,s{SeqL ?s{SeqLis equivalent tofalse.

As a result, to allow sharing, we must establishanother specification:

{s{SeqL} (append s s)

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

Duplicate workfor us.Increased complicationand/or duplicate work for the user.

(12)

Fractional permissions to the rescue...?

Could sequence concatenation be specified as follows in Concurrent SL?

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

{λs3. s3{Seq(L1++L2) ? π1·(s1{SeqL1)? π2·(s2{SeqL2)} Yes, if the logic allowsscaling,π·H. This requires existential quantification to be restricted so as to be precise (Boyland, 2010).

Without scaling, one must defines{SeqπL.

This addresses problem facets 3 and 4,

I but is stillnoisy,

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

“Hiding the fractions” (Heule et al, 2013) is cool but requires yet more machinery.

(13)

Fractional permissions to the rescue...?

Could sequence concatenation be specified as follows in Concurrent SL?

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

{λs3. s3{Seq(L1++L2) ? π1·(s1{SeqL1)? π2·(s2{SeqL2)} Yes, if the logic allowsscaling,π·H. This requires existential quantification to be restricted so as to be precise (Boyland, 2010).

Without scaling, one must defines{SeqπL. This addresses problem facets 3 and 4,

I but is stillnoisy,

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

“Hiding the fractions” (Heule et al, 2013) is cool but requires yet more machinery.

(14)

In this paper

We propose a solution that is:

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

I but significantlysimpler.

Our contributions:

I introducing aread-only modality, RO.

RO(H)representstemporaryread-only access to the memory governed byH.

I findingsimple and sound reasoning rulesfor RO.

I proposinga modelthat justifies these rules.

(15)

Some Intuition

Reasoning Rules

Model

Conclusion

(16)

Our solution

We would like the specification ofappendto look like this:

{RO(s1{SeqL1) ?RO(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 specimpliesthe earlier spec.— (slide after next)

(17)

Our solution

We would like the specification ofappendto look like this:

{RO(s1{SeqL1) ?RO(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 specimpliesthe earlier spec.— (slide after next)

(18)

Our solution, facet 4: sharing is permitted

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

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

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

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

consequence

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

(19)

Our solution, facet 4: sharing is permitted

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

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

{ λs3. s3{Seq(L++L) } { RO(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

(20)

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

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

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

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

{ RO(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.

(21)

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

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

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

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

{ RO(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

(22)

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

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

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

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

{ RO(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 weakened

(23)

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

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

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

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

{ RO(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

(24)

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

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

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

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

{ RO(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

(25)

Some Intuition

Reasoning Rules

Model

Conclusion

(26)

Permissions

The syntax of permissions is as follows:

H := [P]|l,→v|H1?H2|H1∨∨H2| ∃∃x.H|RO(H) EverypermissionHhas a read-only form RO(H).

(27)

Properties of RO

Read-only access to a data structure entails read-only access to its parts:

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

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

RO([P]) = [P]

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

RO(H) . RO(H0) ifH.H0

(28)

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

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

(29)

A new frame rule

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

frame rule

{H}t{Q} normalH0 {H?H0}t{Q?H0}

read-only frame rule

{H?RO(H0)}t{Q} normalH0 {H?H0}t{Q?H0}

This says: upon entry into a block,H0istemporarily replacedwith RO(H0), and upon exit,magically re-appears.

The side condition normalH0means roughly thatH0has no RO components.

This means thatread-only permissions cannot be framed out.

If they could, the read-only frame rule would clearly be unsound. (Exercise!)

(30)

How read-only permissions are used

No reasoning rule involves a triple whose postcondition contains RO.

Read-only permissions always appear inpreconditions, never in postconditions.

They are alwayspassed down, never returned.

In fact, in the model, we will see that, in a triple{H}t{Q}:

I the postcondition applies only tosome read-write fragmentof the final heap;

I the read-only part of the heapmust be preservedanyway, so there is no need for the postcondition to describe it.

(31)

Some Intuition

Reasoning Rules

Model

Conclusion

(32)

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).

(33)

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

(34)

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

(35)

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

(36)

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

(37)

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

(38)

The read-only modality

h h’

RO(H)is interpreted as follows:

RO(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.

(39)

The read-only modality

h h’

RO(H)is interpreted as follows:

RO(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.

(40)

The read-only modality

h h’

RO(H)is interpreted as follows:

RO(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.

(41)

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=∅

(42)

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

(43)

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

(44)

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

(45)

Soundness

Theorem

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

Proof.

“Straightforward”. Machine-checked.

(46)

Some Intuition

Reasoning Rules

Model

Conclusion

(47)

We propose:

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

I a simple modelthat explains why this is sound.

We believe that temporary read-only permissions sometimes help state moreconcise,accurate,usefulspecifications, and lead to simpler proofs.

Possible future work: an implementation in CFML (Charguéraud).

(48)

Amnesia (1/2)

Supposepopulationhas this “RO” specification:

{RO(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 “RO” is sugar for repeatingh{HashTableMin the pre and post, then the proof offooruns into a problem...

(49)

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 “RO” is sugar, the specification ofpopulationisweakerthan it seems.

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

Références

Documents relatifs

[r]

When accessing a database through SQL from an ordinary programming language, such as C# or Java, there is typically a strict segregation between data under the control of the DB

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

I a simple extension of Separation Logic with a read-only modality;. I a simple model that explains why this

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

Our empirical analysis for Swiss cantons over the period 1984–2005 suggests that fiscal rules have an economically and statistically significant negative effect on the probability of

Prenez  le  débat  publié  ce  mois-ci  (page 1432)  sur  les  β-agonistes  pour  la  maladie  pulmonaire 

E very day thousands of women perform home pregnancy tests (HPTs) with their fingers crossed, hoping for either a positive or negative result, as the case may be.. Much rests on