200 likes | 351 Views
Using history invariants to verify observers. K. Rustan M. Leino and Wolfram Schulte Microsoft Research, Redmond. ESOP 2007 Braga, Portugal 28 March 2007. Overall goal. Specify and statically verify programs Use modular verification (local reasoning) These require:
E N D
Using history invariants to verify observers K. Rustan M. Leino and Wolfram Schulte Microsoft Research, Redmond ESOP 2007Braga, Portugal28 March 2007
Overall goal • Specify and statically verify programs • Use modular verification (local reasoning)These require: • Invariants of data structures • Support for common programming patterns
In this talk:Observer pattern Observer Subject Observer Observer
In this talk:Observer pattern or: Collection / Iterator pattern Iterator Collection Iterator Iterator
Review of the heap logic of theBoogie methodology class C {int x, y;invariant x ≤ y; void M() { expose (this) { x++; P(); y++; }} Object is valid Object is mutable Program invariant:( o o.valid Inv(o)) Invariant checked here
Review:Representation (rep) objects classFastDictionary {rep Dictionary d;rep Cache c;invariant contents = d.contentsc.keys contents; :Fast-Dictionary d c :Dictionary :Cache Program invariant, for any rep field d:( o o.valid o.d.valid)
Review:Visibility-based invariants class Node {Node next, prev;invariant (next = null next.prev = this) (prev = null prev.next = this); next next next :Node :Node :Node :Node prev prev prev
Subject, observers :MyObserver class Subject {int data; List<Observer> observers; …} interface Observer { void Update(); } classMyObserver : Observer { Subject s; int d; invariant d = s.data; … } classYourObserver : Observer { Subject s; int d; invariant d ≤ s.data; … } Note that scannotbe a rep field,because one observer cannot be the sole owner of the subject :MyObserver :Subject :YourObserver
Modular verification problem :MyObserver :MyObserver class Subject {int data; List<Observer> observers; void Inc() {expose (this) { data++;foreach (o in observers) {o.Update(); } }} } interface Observer { void Update(); } :Subject :YourObserver Program invariant:( o o.valid Inv(o))
Modular verification problem :MyObserver :MyObserver class Subject {int data; List<Observer> observers; void Inc() {expose (this) {expose (all o in observers) { data++;foreach (o in observers) {o.Update(); } } }} } interface Observer { void Update(); } :Subject :YourObserver … or check the observer “update guards” here? How to check invariantsof the observers here?
Our solution • Declare (monotonic) evolution of the subject data: class Subject {int data;history invariant old(data) ≤ data; • … and let observer invariants depend on the subject data, provided these invariants are automatically maintained under the evolution of the subject data: classSomeObserver : Observer {subject Subject s; int data;invariantdata ≤ s.data;
History invariants • 2-state predicateshistory invariant R(this)σ,τ; • Holds of ordered pairs of states: valid Program invariant: (σ,τ σ ≤ τ ( o R(o)σ,τ)) Program invariant: (σ,τ σ ≤ τ ( o [o.valid]σ [o.valid]τ R(o)σ,τ))
Checking history invariants • Checked to be reflexive and transitive • Checked in the states that bracket expose statements: στ expose (o) { … } Check R(o)σ,τ here
Observer invariants • class Subject { historyinvariant R(this)σ,τ; … }class Observer {subjectSubject s;invariant Inv(this); Program invariant:( o o.valid o.s.valid Inv(o)) expose (o) { … } check o.s.valid Inv(o) here
Checking observer invariants • class Subject { historyinvariant R(this)σ,τ; … }class Observer {subjectSubject s;invariant Inv(this); • Checked to satisfy: (σ,τ σ ≤ τ ( o [o.valid]σ ( f [o.f]σ = [o.f]τ) [o.s.valid]σ [o.s.valid]τ R(o.s)σ,τ [Inv(o)]τ))
Soundness theorems Program invariant, for any history invariant R: (σ,τ σ ≤ τ ( o [o.valid]σ [o.valid]τ R(o)σ,τ)) • Proofs: see paper Program invariant, for any object invariant Inv:( o o.valid o.s.valid Inv(o))
Specification idiom • class Subject {intver; T data;historyinvariantold(ver) = ver old(data) data; • class Observer {subjectSubject s;intver; T data;invariant s.ver = ver s.data data; temporal relation spatial relation
Example: Iterator classIterator {intver;subject Collection c;invariant ... c ...; T Next()requires this.validc.validthis.ver == c.ver;{ ...}
Related work • History invariants are used elsewhere • assume / guarantee • constraints [Liskov & Wing 1994] • … • Visibility-based invariants [e.g., Leino & Müller 2004] • Update guards [Barnett & Naumann 2004] • Separation logic [e.g., Parkinson & Bierman 2005] • could also benefit from history invariants • Static class invariants [Leino & Müller 2005] • multiple-”owner” situation
Conclusion • Local reasoning for observer invariants • Future work: implementation (in Spec#)