cristian gherghina 1, cristina david 1, shengchao qin 2, wei-ngan chin 1 1 national university of...
TRANSCRIPT
Cristian Gherghina1, Cristina David1, Shengchao Qin2, Wei-Ngan Chin1
1 National University of Singapore2 University of Teesside
Structured Specifications for Better Verification of Heap-Manipulating Programs
2
FM 2011
Aim
Our aim is to add structures to the specifications for improving: precision: verification succeeds for more
scenarios. efficiency: faster verification. conciseness: more concise specifications.
3
FM 2011
Verifier
Separation Logic Prover
ProgramCode
Pre/PostConditions
Separation logic:• Used to reason about shared mutable data structures.• emp // heap is empty• x y // heap has exactly one cell• A * B // heap is divided so that A holds in
// one partition, while B the other
HIP/SLEEK
4
FM 2011
HeapPredicates
Verifier
Separation Logic Prover
ProgramCode
Pre/PostConditions
HIP/SLEEK
data node{int val; node next}ll<root, n> = root=null n=0
rootnode<_,q> * ll<q,n-1>
5
FM 2011
Pure Provers(Omega, Mona,
Isabelle)
HeapPredicates
Verifier
Separation Logic Prover
ProgramCode
Pre/PostConditions
HIP/SLEEK
6
FM 2011
• What can we prove?– Properties of mutable data structures.– Sortedness, length, height-balanced, etc.
• What must the user provide?– Heap predicates.– Pre and post conditions for each method (together with loop
invariants).
HeapPredicates
Verifier
Separation Logic Prover
ProgramCode
Pre/PostConditions
SPECIFICATION
HIP/SLEEK
Pure Provers(Omega, Mona,
Isabelle)
FM 2011
7
User intuition
Spec.
Structured spec.
Triggers techniques during the proving
process
Better verification
Formula staging
Case analysis
Early/lateInstanti-ations
8
FM 2011
Agenda
Background
Case induced specifications
Early vs. Late instantiations
Conclusions
Staged formulae
9
FM 2011
rootnode<v, p, q> avl<p, h1, n1, B1, _> avl<q, h2, n2, B2, _> D
rootnode<v, p, q> avl<p, h1, n1, B1, _> avl<q, h2, n2, B2, _> D1+ h1 = h2 b=-1
h1=h2 b=0
avlroot,h,n,B,b root=null h=n=b=0 B={ } rootnode<v, p, q> avl<p, h1, n1, B1, _>
avl<q, h2, n2, B2, _> D
h1 = 1 + h2 b=1
AVL tree with original spec
D = (n=1 + n1 + n2 B={v} U B1 U B2
x B1.x v x B2. x > v)
Binary search tree
Balance factorheight size bag balance
data node{ int val; node left; node right;}
10
FM 2011
AVL tree with original spec
avlroot,h,n,B,b root=null h=n=b=0 B={ } rootnode<v, p, q> avl<p, h1, n1, B1, _>
avl<q, h2, n2, B2, _> D rootnode<v, p, q> avl<p, h1, n1, B1, _> avl<q, h2, n2, B2, _> D rootnode<v, p, q> avl<p, h1, n1, B1, _> avl<q, h2, n2, B2, _> D
D = (n=1 + n1 + n2 B={v} U B1 U B2
x B1.x v x B2. x > v)
h1=h2 b=0
h1 = 1 + h2 b=1
1+ h1 = h2 b=-1
11
FM 2011
AVL tree with original spec
avlroot,h,n,B,b root=null h=n=b=0 B={ } rootnode<v, p, q> avl<p, h1, n1, B1, _>
avl<q, h2, n2, B2, _> D
D = (n=1 + n1 + n2 B={v} U B1 U B2
x B1.x v x B2. x > v)
h1=h2 b=0
h1 = 1 + h2 b=1
1+ h1 = h2 b=-1
then Staged
formula
12
FM 2011
Agenda
Background
Case induced specifications
Early vs. Late instantiations
Conclusions
Staged formulae
13
FM 2011
node tail (node x)
requires ll⟨x,n⟩ ∧ n>0
ensures (res=null ∧ n=1) ∨ (ll⟨res,n-1⟩ ∧ n1);{
node aux = x.next;
return aux;
}
∃q · x node _ , q ll q,n−1 n⟨ ⟩∗ ⟨ ⟩ ∧ >0
Tail function
ll x,n n>0⟨ ⟩ ∧
x node _, aux ll aux,n−1 n⟨ ⟩∗ ⟨ ⟩ ∧ >0
x node _, res ll res,n−1 n⟨ ⟩∗ ⟨ ⟩ ∧ >0
x node _, res ll res,n−1 n⟨ ⟩∗ ⟨ ⟩ ∧ >0 |- postcondition
data node{ int val; node next}ll<root, n> = root=null n=0
rootnode<_,q> * ll<q,n-1>
14
FM 2011
Entailment with inductive predicates
1 |- 2 * r
Determine if the heap in 1 contains the heap in 2
r is the residue of 1 not matching 2
Separation logic formula
FM 2011
x node _, res ll res, n−1 ⟨ ⟩∗ ⟨ ⟩ n>0 |- (res=null n=1) * r
x node _, res ll res, n−1 ⟨ ⟩∗ ⟨ ⟩ n>0 |- (res=null n=1) ∨(ll res,n−1 ⟨ ⟩ n1)
Entailment with inductive predicates
x node _, res ll res, n−1 ⟨ ⟩∗ ⟨ ⟩ n>0 |- (ll res, n−1 ⟨ ⟩ n1) * r
Entailment fails!
15
node tail (node x) requires ll x,n n>0 ⟨ ⟩ ∧ensures (res=null n=1) (ll res,n-1 n∧ ∨ ⟨ ⟩ ∧ 1);
16
FM 2011
node tail (node x) requires ll⟨x,n⟩ ∧ n>0 ensures (res=null ∧ n=1) ∨ (ll⟨res,n-1⟩ ∧
n1);
Tail function
Disjunction is difficult to
reason about, leading to
incompleteness.
17
FM 2011
Tail function - structured
node tail (node x) requires ll⟨x,n⟩ ∧ n > 0 case {n=1 → ensures res = null ;n1 → ensures ll⟨res,n-1⟩;
}
18
FM 2011
Automatic case analysis
|- case {1 -> Z1; 2 -> Z2}
too general
∧ 1 |- Z1
∧ 2 |- Z2
strengthened by case analysis
disjoint conditions
19
x node _, res ll res,n−1 n>0 ⟨ ⟩∗ ⟨ ⟩ ∧ ∧ n=1|- (res=null) * r
x node _, res ll res,n−1 n>0 |- case { n=1 → ensures res = ⟨ ⟩∗ ⟨ ⟩ ∧null;
n1 → ensures ll res,n-⟨1 ;}⟩
Entailment with inductive predicates
x node _, res ll res,n−1 n>0 ⟨ ⟩∗ ⟨ ⟩ ∧ ∧ n1|- (ll res,n−1 ) * ⟨ ⟩ r
Entailments succeed! FM 2011
node tail (node x) requires ll x,n n>0 ⟨ ⟩ ∧
case { n=1 → ensures res = null; n1 → ensures ll res,n-1 ;}⟨ ⟩
20
FM 2011
node mergeAVL(node t1, node t2)
requires avl⟨t1, s1, h1, b1⟩ * avl⟨t2, s2, h2, b2⟩
ensures t1 = null avl⟨res, s2, h2, b2⟩ Ç
t1 != null avl⟨res, s1+s2, _, _⟩;
Example
heightsize balance
21
FM 2011
node mergeAVL(node t1, node t2)
case{ t1 =null → requires avl⟨t2, s2, h2, b2⟩
ensures avl⟨res, s2, h2, b2⟩;
t1!=null →requires avl⟨t2, s2, h2, b2⟩∗avl⟨t1, s1, _, _⟩
ensures avl⟨res, s1+s2, _, _⟩};
Example
22
FM 2011
node mergeAVL(node t1, node t2)
requires avl⟨t2, s2, h2, b2⟩
case{ t1 =null → requires avl⟨t2, s2, h2, b2⟩
ensures avl⟨res, s2, h2, b2⟩;
t1!=null →requires avl⟨t2, s2, h2, b2⟩∗avl⟨t1, s1, _, _⟩
ensures avl⟨res, s1+s2, _, _⟩};
Example
23
FM 2011
node mergeAVL(node t1, node t2)
requires avl⟨t2, s2, h2, b2⟩
case{ t1 =null → ensures avl⟨res, s2, h2, b2⟩;
t1!=null →requires avl⟨t1, s1, _, _⟩
ensures avl⟨res, s1+s2, _, _⟩};
Example
24
FM 2011
Agenda
Background
Case induced specifications
Early vs. Late instantiations
Conclusions
Staged formulae
25
FM 2011
Instantiations (1)
Different types of bindings for the logical variables (of consequent) during the entailment.
Used for the variables linking the precondition with the postcondition.
int length (node x)requires x::ll<n>
ensures x::ll<n> res=n
logical var
program var
26
FM 2011
Instantiations (2)
x node<_,null> |- n.(x::ll<n> n>0) x node<_,null> |- n.(x node<_,q> * ll<q,n-1> n>0)
n=1 |- n-1=0 n>0 Instantiation: n=1
data node{ int val; node next}ll<root, n> = root=null n=0 rootnode<_,q> *
ll<q,n-1>
Entailment succeeds!
27
FM 2011
data cell {int val}
cellPred⟨root, i⟩ = (root=null i3) (root cell⟨_⟩ i>3); Early instantiation:
p = null |- k.(cellPred⟨p, k⟩ k>2) * r
p = null |- k.((p=null k3) k>2) * r
p = null k3|- (p=null k>2 k3) * r
Instantiation: k3 Late instantiation:
p = null |- ([k] cellPred⟨p, k⟩ k>2) * r
p = null |- k. (p=null k3 k>2) * r
Instantiation: k3 k>2
Instantiations (3)
Entailment fails!
Entailment succeeds!
28
FM 2011
Early vs. Late instantiation
Triggered for just the matched predicate.
Minimizes the use of existential
quantification.
Triggered for the entire formula.
More complete.
Early instantiation: Late instantiation:
FM 2011
Experiments
29
30
FM 2011
Conclusion
The structured specification mechanism:
Enables automatic case analysis.
Promotes a more modular verification, where larger/hard proofs are broken into smaller/simpler proofs.
Guides the steps taken by the prover from the specification level.
31 Thank you!
32
Limerick: On verification
This work improves the specificationBased on a logic of separationWe propose case analysisTo be used in my thesisFor a better verification!
33
FM 2011
Separation logic - example
3
y
x 3,y
x 3
y
(x 3,y) * (y 3,z)
3
z
x
34
FM 2011
then case { h1 = h2=> b=0
1+h1 = h2=> b=-1 h1 = 1+ h2 => b=1}
AVL tree with original spec
avlroot,h,n,B,b root=null h=n=b=0 B={ } rootnode<v, p, q> avl<p, h1, n1, B1, b1>
avl<q, h2, n2, B2, b2> D
D = (n=1 + n1 + n2 B={v} U B1 U B2
x B1.x v x B2. x > v)
h1=h2 b=0
h1 = 1 + h2 b=1
1+ h1 = h2 b=-1
35
FM 2011
then case { h1 = h2=> b=0
1+h1 = h2=> b=-1 h1 = 1+ h2 => b=1}
AVL tree with original spec
avlroot,h,n,B,b root=null h=n=b=0 B={ } rootnode<v, p, q> avl<p, h1, n1, B1, b1>
avl<q, h2, n2, B2, b2> D
D = (n=1 + n1 + n2 B={v} U B1 U B2
x B1.x v x B2. x > v)
Staged formula
Case induced specs
36
FM 2011
Instantiations - examples
data cell {int val} cellPred⟨root, i⟩ = (root=null i3) (root cell⟨_⟩ i>3);
Early instantiation:
p cell⟨_⟩ |- (cellPred⟨p, k⟩ k>2) * r
k>3 |- k>3 k>2 * r
Late instantiation:
Both entailments
succeed!
p cell _ ⟨ ⟩ |- ([k] cellPred⟨p, k⟩ k>2)* r
p cell _ ⟨ ⟩ |- k. (k>3 k>2) * r
37
FM 2011
ll<root, n> = root=null n=0 rootnode<_,q> * ll<q,n-1>
Heap predicate for a singly-linked list
data node{ int val; node next}
root …..q
^
38
FM 2011
Pre and post conditions
int length(node x)
{ if (x==null)
then 0 else 1+length(x.next)}
requires ll x,n⟨ ⟩ensures ll x,n res=n;⟨ ⟩∧
39
FM 2011
data cell {int val}
cellPred⟨root, i⟩ = (root=null i3) (root cell⟨_⟩ i>3); Early instantiation:
p = null |- k.(cellPred⟨p, k⟩ k>2) * r
p = null |- k.((p=null k3) k>2) * r
p = null k3 |- (p=null k3) k>2 * r
p = null k3 |- k>2 * r
Instantiation: k3
Instantiations - examples
Entailment fails!
40
FM 2011
Aim
Typically, a specification mechanism focuses on: expressiveness: verification of more properties. abstraction: information hiding in spec. modularity: more readable and reusable specs.
Our aim is to add structures to the specs for improving: precision: verification succeeds for more scenarios. efficiency: faster verification. conciseness: more concise specifications.