Verification As a Matter Of Course. Bertrand Meyer ETH Zurich, Eiffel Software & ITMO
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
Bertrand Meyer
ETH Zurich, Eiffel Software & ITMO
With Cristiano Calcagno, Carlo Furia, Alexander Kogtenkov*, Martin Nordio, Manuel Oriol+, Yu Pei, Nadia Polikarpova, Emmanuel Stapf*, Julian Tschannen, Stephan van Staden, Yi Wei, Andreas Zeller= & others
*Eiffel Software
+ETH, then U. of York, now ABB
=U. Saarbrücken
Microsoft Summer School, Moscow, July 2011
SEC-R conference in October 2011
ESEC 2013 will take place in Saint Petersburg
New LinkedIn group:
Программная Инженерия/ Software Engineering Russia
Software Engineering Seminar in Saint PetersburgITMO and Polytechnical University (V. Itsykson)
Every Thursday 18-21, visitors welcome
http://meyerseminar.org
Scope & Goals
Simple Web sites, spreadsheets, …
Enterprise computing, simulation, “soft” real-time, …
Enterprise computing, simulation, “soft” real-time, …
Transportation, critical infrastructure, “hard” real-time, …
Dynamic allocation
Classes, objects
Inheritance
Polymorphism,dynamic binding
Exception handling
Closures (agents)
Exceptions
Genericity
...
The EVE environment
Test results
AutoProof
Suggestions
Inter.prover
Test execution
EVE
AutoTest
Test case generation
Aliasanalysis
Suggestions
Invariantinference
Sep. logicprover
Invariantinference
Arbiter
AutoFix
Carlo Furia, Julian Tschannen, Martin Nordio
+ More modular
+ Scales up better
- Not always feasible
- Often tests idealized version of the software
- Captures only specified properties
+ Generally possible
+ Can be automated
+ Tests software as it is
+ Can integrate non-software parts
- Partial (very!)
- Captures only specified properties
- Not always feasible
“Ich bin der Geist, der stets verneint”Goethe, Faust, Act I
FiodorChaliapineas Mephistopheles
To test a software system is to try to make it fail
Ilinca CiupaAndreas LeitnerYi WeiEmmanuel StapfArno FivaManuel Oriol…
Bernd Schoeller
*
*
Test:
s1, s2: SET
s2 s1
*SET
+SET2
+SET1
+
+
*: Deferred
+: Effective
I.Ciupa, A. Leitner,M.Oriol, A. PretschnerICST 2008 (best paper)
On a small EiffelBase subset,we compared:
Nadia PolikarpovaIlincaCiupaISSTA 2009
How do programmer-written and inferred contracts compare?
Can contract inference be used to improve the quality of programmer-written contracts?
Yi Wei, Yu Pei, Andreas Zeller, ISSTA 2010
Yi Wei, Yu Pei, Carlo Furia, ASE 2011 (etc.)
Passing & failing test cases
Difference
Fix to minimize
the difference
Towardscompletecontracts
count
index
1
v
-- Previous elements unchanged!
put_right (v: G)
-- Insert v to the right of cursor
require
index <= count
ensure
i_th (index + 1) = v
count =oldcount + 1
index =oldindex
end
Bernd Schoeller, Tobias Widmer (2008)Nadia Polikarpova (VSTTE 2010)
Contracts are typically incomplete (unlike those of fully formal approaches such as Z)
Our solution:
A model is a mathematical interpretation of the structures
Model library: MML (Mathematical Model Library)
Fully applicative (no side effects, attributes, assignment etc.)
But: expressed in Eiffel (preserving executability)
count
index
1
v
-- Previous elements unchanged!
put_right (v: G)
-- Insert v to the right of cursor
require
index <= count
ensure
i_th (index + 1) = v
count =oldcount + 1
index =oldindex
end
note
model: sequence, index
classLIST [G]
...
sequence: MML_SEQUENCE [G]
put_right (v: G)
-- Insert v to the right of cursor.
require
index <= sequence.count
ensure
sequence =
old(sequence.front (index).extended (x)
+ sequence.tail (index + 1))
index = oldindex
end
...
Testing found 4 “functional” faults by violation of model-based contracts
Negative Variables& the Essenceof Object-Oriented Programming
“Principle of general relativity”: every operation in a class is expressed relative to a “current object” (self, this, Current), known only at execution time
class C feature
r
do
x := 1
x . f (...)
end
...
end
Need to model this property in the logic
Notations:
(for variable v and expression e; generalized to vectors of variables and expressions)
xv = <xu, x v, x v, …>
(call r (c)) (s) = r (s [r : c])
(Ignoring recursion)
Standard solution (e.g. Peter Müller’s thesis):in r, replace all occurrences of an attribute a by Current.a
(Inadequate!)
Known by the target as x’ y
Current
y
x’
x
Target object
call x r (c)
= xr(s [r: x’c])
= x(P(r) [r: x’c])
Unqualified calls:
(call r (c)) (s) = r (s [r : c])
Qualified calls:
(call x r (c)) (s) = xcall r (x’ c) (s)
Proper rule
Reminder: inadequate rule
Framing:a language convention
In a class ACCOUNT:
deposit (sum: INTEGER)
require ...
do...
ensure
balance = old balance + sum
end
What about other queries other than balance, e.g.
owner, account_number, overdraft_limit...?
What about descendant classes, e.g. MAFIA_ACCOUNT?
; cur: CURRENCY
old
has_penalty = (cur /= currency)
involved (is_overdraft)
This also avoids introducing a special language notation to express that a routine is pure
A routine may only modify queries listed (outside of an oldexpression) in its postcondition
The Alias Calculus
Broy volume (IJSI, 2011)
Given expressions e and f, and a program location p:
Can e and f ever be attached to the same object at p?
Alias analysis can be a key tool for proving O-O programs (as an alternative to separation logic)
b
-- c = c, i.e. True
a
?
set_a (c)
x.set_a (c)
Understand as
x.a := c
-- y.a = b
-- y.a = b
x
-- x.a = c
-- x.a = c
y
c
1. Without it, cannot apply standard proof techniques to programs involving pointers
2. Concurrent program analysis, in particular deadlock
3. Program optimization
A binary relation is an alias relationif it is symmetric andirreflexive
Can alias x to y
and y to z
but not x to z
Relation of interest:
“In the computation, x might become aliased to y”
Definition:
Not necessarily transitive:
ifcthen
x := y
else
y := z
end
D
Identity on E
=
Set difference
{[x, y], [y, x], [y, z], [z, y]}
{[x, y], [y, x], [x, z], [z, x], [y, z], [z, y]}
rr r-1― Id [E]
x, y, y, z, x, u, v
{x, y} { y, z} {x, u, v}
x
, y
y
y
y, z
y
y
x,
u, v
x
x
Canonical form of an alias relation: e.g.
, meaning
None of the sets of variablesis a subset of another
Value nodes
Value nodes
Value nodes
Source node
In canonical form: no label is subset of another; each label has at least two variables
x
, y
y, z
x,
u, v
“Minus”
Set of all variables
“Quotient”, similar to equivalence class in equivalence relation
If a is an alias relation in in and A a set, the following are alias relations:
r \– A = r — E x A
a / x = {y: E | (y = x) [x, y] a}
The purpose of the calculus is to define, for any instruction p and any alias relation a, the value of
a » p
which denotes:
The aliasing relation resulting from executing
pfrom an initial state in which the aliasing
relation is a
For an entire program: compute » p
-- Eiffel: x := Void
-- Java etc.: x = null;
a » skip = a
a » (then p else q end )= (a » p) (a » q)
a » (p ; q) = (a » p) » q
a » (forget x) = a \- {x}
a » create x = a \- {x}
a deprived of all pairs involving x
Symmetrize and de-reflect
All pairs of the form [x, y]or [x, u] where u was aliased to y
a » (x := y) = given
b = a \- {x}
then
b ({x} x (b / y))
end
“Minus”
“Quotient
r \– A = r — E x A
a / x = {y: E | (y = x) [x, y] a}
a » cut x, y = a ― x, y
Alias relation:
t, u, t, y
t, u, x, t, y, x
cut x, y informs the alias calculus with non-alias properties that come from other sources
Example:
ifm < n thent := u elset := y end
m := m + 1
ifm < n thenx := t end
In fact x cannot be aliased to y (only to u), but the alias theory does not know this property
To express it, add the instructioncut x, y;
This expressionrepresents
checkx /= y end (Eiffel)
assertx != y ; (JML, Spec#)
(auxiliary notion)
nN
a » p0 = a
a » pn+1 = (a » pn) » p -- For n 0
a » (loop p end) = (a » pn)
t0 = a
tn+1 = tn(tn » p)
r
r
r (args) do p end
r
a » callr (c) = a » [r : c]--
x := e f
a deprived of all pairs involving x
All u aliased to yin b, plusy itself
All pairs [x, u] where u is either aliased to y in b or y itself
This includes[x, y] !
a » (x := y) = given
b = a \- {x}
then
b ({x} x (b / y) )
end
x
y
x
x
z
xdoes not get aliased tox y!
(only to any z that was aliased tox y)
adeprived of all pairs involving x
or an expression starting with x
a » (x := y) = given
b = a \- {x}
then
b ({x} x (b / y))
end
Value nodes
Value nodes
Value nodes
Source node
Single source node(represents stack)
Each value node represents a set of possible run-time values
Links: only from source tovalue nodes (will becomemore interesting with E4!)
Edge label: set ofvariables; indicates theycan all be aliased to each other
x
, y
y, z
x,
u, v
In canonical form: no label is subset of another; each label has at least two variables
Value nodes
Value nodes
Object nodes
Source node
x
y
x
x
z
Links may now exist between value nodes(now called object nodes)
Cycles possible (see next)
:= x y
Negated variables
Negated variables
a
x’
x
call x r (a, b)
With, in a class C:
r (t: T ; u: U)
The formals mean
t: x’ a
u: x’ b
c, d
,
xu, xv
x r
u,v,x’c,x’d
x’
x
u := x’ c
a » call x r (c)= x ((x’ a) » call r (x’c))
c := d
call
with
r
do
v := u
end
Alias relation:
, d
, d
c
,
c, d
x f
Current
Prefix with x’ :
x’
x
u,
x’c, x’ d
x
v,
x
u := x’ c
x’c, x’d
u, x’ c, x’ d
c,
x
d
x
v, u, x’ c, x’d
x’c, x’d
Prefix with x:
u,
c
x
x’c,
d
x
v,
c,
x
xv, xu, c, d
x
a » call x r (c)= x ((x’ a) » call r (c)
A Calculus ofObject Programs
reverse
local
previous, next: LINKABLE [G]
do
from
next :=first ; previous :=Void
invariant
first
right
next right+ previous right= - oldfirst right
?
right
previous
right
next
right
?
first right= - old first right
end
Compositional logic for programming languages
Calculus of object structures
Inverse variables
Alias calculus
The proof
Compositional logic deals with properties of the form
i;e
where i is an instruction and e an expression
Meaning: the value of e after executing i
Expressed in terms of values of expressions before this execution
Examples:
(x := 1);x = 1
(x := x + 1);x = x + 1
Denotational:
State s: State where State = Variable Value
Expression e : State Valuee.g.e (s) = 3
Command c : State State
Advantage: defines program as mathematical object
Disadvantage: not verification oriented
Axiomatic (Hoare):
Pre-post:{P} A {Q}
Advantage: intended for verification; invariants
Disadvantage: not a calculus
Axiomatic (Weakest precondition):
Operator: A wp Q
Advantage: Calculus version of Hoare logic
Disadvantage: Boolean expressions only
CA
-- Only if e does not involve the oldoperator (see next)
i ;(x y) = (i ;x) (i ;y) Distributivity
-- For most operators
CD
i ;(j ;e) = (i ;j) ;e Associativity
A
C
B
g
a
f
f g
Composition is associative:
[f g]h = f [g h]
Given
f : AB
g : BC
their composition
f g: A C
is the function
a | g (f (a))
Instructions
i, j: State State
Expressions
e: State Value
Then “;” is the usual composition “”, as in e.g.
i ;j (State State) (State State),i.e. (State State)
i ;e (State State) (State Value),i.e. (State Value)
i ;j ;e -- Using associativity (CA1)
It is again a form of composition, but applied to functions working on the “current object”
Instructions
i, j: Object State State
Expressions
e: Object State Value
Then
i ;j = o | s | (i (o)j (o)) (s)
i ;e = o | s | (i (o)e (o)) (s)
i;olde = e
OLD
((x := 0 ;x := 1));old x= x
(x := 0) ; ((x := 1);old x)=(x := 0) ;x
= 0
For any instruction iand any expression e:
General convention: x, y, z indicate different variables (values may be the same)
:=
A1
(xe) ;x= e
A2
:=
(xe);y= y
This rule applies to values of any type, including references, but will be extended for object expressions
To be proved:
CD
By distributivity of ; for =, this is:
((item:=item+1) ;item) = (item:=item+1) ;olditem+1
By the rule of old, this is:
((item:=item + 1) ;item) = item + 1
OLD
By the assignment rule, this is:
item + 1 = item + 1
A1
(item:= item + 1);(item= olditem + 1)
UC
UC
US2
US1
For an attribute a of type T, consider the routine
set_a (f: T) do whatever ; a := f end
Then
(callset_a (c)) ; a = c
Proof: this is a direct application of the preceding result
(call r (c)) ; e = r[r : c] ; e
A more general version of the theorem ( ) applies to any routine with the postcondition a = f
Proof: add at the end of the routine an instruction a := f ; this does not change its semantics. Then apply .
a purged of expressions starting with x
a [x: y] = given b = a\- {x}thenb ({x} x(b/y))end
nN
a » call x r (a) = x(x’(a [xr:a]) » r) \– x r
x
z
y
Current
x y z
:=
(xe) ;y= y
A2
A1
:=
(xe);x= e
Special case
A3
:=
(xe) ;x p= ep
A4
:=
(xe) ;y p= yp
Reminder for variables and expressions of non-ref types:
A3
p
x
O1
:=
(xe) ;x p = e p
e
y
Current
z
O2
A3
holds under the following condition: no prefix of p is of the form qx where eq may be aliased to Current (“x is cycle-free forebeforep”)
This condition holds in particular if the structure is acyclic
right
right
right
right
right
1
2
3
4
5
right
previous
next
- previous right +next right ~oldright
reverse
local
previous, next: LINKABLE [G]
do
from
next :=first ; previous :=Void
invariant
first
right
- previous right+ next right= oldfirst right
?
- previous right+ next right
right
previous
right
next
right
?
- first right=old first right
end
In a class C, an attribute
a: C
is acyclic if no element of amay be aliased to Current
One-element sequence
SC1
Sequence concatenation
x
x
x
x
Current
SC2
AS1
:=
A3
(xe) ;x q= eq
Theorem:
(x := e) ;x p a = e p a
(also applicable if a is x, and if the path p is empty)
Proof: since the two sides are sequences, it suffices to prove that elements of the sequences are pairwise equal. The individual equalities to prove are
(x := e) ;x p an= e p an
where anisa a … a (n times), for a finite number of values of n starting at 0. They follow from
which is applicable since by the definition of every an path is acyclic. (q in this equality is p an.)
AS2
SC1
CD
CUR
AS1
US2
QS
Consider set_a (f: T) with the postcondition a = f
Unqualified setter theorem (reminder):
(callset_a (c)) ; a = c
AS2
Qualified closure assignment theorem:
(callx set_a (c)) ;x a = <x>+ c a
QC
Proof:
(callx set_a (c)) ;x a = <(callx set_a (c)) ; x>
+ (callx set_a (c)) ; x a a
(callx set_a (c)) ; x = x
(callx set_a (c)) ; x a a = c a
SC2
AS1
Reminder:
(x := e) ; x = <Current>+ e x
reverse
local
previous, next: LINKABLE [G]
do
from
next :=first ; previous :=Void
invariant
first
right
- previous right+ next right
right
previous
right
next
right
?
- first right=old first right
end
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
previous right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
<previous> + temp right
previous right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
<previous> + temp right
<previous> + temp right
previous right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
<next> + temp right
<previous> + temp right
<previous> + temp right
previous right
- previous right+ next right
<next> + previous right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
<next> + temp right
<previous> + temp right
<previous> + temp right
previous right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
next right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
next right
next right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
next right right
next right
next right
- previous right+ next right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
next right right
next right right
next right
next right
- previous right+ next right
next right right
temp := previous
previous:= next
next:=next right
previous put_right (temp)
next right right
next right right
next right
next right
- previous right+ next right
<next> + previous right
next right right
–
+
temp := previous
previous:= next
next:=next right
previous put_right (temp)
- previous right+ next right
<next> + previous right
next right right
–
+
temp := previous
previous:= next
next:= next right
previous put_right (temp)
– previous right + <next>
next right right
=
+
– previous right
next right
=
+
- previous right+ next right
Conclusion