Modular Verification via
Separation Logic
Wei-Ngan Chin
National University of Singapore
( joint work with Cristian, Cristina,
Le Binh, Huu Hai, Shengchao)
1
Quote
“Trust but Verify.”
by Ronald Reagan.
“The Goliath of totalitarianism will be
brought down by the David of the microchip.”
by Ronald Reagan.
2
Paraphrase
“The reputation of corporations can be
brought down by software and other bugs.”
3
4
5
6
7
MAS near accident Aug 2005
Boeing 777-200
Software took readings from a faulty
accelerometer when a second one failed
8
9
Proposition
Design and build software that are
correct by construction.
Use tools to find bugs early.
10
Background
• 2000’s : impressive practical advances in automatic
program verification
• SLAM : verified safety protocol properties of device
drivers in Windows (now as a library in Windows 7)
• ASTREE : no runtime errors in Airbus
• Missing Link :
• ASTREE : no dynamic pointer allocation
• SLAM : assumes memory safety
• Many important programs make serious use of heap
.. but heap verification is hard.
11
Challenges
• Aliasing, heap/memory and recursion.
• Complex data structures with invariants.
Our Search for Solution
Types Separation Logic
12
Outline
• Introducing Separation Logic
• Modularity 1 : Leveraging Pure Provers
• Modularity 2 : Structured Specs
• Modularity 3 : OO Verification
• Conclusion
13
Separation Logic
• Extension to Hoare logic to reason about shared
mutable data structures.
• Foundations
• O’Hearn and Pym, “The Logic of Bunched
Implications”, Bulletin of Symbolic Logic 1999
• Reynolds, “Separation Logic: A Logic for Shared
Mutable Data Structures”, LICS 2002
14
Separation Logic
Formula :
xy yx
x
y
Heap :
15
Separation Logic
Formula :
xy
x
y
Heap :
16
Separation Logic
yx
Formula :
x
y
Heap :
17
Separation Logic
Formula :
xy yx
x
y
Heap :
x=10
y=20
10
20
20
10
18
Separation Logic
Formula :
xy
x
y
Heap :
x=10
y=20
10
20
19
Separation Logic
yx
Formula :
x
y
Heap :
x=10
y=20
20
10
20
Separation Logic
Formula :
xy yx
x
y
Heap :
21
Formula for Heaplet
• Add to Classical Logic
• emp
// heaplet is empty
• x y // heaplet has exactly one cell
• A * B // heaplet is divided so that A holds in
// one partition, while B the other
not multiply!
• Add inductive definitions, lemmas and
other fancy operators.
22
A Substructural Logic
• Logic for resources (i.e. memory)
No duplication
A `A*A
(10 2) ` (10 2) * (10 2)
No Loss
A*B `A
(10 2) * (20 3) ` (10 2)
unless we use
intuitionistic logic
23
An Inconsistency
• Trying to be two places at same time!
(x 2) * (x 2)
10
10
2
2
(x 2) * (x 2) ` false
24
Alternative View
More generally :
(x _) * (y _) ` x y
25
Reasoning over Heap Update
{ (x _) * R } [x]:=7 { (x 7) * R }
unchanged frame
Using frame rule :
{ x _ } [x]:=7 { x 7 }
{ true } [x]:=7 { ?? }
26
Deallocation/Allocation
{ x _ } dispose(x) { emp }
{ true } dispose(x) { ?? }
{ emp } x=cons(a,b) { x a,b }
27
Sequential Composition
Intermediate state
{ P } E1 { R }
{ 9 res . R } E2 { Q }
{ P } E1 ; E2 { Q}
• Intermediate state computed in a
forward manner.
28
Frame Rule
footprint
{ P } code { Q }
{ P * R } code { Q * R }
• Memory footprint captures the heap
state that is accessed by a given code.
29
Before Separation Logic
Example : to dispose all nodes in a linked list.
{ list(x) Æ reach(p,n) }
deleteNodes(x)
{ : allocated(n) }
With Separation Logic
{ list(x) }
deleteNodes(x)
{ emp }
30
Outline
• Introducing Separation Logic
• Modularity 1 : Leveraging Pure Provers
• Modularity 2 : Structured Specs
• Modularity 3 : OO Verification
• Conclusion
31
Overall System
Code
Pre/Post
code verifier
(HIP)
Predicates
Lemmas
separation
logic prover
(SLEEK)
range of pure provers …
Omega, MONA, Coq, SMT, Redlog
32
Inductive Predicates
root:: lsegp root=p
9 r . root::node_,r r::lsegp
x::lsegy * y::lseg x
x
x::lsegy
y
y::lsegx
33
… with Size
root:: lsegp,n root=p Æ n=0
9 r . root::node_,r r::lsegp,n-1
inv n ¸ 0
x
x::lsegy,3
y
y::lsegx,2
34
… with Size & Bag
root:: lsegp,n,S root=p Æ n=0 Æ S={}
9 r . root::nodev, r r::lsegp,n-1,S1
Æ S={v} [ S1
inv n ¸ 0 & n=|S|
35
.. with Sortedness
root:: lsortp,S root=p Æ S={}
9 r . root::nodev, r r::lsortp,S1
Æ S={v} [ S1 Æ 8 x 2 S1. v · x
36
.. with AVL balancing
root::avlh root = null Æ h = 0
Ç root::nodeh_, p, qi p::avlhh1i q::avlhh2i
Æ -1 · h1-h2 · 1 Æ h=1+max(h1,h2)
inv h¸0
37
Lemmas
• Used to relate predicates
x::lsortp,S ) x::lseg<p,n,S> Æ n=|S|
Philosophy : Lemmas invented by
users but automatically proven and
applied by our system.
38
Example of Code Specification
node insert(node x, node vn)
requires x::lsortnull,Svn::nodev,_Æxnull
ensures res::lsortnull,S [ {v}
{
if (vn.val≤x.val) then {
vn.next = x;
return vn; }
else if (x.next=null) then {
x.next = vn; vn.next = null;
return x; }
else { x.next = insert(x.next, vn);
return x; }
}
39
Separation Logic Entailment
1 ` 2 3
antecedent
consequent
residual
• 1 must “subsumes” all heap nodes in 2.
• Residual nodes are then kept in 3.
• ALGORITHM : Ensure all nodes in 2 are
subsumed by 1, then convert to an arithmetic
implication check.
40
Features
• Unfold/Fold Transformation.
• Supports Existential Instantiation
• Supports Proof Search (with Lemmas)
• Approximation to Pure Provers
41
Approximation to Pure Form
• Entailment is reduced to implication of
pure constraints when the consequent’s
heap is empty.
• Each predicate is approximated by a pure
constraint (based on its invariant).
42
Approximation
XPuren(x::nodeh i y::nodeh i)
= (ex i. x=i Æ i>0) (ex j. y=j Æ j>0)
= i,j. (x=i Æ i>0 Æ y=j Æ j>0 Æ ij)
XPure0(x::lseghnull,ni)
=n¸0
XPure1(x::lseghnull,ni)
too weak
more info
= i. (x=0 Æ n=0 Ç x=i Æ i>0 Æ n-1¸0)
43
Outline
• Introducing Separation Logic
• Modularity 1 : Leveraging Pure Provers
• Modularity 2 : Structured Specs
• Modularity 3 : OO Verification
• Conclusion
44
Flat Specification
disjunctive normal form
pure logic
heap logic
Simple but less readable and less modular.
45
Example with Original Spec
root::avlh,n,S,b root=null Æ h=n=b=0 Æ S={ }
Ç root::nodehv, p, qi p::avlhh1,n1,S1,b1i
q::avlhh2,n2,S2,b2iÆ h1=h2 Æ b=0 Æ D
Ç root::nodehv, p, qi p::avlhh1,n1,S1,b1i
q::avlhh2,n2,S2,b2iÆ 1+h1=h2 Æ b=-1 Æ D
Ç root::nodehv, p, qi p::avlhh1,n1,S1,b1i
q::avlhh2,n2,S2,b2iÆ h1=1+h2 Æ b=1 Æ D
inv h¸0 Æ n ¸ 0 Æ -1· b· 1
D = (n=1+n1+n2 Æ S={v} [ S1 [ S2 Æ
8 x 2 S1. x · v Æ 8 x 2 S2 x ¸ v)
46
with Structured Spec
root::avlh,n,S,b case
root=null ! h=n=b=0 Æ S={ }
case analysis
root null ! root::nodehv, p, qip::avlhh1,n1,S1,b1i
q::avlhh2,n2,S2,b2iÆ n=1+n1+n2 Æ
S={v}[S1 [S2 Æ 8 x2S1.x · v Æ 8 x2S2.x ¸ v
case h1=h2! b=0
1+h1=h2! b=-1
staged formula
h1=1+h2! b=1
inv h¸0 Æ n ¸ 0 Æ -1· b· 1
47
Structured Spec
• More readable.
• Better sharing.
• More precise ‘cos of case analysis.
• Better scalability
48
Experiment
49
Better Scalability
• Explicitly break into smaller proofs.
• Modularity allows down-sized formula.
Important when pure provers are unscalable.
• AVL example : 987 sec 76 sec.
50
Outline
• Introducing Separation Logic
• Modularity 1 : Leveraging Pure Provers
• Modularity 2 : Structured Specs
• Modularity 3 : OO Verification
• Conclusion
51
Challenges of OO Verification
• Must support behavioral subtyping
• Must support class/method inheritance
• Must support casting/invariant
• Must be precise and efficient
(avoid re-verification).
52
2
Static and Dynamic Spec
• A static spec:
• describes just a single method
• used for statically-dispatched calls (e.g. super/direct)
• can be very precise
• A dynamic spec:
• describes a method and its overriding methods
• used for dynamically-dispatched calls
53
11
Example
class Cnt { int val;
static this::Cnt<n> ! this::Cnt<n+1>
Cnt(int v) {this.val:=v}
void tick() {this.val:=this.val+1} dynamic this::Cnt<n>$ ! this::Cnt<b>$
int get() {this.val}
Æ n+1 · b · n+2
void set(int x) {this.val:=x} }
class FastCnt extends Cnt {
static this::Cnt<n> ! this::Cnt<n+2>
FastCnt(int v) {this.val:=v}
void tick() {this.val:=this.val+2} dynamic this::Cnt<n>$ !
}
this::Cnt<b+2>$
54
12
Key Principles
• Modular meas minimise code re-verificaion.
• Code verification is done only once per method.
• Dynamic spec is either given or derived.
• Must ensure:
min. re-verification
<:
inherited
method
Static-SpecC
<:
Dyn-SpecA
<:
Static-SpecA
Dyn-SpecB
overriding
method
55
6
Specification Subsumption
Given:
a method A.mn with the spec (preA ! postA)
its overriding method B.mn, with the spec (preB ! postB)
The spec (preB ! postB) is a subtype of (preA ! postA) if:
preA Æ type(this)<:B ` preB *
* postB ` postA
(preB ! postB) <:B (preA ! postA)
contravariance
frame rule
covariance
56
8
Conclusion
• Verified software is here to stay.
• Interesting applications e.g. verification is
used to teach programming at HCMCUT.
• Many challenges ahead still for
verification, e.g. scalability, automation,
expressivity, concurrency, inference.
57
Prototypes Developed
• SLEEK – Entailment Prover
• HIP – Verifier for Imperative Language
• HIPO – Verifier for OO Language.
58
© Copyright 2026 Paperzz