Logical Reasoning for Disjoint Permissions
Abstract
Resource sharing is a fundamental phenomenon in concurrent programming where several threads have permissions to access a common resource. Logics for verification need to capture the notion of permission ownership and transfer. One typical practice is the use of rational numbers in (0, 1] as permissions in which 1 is the full permission and the rest are fractional permissions. Rational permissions are not a good fit for separation logic because they remove the essential “disjointness” feature of the logic itself. We propose a general logic framework that supports permission reasoning in separation logic while preserving disjointness. Our framework is applicable to sophisticated verification tasks such as doing induction over the finiteness of the heap within the object logic or carrying out biabductive inference. We can also prove precision of recursive predicates within the object logic. We developed the ShareInfer tool to benchmark our techniques. We introduce “scaling separation algebras,” a compositional extension of separation algebras, to model our logic, and use them to construct a concrete model.
1 Introduction
Fractional permissions (also called “shares”) are a relatively simple enhancement to separation logic’s original notion of disjointness [4]. Rather than owning a resource (e.g. a memory cell) entirely, a thread is permitted to own a part/fraction of that resource. The more of a resource a thread owns, the more actions it is permitted to take, a mapping called a policy. In this paper we will use the original policy of Bornat [4] to keep the examples straightforward: nonzero ownership of a memory cell permits reading while full ownership also permits writing. More modern logics allow for a variety of more flexible share policies [13, 28, 42], but our techniques still apply. Fractional permissions are less expressive than the “protocolbased” notions of disjointness used in program logics such as FCSL [38, 44], Iris [30], and TaDa [16], but are wellsuited for common concurrent programming patterns such as read sharing and so have been incorporated into many program logics and verification tools [19, 26, 28, 31, 36, 41].

Section 3 it distributes with bientailments—e.g. \(\pi \cdot (P \wedge Q) \dashv \vdash (\pi \cdot P) \wedge (\pi \cdot Q)\)—enabling rewriting techniques and both forwards and backwards reasoning;

Section 4 it works smoothly with the inference process of biabduction [10]; and

Section 5 the side conditions required for bientailments and biabduction can be verified directly in the object logic, leveraging existing entailment checkers.
There has been significant work in recent years on tool support for protocolbased approaches [15, 19, 29, 30, 48], but they require significant user input and provide essentially no inference. Fractional permissions and protocolbased approaches are thus complementary: fractionals can handle large amounts of relatively simple concurrent code with minimal user guidance, while protocolbased approaches are useful for reasoning about the implementations of finegrained concurrent data structures whose correctness argument is more sophisticated.
In addition to Sects. 3, 4 and 5, the rest of this paper is organized as follows.

Section 2 We give the technical background necessary for our work.

Section 6 We document ShareInfer [1], a tool that uses the logical tools developed in Sects. 3, 4 and 5 to infer frames and antiframes and check the necessary side conditions. We benchmark ShareInfer with 27 selective examples.

Section 7 We introduce scaling separation algebra that allows us to construct predicate multiplication on an abstract structure in a compositional way. We show such model can be constructed from Dockins et al.’s tree shares [21]. The key technical proofs in Sects. 5 and 7 have been verified in Coq [1].

Section 8 We prove that there are no useful share models that simultaneously satisfy disjointness and two distributivity axioms. Consequently, at least one axioms has to be removed, which we choose to be the left distributivity. We also prove that the failure of twosided distributivity forces a side condition on a key proof rule for predicate multiplication.

