Modular Verification of Higher-Order Methods in JML Gary T. Leavens, Steve Shaner, and David A. Naumann Support from US NSF grant CCF-0429567.

Post on 26-Mar-2015

219 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

Modular Verification of Higher-Order Methods in JML

Gary T. Leavens,Steve Shaner, and David A.

NaumannSupport from US NSF grant

CCF-0429567

Summary

Problem How to reason about

higher-order methods?Approach Greybox [Büchi-Weck97,99]

specifications, Copy rule / substitution [Morgan88], Structurally-restricted refinement

Contribution Structural matching for refinement Integration with JML

Background:Higher-Order Methods A higher-order method (HOM)

makes mandatory callsto weakly-specified methods

Example (part 1)Class with a `method parameter’

public class Counter { protected /*@ spec_public @*/ int count

= 0; protected /*@ spec_public @*/ Listener

lnr;

//@ assignable this.lnr; //@ ensures this.lnr == lnr; public Counter(Listener lnr) { // parameter this.lnr = lnr; }

Example (part 2): HOM

public void bump() { this.count = this.count + 1; this.lnr.actionPerformed(this.count);

}}

Mandatory Calls areWeakly Specifiedpublic interface Listener {

//@ assignable this.objectState; void actionPerformed(int x);}

Subtype of Listener

public class LastVal implements Listener { private /*@ spec_public @*/ int val = 0;

//@ in objectState;

//@ ensures \result == this.val; public /*@ pure @*/ int getVal() { return

this.val; }

//@ also //@ assignable objectState; //@ ensures this.val == x; public void actionPerformed(int x) { this.val = x; }}

Subtype of Listener

public class LastVal implements Listener { private /*@ spec_public @*/ int val = 0;

//@ in objectState;

//@ ensures \result == this.val; public /*@ pure @*/ int getVal() { return

this.val; }

//@ also //@ assignable objectState; //@ ensures this.val == x; public void actionPerformed(int x) { this.val = x; }}

Reasoning Problem:Want strong conclusionsLastVal lv = new LastVal();//@ assert lv.val == 0;Counter c = new Counter(lv);//@ assert c.lnr == lv && c.count == 0; c.bump();//@ assert lv.val == 1;

Why is strong conclusion valid?Copy rule and substitutionsLastVal lv = new LastVal();//@ assert lv.val == 0;Counter c = new Counter(lv);//@ assert c.lnr == lv && c.count == 0; c.count = c.count+1;c.lnr.actionPerformed(c.count);//@ assert lv.val == 1;

Problem Summary

Specification of higher-order methods(challenge 8 in [Leavens-Leino-Müller06]) Abstract

Specifies mandatory calls Suppress other details

Allows strong conclusions (challenge 9) Copy rule and substitution

Soundness Must make mandatory calls

Use of Higher-Order Methods

Key in design patterns [Gamma-etal95]: Observer Template Method Chain of Responsibility

Clients of design patterns: Interpreter Command State Strategy Visitor

How to Specify HOMs?Standard Pre/Post …/*@ assignable this.count, lnr.objectState; @ ensures this.count ==\old(this.count+1); @*/public void bump() {

this.count = this.count + 1;this.lnr.actionPerformed(this.count);

}

… Is Not Enough

LastVal lv = new LastVal();//@ assert lv.val == 0;Counter c = new Counter(lv);//@ assert c.lnr == lv && c.count == 0; c.bump();//@ assume c.count == 1;//@ hence_by (* ??? *);//@ assert lv.val == 1;

Higher-Order Specifications?E.g., [Ernst-Navlakhla-Ogden82]:

/*@ forall int x; @ requires \req(this.lnr.actionPerformed)(x); @ assignable this.count, @ \asgn(this.lnr.actionPerformed); @ ensures this.count ==\old(this.count+1) @ &&\ens(this.lnr.actionPerformed)

(this.count); @*/public void bump() { /* … */ }

Problems with Higher-Order Specifications Often longer and more complex than

code Harder to learn and teach Harder for tools to work with? Calls are not mandatory

Greybox (Ref. Calc.) Approach [Büchi–Weck97, 99]

vs.

Better:lnr.actionPerformed()

lnr.actionPerformed()

c.count++

/*@ public model_program { @ normal_behavior @ assignable this.count; @ ensures this.count ==\

old(this.count+1); @ @ this.lnr.actionPerformed(this.count); @ } @*/public void bump() { /* … */ }

Greybox Approach in JML:Model Program Specification

Reasoning About HOM Calls

LastVal lv = new LastVal();//@ assert lv.val == 0;Counter c = new Counter(lv);//@ assert c.lnr == lv && c.count == 0; c.bump();//@ assert lv.val == 1;

Approach: Model Program Copy Rule and SubstitutionLastVal lv = new LastVal();//@ assert lv.val == 0;Counter c = new Counter(lv);//@ assert c.lnr == lv && c.count == 0; /*@ normal_behavior @ assignable c.count; @ ensures c.count == \

old(c.count+1); @*/c.lnr.actionPerformed(c.count);//@ assert lv.val == 1;

Rule for HOM Calls(Copy Rule + Substitution)

P { y.m(z); } Q

y: T, methType(T,m) = x:S -> void,

specFor(T,m) = C,

C’ = C [y,z/this,x], P { C’ } Q

Strong Conclusions fromCopy + Contextual Knowledge

//@ assert c.lnr == lv;c.bump();

Copy/Substitute model program

/*@ normal_behavior @ assignable c.count; @ ensures c.count == \old(c.count+1); @*/c.lnr.actionPerformed(c.count);

Context

lv.actionPerformed(c.count);

+

Soundness fromRestricting Implementations For soundness of HOM call rule:

(copy rule) body refines model program

(use of context) restrict refinement somandatory calls must happen in specified states

Notion of Refinement with Mandatory Calls in Given States Need to define

“structure-preserving refinement” Approach:

Restrict implementations Pattern matching

Model program vs. Implementation

Kinds of Patterns

Refinable (holes, wildcards) Specification statements

(normal_behavior) Mandatory

Calls Everything else

Pattern Matching

normal_behavior … following normal_behavior …{ C }

Model program

Method implementati

on

m();

m();

Implementing Higher-Order Methods/*@ public model_program { @ normal_behavior @ assignable this.count; @ ensures this.count == \

old(this.count+1); @ this.lnr.actionPerformed(this.count); @ } @*/public void bump() { /*@ following normal_behavior @ assignable this.count; @ ensures this.count == \

old(this.count+1);@*/ { this.count = this.count+1; } this.lnr.actionPerformed(this.count);}

Refinement

P ⊑ C iff C pattern matches against P The resulting following statements

are provable

Rule for following

P { following normal_behavior requires P’; ensures Q’;

C

} Q

P ==> P’, Q’ ==> Q,

P’ { C } Q’

Future Work

Soundness argument Connection to Büchi and Weck’s work

(refinement of traces) Case studies Implementation in JML tools Exceptions Concurrency

Related Work

Büchi and Weck (1997, 99): Idea of greybox approach Trace semantics Doesn’t focus on reasoning about calls Needs definition of structure

preservationMorgan (1988): Uses adaptation and substitution for

procedures

Related Work

Ernst, Navlakhla, and Ogden (1982): Higher-order logic specifications Harder to write and use Mandatory calls might not be madeSoundarajan and Fridella (2004): Higher-order trace-based specifications Can ensure mandatory calls are made Harder to write and use

Conclusions

Greybox (refinement-style) model programs Clear specification of HOMs Allow strong conclusions

Soundness: Restrictions on refinement Use of pattern matching

top related