Predicate Abstraction and
Canonical Abstraction
for Singly-linked Lists
Roman Manevich
Mooly Sagiv
Tel Aviv University
Eran Yahav
G. Ramalingam
IBM T.J. Watson
Motivating Example 1: CEGAR
curr = head;
while (curr != tail) {
assert (curr != null);
curr = curr.n;
}
curr
head
n
n … n
n
tail
Counterexample-guided abstraction refinement
generates following predicates:
curr.n ≠ null ,
curr.n.n ≠ null ,
… after i refinement steps:
curr(.n)i ≠ null
2
Motivating Example 1: CEGAR
curr = head;
while (curr != tail) {
assert (curr != null);
curr = curr.n;
}
curr
head
n
n … n
n
tail
In general, problem is undecidable:
V. Chakaravathy [POPL 2003]
State-of-the-art canonical abstractions can prove
assertion
3
Motivating Example 2
// @pre cyclic(x)
t = null;
y = x;
while (t != x && y.data < low) {
t = y.n; y = t;
}
z = y;
while (z != x && z.data < high) {
t = z.n; z = t;
}
t = null;
if (y != z) {
y.n = null;
y.n = z;
}
// @post cyclic(x)
4
Motivating Example 2
@pre cyclic(x)
@post cyclic(x)
z
z
n
n
n
n
n
x
x
n
n
n
n
n
n
n
y
y
5
Existing Canonical Abstraction
concrete
z
n
abstract
z,cn
order between variables lost!
cannot establish @post cyclic(x) rx,ry,rz
n
n
n
x,cn
rx,ry,rz
x
n
n
n
n
n
n
n
n
n
n
y
y,cn
rx,ry,rz
6
cn
rx,ry,rz
Overview and Main Results
Current predicate abstraction refinement methods not
adequate for analyzing heaps
Predicate abstraction can simulate arbitrary finite abstract
domains
New family of abstractions for lists
Often requires too many predicates
Bounded number of sharing patterns
Handles cycles more precisely than existing canonical abstractions
Encode abstraction with two methods:
Canonical abstraction
Polynomial predicate abstraction
7
Outline
New abstractions for lists
Observations on concrete shapes
Static naming scheme
Encoding via predicate abstraction
Encoding via canonical abstraction
Controlling the number of predicates via heap-sharing
depth parameter
Experimental results
Related work
Conclusion
8
Concrete Shapes
Assume the following class of (list-) heaps
Heap contains only singly-linked lists
No garbage (easy to handle)
A heap can be decomposed into
Basic shape (sharing pattern)
List lengths
9
Concrete Shapes
class SLL {
Object value;
SLL n;
}
x
y
n
n
n
n
n
n
n
n
n
10
n
n
n
n
n
Interrupting Nodes
Interruption:
node pointed-to by a variable
or shared by n fields
x
y
n
n
n
n
n
n
n
n
n
n
n
#interruptions ≤ 2 · #variables
(bounded number of sharing patterns)
11
n
n
n
Maximal Uninterrupted Lists
Maximal uninterrupted list:
maximal list segment between two interruptions
not containing interruptions in-between
x
y
n
n
n
n
n
n
n
n
n
12
n
n
n
n
n
Maximal Uninterrupted Lists
max. uninterrupted 1
x
y
n
n
n
n
n
n
n
n
max. uninterrupted 2
n
n
n
n
n
max. uninterrupted 3
max. uninterrupted 4
13
n
Maximal Uninterrupted Lists
number of links
x
y
n
n
n
n
4
4
n
n
n
n
2
n
n
n
n
4
n
14
n
Maximal Uninterrupted Lists
Abstract lengths: {1,2,>2}
x
y
n
n
n
n
>2
>2
n
n
n
n
2
n
n
n
n
>2
n
15
n
Using Static Names
Goal: name all sharing patterns
Prepare static names for interruptions
Prepare static names for max.
uninterrupted lists
Derive predicates for canonical abstraction
Derive predicates for predicate abstraction
All names expressed by FOTC formulae
16
Naming Interruptions
We name interruptions by adding auxiliary variables
For every variable x : x1,…,xk
(k=#variables)
x2
x1
x
y
n
n
n
n
n
n
n
n
n
y1
17
n
n
y2
n
n
n
Naming Max. Uninterrupted
Lists
[x1,x2]
[x1,y2]
[y1,x2]
[y1,y2]
[x,x1]
[x,y1]
x
y
x2
x1
n
n
n
n
n
n
n
n
n
y1
[y,x1]
[y,y1]
18
n
n
y2
n
[x2,x2]
[x2,y2]
[y2,x2]
[y2,y2]
n
n
A Predicate Abstraction
For every pair of variables x,y (regular and auxiliary)
For every variable x (regular and auxiliary)
Aliased[x,y] = x and y point to same node
UList1[x,y] = max. uninterrupted list of length 1
UList2[x,y] = max. uninterrupted list of length 2
UList[x,y] = max. uninterrupted list of any length
UList1[x,null] = max. uninterrupted list of length 1
UList2[x,null] = max. uninterrupted list of length 2
UList[x,null] = max. uninterrupted list of any length
Predicates expressed by FOTC formulae
19
Predicate Abstraction Example
x2
x1
x
concrete
y
n
n
n
n
n
n
n
n
Aliased[x,x]
Aliased[y,y]
n
y1
n
n
n
n
y2
Aliased[x1,x1] Aliased[x2,x2]
Aliased[y1,y1] Aliased[y2,y2] Aliased[x1,y1] Aliased[y1,x1]
abstract
Aliased[x2,y2] Aliased[y2,x2] UList[x,x1]
UList[x,y1]
UList2[x1,x2]
UList2[x1,y2]
UList2[y1,x2]
UList2[y1,y2]
UList[x1,x2]
UList[x1,y2]
UList[y1,x2]
UList[y1,y2]
UList[y,x1]
UList[y,y1]
UList[x2,x2]
UList[x2,y2]
UList[y2,x2]
UList[y2,y2]
20
n
A Canonical Abstraction
For every variable x (regular and auxiliary)
x(v) = v is pointed-to by x
cul[x](v) = uninterrupted list from node
pointed-to by x to v
Predicates expressed by FOTC formulae
21
Canonical Abstraction Example
concrete
cul[x1]
cul[y1]
cul[x]
x2
x1
xx
yy
n
n
n
n
n
n
n
n
n
y1
cul[y]
22
cul[x2]
cul[y2]
n
n
y2
n
n
n
Canonical Abstraction Example
abstract
cul[x1]
cul[y1]
cul[x]
x2
x1
xx
yy
n
n
cul[x2]
cul[y2]
n
n
n
n
n
n
n
n
y1
n
cul[y]
23
y2
Canonical Abstraction
of Cyclic List
concrete
abstract
cul[z]
z
n
z
n
n
n
n
x
x
n
n
n
n
n
n
n
n
n
cul[x]
cul[y]
y
y
24
Canonical Abstraction
of Cyclic List
abstract pre
cul[z]
abstract post
cul[z]
z
n
n
n
x
n
n
n
n
x
n
n
n
n
cul[x]
z
n
cul[x]
cul[y]
cul[y]
y
y
25
Heap-sharing Depth
In this example the heap-sharing depth is 2
In practice depth expected to be low (≤ 1)
x2
x1
x
y
n
n
n
n
n
n
n
n
n
y1
26
n
n
y2
n
n
n
Setting the Heap-sharing Depth
Setting the heap-sharing depth parameter to 1
results in lost information about shape
x1
x
y
n
n
n
n
n
n
n
n
n
n
n
n
n
y1
Heap-sharing depth parameter d determines
number of static names : control over number of predicates
27
n
Experimental Results
28
Related Work
Dor, Rode and Sagiv [SAS ’00]
Sagiv, Reps and Wilhelm [TOPLAS ‘02]
Semi-automatic predicate abstraction for shape analysis
Balaban, Pnueli and Zuck [VMCAI ’05]
General framework + abstractions for lists
Dams and Namjoshi [VMCAI ’03]
Checking cleanness in lists
Predicate abstraction for shapes via small models
Deutsch [PLDI ’94]
Symbolic access paths with lengths
29
Conclusion
New abstractions for lists
Observations about concrete shapes
Precise for programs containing heaps with
sharing and cycles, ignoring list lengths
Parametric in sharing-depth d:[1…k]
Encoded new abstractions via
Canonical abstraction O(d·k)
Polynomial predicate abstraction O(d2·k2)
d=1 sufficient for all examples
30
Missing from Talk
Simulating abstract domains by pred. abs.
Formal definition of abstractions
Abstract transformers
Decidable logic can be automatically derived
Abstraction equivalence:
for every two concrete heaps H1,H2
βPA(H1)=βPA(H2) iff βC(H1)=βC(H2)
Abstractions with less predicates
Cycle breaking
Linear static naming scheme
31
Merci
32
Simulating Finite Domains
by Predicate Abstraction
Assume finite abstract domain of numbered
elements {1,…,n}
Naïve simulation
Predicates {Pi} i=1…n
Pi Holds when abstract program state is i
Simulation using logarithmic number of
predicates
Use binary representation of numbers
Predicates {Pj} j=1…log n
Pj Holds when j-th bit of abstract program state is 1
33
© Copyright 2026 Paperzz