Separation Logic

Separation Logic is a refinement of Hoare Logic that adds the ability to reason about pointer manipulation, in particular Pointer Aliasing.

[2025-03-18 Tue]

Have an abstract set of heap addresses Addr Addr \mathrm{Addr} , and a set of heaps H 𝐻 H which are indexed by Finite subsets of addresses. Also have a store, which maps variables to values.

H=⋃A⊆Addr(A⇀V)𝐻subscript𝐴Addr⇀𝐴𝑉\par H=\bigcup_{A\subseteq\mathrm{Addr}}(A\rightharpoonup V)

Alternatively, a heap is a Finitely Supported Partial Function Addr ⇀ V ⇀ Addr 𝑉 \mathrm{Addr}\rightharpoonup V .

Moreover, have a simple imperative language that is extended with allocation of cons cells, pointer dereferencing, pointer arithmetic, mutation, and deallocation.

Note that the expression language is separate from commands; this is similar to A Normal Form.

Logic is standard predicate calculus, plus:

Frame Rule

The all-important frame rule lets us lift a proof of a local property into a more global property, provided that c 𝑐 c does not touch the parts of the heap that the extended property mentions.

\Hoare⁢P⁢c⁢Q\Hoare⁢P∗R⁢c⁢Q∗R\Hoare𝑃𝑐𝑄\Hoare𝑃𝑅𝑐𝑄𝑅\par\frac{\Hoare{P}{c}{Q}}{\Hoare{P*R}{c}{Q*R}}

Examples

Reversing a List

struct list_t {
  int head;
  list_t *tail;
}

void reverse(list_t *i) {
  list_t *j = NULL;
  while (i != NULL) {
    list_t k = i->tail;
    i->tail = j;
    j = i;
    i = k;
  }
}

To prove that \Hoare ⁢ 𝗅𝗂𝗌𝗍 ⁢ α 0 ⁢ i ⁢ reverse ⁢ ( i ) ⁢ 𝗅𝗂𝗌𝗍 ⁢ α 0 † ⁢ j \Hoare 𝗅𝗂𝗌𝗍 subscript 𝛼 0 𝑖 reverse i 𝗅𝗂𝗌𝗍 superscript subscript 𝛼 0 † 𝑗 \Hoare{\mathsf{list}\;\alpha_{0}\;i}{\mathrm{reverse(i)}}{\mathsf{list}\;% \alpha_{0}^{\dagger}\;j} (where α † superscript 𝛼 † \alpha^{\dagger} is list reversal), the invariant

∃α,β.𝗅𝗂𝗌𝗍⁢α⁢i∧𝗅𝗂𝗌𝗍⁢β⁢j∧α0†=α†+βformulae-sequence𝛼𝛽𝗅𝗂𝗌𝗍𝛼𝑖𝗅𝗂𝗌𝗍𝛽𝑗superscriptsubscript𝛼0†superscript𝛼†𝛽\exists\alpha,\beta.\;\mathsf{list}\;\alpha\;i\land\mathsf{list}\;\beta\;j% \land\alpha_{0}^{\dagger}=\alpha^{\dagger}+\beta

doesn't get you want you need due to aliasing concerns; instead, we need to use the the invariant

(∃α,β.𝗅𝗂𝗌𝗍αi∗𝗅𝗂𝗌𝗍βj)∧α0†=α†+β(\exists\alpha,\beta.\;\mathsf{list}\;\alpha\;i*\mathsf{list}\;\beta\;j)\land% \alpha_{0}^{\dagger}=\alpha^{\dagger}+\beta

where P ∗ Q 𝑃 𝑄 P*Q is the separating conjunction, which asserts that the heap can be split into two disjoint halves where P 𝑃 P holds on one half and Q 𝑄 Q holds on the other.