390 likes | 512 Views
Enhancing Modular OO Verification with Separation Logic. Wei-Ngan Chin 1,2 Cristina David 1 Huu Hai Nguyen 2 Shengchao Qin 3 1 National University of Singapore 2 Singapore-MIT Alliance 3 Durham University. Challenges of OO Verification. Must support behavioral subtyping .
E N D
Enhancing Modular OO Verification with Separation Logic Wei-Ngan Chin1,2Cristina David1 Huu Hai Nguyen2 Shengchao Qin3 1 National University of Singapore 2 Singapore-MIT Alliance 3 Durham University POPL 2008
Challenges of OO Verification Must support behavioral subtyping. Must support class inheritance. Must support casting. Good to support class invariants. Good to support super/direct calls. • precision • efficiency(minimize code re-verification) Tokyo 2008
Separation Logic and Abstraction [Parkinson&Bierman, POPL’05] • Introduces abstract predicate family • allows a definition for each class type • very powerful idea • Re-verification when method inherited • Cannot handle super calls • Specs may be imprecise Tokyo 2008
Separation Logic • Foundations: • O’Hearn and Pym, “The Logic of Bunched Implications”, Bulletin of Symbolic Logic 1999 • Reynolds, “Separation Logic: A Logic for Shared Mutable Data Structures”, LICS 2002 • Extension to Hoare logic to reason about shared mutable data structures p1* p2: the heap can be split into two disjoint parts (p1 holds for one part and p2 holds for the other) Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
Behavioral Subtyping • Liskov's Substitutivity Principle (1988) : • an object of a subclass can always be passed to a location where an object of its superclass is expected • enforce behavioral subtyping with a subsumption relation Tokyo 2008
covariance contravariance Specification Subsumption Relation class A { t mn(..) where preA *! postA {...} } class B extends A { t mn(..) where preB *! postB {...} } Spec (preB*!postB) is a subtype of (preA*!postA) if: (preB *! postB) <:B (preA *! postA) preA old(preA)Æ ) preB postB ) postA Leavens&Naumann(‘06) Tokyo 2008
Enhanced Specification Subsumption `{P} c {Q} `{P *} c {Q *} • With the help of frame rule • Spec (preB*! postB) is a subtype of (preA*! postA) if: • )preB postB • (preB*!postB) <:B (preA*!postA) preA * )postA * Ætype(this)<:B Castagna(TOPLAS‘95) Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
Static and Dynamic Spec • A static spec: • describes just a single method • used for statically-dispatched calls (e.g. super/direct) • can be very precise • A dynamic spec: • describes a method and its overriding methods • used for dynamically-dispatched calls • less precise Tokyo 2008
Static and Dynamic Specs : Example static this::Cnt<n>$ *! this::Cnt<n+1>$ dynamic this::Cnt<n>$ *! this::Cnt<b>$ • class Cnt { int val; • Cnt(int v) {this.val:=v} • void tick() {this.val:=this.val+1} • int get() {this.val} • void set(int x) {this.val:=x} } • class FastCnt extends Cnt { • FastCnt(int v) {this.val:=v} • void tick() {this.val:=this.val+2} } • class PosCnt extends Cnt inv this.val¸0 { • PosCnt(int v) {this.val:=v} • void set(int x) {if x¸0 then this.val:=x else error()} } Tokyo 2008
Æ n¸0 Æ n+1·b·n+2 Cnt.tick is overridden ) weaken the postcond PosCnt has inv this.val¸0 ) strengthen the precond Static and Dynamic Specs : Example static this::Cnt<n>$ *! this::Cnt<n+1>$ dynamic this::Cnt<n>$ *! this::Cnt<b>$ • class Cnt { int val; • Cnt(int v) {this.val:=v} • void tick() {this.val:=this.val+1} • int get() {this.val} • void set(int x) {this.val:=x} } • class FastCnt extends Cnt { • FastCnt(int v) {this.val:=v} • void tick() {this.val:=this.val+2} } • class PosCnt extends Cnt inv this.val¸0 { • PosCnt(int v) {this.val:=v} • void set(int x) {if x¸0 then this.val:=x else error()} } Æ n+1·b·n+2 Æ b=n+1 Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
min. re-verification Static-Spec(A.mn) <: Dyn-Spec(A.mn) Key Principles • Static spec must be given for each new method. • Code verification is done only for static spec. • Dynamic spec is either given or derived. • Subsumption relations: class A { // defines mn } Tokyo 2008
min. re-verification Static-Spec(A.mn) <: Dyn-Spec(A.mn) ensures behavioral subtyping <: Dyn-Spec(B.mn) Key Principles • Static spec must be given for each new method. • Code verification is done only for static spec. • Dynamic spec is either given or derived. • Subsumption relations: class A { // defines mn } class B extends A { // overrides mn } Tokyo 2008
min. re-verification Static-Spec(A.mn) <: Dyn-Spec(A.mn) ensures behavioral subtyping min. re- verification <: <: Dyn-Spec(B.mn) Static-Spec(C.mn) Key Principles • Static spec must be given for each new method. • Code verification is done only for static spec. • Dynamic spec is either given or derived. • Subsumption relations: class A { // defines mn } class B extends A { // overrides mn } class C extends A { // inherits mn } Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
extension record for the extra fields of B Object Representation fields of A fields of B class A { // fields v1..n .... } y::A<t,v1..n,q>*q::Ext<B,w1..m,p> upcast downcast class B extends A { // fields w1..m .... } y::B<t,v1..n,w1..m,p> actual type extension fields Tokyo 2008
Object Representation class A { // fields v1..n .... } y::A<t,v1..n,q>*q::Ext<B,w1..m,p> upcast downcast class B extends A { // fields w1..m .... } y::B<t,v1..n,w1..m,p> LOSSLESS CASTING Tokyo 2008
Partial and Full Views Seen as a c-class obj (actual type t) Fields v1..n of c-class Other fields w1..m of subclass t of c x Partial view: - x::c<t,v1..n,p> - no extension records - shorthand x::c<v1..n> • Static specs • Improves precision Full view: - x::c<t,v1..n,p>* p::ExtAll<c,t> - ExtAll<c,t> captures all the extensions of subclass t of c - shorthand x::c<v1..n>$ • Dynamic specs Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
Ensuring Class Invariants Q: How and when to check for class inv? class PosCnt extends Cnt inv this.val¸0 { ... } Invariant-enhanced predicate: root::PosCnt#I<t,v,p> == root::PosCnt<t,v,p> * v¸0 Tokyo 2008
Invariant-Enhanced Predicate : Example inv is temporarily broken • class PosCnt extends Cnt inv this.val¸0 { • ... • void set(int x) static this::PosCnt<v> Æ x¸0 *! this::PosCnt#I<x> • void tick() static this::PosCnt#I<v> *! this::PosCnt#I<v+1> • ... • } Tokyo 2008
Invariant-Enhanced Predicate : Example inv is temporarily broken • class PosCnt extends Cnt inv this.val¸0 { • ... • void set(int x) static this::PosCnt<v> Æ x¸0 *! this::PosCnt#I<x> • void tick() static this::PosCnt#I<v> *! this::PosCnt#I<v+1> • ... • } • inv enforced at each call site • assumed at the beginning of method decl Tokyo 2008
Invariant-Enhanced Predicate : Example inv is temporarily broken • class PosCnt extends Cnt inv this.val¸0 { • ... • void set(int x) static this::PosCnt<v> Æ x¸0 *! this::PosCnt#I<x> • void tick() static this::PosCnt#I<v> *! this::PosCnt#I<v+1> • ... • } • inv enforced at the end of the method decl • assumed after each call site • inv enforced at each call site • assumed at the beginning of method decl Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
Is there a need to re-verify spB against body of mn? Re-verification of Inherited Methods class A { // fields v* ... t mn(…) static spA { ..body .. } } class B extends A { // fields w* .. t mn(…) static spB // method mn is inherited } Tokyo 2008
Statically-Inherited Method: Intuition Seen as a c-class obj (actual type t) Fields v1..n of c-class Other fields w1..m of subclass t of c this Will a call this.mn(...) modify w*? NO YES B.mn is statically inherited NOT statically inherited Tokyo 2008
Statically-Inherited Method: Definition class A { // fields v* ... t mn(…) static spA { ... this.mn2(); ... } } • A.mn is statically-inherited into B if: • it is not overridden in B class B extends A { // fields w* .. t mn(…) static spB // method mn is inherited } Tokyo 2008
Statically-Inherited Method: Definition class A { // fields v* // defines mn2 ... t mn(…) static spA { ... this.mn2(); ... } } • A.mn is statically-inherited into B if: • it is not overridden in B • for all the calls this.mn2(..) with • mnmn2, B.mn2 is statically-inherited from A.mn2 class B extends A { // fields w* // inherits mn2 .. t mn(…) static spB // method mn is inherited } Tokyo 2008
Re-verification of Inherited Methods Q: Verify spB against the body of A.mn? B.mn statically inherited or full views used? YES NO spB inherited? NO YES NO VERIFICATION spA<:spB verify spB against the body of A.mn Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
Deriving Specs (2) • Specification Specialization • strengthen dynamic spec of overriding method with the dynamic spec of overridden method • intersection type • Specification Abstraction • weaken dynamic spec of overridden method with dynamic spec of the overriding method • union type Tokyo 2008
Outline • Introduction • Our Approach • Enhanced Spec Subsumption • Static & Dynamic Specs • Key Principles • Object Representation • Class Invariants • Avoiding Re-verification • Deriving Specs • Experimental Results • Conclusion Tokyo 2008
Initial Experiment • Code Verification > Spec Subsumption Checking Tokyo 2008
Conclusion • Advocate co-existence of static and dynamic specs • Key principles: • use static spec where possible )precision • keep code re-verifications to a minimum )efficiency • Slight emphasis on static specs: • can derive dynamic specs • Must support: • behavioral subtyping, class inheritance, casting • Good to support: • class invariants, super/direct calls • Danger: • lose precision, efficiency Tokyo 2008
Thank you! • Questions? Tokyo 2008
Spec Subsumption Checking • Static_spec(Cnt.set) <: Dyn_spec(Cnt.set) • this::Cnt<t,v,p>*->this::Cnt<t,x,p> <: • this::Cnt<t,v,q>*q::ExtAll<Cnt,t> /\ x>=0 • *->this::Cnt<t,x,q>*q::ExtAll<Cnt,t> • Contravariance on precond: • this::Cnt<t,v,q>*q::ExtAll<Cnt,t> /\ x>=0 |-this::Cnt<t,v,p>* • = p::ExtAll<Cnt,t> /\ x>=0 • Covariance on postcond: • this::Cnt<t,x,p>*|- this::Cnt<t,x,q>*q::ExtAll<Cnt,t> Tokyo 2008
Spec Subsumption Checking • Dyn_spec(PosCnt.set) <: Dyn_spec(Cnt.set) • this::PosCnt<v>$ *! this::PosCnt#I<x>$ <: • this::Cnt<v>$ /\ x>=0 /\ (type(this)<:PosCnt) • *! this::Cnt<x>$ • Contravariance on precond: • this::Cnt<v>$ /\ x>=0 /\ (type(this)<:PosCnt)|-this::PosCnt<v>$ * • = x>=0 • Covariance on postcond: • this::PosCnt#I<x>$ * |- this::Cnt<t,x,q>$ Tokyo 2008