techniques for proving programs with pointers a. tikhomirov
TRANSCRIPT
Techniques for proving programs with pointers
A. Tikhomirov
2
Why is it important?
• Every program works not only with stack but stores intermediate data in heap and use pointers to operate with heap.
• Common program verification techniques couldn’t work with pointers and heap.
3
SEPARATION LOGICJohn C. Reynolds, Peter O’Hearn
4
Fail using Hoare Logic
• Structure of Hoare Logic assignment judgment couldn't work with heap.
int x = 5;int *y = &x; // *y = 5 x = 3; // *y = 3 Hoare logic doesn’t specify
holding of *y
FAIL
5
Separation Logic
• Representing the Heap• Assertions
empty heap singleton heap separating
conjunction separating implication
assertassert
assertassert
emp
assert
*
*
expexp
:
6
Separation Logic
• Asserts that x points to an adjacent pair of cells containing u, v (x stores address α and the heap maps α into u and (α +1) into v)
;]1[; ][:
,
vu
vux
7
Singleton heap
• Reference pointer to some cell• Asserts that x points to an adjacent pair of
sells containing 1 and y.
yx ,1 xy ,1
8
Separating conjunction
xyyx ,1*,1
• The separating conjunction constructs a heap property from two disjoint heaps
9
Logical conjunction
• Could be ambiguous in heap, x and y could be aliases ,or disjoint.
xyyx ,1,1
10
Lists
• List representation
11
Frame rule
• Frame rule:
This rule holds as long as free variables in s not mentioned in R.
}*{}*{
}{}{
QRsPR
QsP
12
Allocation
• Allocation rule (local):
• Allocation rule (global):
}{)(:}{ eveallocv emp
}*){()(:}{ reveallocvr
13
Deallocation
• Dispose rule (local):
• Dispose rule (global):
}{}{ empedisposee
}{}*){( redisposere
14
Heap write (mutation)
• Mutation forward rule (local):
• Mutation forward rule (global):
}{:][}{ eeeee
}*){(:][}*){( reeeere
15
Examples of Operational Semantics
• Allocation x := cons(y, z)
• Heap lookup y := [x+1]
• Mutation [x + 1] := 3
• Deallocation dispose(x+1)
Store: [x:3, y:40, z:17]
Heap: empty
Store: [x:37, y:40, z:17]
Heap: [37:40, 38:17]
Store: [x:37, y:17, z:17]
Heap: [37:40, 38:3]
Store: [x:37, y:17, z:17]
Heap: [37:40, 38:17]
Store: [x:37, y:17, z:17]
Heap: [37:40]
16
Example: Swap
• Function in which the contents of two heap cells are swapped:
t1 := [v1]t2 := [v2][v1] := t2[v2] := t1
}*/{***/*}*{ 12212211 vvvvncomputatiovvvv
17
Example: Swapvoid swap (int* v1, int* v2) {
t1:= [v1]
t2 := [v2]
[v1] := t2
[v2] := t1
}
// {v1 > v1’ * v2 > v2’}
// {t1 = v1’ & v1 > v1’ * v2 > v2’}
// {t1 = v1’ & t2 = v2’ & v1 > v1’ * v2 > v2’}
// {t1 = v1’ & t2 = v2’ & v1 > v2’ * v2 > v2’}
// {t1 = v1’ & t2 = v2’ & v1 > v2’ * v2 > v1’}
18
Example: Doubly Indirect References
• Mutating the value of a double indirect reference (a pointer to a pointer):
}*/{***/*}*{ vwwpncomputatiowwp
19
Example: Doubly Indirect References
void write (int** p, int v) {
t:= [p]
[t] := v
}
// {p > w * w > —}
// {p > w} Frame rule – begin
// {t = w & p > w} Mutation// {t = w & p > w * w > —} Frame rule — end
// {t = w & w > —} Frame rule — begin
// {t = w & w > v} Mutation
// {t = W & p > w * w > v} Frame rule — end// {p > w * w > v} Remove extra stack assertion
20
Example: Doubly Indirect References
• Attempting to aggressively apply Frame rule to entire block would result in a stuck proof.
void write (int** p, int v) {
// {p > w * w > —}// {p > w} Frame rule – begin t:= [p]// {t = w & p > w} Mutation [t] := v// {??} Stuck – no mapping for w// {t = W & p > w * w > v} Frame rule — end
}
21
Example: DeleteTree
void deleteTree (t) {
local i,j; if (t != nil) {
i = [t] j = [t+1]
deleteTree(j) deleteTree(i)
dispose(t) }
}
// {tree(t)}
// {tree(t) ^ t != nil}
// {∃x,y. t > (x,y) * tree(x) * tree(y)}
// {emp}
// {t > (i,j) * tree(i) * tree(j)}
// {t > (i,j) * tree(i)}// {t > (i,j) * nil}
// {emp}
22
Example: List reverse
list reverse (x) {
y = nil; while (x != nil) {
t := [x]; x := [y];
y := x; x := t; } return y;
}
// {list(x)}
// {list(y)}
// {list(x) * list(y)}// {x != nil ^ list(x) * list(y)}
// {x > t ^ list(t) * list(y)}// {x > y ^ list(x) * list(y)}
// {list(t) * list(x)}
// {list(t) * list(y)}
// {list(x) * list(y)}
// {x = nil ^ list(x) * list(y)}
23
Conclusion
• Extension of Hoare logic– Could use verification tools, that work with Hoare
logic• For automatic proving– Assertions– Pre and post-conditions
24
SHAPE ANALYSISReinhard Wilhelm, Mooly Sagiv, Thomas Reps
25
Shape Analysis
• Somewhat constrained view of programs• Static code analysis• Program verification
26
Destructive Reverse
27
Input to reverse
• (a) lists of length at least 2• (b) list of length 1
28
Input to reverse
• List structure of size from 0 to 4
29
Graph interpretation
• Rectangle box containing p represent pointer variable p
• Ovals – abstract locations– solid – represents exactly one heap cell– dotted – represent one or more heap cells
• Edge – label c between locations m and m’– solid – c component of m will point to m’– dotted - c component of m may point to m’
30
3-value logic
• solid means “always holds”• absent means “never hold”• dotted means “don’t know”
31
Execution states
• (a) – shape arise before executing x=x->n• (b) & – (c) after executing x=x->n on shape (a)
32
Insert algorithm
• The same list structure
33
Execution States (1)
y = x;
while (y->n != NULL) {y = y->n}
34
Execution States (2)
t = malloc();
t -> data = n
35
Execution States (3)
e = y->n;
36
Execution States (4)
t->n = NULL;
t->n = e;
37
Execution States (5)
y->n = NULL;
38
Execution States (6)
y->n = t;
39
Conclusion
• Code analysis– NULL-pointers;– May-Alias;– Must-Alias;– Sharing;– Reachability;– Disjointness;– Cyclicity;– Shape;