390 likes | 474 Views
Techniques for proving programs with pointers. A. Tikhomirov. 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.
E N D
Techniques for proving programs with pointers A. Tikhomirov
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.
John C. Reynolds, Peter O’Hearn Separation Logic
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
Separation Logic • Representing the Heap • Assertions empty heap singleton heap separating conjunction separating implication
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)
Singleton heap • Reference pointer to some cell • Asserts that x points to an adjacent pair of sells containing 1 and y.
Separating conjunction • The separating conjunction constructs a heap property from two disjoint heaps
Logical conjunction • Could be ambiguous in heap, x and y could be aliases ,or disjoint.
Lists • List representation
Frame rule • Frame rule: This rule holds as long as free variables in s not mentioned in R.
Allocation • Allocation rule (local): • Allocation rule (global):
Deallocation • Dispose rule (local): • Dispose rule (global):
Heap write (mutation) • Mutation forward rule (local): • Mutation forward rule (global):
Examples of Operational Semantics Store: [x:3, y:40, z:17] Heap: empty • Allocation x := cons(y, z) • Heap lookup y := [x+1] • Mutation [x + 1] := 3 • Deallocation dispose(x+1) Store: [x:37, y:40, z:17] Heap: [37:40, 38:17] Store: [x:37, y:17, 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]
Example: Swap • Function in which the contents of two heap cells are swapped: t1 := [v1] t2 := [v2] [v1] := t2 [v2] := t1
Example: Swap void 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’}
Example: Doubly Indirect References • Mutating the value of a double indirect reference (a pointer to a pointer):
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
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 }
Example: DeleteTree // {tree(t)} void deleteTree (t) { local i,j; if (t != nil) { i = [t] j = [t+1] deleteTree(j) deleteTree(i) dispose(t) } } // {tree(t) ^ t != nil} // {∃x,y.t > (x,y) * tree(x) * tree(y)} // {t > (i,j) * tree(i) * tree(j)} // {t > (i,j) * tree(i)} // {t > (i,j) * nil} // {emp} // {emp}
Example: List reverse // {list(x)} list reverse (x) { y = nil; while (x != nil) { t := [x]; x := [y]; y := x; x := t; } return 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)} // {list(y)}
Conclusion • Extension of Hoare logic • Could use verification tools, that work with Hoare logic • For automatic proving • Assertions • Pre and post-conditions
Reinhard Wilhelm, MoolySagiv, Thomas Reps Shape ANALYSIS
Shape Analysis • Somewhat constrained view of programs • Static code analysis • Program verification
Input to reverse • (a) lists of length at least 2 • (b) list of length 1
Input to reverse • List structure of size from 0 to 4
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 mwill point to m’ • dotted - c component of mmay point to m’
3-value logic • solid means “always holds” • absent means “never hold” • dotted means “don’t know”
Execution states • (a) – shape arise before executing x=x->n • (b) & – (c) after executing x=x->n on shape (a)
Insert algorithm • The same list structure
Execution States (1) y = x; while (y->n != NULL) {y = y->n}
Execution States (2) • t = malloc(); • t -> data = n
Execution States (3) • e = y->n;
Execution States (4) • t->n = NULL; • t->n = e;
Execution States (5) • y->n = NULL;
Execution States (6) • y->n = t;
Conclusion • Code analysis • NULL-pointers; • May-Alias; • Must-Alias; • Sharing; • Reachability; • Disjointness; • Cyclicity; • Shape;