Section 9 We discuss related work before delivering our conclusion.
2 Technical Preliminaries
Share Models. An (additive) share model \((\mathcal {S},\oplus )\) is a partial commutative monoid with a bottom/empty element \(\mathcal {E}\) and top/full element \(\mathcal {F}\). On the rationals in [0, 1], \(\oplus \) is partial addition, \(\mathcal {E}\) is 0, and \(\mathcal {F}\) is 1. We also require the existence of complements \(\overline{\pi }\) satisfying \(\pi \,\oplus \, \overline{\pi } = \mathcal {F}\); in \(\mathbb {Q}\), \(\overline{\pi } \,{\mathop {=}\limits ^\mathrm{{def}}}\, 1  \pi \).
3 Predicate Multiplication
The intuition behind the proof is simple. First in line 3, we check if \(\mathtt {x}\) is null; if so we are in the base case of the \(\mathsf {tree}\) definition and can simply return. If not we can eliminate the left disjunct and can proceed to split the \(\star \)separated bits into disjoint subtrees \(\mathtt {l}\) and \(\mathtt {r}\), and then dividing the ownership of those bits into two “halves”. Let Open image in new window and Open image in new window . When we start the parallel computation on lines 4 and 7 we want to pass the left branch of the computation the \(\mathcal {L}\otimes \pi \)share of the spatial resources, and the right branch of the computation the \(\mathcal {R}\otimes \pi \). In both branches we then need to show that we can read from the data cell, which in the simple policy we use for this paper boils down to making sure that the product of two non\(\mathcal {E}\) shares cannot be \(\mathcal {E}\). This is a basic property for reasonable share models with multiplication. In the remainder of the parallel code (lines 5–6 and 8–9) we need to make recursive calls, which is done by simply instantiating \(\pi \) with \(\mathcal {L}\otimes \pi \) and \(\mathcal {R}\otimes \pi \) in the recursive specification (as well as \(\mathtt {l}\) and \(\mathtt {r}\) for x). The later half proof after the parallel call is pleasantly symmetric to the first half in which we fold back the original tree predicate by merging the two halves \(\mathcal {L}\otimes \pi \) and \(\mathcal {R}\otimes \pi \) back into \(\pi \). Consequently, we arrive at the postcondition \(\pi \cdot \textsf {tree}(x)\), which is identical to the precondition.
3.1 Proof Rules for Predicate Multiplication
Most of the spatial rules are also simple. Recall that \(\mathsf {emp} \,{\mathop {=}\limits ^\mathrm{{def}}}\, \langle \top \rangle \), so DotPure yields \(\pi \cdot \mathsf {emp} \dashv \vdash \mathsf {emp}\). The DotFull rule says that \(\mathcal {F}\) is the scalar identity on predicates, just as it is the multiplicative identity on the share model itself. The DotDot rule allows us to “collapse” repeated predicate multiplication using share multiplication; we will shortly see how we use it to verify the recursive calls to processTree. Similarly, the DotMapsTo rule shows how predicate multiplication combines with basic mapsto by multiplying the associated shares together. All three rules are bidirectional and require no side conditions.
The DotStar rule shows how predicate multiplication distributes into and out of the separating conjunction \(\star \). It is also bidirectional. Crucially, the \(\dashv \) direction fails on nondisjoint share models like \(\mathbb {Q}\), which is the “deeper reason” for the deformation of recursive structures illustrated in Fig. 1. On disjoint share models like Open image in new window , we get equational reasoning \(\dashv \vdash \) subject to the side condition of uniformity. Informally, \(P \vdash \textsf {uniform}(\pi ')\) asserts that any heap that satisfies P has the permission \(\pi '\) uniformly at each of its defined addresses. In Sect. 8 we explain why we cannot admit this rule without a side condition.
3.2 Verification of processTree using predicate multiplication
We now explain how the proof of \(\texttt {processTree}\) is carried out in Fig. 4 using scaling rules in Fig. 3. In line 2, we unfold the definition of predicate \(\textsf {tree}(x)\) which consists of one base case and one inductive case. We reach line 3 by pushing \(\pi \) inward using various rules \(\textsc {DotPure}\), \(\textsc {DotDisj}\), \(\textsc {DotExis}\), \(\textsc {DotMapsto}\) and \(\textsc {DotStar}\). To use \(\textsc {DotStar}\) we must prove that \(\mathsf {tree}(x)\) is \(\mathcal {F}\)uniform, which we show how to do in Sect. 5.4. We prove this lemma once and use it many times.
The base base \(\mathtt {x} = \texttt {null}\) is handled in lines 4–5 by applying rule \(\textsc {DotPure}\), i.e., \(\langle \mathtt {x} = \texttt {null} \rangle \vdash \pi \cdot \langle \mathtt {x} = \texttt {null} \rangle \) and then \(\textsc {DotPos}\), \(\pi \cdot \langle \mathtt {x} = \texttt {null} \rangle \vdash \pi \cdot \mathsf {tree}(x)\). For the inductive case, we first apply \(\textsc {DotFull}\) in line 7 and then replace \(\mathcal {F}\) with \(\mathcal {L}\oplus \mathcal {R}\) (recall that \(\mathcal {R}\) is \(\mathcal {L}\)’s compliment). On line 9 we use \(\textsc {DotPlus}\) to translate the split on shares with \(\oplus \) into a split on heaps with \(\star \).
We show only one parallel process; the other is a mirror image. Line 10 gives the precondition from the Parallel rule, and then in lines 11 and 12 we continue to “push in” the predicate multiplication. To verify the code in lines 13–14 just requires Frame. Notice that we need the DotDot rule to “collapse” the two uses of predicate multiplication into one so that we can apply the recursive specification (with the new \(\pi '\) in the recursive precondition equal to \(\mathcal {L}\otimes \pi \)).
Having taken the predicate completely apart, it is now necessary to put Humpty Dumpty back together again. Here is why it is vital that all of our proof rules are bidirectional, without which we would not be able to reach the final postcondition \(\pi \cdot \mathsf {tree}(x)\). The final wrinkle is that for line 19 we must prove the precision of the \(\mathsf {tree}(x)\) predicate. We show how to do so with example in Sect. 5.4, but typically in a verification this is proved once per predicate as a lemma.
4 Biabductive Inference with Fractional Permissions
Biabduction is a separation logic inference process that helps to increase the scalability of verification for sizable programs [22, 49]; in recent years it has been the focus of substantial research for (sequential) separation logic [8, 10, 11, 32]. Biabduction aims to infer the missing information in an incomplete separation logic entailment. More precisely, given an incomplete entailment \(A \star [??] \vdash B \star [??]\), we would like to find predicates for the two missing pieces [??] that complete the entailment in a nontrivial manner. The first piece is called the antiframe while the second is the inference frame. The standard approach consists of two sequential subroutines, namely the abductive inference and frame inference to construct the antiframe and frame respectively. Our task in this section is to show how to upgrade these routines to handle fractional permissions so that biabduction can extend to concurrent programs. As we will see, disjointness plays a crucial role in antiframe inference.
4.1 Fractional Residue Computation
4.2 Extension of Predicate Axioms
4.3 Abductive Inference and Frame Inference
The discussion of fractional residue computation in Sect. 4.1 and extension of recursive predicate rules in Sect. 4.2 ensure a smooth upgrade of the biabduction algorithm to fractional form. We demonstrate this intuition using the example in Fig. 5. The partial consequent is a fractional \(\textsf {tree}(x)\) predicate with permission \(\pi _3\) while the partial antecedent is star conjunction of a fractional mapsto predicate of address x with permission \(\pi _1\), a fractional \(\textsf {tree}(x_1)\) predicate with permission \(\pi _2\) and a null pointer \(x_2\). Following the spirit of Calcagno et al. [10], the steps in both subroutines include applying the folding and unfolding rules for predicate \(\textsf {tree}\) and then matching the corresponding pair of fragments from antecedent and consequent. On the other hand, the upgraded part is reflected through the use of the two new rules \(\textsc {Msub}\) and \(\textsc {Psub}\) to compute the fractional residues as well as a more general system of folding and unfolding rules for predicate \(\textsf {tree}\). We are then able to compute the antiframe Open image in new window and the inference frame Open image in new window respectively.
5 A Proof Theory for Fractional Permissions
Our main objective in this section is to show how to discharge the uniformity and precision side conditions required by the DotStar and DotPlus rules. To handle recursive predicates like \(\mathsf {tree}(x)\) we develop set of novel modallogic based proof rules to carry out induction in the heap. To allow tools to leverage existing entailment checkers, all of these techniques are done in the object logic itself, rather than in the metalogic. Thus, in Sect. 5, we do not assume a concrete model for our object logic (in Sect. 7 we will develop a model).
First we discuss new proof rules for predicate multiplication and fractional mapsto (Sect. 5.1), precision (Sect. 5.2), and induction over fractional heaps (Sect. 5.3). We then conclude (Sect. 5.4) with two examples of proving real properties using our proof theory: that \(\mathsf {tree}(x)\) is \(\mathcal {F}\)uniform and that \(\mathsf {list}(x)\) is precise. Some of the theorems have delicate proofs, so all of them have been verified in Coq [1].
5.1 Proof Theory for Predicate Multiplication and Fractional MapsTo
In Sect. 3 we presented the key rules that someone who wants to verify programs using predicate multiplication is likely to find convenient. On page 13 we present a series of additional rules, mostly used to establish the “uniform” and “precise” side conditions necessary in our proofs.
Proving the side conditions for DotPlus and DotStar. Figure 7 contains some rules for establishing that P is \(\pi \)uniform (i.e. \(P \vdash \mathsf {uniform}(\pi )\)) and that P is precise. Since uniformity is a simple property, the rules are easy to state:
To use predicate multiplication we will need to prove two kinds of side conditions: \(\mathsf {uniform}\textsc {/}\mathsf {emp}\) tells us that \(\mathsf {emp}\) is \(\pi \)uniform for all \(\pi \); the conclusion (all defined heap locations are held with share \(\pi \)) is vacuously true. The \(\mathsf {uniform}\textsc {Dot}\) rule tells us that if P is \(\pi \)uniform then when we multiply P by a fraction \(\pi '\) the result is \((\pi ' \! \otimes \pi )\)uniform. The \(\mapsto \mathsf {uniform}\) rule tells us that pointsto is uniform. The \(\mathsf {uniform}\star \) rule possesses interesting characteristics. The \(\dashv \) direction follows from \(\mathsf {uniform}\textsc {/}\mathsf {emp}\) and the \(\star \mathsf {emp}\) rule (\(P \star \mathsf {emp} \dashv \vdash P\)). The \(\vdash \) direction is not automatic but very useful. One consequence is that from \(P \vdash \mathsf {uniform}(\pi )\) and \(Q \vdash \mathsf {uniform}(\pi )\) we can prove \(P \star Q \vdash \mathsf {uniform}(\pi )\). The \(\vdash \) direction follows from disjointness but fails over nondisjoint models such as rationals \(\mathbb {Q}\).
The \(\mapsto \textsc {precise}\) rule tells us that pointstos are precise. The DotPrecise rule is a partial solution to proving precision. It states that \(\pi \cdot P\) is precise if and only if P is precise. We will next show how to prove that P itself is precise.
5.2 Proof Theory for Proving that Predicates Are Precise
That said, two notions are closely connected as given in the \(\mathsf {precisely}\textsc {Precise}\) rule. We also give introduction \(\mathsf {precisely}\textsc {Right}\) and elimination rules \(\mathsf {precisely}\textsc {Left}\) that make a connection between precision and an “antidistribution” of \(\star \) over \(\wedge \).
We also give a number of rules for showing how \(\mathsf {precisely}\) combines with the connectives of our logic. The rules for propositional \(\wedge \) and separating \(\star \) conjunction follow wellunderstood patterns, with the addition of an arbitrary premise context G being the key feature. The rule for disjunction \(\vee \) is a little trickier, with an additional premise that forces the disjunction to be exclusive rather than inclusive. An example of such an exclusive disjunction is in the standard definition of the \(\mathsf {tree}\) predicate, where the first disjunct \(\langle x = \mathtt {null} \rangle \) is fundamentally incompatible with the second disjunct \(\exists d,l,r. x \mapsto d,l,r \star \ldots \) since \(\mapsto \) does not allow the address to be \(\mathtt {null}\) (by rule \(\mapsto \mathtt {null}\) from Fig. 6). The rules for universal quantification \(\forall \) existential quantification \(\exists \) are essentially generalizations of the rules for the traditional conjunction \(\wedge \) and disjunction \(\vee \).
It is now straightforward to prove the precision of simple predicates such as \(\langle x = \mathtt {null} \rangle \vee (\exists y. x \mapsto y \star y \mapsto 0)\). Finding and proving the key lemmas that enable the proof of the precision of recursive predicates remains a little subtle.
5.3 Proof Theory for Induction over the Finiteness of the Heap
Recursive predicates such as \(\mathsf {list}(x)\) and \(\mathsf {tree}(x)\) are common in SL. However, proving properties of such predicates, such as proving that \(\mathsf {list}(x)\) is precise, is a little tricky since the \(\mu \textsc {FoldUnfold}\) rule provided by the Tarski fixed point does not automatically provide an induction principle. Generally speaking such properties follow by some kind of induction argument, either over auxiliary parameters (e.g. if we augment trees to have the form \(\mathsf {tree}(x,\tau )\), where \(\tau \) is an inductivelydefined type in the metalogic) or over the finiteness of the heap itself. Both arguments usually occur in the metalogic rather than the object logic.
We have two contributions to make for proving inductive properties. First, we show how to do induction over the heap in a fractional setting. Intuitively this is more complicated than in the nonfractional case because there are infinite sequences of strictly smaller subheaps. That is, for a given initial heap \(h_0\), there are infinite sequences \(h_1\), \(h_2\), ...such that \(h_0 \supsetneq h_1 \supsetneq h_2 \supsetneq \ldots \). The disjointness property does not fundamentally change this issue, so we illustrate with an example with the shares in \(\mathbb {Q}\). The heap \(h_0\) satisfying \(\,\,x {\mathop {\mapsto }\limits ^{1}} y\,\,\) is strictly larger than the heap \(h_1\) satisfying \(\,\,x {\mathop {\mapsto }\limits ^{\frac{1}{2}}} y\,\,\), which is strictly larger than the heap \(h_2\) satisfying \(\,\,x {\mathop {\mapsto }\limits ^{\frac{1}{4}}} y\,\,\); in general \(h_i\) satisfies \(\,\,x {\mathop {\mapsto }\limits ^{\frac{1}{2^i}}} y\,\,\). Since our sequence is infinite, we cannot use it as the basis for an induction argument. The solution is that we require that the heaps decrease by at least some constant size c. If each heap subsequent heap must shrink by at least e.g. \(c=0.25\) of a memory cell then the sequence must be finite just as in the nonfractional case, i.e. \(c=\mathcal {F}\). More sophisticated approaches are conceivable (e.g. limits) but they are not easy to automate and we did not find any practical examples that require such methods.
Our second contribution is the development of a proof theory in the object logic that can carry out these kinds of induction proofs in a relatively straightforward way. The proof rules that let us do so are given in Fig. 9. Once good lemmas are identified, we find doing induction proofs over the finite heap formally in the object logic simpler than doing the same proofs in the metalogic.
The key to our induction rules is two new operators: “within” \(\circledcirc \) and “shrinking” \(\rhd _\pi \). Essentially \(\rhd _\pi P\) is used as an induction guard, preventing us from applying our induction hypothesis P until we are on a \(\pi \)smaller subheap. When \(\pi = \mathcal {F}\) we sometimes write just \(\rhd P\). Semantically, if h satisfies \(\rhd _\pi P\) then P is true on all strict subheaps of h that are smaller by at least a \(\pi \)piece. Accordingly, the key elimination rule \(\rhd _\pi \!\star \) may seem natural: it verifies that the induction guard is satisfied and unlocks the underlying hypothesis. To start an induction proof to prove an arbitrary goal \(\top \,\models \, P\), we use the rule W to introduce an induction hypothesis, resulting in the new entailment goal of \(\rhd _\pi P \vdash P\).
Some definitions, such as \(\mathsf {list}(x)\), have only one “recursive call”; others, such as \(\mathsf {tree}(x)\) have more than one. Moreover, sometimes we wish to apply our inductive hypothesis immediately after satisfying the guard, whereas other times it is convenient to satisfy the guard somewhat before we need the inductive hypothesis. To handle both of these issues we use the “within” operator \(\circledcirc \) such that \(h \,\models \, \circledcirc P\) means P is true on all subheaps of h, which is the intuition behind the rule \(\circledcirc \!\star \). To apply our induction hypothesis somewhat after meeting its guard (or if we wish to apply it more than once) we use the \(\rhd _\pi \!\circledcirc \) rule to add the \(\circledcirc \) modality before eliminating the guard. We will see an example of this shortly.
5.4 Using Our Proof Theory
We now turn to two examples of using our proof theory from page 13 to demonstrate that the rule set is strong and flexible enough to prove real properties.
Proving that \(\mathsf {tree}(x)\) is \(\mathcal {F}\)uniform. Our logical rules for induction and uniformity are able to establish the uniformity of predicates in a fairly simple way. Here we focus on the \(\mathsf {tree}(x)\) predicate because it is a little harder due to the two recursive “calls” in its unfolding. For convenience, we will write \(\mathsf {u}(\pi )\) instead of \(\mathsf {uniform}(\pi )\).
In Fig. 10 we give four key lemmas used in our proof^{2}. All four are derived (with a little cleverness) from the proof rules given in Fig. 8. We sketch the proof as follows. To prove \(\text {precise}(\mathsf {list}(x))\) we first use the \(\mathsf {precisely}\textsc {Precise}\) rule to transform the goal into \(\top \vdash \mathsf {precisely}(\mathsf {list}(x))\). We cannot immediately apply rule W, however, since without a concrete \(\star \)separated conjunct outside the \(\mathsf {precisely}\), we cannot dismiss the inductive guard with the \(\rhd _\pi \!\star \) rule. Accordingly, we next use lemma (A) and standard natural deduction to reach the goal \(\top \vdash \forall x. (\mathsf {list}(x) \star \top ) \Rightarrow \mathsf {precisely}(\mathsf {list}(x))\), after which we apply rule W with \(\pi = \mathcal {F}\).
6 The ShareInfer fractional biabduction engine
Having described our logical machinery in Sects. 3, 4 and 5, we now demonstrate that our techniques are wellsuited to automation by documenting our \(\textsf {ShareInfer}\) prototype [1]. Our tool is capable of checking whether a userdefined recursive predicate such as \(\textsf {list}\) or \(\textsf {tree}\) is uniform and/or precise and then conducting biabductive inference over a separation logic entailment containing said predicates.
ShareInfer is around 2.5k LOC of Java. We benchmarked it with 27 selective examples from three categories: precision, uniformity and biabduction. The benchmark was conducted with a 3.4 GHz processor and 16 GB of memory. Our results are given in Fig. 11. Despite the complexity of our proof rules our performance is reasonable: \(\textsf {ShareInfer}\) only took 75.9 ms to run the entire example set, or around 2.8 ms per example. Our benchmark is small, but this performance indicates that more sophisticated separation logic verifiers such as HIP/SLEEK [14] or Infer [9] may be able to use our techniques at scale.
7 Building a Model for Our Logic
Our task now is to provide a model for our proof theories. We present our models in several parts. In Sect. 7.1 we begin with a brief review of Cancellative Separation Algebras (CSA). In Sect. 7.2 we explain what we need from our fractional share models. In Sect. 7.3 we develop an extension to CSAs called “Scaling Separation Algebras” (SSA). In Sect. 7.5 we develop the machinery necessary to support our rules for objectlevel induction over the heap. We have verified in Coq [1] that the models in Sect. 7.1 support the rules in Fig. 8, the models in Sect. 7.3 support the rules Figs. 3 and 7, and the models in Sect. 7.5 support the rules in Fig. 9.
7.1 Cancellative Separation Algebras
7.2 Fractional Share Algebras
A fractional share algebra \(\langle S,\oplus ,\otimes ,\mathcal {E},\mathcal {F} \rangle \) (FSA) is a set S with two operations: partial addition \(\oplus \) and total multiplication \(\otimes \). The substructure \(\langle S,\oplus \rangle \) is a CSA with the single unit \(\mathcal {E}\). For the reasons discussed in Sect. 2 we require that \(\oplus \) satisfies the disjointness axiom \(a \oplus a = b \Rightarrow a = \mathcal {E}\). Furthermore, we require that the existence of a top element \(\mathcal {F}\), representing complete ownership, and assume that each element \(s \in S\) has a complement \(\overline{s}\) such that \(s \oplus \overline{s} = \mathcal {F}\).
Often (e.g. in the fractional \(\mapsto \) operator) we wish to restrict ourselves to the “positive shares” \(S^{+} \,{\mathop {=}\limits ^\mathrm{{def}}}\, S \setminus \{\mathcal {E}\}\). To emphasize that a share is positive we often use the metavariable \(\pi \) rather than s. \(\oplus \) is still associative, commutative, and cancellative; every element other than \(\mathcal {F}\) still has a complement. To enjoy a partial order on \(S^{+}\) and other SA or CSAlike structures that lack identities (sometimes called “permission algebras”) we define \(\pi _1 \subseteq \pi _2 \,{\mathop {=}\limits ^\mathrm{{def}}}\, (\exists \pi '. \pi _1 \oplus \pi ' = \pi _2) \vee (\pi _1 = \pi _2)\).
For the multiplicative structure we require that \(\langle S,\otimes ,\mathcal {F} \rangle \) be a monoid, i.e. that \(\otimes \) is associative and has identity \(\mathcal {F}\). Since we restrict mapstos and the permission scaling operator to be positive, we want \(\langle S^{+}, \otimes , \mathcal {F} \rangle \) to be a submonoid. Accordingly, when \(\{\pi _1,\pi _2\} \subset S^{+}\), we require that \(\pi _1 \otimes \pi _2 \ne \mathcal {E}\). Finally, we require that \(\otimes \) distributes over \(\oplus \) on the right, that is \((s_1 \oplus s_2) \otimes s_3 = (s_1 \otimes s_3) \oplus (s_2 \otimes s_3)\); and that \(\otimes \) is cancellative on the right given a positive left multiplicand, i.e. \(\pi \otimes s_1 = \pi \otimes s_2 \Rightarrow s_1 = s_2\).
The tree share model we present in Sect. 2 satisfies all of the above axioms, so we have a nontrivial model. As we will see shortly, it would be very convenient if we could assume that \(\otimes \) also distributed on the left, or if we had multiplicative inverses on the left rather than merely cancellation on the right. However, we will see in Sect. 8.2 that both assumptions are untenable.
7.3 Scaling Separation Algebra
We need to understand how all of the ingredients in an SSA relate to each other to prove the core logical rules on page 13. We distill the various relationships we need to model our logic in Fig. 12. Although there are a goodly number of them, most are reasonably intuitive.
7.4 Compositionality of Scaling Separation Algebras
Despite their complex axiomatization, we gain two advantages from developing SSAs rather than directly proving our logical axioms on a concrete model. First, they give us a precise understanding of exactly which operations and properties (\(S_1\)–\(S_{14}\)) are used to prove the logical axioms. Second, following Dockins et al. [21] we can build up large SSAs compositionally from smaller SSAs.
To do so cleanly it will be convenient to consider a slight variant of SSAs, “Weak SSAs” that allow, but do not require, the existence of identity elements in the underlying CSA model. A WSSA satisfies exactly the same axioms as an SSA, except that we use the weaker \(\subseteq _H\) definition we defined for permission algebras, i.e. \(a_1 \subseteq _H a_2 \,{\mathop {=}\limits ^\mathrm{{def}}}\, (\exists a'. a_1 \oplus _H a' = a_2) \vee (a_1 = a_2)\). Note that \(S_5\) and \(S_9\) are vacuously true when the CSA does not have identity elements. We need identity elements to prove the logical axioms from the model; we only use WSSAs to gain compositionality as we construct a suitable final SSA. Keeping the share components \(\langle S,\oplus _S,\otimes _S,\mathcal {E},\mathcal {F} \rangle \) constant, we give three SSA constructors to get a flavor for what we can do with the remaining components \(\langle H,\oplus _H, force , mul \rangle \).
Example 1
(Shares). The share model \(\langle S, \oplus _S \rangle \) is an SSA, and the positive (non\(\mathcal {E}\)) shares \(\langle S^{+}, \oplus \rangle \) are a WSSA, with \( force _S(\pi ,\pi ') {\mathop {=}\limits ^\mathrm{{def}}}\pi \) and \( mul _S(\pi ,\pi ') {\mathop {=}\limits ^\mathrm{{def}}}\pi \otimes \pi '\).
Example 2
(Semiproduct). Let \(\langle A,\oplus _A, force _A, mul _A \rangle \) be an SSA/WSSA, and B be a set. Define \((a_1,b_1) \oplus _{A \times B} (a_2,b_2) = (a_3,b_3) {\mathop {=}\limits ^\mathrm{{def}}}a_1 \oplus _A a_2 = a_3 \wedge b_1 = b_2 = b_3\), \( force _{A \times B}(\pi ,(a,b)) {\mathop {=}\limits ^\mathrm{{def}}}( force _A(\pi ,a),b)\), and \( mul _{A \times B}(\pi ,(a,b)) {\mathop {=}\limits ^\mathrm{{def}}}( mul _A(\pi ,a),b)\). Then \(\langle A \times B, \oplus _{A \times B}, force _{A \times B} , mul _{A \times B} \rangle \) is an SSA/WSSA.
Example 3
(Finite partial map). Let A be a set and \(\langle B,\oplus _B, force _B, mul _B \rangle \) be an SSA/WSSA. Define \(f \oplus _{A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B} g = h\) pointwise [21]. Define \( force _{A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B}(\pi ,f) {\mathop {=}\limits ^\mathrm{{def}}}\lambda x. force _B(\pi ,f(x))\) and likewise define \( mul _{A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B}(\pi ,f) {\mathop {=}\limits ^\mathrm{{def}}}\lambda x. mul _B(\pi , f(x))\). The structure \(\langle A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B,{\oplus \!}_{A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B}, force\! _{A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B}, mul\! _{A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} B} \rangle \) is an SSA.
Using these constructors, \(A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} (S^{+},V)\), i.e. finite partial maps from addresses to pairs of positive shares and values, is an SSA and thus can support a model for our logic. We also support other standard constructions e.g. sum types \(+\).
7.5 Model for Inductive Logic
8 Lower Bounds on Predicate Multiplication
In Sect. 7 we gave a model for the logical axioms we presented in Fig. 3 and on page 13. Our goal here is to show that it is difficult to do better, e.g. by having a premisefree DotStar rules or a bidirectional DotImpl rule. In Sect. 8.1 we show that these logical rules force properties on the share model. In Sect. 8.2 we show that disjointness puts restrictions on the class of share models. There are no nontrivial models that have left inverses or satisfy both left and right distributivity.
8.1 Predicate Multiplication’s Axioms Force Share Model Properties
The SSA structures we gave in Sect. 7.3 are good for building models that enable the rules for predicate multiplication from Fig. 3. However, since they impose intermediate algebraic and logical signatures between the concrete model and rules for predicate multiplication, they are not good for showing that we cannot do better. Accordingly here we disintermediate and focus on the concrete model \(A {\mathop {\rightharpoonup }\limits ^{\mathsf {fin}}} (S^{+},V)\), that is finite partial maps from addresses to pairs of positive shares and values. The join operations on heaps operates pointwise [21], with \((\pi _1,v_1) \oplus (\pi _2,v_2) = (\pi _3, v_3) {\mathop {=}\limits ^\mathrm{{def}}}\pi _1 \oplus _S \pi _2 = \pi _3 \wedge v_1 = v_2 = v_3\), from which we derive the usual SA model for \(\star \) and \(\mathsf {emp}\) (Sect. 7.1). We define \(h \,\models \, \,\,x {\mathop {\mapsto }\limits ^{\pi }} y\,\, \,{\mathop {=}\limits ^\mathrm{{def}}}\, dom (h) = \{x\} \wedge h(x) = (\pi ,y)\). We define scalar multiplication over heaps \(\otimes _H\) pointwise as well, with \(\pi _1 \otimes (\pi _2, v) \,{\mathop {=}\limits ^\mathrm{{def}}}\, (\pi _1 \otimes _S \pi _2, v)\), and then define predicate multiplication by \(h \,\models \, \pi \cdot P \,{\mathop {=}\limits ^\mathrm{{def}}}\, \exists h'.~ h' = \pi \otimes _H h' = h \wedge h' \,\models \, P\). All of the above definitions are standard except for \(\otimes _H\), which strikes us as the only choice (up to commutativity), and predicate multiplication itself.
By Sect. 7 we already know that this model satisfies the rules for predicate multiplication, given the assumptions on the share model from Sect. 7.2. What is interesting is that we can prove the other direction: if we assume that the key logical rules from Fig. 3 hold, they force axioms on the share model. The key correspondences are: DotFull forces that \(\mathcal {F}\) is the left identity of \(\otimes _S\); DotMapsTo forces that \(\mathcal {F}\) is the right identity of \(\otimes _S\); DotMapsTo forces the associativity of \(\otimes _S\); the \(\dashv \) direction of DotConj forces the right cancellativity of \(\otimes _S\) (as does DotImpl and the \(\dashv \) direction of DotUniv); and DotPlus, which forces right distributivity of \(\otimes _S\) over \(\oplus _S\).
8.2 Disjointness in a Multiplicative Setting
Our goal now is to explore the algebraic consequences of the disjointness property in a multiplicative setting. Suppose \(\langle S,\oplus \rangle \) is a CSA with a single unit \(\mathcal {E}\), top element \(\mathcal {F}\), and \(\oplus \) complements \(\overline{s}\). Suppose further that shares satisfy the disjointness property \(a \oplus a = b \Rightarrow a = \mathcal {E}\). For the multiplicative structure, assume \(\langle S,\otimes ,\mathcal {F} \rangle \) is a monoid (i.e. the axioms forced by the DotDot, DotMapsTo, and DotFull rules). It is undesirable for a share model if multiplying two positive shares (e.g. the ability to read a memory cell) results in the empty permission, so we assume that when \(\pi _1\) and \(\pi _2\) are non\(\mathcal {E}\) then their product \(\pi _1 \otimes \pi _2 \ne \mathcal {E}\).
9 Related Work
Fractional permissions are essentially used to reason about resource ownership in concurrent programming. The wellknown rational model \(\langle [0,1],+ \rangle \) by Boyland et al. [5] is used to reason about joinfork programs. This structure has the disjointness problem mentioned in Sect. 2, first noticed by Bornat et al. [4], as well as other problems discussed in Sects. 3, 4, and [2]. Boyland [6] extended the framework to scale permissions uniformly over arbitrary predicates with multiplication, e.g., he defined \(\pi \cdot P\) as “multiply each permission \(\pi '\) in P with \(\pi \)”. However, his framework cannot fit into SL and his scaling rules are not bidirectional. Jacobs and Piessens [28] also used rationals for scaling permissions \(\pi \cdot P\) in SL but only obtained one direction for \(\textsc {DotStar}\) and \(\textsc {DotPlus}\). A different kind of scaling permission was used by DinsdaleYoung et al. [20] in which they used rationals to define permission assertions \([A]_\pi ^r\) to indicate a thread with permission \(\pi \) can execute the action A over the shared region r.
There are other flavors of permission besides rationals. Bornat et al. [4] introduced integer counting permissions \(\langle \mathbb {Z},+,0 \rangle \) to reason about semaphores and combined rationals and integers into a hybrid permission model. Heule et al. [23] flexibly allowed permissions to be either concretely rational or abstractly readonly to lower the nuisance of detailed accounting. A more general readonly permissions was proposed by Charguéraud and Pottier [13] that transforms a predicate P into readonly mode \(\mathsf {RO}(P)\) which can duplicated/merged with the bientailment \(\mathsf {RO}(P) \dashv \vdash \mathsf {RO}(P) \star \mathsf {RO}(P)\). Their permissions distribute pleasantly over disjunction and existential quantifier but only work one way for \(\star \), i.e., \(\mathsf {RO}(H_1 \star H_2) \vdash \mathsf {RO}(H_1) \star \mathsf {RO}(H_2)\). Parkinson [41] proposed subsets of the natural numbers for shares \(\langle \mathcal {P}(\mathbb {N}),\uplus \rangle \) to fix the disjointness problem. Compared to tree shares, Parkinson’s model is less practical computationally and does not have an obvious multiplicative structure.
Protocolbased logics like FCSL [38] and Iris [30] have been very successful in reasoning about finegrained concurrent programs, but their high expressivity results in a heavyweight logic. Automation (e.g. inference such as we do in Sect. 4) has been hard to come by. We believe that fractional permissions and protocolbased logics are in a meaningful sense complementary rather than competitors.
Verification tools often implement rational permissions because of its simplicity. For example, VeriFast [29] uses rationals to verify programs with locks and semaphores. It also allows simple and restrictive forms of scaling permissions which can be applied uniformly over standard predicates. On the other hand, HIP/SLEEK [31] uses rationals to model “thread as resource” so that the ownership of a thread and its resources can be transferred. Chalice [36] has rational permissions to verify properties of multithreaded, objectedbased programs such as data races and deadlocks. Viper [37] has an expressive intermediate language that supports both rational and abstract permissions. However, a number of verification tools have chosen tree shares due to their better metatheoretical properties. VST [3] is equipped with tree share permissions and an extensive tree share library. HIP/SLEEK uses tree shares to verify the barrier structure [26] and has its own complete share solver [33, 35] that reduces tree formulae to Boolean formulae handled by Z3 [17]. Lastly, tree share permissions are featured in HeapHop [47] to reason over asynchronous communications.
10 Conclusion
We presented a separation logic proof framework to reason about resource sharing using fractional permissions in concurrent verification. We support sophisticated verification tasks such as inductive predicates, proving predicates precise, and biabduction. We wrote ShareInfer to gauge how our theories could be automated. We developed scaling separation algebras as compositional models for our logic. We investigated why our logic cannot support certain desirable properties.
Footnotes
 1.
We write \(\,\,x {\mathop {\mapsto }\limits ^{\pi }} (v_1,\ldots ,v_n)\,\,\) for \(\,\,x {\mathop {\mapsto }\limits ^{\pi }} v_1\,\, \star \,\,(x+1) {\mathop {\mapsto }\limits ^{\pi }} v_2\,\, \star \ldots \star \,\,(x+n1) {\mathop {\mapsto }\limits ^{\pi }} v_n\,\,\).
 2.
We abuse notation by reusing the inference rule format to present derived lemmas.
References
 1.
 2.
 3.Appel, A.W.: Verified software toolchain. In: Barthe, G. (ed.) ESOP 2011. LNCS, vol. 6602, pp. 1–17. Springer, Heidelberg (2011). https://doi.org/10.1007/9783642197185_1CrossRefGoogle Scholar
 4.Bornat, R., Cristiano, C., O’Hearn, P., Parkinson, M.: Permission accounting in separation logic. In: POPL (2005)Google Scholar
 5.Boyland, J.: Checking interference with fractional permissions. In: Cousot, R. (ed.) SAS 2003. LNCS, vol. 2694, pp. 55–72. Springer, Heidelberg (2003). https://doi.org/10.1007/3540448985_4CrossRefGoogle Scholar
 6.Boyland, J.T.: Semantics of fractional permissions with nesting. ACM Trans. Program. Lang. Syst. 32(6), 22 (2010)CrossRefGoogle Scholar
 7.Brotherston, J., Bornat, R., Calcagno, C.: Cyclic proofs of program termination in separation logic. In: POPL (2008)CrossRefGoogle Scholar
 8.Brotherston, J., Gorogiannis, N., Kanovich, M.: Biabduction (and related problems) in array separation logic. In: de Moura, L. (ed.) CADE 2017. LNCS (LNAI), vol. 10395, pp. 472–490. Springer, Cham (2017). https://doi.org/10.1007/9783319630465_29CrossRefGoogle Scholar
 9.Calcagno, C., Distefano, D., Dubreil, J., Gabi, D., Hooimeijer, P., Luca, M., O’Hearn, P., Papakonstantinou, I., Purbrick, J., Rodriguez, D.: Moving fast with software verification. In: Havelund, K., Holzmann, G., Joshi, R. (eds.) NFM 2015. LNCS, vol. 9058, pp. 3–11. Springer, Cham (2015). https://doi.org/10.1007/9783319175249_1CrossRefGoogle Scholar
 10.Calcagno, C., Distefano, D., O’Hearn, P., Yang, H.: Compositional shape analysis by means of biabduction. In: POPL (2009)CrossRefGoogle Scholar
 11.Calcagno, C., Distefano, D., Vafeiadis, V.: Biabductive resource invariant synthesis. In: Hu, Z. (ed.) APLAS 2009. LNCS, vol. 5904, pp. 259–274. Springer, Heidelberg (2009). https://doi.org/10.1007/9783642106729_19CrossRefGoogle Scholar
 12.Calcagno, C., O’Hearn, P.W., Yang, H.: Local action and abstract separation logic. In: LICS, pp. 366–378 (2007)Google Scholar
 13.Charguéraud, A., Pottier, F.: Temporary readonly permissions for separation logic. In: Yang, H. (ed.) ESOP 2017. LNCS, vol. 10201, pp. 260–286. Springer, Heidelberg (2017). https://doi.org/10.1007/9783662544341_10CrossRefGoogle Scholar
 14.Chin, W.N., David, C., Nguyen, H.H., Qin, S.: Automated verification of shape, size and bag properties via userdefined predicates in separation logic. Sci. Comput. Program. 77(9), 1006–1036 (2012)CrossRefGoogle Scholar
 15.Chin, W.N., Le, T.C., Qin, S.: Automated verification of countdownlatch (2017)Google Scholar
 16.da Rocha Pinto, P., DinsdaleYoung, T., Gardner, P.: TaDA: a logic for time and data abstraction. In: Jones, R. (ed.) ECOOP 2014. LNCS, vol. 8586, pp. 207–231. Springer, Heidelberg (2014). https://doi.org/10.1007/9783662442029_9CrossRefGoogle Scholar
 17.de Moura, L., Bjørner, N.: Z3: an efficient SMT solver. In: Ramakrishnan, C.R., Rehof, J. (eds.) TACAS 2008. LNCS, vol. 4963, pp. 337–340. Springer, Heidelberg (2008). https://doi.org/10.1007/9783540788003_24CrossRefGoogle Scholar
 18.DinsdaleYoung, T., Birkedal, L., Gardner, P., Parkinson, M., Yang, H.: Views: compositional reasoning for concurrent programs. In: POPL (2013)Google Scholar
 19.DinsdaleYoung, T., Pinto, P.D.R., Andersen, K.J., Birkedal, L.: Caper: automatic verification for finegrained concurrency. In: ESOP (2017)CrossRefGoogle Scholar
 20.DinsdaleYoung, T., Dodds, M., Gardner, P., Parkinson, M.J., Vafeiadis, V.: Concurrent abstract predicates. In: D’Hondt, T. (ed.) ECOOP 2010. LNCS, vol. 6183, pp. 504–528. Springer, Heidelberg (2010). https://doi.org/10.1007/9783642141072_24CrossRefGoogle Scholar
 21.Dockins, R., Hobor, A., Appel, A.W.: A fresh look at separation algebras and share accounting. In: Hu, Z. (ed.) APLAS 2009. LNCS, vol. 5904, pp. 161–177. Springer, Heidelberg (2009). https://doi.org/10.1007/9783642106729_13CrossRefGoogle Scholar
 22.Guo, B., Vachharajani, N., August, D.I.: Shape analysis with inductive recursion synthesis. In: PLDI (2007)Google Scholar
 23.Heule, S., Leino, K.R.M., Müller, P., Summers, A.J.: Fractional permissions without the fractions. In: FTfJP, pp. 1:1–1:6 (2011)Google Scholar
 24.Hobor, A.: Oracle Semantics. Ph.D. thesis, Department of Computer Science, Princeton University, Princeton, October 2008Google Scholar
 25.Hobor, A., Gherghina, C.: Barriers in concurrent separation logic. In: Barthe, G. (ed.) ESOP 2011. LNCS, vol. 6602, pp. 276–296. Springer, Heidelberg (2011). https://doi.org/10.1007/9783642197185_15CrossRefGoogle Scholar
 26.Hobor, A., Gherghina, C.: Barriers in concurrent separation logic: now with tool support! Log. Methods Comput. Sci. 8(2) (2012)Google Scholar
 27.Hoenicke, J., Majumdar, R., Podelski, A.: Thread modularity at many levels: a pearl in compositional verification. In: POPL (2017)Google Scholar
 28.Jacobs, B., Piessens, F.: Expressive modular finegrained concurrency specification. In: POPL (2011)Google Scholar
 29.Jacobs, B., Smans, J., Piessens, F.: A quick tour of the verifast program verifier. In: Ueda, K. (ed.) APLAS 2010. LNCS, vol. 6461, pp. 304–311. Springer, Heidelberg (2010). https://doi.org/10.1007/9783642171642_21CrossRefGoogle Scholar
 30.Jung, R., Swasey, D., Sieczkowski, F., Svendsen, K., Turon, A., Birkedal, L., Dreyer, D.: Iris: monoids and invariants as an orthogonal basis for concurrent reasoning. In: POPL (2015)CrossRefGoogle Scholar
 31.Le, D.K., Chin, W.N., Teo, Y.M.: Threads as resource for concurrency verification. In: PEPM (2015)Google Scholar
 32.Le, Q.L., Gherghina, C., Qin, S., Chin, W.N.: Shape analysis via secondorder biabduction. In: Biere, A., Bloem, R. (eds.) CAV 2014. LNCS, vol. 8559, pp. 52–68. Springer, Cham (2014). https://doi.org/10.1007/9783319088679_4CrossRefGoogle Scholar
 33.Le, X.B., Gherghina, C., Hobor, A.: Decision procedures over sophisticated fractional permissions. In: Jhala, R., Igarashi, A. (eds.) APLAS 2012. LNCS, vol. 7705, pp. 368–385. Springer, Heidelberg (2012). https://doi.org/10.1007/9783642351822_26CrossRefGoogle Scholar
 34.Le, X.B., Hobor, A., Lin, A.W.: Decidability and complexity of tree shares formulas. In: FSTTCS (2016)Google Scholar
 35.Le, X.B., Nguyen, T.T., Chin, W.N., Hobor, A.: A certified decision procedure for tree shares. In: Duan, Z., Ong, L. (eds.) ICFEM 2017. LNCS, vol. 10610, pp. 226–242. Springer, Cham (2017). https://doi.org/10.1007/9783319686905_14CrossRefGoogle Scholar
 36.Leino, K.R.M., Müller, P.: A basis for verifying multithreaded programs. In: Castagna, G. (ed.) ESOP 2009. LNCS, vol. 5502, pp. 378–393. Springer, Heidelberg (2009). https://doi.org/10.1007/9783642005909_27CrossRefGoogle Scholar
 37.Müller, P., Schwerhoff, M., Summers, A.J.: Viper: a verification infrastructure for permissionbased reasoning. In: Jobstmann, B., Leino, K.R.M. (eds.) VMCAI 2016. LNCS, vol. 9583, pp. 41–62. Springer, Heidelberg (2016). https://doi.org/10.1007/9783662491225_2CrossRefzbMATHGoogle Scholar
 38.Nanevski, A., LeyWild, R., Sergey, I., Delbianco, G.A.: Communicating state transition systems for finegrained concurrent resources. In: Shao, Z. (ed.) ESOP 2014. LNCS, vol. 8410, pp. 290–310. Springer, Heidelberg (2014). https://doi.org/10.1007/9783642548338_16CrossRefzbMATHGoogle Scholar
 39.Nguyen, H.H., David, C., Qin, S., Chin, W.N.: Automated verification of shape and size properties via separation logic. In: Cook, B., Podelski, A. (eds.) VMCAI 2007. LNCS, vol. 4349, pp. 251–266. Springer, Heidelberg (2007). https://doi.org/10.1007/9783540697381_18CrossRefGoogle Scholar
 40.OHearn, P.W.: Resources, concurrency, and local reasoning. Theor. Comput. Sci. 375(1–3), 271–307 (2007)MathSciNetCrossRefGoogle Scholar
 41.Parkinson, M.: Local Reasoning for Java. Ph.D. thesis, University of Cambridge (2005)Google Scholar
 42.Parkinson, M.J., Bornat, R., O’Hearn, P.W.: Modular verification of a nonblocking stack. In: POPL (2007)Google Scholar
 43.Reynolds, J.C.: Separation logic: a logic for shared mutable data structures. In: LICS (2002)Google Scholar
 44.Sergey, I., Nanevski, A., Banerjee, A.: Mechanized verification of finegrained concurrent programs. In: PLDI (2015)CrossRefGoogle Scholar
 45.Vafeiadis, V.: Modular finegrained concurrency verification. Ph.D. thesis (2008)Google Scholar
 46.Vafeiadis, V., Parkinson, M.: A marriage of rely/guarantee and separation logic. In: Caires, L., Vasconcelos, V.T. (eds.) CONCUR 2007. LNCS, vol. 4703, pp. 256–271. Springer, Heidelberg (2007). https://doi.org/10.1007/9783540744078_18CrossRefGoogle Scholar
 47.Villard, J.: Heaps and Hops. Ph.D. thesis, Laboratoire Spécification et Vérification, École Normale Supérieure de Cachan, France, February 2011Google Scholar
 48.Windsor, M., Dodds, M., Simner, B., Parkinson, M.J.: Starling: lightweight concurrency verification with views. In: Majumdar, R., Kunčak, V. (eds.) CAV 2017. LNCS, vol. 10426, pp. 544–569. Springer, Cham (2017). https://doi.org/10.1007/9783319633879_27CrossRefGoogle Scholar
 49.Yang, H., Lee, O., Berdine, J., Calcagno, C., Cook, B., Distefano, D., O’Hearn, P.: Scalable shape analysis for systems code. In: Gupta, A., Malik, S. (eds.) CAV 2008. LNCS, vol. 5123, pp. 385–398. Springer, Heidelberg (2008). https://doi.org/10.1007/9783540705451_36CrossRefGoogle Scholar
Copyright information
Open Access This chapter is licensed under the terms of the Creative Commons Attribution 4.0 International License (http://creativecommons.org/licenses/by/4.0/), which permits use, sharing, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons license and indicate if changes were made. The images or other third party material in this book are included in the book's Creative Commons license, unless indicated otherwise in a credit line to the material. If material is not included in the book's Creative Commons license and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.