Verification of Programs with Inspector Methods
310 likes | 440 Vues
This talk focuses on the specification and verification of object-oriented modules utilizing inspector methods for information hiding. It addresses the challenges posed by aliasing, method-effect framing, and sound first-order logic verification condition generation. The outline includes discussions on single-object inspector methods, object invariants and ownership, multi-dependent inspector methods, and subclassing. Additionally, related and future work will be covered to provide insights into the effectiveness of these verification techniques in ensuring program reliability and correctness.
Verification of Programs with Inspector Methods
E N D
Presentation Transcript
Verification of Programs with Inspector Methods Bart Jacobs and Frank Piessens Dept. CS, K.U.Leuven, Belgium
Goal • Specification and verification • Of object-oriented modules • Using inspector methods • For information hiding • In method contracts and object invariants
Difficulties • The combination of • Aliasing • Information hiding • Method effect framing • Sound first-order logic verification condition generation
Outline of the Talk • Single-object inspector methods • Object invariants and ownership • Multi-dependent inspector methods • Subclassing • Related work, future work, conclusion
Outline of the Talk • Single-object inspector methods • Object invariants and ownership • Multi-dependent inspector methods • Subclassing • Related work, future work, conclusion
class Cell { int x; inspectorint getX() { return x; } Cell(int x) ensures getX() == x; { this.x = x; } } Cell c1 = new Cell(1); Cell c2 = new Cell(2); assert c1.getX() == 1; Single-ObjectInspector Methods
Background Predicates • get(set(s,f,v),f) == v • f1!=f2==>get(set(s,f1,v),f2) == get(s,f2) • get2(s,f1,f2) == get(get(s,f1),f2)) • set2(s,f1,f2,v) ==set(s, f1, set(get(s, f1), f2, v))
Single-ObjectInspector Methods (forall H, o :: Cell_getX(o, get(H,o)) == get2(H,o,Cell_x)) ==> H1 == set2(H0,this,Cell_x,x) ==> Cell_getX(this,get(H1,this)) == x class Cell { int x; inspectorint getX() { return x; } Cell(int x) ensures getX() == x; { this.x = x; } }
Single-ObjectInspector Methods get2(H0,c1,alloc) == false ==> H1 == set2(H0,c1,alloc,true) ==> (forall o :: get2(H1,o,alloc) ==>get2(H2,o,alloc) && (o != c1 ==> get(H2, o) == get(H1,o))) ==> Cell_getX(c1,get(H2,c1)) == 1 ==> get2(H2,c2,alloc) == false ==> H3 = set2(H2,c2,alloc,true) ==> (forall o :: get2(H3,o,alloc) ==> get2(H4,o,alloc) && (o != c2 ==> get(H4,o) == get(H3,o))) ==> Cell_getX(c2,get(H4,c2)) == 2 ==> Cell_getX(c1,get(H4,c1)) == 1 Cell c1 = new Cell(1); Cell c2 = new Cell(2); assert c1.getX() == 1;
Single-ObjectInspector Methods • When verifying mutator methods: the abstraction relation is assumed • When verifying client code: frame conditions on object states are assumed • Inspector method functions take the receiver’s state as an argument
Outline of the Talk • Single-object inspector methods • Object invariants and ownership • Multi-dependent inspector methods • Subclassing • Related work, future work, conclusion
class List { rep int[] elems; int count; invariant 0 <= count; invariant count <= elems.length; inspector int getCount() { return count; } inspector int getItem(int index) requires 0 <= index; requires index < getCount(); { return elems[index]; } derived_invariant 0 <= getCount(); void add(int x) requires !committed && inv; modifiesthis.*; ensures !committed && inv; ensures getCount() = old(getCount()) + 1; ensures forall{int i inold((0:getCount())); getItem(i) == old(getItem(i))}; ensures getItem(old(getCount())) == x; { unpackthis; count++; EnsureCapacity(count); elems[count – 1] = x; packthis; } Object Invariantsand Ownership
Object Invariants in the Boogie Methodology • Each object gets an inv bit • Updating o.f requires !o.inv • pack o; checks o’s declared invariant Inv(o) and sets o.inv = true; • unpack o; sets o.inv = false; • It follows that if o.inv, then Inv(o) • if o.inv is true, then “o is valid”; otherwise “o is mutable”
Object Ownership in the Boogie Methodology • Ownership allows inspector methods and object invariants to depend on objects other than the receiver • The ownership relation is dynamic • An object owns its rep objects (i.e. the objects pointed to by its rep fields) whenever it is valid • pack o; • requires that o’s rep objects are not owned by any object • causes o to take ownership of its rep objects and sets their committed bits • unpack o; causes o to release ownership of its rep objects and clears their committed bits • It follows • that an object has at most one owner • that o.committed iff o has an owner
Object Ownership in the Boogie Methodology • Committed objects can be unpacked and modified only by first unpacking their owner • o’s inspector methods and object invariant may depend on o’s rep objects
List l1 = new List(); List l2 = new List(); l1.add(5); l2.add(6); assert l1.getItem(0) == 5; ... ==> List_getItem(l1, get(H5,l1),0) == 5 ==> (forall o :: get2(H5,o,alloc) ==> (get2(H6,o,alloc) && (!get2(H5,o,committed) && o != l2 ==> get(H6,o) == get(H5,o)))) ==> List_getItem(l1, get(H6,l1),0) == 5 unpackthis; count++; EnsureCapacity(count); elems[count – 1] = x; packthis; assert getItem(getCount() - 1) == x; assert !committed && !inv; assert !elems.committed && elems.inv; assert 0 <= count && count <= elems.length; inv = true; elems.committed = true; elems_state = H[elems]; (forall H,o,i :: Reachable(H) ==> get2(H,o,alloc) ==> get2(H,o,inv) ==> 0 <= i && i <= List_getCount(o,get(H,o)) ==> List_getItem(o,get(H,o),i) == get(get(get(H,o),List_elems_state),i)) Encoding of Inspector Method Calls
Encoding of Inspector Method Calls • To make method effect framing work, inspector method functions continue to take just the state of the receiver object as an argument • However, they may depend on owned objects as well • Solution: When packing an object, the state of each rep object o.f is copied into a special field o.f_state
Outline of the Talk • Single-object inspector methods • Object invariants and ownership • Multi-dependent inspector methods • Subclassing • Related work, future work, conclusion
Multi-dependent Inspector Methods class IntCell { inspectorint get() { ... } void set(int value) { ... } } class IntSet { inspectorbool contains(state IntCell c) { ... } void add(IntCell c) ensuresforall{state IntCell c2; contains(c2) == (old(contains(c2)) || c2.get() == c.get())}; { ... } }
Termination of Inspector Methods • An inspector method’s receiver is implicitly unpacked for the duration of the call • Also, object creations and explicit packs or unpacks are not allowed in inspector methods • Therefore, the number of valid objects decreases at each nested call
Outline of the Talk • Single-object inspector methods • Object invariants and ownership • Multi-dependent inspector methods • Subclassing • Related work, future work, conclusion
class Cell { int x; invariant 0 <= x; inspectorint getX() { return x; } derived_invariant 0 <= getX(); dynamic_invariant 0 <= getX(); void setX(int x) requires !committed && inv; requires 0 <= x; modifies this.*; ensures !committed && inv; ensures getX() == x; {unpackthis; this.x = x; packthis;} } class MyCell extends Cell { invariant 1 <= super.getX(); inspectorint getX() { returnsuper.getX() – 1; } void setX(int x) requires !committed && inv; requires 0 <= x; modifiesthis.*; ensures !committed && inv; ensures getX() == x; { unpack this; super.setX(x + 1); pack this; } } Subclassing
Subclassing: Encoding • c1.x --> get3(H,c1,Cell,Cell_x) • c1.getX() --> Cell_getX_dyn(c1,get2(H,c1,typeof(c1))) • super.getX() --> Cell_getX(c1,get2(H,c1,Cell)) • (forall o :: typeof(o) == Cell ==> Cell_getX_dyn(o,s) == Cell_getX(o,s)) • (forall o :: typeof(o) == MyCell ==> Cell_getX_dyn(o,s) == MyCell_getX(o,s)) • pack (MyCell)o; --> ... H’ == set3(H,o,MyCell,super_state, get2(H,o,Cell)) …
Outline of the Talk • Single-object inspector methods • Object invariants and ownership • Multi-dependent inspector methods • Subclassing • Related work, future work, conclusion
Related Work • Boogie methodology • Method calls in specifications • State abstraction in ownership systems • Ownership-free approaches
Relation toBoogie Methodology • Based on [Barnett, DeLine, Fähndrich, Leino, Schulte 2004] • Differences: • Heap maps object refs to object states • pack o; copies owned object states • Frame conditions are object-granular • inv and committed bits are per frame
Method Calls in Specifications • Discussed by [Darvas, Müller 2005] • Does not deal with framing issue
State Abstraction in Ownership Systems • Read and write effects in ownership type systems (e.g. [Boyapati 2004]) • Model fields and the Universe type system [Müller 2002] • Also supports visibility-based dependencies on peers • Model fields on top of the Boogie methodology [Leino, Müller 2006]
Ownership-free Approaches • Dynamic frames [Kassios 2005] • Abstract predicates in separation logic [Parkinson 2005] • More flexible • Not implemented in automatic program verifier (but: Smallfoot)
Future Work • Soundness proof • Visibility-based dependencies
Conclusion • State abstraction for OO programs • Supports standard coding pattern • Implemented in automatic program verifier • Supports multi-dependent inspector methods, quantification over object states, subclassing