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=AAddr(AV)𝐻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.

\HoarePcQ\HoarePRcQR\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𝛼0superscript𝛼𝛽\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.