Verifying Executable Object-Oriented Specifications with Separation Logic Stephan van Staden, Cristiano Calcagno, Bertrand Meyer Introduction Executable and separation logic specifications Examples: Executable specifications can be evaluated at runtime. Useful for debugging and testing. Lightweight Separation logic specifications are useful for verification 2 Executable specifications Verification questions: 1) Can we always execute them? Will their preconditions always be satisfied? Example: It does not make sense to talk about the first element of a newly created empty list 2) Will they always hold at runtime if executed? Example: A newly created empty list will not contain 10 elements 3) Will it matter if they are executed or not? Are they independent of the essence of the code? Complicated due to side-effects: modify object structures, nondeterministic, spawn threads, … Example: Does it matter if the postcondition of inserting an element checks whether it is in the list by allocating an iterator and affecting iterator bookkeeping? 3 Our contributions Allow both styles of specification. Reason about both using connecting implications, which answer all three questions posed before Reason about arbitrary side-effects in executable specifications with a new notion called relative purity 4 Relative purity Existing approaches classify side-effects in executable specifications as intrinsically harmful or not If B is pure relative to P, then • P is a footprint of B • B can only perform side-effects permitted by P • B must re-establish P, so it cannot “change things from the P point of view” Purity is in the eye of the asserter 5 Examples x.f := e; False is pure relative to relative to True insert(4); not is_empty is pure relative to not pure relative to , but not pure , but 6 Precondition verification Given a sep logic predicate P and an executable assertion B which should hold at the same program point, does B somehow follow from P? Yes iff the connecting implication P Lemma: If P B holds B, then B is pure relative to P 7 Example For remove_first: Proof: 8 Postcondition verification Postconditions may contain old-expressions: evaluated before the body is executed The connecting implication P,Q C means that any prestate satisfying P and any post-state satisfying Q are sufficient to evaluate C to True: Let old(E1),…,old(En) be the old-expressions in B P,Q \ra B =def \exists R \cdot {P}(v1:=E1,…,vn:=En){P*R} and {Q*R}v:=B[v1;…;vn]{Q/\v=True} B[v1;…;vn] =def B[v1/old(E1),…,vn/old(En)] 9 Example For remove_first: Proof: 10 Proof obligations summary 11 Implementation Reasoning support implemented in jStar Basic ingredients: symbolic execution, implication checking, frame inference Demonstration 12 Other work Class invariants Extracting predicates from executable specifications, i.e. work involving connecting implications of the form B P Connecting double implications of the form P B provide an integration of the two specification techniques 13 Related work Executable specifications • Eiffel • ESC • Spec# • JML: jmlc, JACK, LOOP Separation logic 14 In conclusion • Give executable assertions a semantics based on their semantics as expressions • Relative purity embraces side-effects in executable assertions • Verification of executable specifications (i.e. answering the three questions) boils down to proving connecting implications • The approach is general: also applicable to languages such as C 15 Thanks! Questions? 16