PPTX

advertisement
Spring 2014
Program Analysis and Verification
Lecture 6: Axiomatic Semantics III
Roman Manevich
Ben-Gurion University
Syllabus
Semantics
Natural
Semantics
Static
Analysis
Automating
Hoare Logic
Abstract
Interpretation
fundamentals
Analysis
Techniques
Crafting your
own
Lattices
Numerical
Domains
Soot
Structural
semantics
Galois
Connections
CEGAR
From proofs to
abstractions
Axiomatic
Verification
Fixed-Points
Alias analysis
Systematically
developing
transformers
Widening/
Narrowing
Shape
Analysis
Domain
constructors
Interprocedural
Analysis
2
Previously
• Hoare logic
– Inference system
– Annotated programs
– Soundness and completeness
• Weakest precondition calculus
3
Axiomatic semantics for While
[assp] { P[a/x] } x := a { P }
[skipp] { P } skip { P }
{ P } S1 { Q }, { Q } S2 { R }
[compp]
{ P } S1; S2 { R }
{b
P } S1 { Q }, { b P } S2 { Q
}
[ifp]
{ P } if b then S1 else S2 { Q }
[whilep]
[consp]
{b P}S{P}
{ P } while b do S { b
{ P’ } S { Q’ }
{P}S{Q}
P}
if P P’ and Q’ Q
4
Weakest precondition
calculus
5
Weakest liberal precondition
• A backward-going predicate transformer
• The weakest liberal precondition for Q is
 wlp(C, Q)
if and only if for all states ’
if C,  ’ then ’ Q
Propositions:
1. p { wlp(C, Q) } C { Q }
2. If p { P } C { Q } then P
wlp(C, Q)
6
Weakest liberal precondition
• A backward-going predicate transformer
• The weakest liberal precondition for Q is
 wlp(C, Q)
if and only if for all states ’
if C,  ’ then ’ Q
Q
wlp(C, Q)
P
C
C(wlp(C, Q))
C(P)
7
Strongest postcondition
• A forward-going predicate transformer
• The strongest postcondition for P is
’ sp(P, C)
if and only if there exists  such that
 P and C,  ’
Propositions:
1. p { P } C { sp(P, C) }
2. If p { P } C { Q } then sp(P, C)
Q
8
Calculating
Weakest
preconditions
By Vadim Plessky (http://svgicons.sourceforge.net/) [see page for license], via Wikimedia Commons
9
Calculating wlp
1.
2.
3.
4.
wlp(skip, Q) = Q
wlp(x := a, Q) = Q[a/x]
wlp(S1; S2, Q) = wlp(S1, wlp(S2, Q))
wlp(if b then S1 else S2, Q) =
(b wlp(S1, Q))
( b wlp(S2, Q))
5. wlp(while b do S, Q) = … ?
hard to capture
10
Calculating the wlp of a loop
Idea: we know the following statements are semantically equivalent
while b do S
if b do (S; while b do S) else skip
Let’s try to substitute and calculate on
wlp(while b do S, Q) =
wlp(if b do (S; while b do S) else skip, Q) =
(b
wlp(S; while b do S, Q))
(b
wlp(S, wlp(while b do S, Q)))
LoopInv = (b
wlp(S, LoopInv))
( b
( b
wlp(skip, Q)) =
( b
Q)
Q)
11
Another variant for WP of loops
• Parametric in the loop invariant
• wlp(while b do { } S, Q) =
where {b
}S{ }
and b
Q
12
Variable swap program – specify
{
t
x
y
{
? }
:= x
:= y
:= t
? }
13
Prove using weakest precondition
{
t
{
x
{
y
{
y=b
:= x
? }
:= y
? }
:= t
x=b
x=a }
y=a }
14
Prove using weakest precondition
{
t
{
x
{
y
{
y=b
:= x
y=b
:= y
x=b
:= t
x=b
x=a }
t=a }
t=a }
y=a }
15
Absolute value program
if x<0 then
x := -x
else
skip
if b then S
is syntactic sugar for
if b then S else skip
The latter form is easier to
reason about
16
Absolute value program – specify
{ ? }
if x<0 then
x := -x
else
skip
{ ? }
17
Absolute value program – specify
{ x=v }
if x<0 then
x := -x
else
skip
{ x=|v| }
18
Prove using weakest precondition
{ x=v
{
if x<0 then
{
x := -x
{
else
{
skip
{
{x=|v|
}
}
}
}
}
}
}
19
Prove using weakest precondition
{ x=v
{ (-x=|v|
x<0)
if x<0 then
{ -x=|v|
x := -x
{ x=|v|
else
{ x=|v|
skip
{ x=|v|
{ x=|v|
(x=|v|
}
x 0) }
}
}
}
}
}
20
Making the proof system
more practical
21
Conjunction rule
{P}S{Q}
{ P’ } S { Q’ }
[conjp]
{ P P’ } S {Q Q’ }
• Allows breaking up proofs into smaller, easier
to manage, sub-proofs
22
Breaks if C is nondeterministic
More useful rules
{P}C{Q}
{ P’ } C { Q’ }
[disjp]
{ P P’ } C {Q Q’ }
{P}C{Q}
[existp] { v. P } C { v. Q v FV(C
}
)
{P}C{Q}
v FV(C
[univp]
{ v. P } C { v. Q }
)
[Invp] { F } C { F } Mod(C) FV(F)={}
• Mod(C) = set of variables assigned to in sub-statements of C
• FV(F) = free variables of F
23
Invariance + Conjunction = Constancy
{P}C{Q}
[constancyp]
Mod(C)
{F P}C{F Q}
FV(F)={}
• Mod(C) = set of variables assigned to in sub-statements of C
• FV(F) = free variables of F
24
Today
• Strongest postcondition
• Extension for memory
• Proving termination
25
Strongest
postcondition
calculus
By Vadim Plessky (http://svgicons.sourceforge.net/) [see page for license], via Wikimedia Commons
26
Floyd’s strongest postcondition rule
{ P } x := a { v. x=a[v/x] P[v/x]
[assFloyd]
}
where v is a fresh variable
The value of x
in the pre-state
• Example
{ z=x } x:=x+1 {
?
}
• This rule is often considered problematic
because it introduces a quantifier – needs to
be eliminated further on
• We will now see a variant of this rule
27
Floyd’s strongest postcondition rule
{ P } x := a { v. x=a[v/x] P[v/x]
[assFloyd]
}
where v is a fresh variable
meaning: {x=z+1}
• Example
{ z=x } x:=x+1 { v. x=v+1 z=v }
• This rule is often considered problematic
because it introduces a quantifier – needs to
be eliminated further on
• We will now see a variant of this rule
28
“Small” assignment axiom
Create an explicit Skolem
variable in precondition
Then assign the resulting
value to x
First evaluate a
in the precondition state
(as a may access x)
[assfloyd] { x=v } x:=a { x=a[v/x] }
where v FV(a)
• Examples:
{x=n} x:=5*y {x=5*y}
{x=n} x:=x+1 {x=n+1}
{x=n} x:=y+1 {x=y+1}
[existp] { n. x=n} x:=y+1 { n. x=y+1} therefore {true} x:=y+1 {x=y+1}
[constancyp] {z=9} x:=y+1 {z=9 x=y+1}
29
“Small” assignment axiom
[assfloyd] { x=v } x:=a { x=a[v/x] }
where v FV(a)
• Examples:
{x=n} x:=5*y {x=5*y}
{x=n} x:=x+1 {x=n+1}
{x=n} x:=y+1 {x=y+1}
[existp] { n. x=n} x:=y+1 { n. x=y+1} therefore {true} x:=y+1 {x=y+1}
[constancyp] {z=9} x:=y+1 {z=9 x=y+1}
30
“Small” assignment axiom
[assfloyd] { x=v } x:=a { x=a[v/x] }
where v FV(a)
• Examples:
{x=n} x:=5*y {x=5*y}
{x=n} x:=x+1 {x=n+1}
{x=n} x:=y+1 {x=y+1}
[existp] { n. x=n} x:=y+1 { n. x=y+1} therefore {true} x:=y+1 {x=y+1}
[constancyp] {z=9} x:=y+1 {z=9 x=y+1}
31
“Small” assignment axiom
[assfloyd] { x=v } x:=a { x=a[v/x] }
where v FV(a)
• Examples:
{x=n} x:=5*y {x=5*y}
{x=n} x:=x+1 {x=n+1}
{x=n} x:=y+1 {x=y+1}
[existp] { n. x=n} x:=y+1 { n. x=y+1} therefore {true} x:=y+1 {x=y+1}
[constancyp] {z=9} x:=y+1 {z=9 x=y+1}
32
Calculating sp
1.
2.
3.
4.
sp(skip, P) = P
sp(x := a, P) = v. x=a[v/x] P[v/x]
sp(S1; S2, P) = sp(S2, sp(S1, P))
sp(if b then S1 else S2, P) =
sp(S1, b P) sp(S2, b P)
5. sp(while b do { } S, P) =
b
where {b
}S{ }
and P  b
33
Prove using strongest postcondition
{ x=a
t := x
y=b }
x := y
y := t
{ x=b
y=a }
34
Prove using strongest postcondition
{ x=a
t := x
{ x=a
y=b }
y=b
t=a }
x := y
y := t
{ x=b
y=a }
35
Prove using strongest postcondition
{ x=a
t := x
{ x=a
x := y
{ x=b
y=b }
y=b
t=a }
y=b
t=a }
y := t
{ x=b
y=a }
36
Prove using strongest postcondition
{ x=a
t := x
{ x=a
y=b }
y=b
t=a }
x := y
{ x=b
y=b
t=a }
y := t
{ x=b
{ x=b
y=a
t=a }
y=a } // cons
37
Prove using strongest postcondition
{ x=v }
if x<0 then
{ x=v
x<0 }
x := -x
{ x=-v
x>0 }
else
{ x=v
x 0 }
skip
{ x=v
x 0 }
{ v<0
x=-v
v 0
{ x=|v| }
x=v }
38
Prove using strongest postcondition
{ x=v }
if x<0 then
{ x=v
x<0 }
x := -x
{ x=-v
x>0 }
else
{ x=v
x 0 }
skip
{ x=v
x 0 }
{ v<0
x=-v
v 0
{ x=|v| }
x=v }
39
Sum program – specify
• Define Sum(0, n) = 0+1+…+n
{
?
x := 0
res := 0
while (x<y) do
res := res+x
x := x+1
{
?
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
}
Background axiom
}
40
Sum program – specify
• Define Sum(0, n) = 0+1+…+n
{ y 0 }
x := 0
res := 0
while (x<y) do
res := res+x
x := x+1
{ res = Sum(0, y) }
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
Background axiom
41
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
res := 0
Inv =
while (x<y) do
res := res+x
x := x+1
{ res = Sum(0, y) }
42
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
Inv =
while (x<y) do
res := res+x
x := x+1
{ res = Sum(0, y) }
43
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv =
while (x<y) do
res := res+x
x := x+1
{ res = Sum(0, y) }
44
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv = { y 0
res=Sum(0, x)
while (x<y) do
x y
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
}
res := res+x
x := x+1
{ res = Sum(0, y) }
45
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv = { y 0
res=Sum(0, x)
x y
}
while (x<y) do
{ y 0
res=m
x=n
n y
m=Sum(0, n)
x<y }
{ y 0
res=m
x=n
m=Sum(0, n)
n<y }
res := res+x
x := x+1
{ res = Sum(0, y) }
46
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv = { y 0
res=Sum(0, x)
x y
}
while (x<y) do
{ y 0
res=m
x=n
n y
m=Sum(0, n)
x<y }
{ y 0
res=m
x=n
m=Sum(0, n)
n<y }
res := res+x
{ y 0
res=m+x
x=n
m=Sum(0, n)
n<y
}
x := x+1
{ res = Sum(0, y) }
47
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv = { y 0
res=Sum(0, x)
x y
}
while (x<y) do
{ y 0
res=m
x=n
n y
m=Sum(0, n)
x<y }
{ y 0
res=m
x=n
m=Sum(0, n)
n<y }
res := res+x
{ y 0
res=m+x
x=n
m=Sum(0, n)
n<y
}
x := x+1
{ y 0
res=m+x
x=n+1
m=Sum(0, n)
n<y
}
{ y 0
res=Sum(0, x)
x=n+1
n<y } // sum axiom
{ y 0
res=Sum(0, x)
x y } // cons
{ res = Sum(0, y) }
48
Sum program – prove
• Define Sum(0, n) = 0+1+…+n
{ x=Sum(0, n) } { y=n+1 }
{ x+y=Sum(0, n+1) }
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv = { y 0
res=Sum(0, x)
x y
}
while (x<y) do
{ y 0
res=m
x=n
n y
m=Sum(0, n)
x<y }
{ y 0
res=m
x=n
m=Sum(0, n)
n<y }
res := res+x
{ y 0
res=m+x
x=n
m=Sum(0, n)
n<y
}
x := x+1
{ y 0
res=m+x
x=n+1
m=Sum(0, n)
n<y
}
{ y 0
res=Sum(0, x)
x=n+1
n<y } // sum axiom
{ y 0
res=Sum(0, x)
x y } // cons
{ y 0
res=Sum(0, x)
x y
x y }
{ y 0
res=Sum(0, y)
x=y }
{ res = Sum(0, y) }
49
Buggy sum program
{ y 0 }
x := 0
{ y 0
x=0 }
res := 0
{ y 0
x=0
res=0 }
Inv = { y 0
res=Sum(0, x) }
= { y 0
res=m
x=n
m=Sum(0, n) }
while (x y) do
{ y 0
res=m
x=n
m=Sum(0, n)
x y
n y }
x := x+1
{ y 0
res=m
x=n+1
m=Sum(0, n)
n y}
res := res+x
{ y 0
res=m+x
x=n+1
m=Sum(0, n)
n y}
{ y 0
res-x=Sum(0, x-1)
n y}
{ y 0
res=Sum(0, x) }
{ y 0
res=Sum(0, x)
{res = Sum(0, y) }
x>y }
50
Handling data structures
51
Problems with Hoare logic and heaps
• { P[a/x] } x := a { P }
• Consider the annotated program
{ y=5 }
y := 5;
The rule works on a syntactic
level unaware of possible
{ y=5 }
aliasing between different
x := &y;
terms (y and *x in our case)
{ y=5 }
*x := 7;
{ y=5 }
• Is it correct?
52
Problems with Hoare logic and heaps
• { P[a/x] } x := a { P }
• {(x=&y
z=5)
(x&y
y=5)}
*x = z;
{ y=5 }
• What should the precondition be?
53
Problems with Hoare logic and heaps
• { P[a/x] } x := a { P }
• {(x=&y
z=5)
(x&y
y=5)}
*x = z;
{ y=5 }
• We split into cases depending on possible aliasing
54
Problems with Hoare logic and heaps
• { P[a/x] } x := a { P }
• {(x=&y
z=5)
(x&y
y=5)}
*x = z;
{ y=5 }
• What should the precondition be?
• Joseph M. Morris: A General Axiom of
Assignment
• A different approach: heaps as arrays
• Really successful approach for heaps is based on
Separation Logic
55
Axiomatizing data types
S ::= x := a | x := y[a] | y[a] := x
| skip | S1; S2
| if b then S1 else S2
| while b do S
• We added a new type of variables – array
variables
– Model array variable as a function y : Z  Z
• We need the two following axioms:
{ y[x a](x) = a }
{ zx  y[x a](z) = y(z) }
56
Array update rules (wlp)
S ::= x := a | x := y[a] | y[a] := x
| skip | S1; S2
A very general approach – allows
| if b then S1 else S2 handling many data types
| while b do S
• Treat an array assignment y[a] := x as an
update to the array function y
– y := y[a x] meaning y’= v. v=a ? x : y(v)
[array-update] { P[y[a x]/y] } y[a] := x { P }
[array-load] { P[y(a)/x] } x := y[a] { P }
57
Array update rules (wlp) example
• Treat an array assignment y[a] := x as an
update to the array function y
– y := y[a x] meaning y’= v. v=a ? x : y(v)
[array-update] { P[y[a x]/y] } y[a] := x { P }
{x=y[i 7](i)} y[i]:=7 {x=y(i)}
{x=7} y[i]:=7 {x=y(i)}
[array-load] { P[y(a)/x] } x := y[a] { P }
{y(a)=7} x:=y[a] {x=7}
58
Array update rules (sp)
In both rules
v, g, and b are fresh
[array-updateF] { x=v
[array-loadF] { y=g
y=g a=b } y[a] := x { y=g[b v]
}
a=b } x := y[a] { x=g(b) }
59
Example of proving
program with arrays
60
Array-max program – specify
nums : array
N : int // N stands for num’s length
{ N 0
nums=orig_nums }
x := 0
res := nums[0]
while x < N
if nums[x] > res then
res := nums[x]
x := x + 1
1. { x=N }
2. { m. (m 0
m<N)  nums(m) res }
3. { m. m 0
m<N
nums(m)=res }
4. { nums=orig_nums }
61
Array-max program
nums : array
N : int // N stands for num’s length
{ N 0
nums=orig_nums }
x := 0
res := nums[0]
while x < N
if nums[x] > res then
res := nums[x]
x := x + 1
Post1: { x=N }
Post2: { nums=orig_nums }
Post3: { m. 0 m<N  nums(m) res }
Post4: { m. 0 m<N
nums(m)=res }
62
Proof strategy
• Prove each goal 1, 2, 3, 4 separately and use
conjunction rule to prove them all
• After proving
– {N 0} C {x=N}
– {nums=orig_nums} C {nums=orig_nums}
• We have proved
– {N 0
{x=N
nums=orig_nums}
C
nums=orig_nums}
• We can refer to assertions from earlier proofs in
writing new proofs
63
Array-max example: Post1
nums : array
N : int // N stands for num’s length
{ N 0 }
x := 0
{ N 0
x=0 }
res := nums[0]
{ x=0 }
Inv = { x N }
while x < N
{ x=k
k<N }
if nums[x] > res then
{ x=k
k<N }
res := nums[x]
{ x=k
k<N }
{ x=k
k<N }
x := x + 1
{ x=k+1
k<N }
{ x N
x N }
{ x=N }
64
Array-max example: Post2
nums : array
N : int // N stands for num’s length
{ nums=orig_nums }
x := 0
{ nums=orig_nums }
res := nums[0]
{ nums=orig_nums }
Inv = { nums=orig_nums }
while x < N
{ nums=orig_nums
x < N }
if nums[x] > res then
{ nums=orig_nums }
res := nums[x]
{ nums=orig_nums }
{ nums=orig_nums }
x := x + 1
{ nums=orig_nums }
{ nums=orig_nums
x N }
{ nums=orig_nums }
65
Array-max example: Post3
nums : array
{ N 0
0 m<N } // N stands for num’s length
x := 0
{ x=0 }
res := nums[0]
{ x=0
res=nums(0) }
Inv = { 0 m<x  nums(m) res }
while x < N
{ x=k
res=oRes
0 m<k  nums(m) oRes }
if nums[x] > res then
{ nums(x)>oRes
res=oRes
x=k
0 m<k  nums(m) oRes }
res := nums[x]
{ res=nums(x)
nums(x)>oRes
x=k
0 m<k  nums(m) oRes }
{ x=k
0 m k  nums(m) res }
{ (x=k
0 m k  nums(m) res)
(oRes nums(x)
res=oRes
x=k
res=oRes
0 m<k 
nums(m) oRes)}
{ x=k
0 m k  nums(m) res }
x := x + 1
{ x=k+1
0 m k  nums(m) res }
{ 0 m<x  nums(m) res }
{ x=N
0 m<x  nums(m) res}
[univp]{ m. 0 m<N  nums(m) res }
66
Proving
termination
67
Total correctness semantics for While
[assp] [ P[a/x] ] x := a [ P ]
[skipp] [ P ] skip [ P ]
[ P ] S1 [ Q ], [ Q ] S2 [ R ]
[compp]
[ P ] S1; S2 [ R ]
[b
[ifp]
[whilep]
[consp]
P ] S1 [ Q ], [ b P ] S2 [ Q
]
[ P ] if b then S1 else S2 [ Q ]
[ P(z+1) ] S [ P(z) ]
P(z+1)  b
[ z. P(z) ] while b do S [ P(0) ] P(0)  b
[ P’ ] S [ Q’ ]
[P]S[Q]
if P P’ and Q’ Q
68
Total correctness semantics for While
[assp] [ P[a/x] ] x := a [ P ]
[skipp] [ P ] skip [ P ]
[ P ] S1 [ Q ], [ Q ] S2 [ R ]
[compp]
[ P ] S1; S2 [ R ]
[b
Rank, or
Loop
variant
[ifp]
[whilep]
[consp]
P ] S1 [ Q ], [ b P ] S2 [ Q
]
[ P ] if b then S1 else S2 [ Q ]
[ b P t=k ] S [ P t<k ]
P  t0
[ P ] while b do S [ b P ]
[ P’ ] S [ Q’ ]
[P]S[Q]
if P P’ and Q’ Q
69
Proving termination
• There is a more general rule based on wellfounded relations
– Partial orders with no infinite strictly decreasing
chains
• Exercise: write a rule that proves only that a
program S, started with precondition P
terminates
[
]S[
]
70
Proving termination
• There is a more general rule based on wellfounded relations
– Partial orders with no infinite strictly decreasing
chains
• Exercise: write a rule that proves only that a
program S, started with precondition P
terminates
[ P ] S [ true ]
71
Array-max – specify termination
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Variant = [
?
]
while x < N
if nums[x] > res then
res := nums[x]
x := x + 1
[
?
]
72
Array-max – specify termination
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Variant = [ N-x ]
while x < N
[
?
]
if nums[x] > res then
res := nums[x]
x := x + 1
[
?
]
[ true ]
73
Array-max – prove loop variant
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Variant = [ t=N-x ]
while x < N
[ x<N
N-x=k
N-x0 ]
if nums[x] > res then
res := nums[x]
x := x + 1
// [ N-x<k
N-x0 ]
[ true ]
74
Array-max – prove loop variant
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Capture initial value of x, since
Variant = [ t=N-x ]
it changes in the loop
while x < N
[ x=x0
x0<N
N-x0=k
N-x00 ]
if nums[x] > res then
res := nums[x]
x := x + 1
// [ N-x<k
N-x0 ]
[ true ]
75
Array-max – prove loop variant
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Variant = [ t=N-x ]
while x < N
[ x=x0
x0<N
N-x0=k
N-x00 ]
if nums[x] > res then
res := nums[x]
[ x=x0
x0<N
N-x0=k
N-x00 ] // Frame
x := x + 1
// [ N-x<k
N-x0 ]
[ true ]
76
Array-max – prove loop variant
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Variant = [ t=N-x ]
while x < N
[ x=x0
x0<N
N-x0=k
N-x00 ]
if nums[x] > res then
res := nums[x]
[ x=x0
x0<N
N-x0=k
N-x00 ] // Frame
x := x + 1
[ x=x0+1
x0<N
N-x0=k
N-x00 ]
// [ N-x<k
N-x0 ]
[ true ]
77
Array-max – prove loop variant
nums : array
N : int // N stands for num’s length
x := 0
res := nums[0]
Variant = [ t=N-x ]
while x < N
[ x=x0
x0<N
N-x0=k
N-x00 ]
if nums[x] > res then
res := nums[x]
[ x=x0
x0<N
N-x0=k
N-x00 ] // Frame
x := x + 1
[ x=x0+1
x0<N
N-x0=k
N-x00 ]
[ N-x<k
N-x0 ] // cons
[ true ]
78
Zune calendar bug
while (days > 365) {
if (IsLeapYear(year)) {
if (days > 366) {
days -= 366;
year += 1;
}
} else {
days -= 365;
year += 1;
}
}
79
Fixed code
while (days > 365) {
if (IsLeapYear(year)) {
if (days > 366) {
days -= 366;
year += 1;
}
else {
break;
}
} else {
days -= 365;
year += 1;
}
}
80
Fixed code – specify termination
[ ? ]
while (days > 365) {
if (IsLeapYear(year)) {
if (days > 366) {
days -= 366;
year += 1;
}
else {
break;
}
} else {
days -= 365;
year += 1;
}
}
[ ? ]
81
Fixed code – specify variant
[ true ]
Variant = [ ? ]
while (days > 365) {
if (IsLeapYear(year)) {
if (days > 366) {
days -= 366;
year += 1;
}
else {
break;
}
} else {
days -= 365;
year += 1;
}
[
?
]
}
[ true ]
82
Fixed code – proving termination
[ true ]
Variant = [ t=days ]
while (days > 365) {
[ days>365
days=k
days0 ]
if (IsLeapYear(year)) {
if (days > 366) {
days -= 366;
year += 1;
}
else {
break; [ false ]
}
} else {
days -= 365;
year += 1;
}
// [ days0
days<k ]
}
[ true ]
Let’s model break by a
small cheat – assume
execution never gets
past it
83
Fixed code – proving termination
[ true ]
Variant = [ t=days ]
while (days > 365) {
[ days0
k=days
days>365 ] -> [ days0
k=days
days>365 ]
if (IsLeapYear(year)) {
[ k=days
days>365 ]
if (days > 366) {
[ k=days
days>365
days>366 ] -> [ k=days
days>366 ]
days -= 366;
[ days=k-366
days>0 ]
year += 1;
[ days=k-366
days>0 ]
}
else {
[ k=days
days>365
days366 ]
break; [ false ]
}
[ (days=k-366
days>0)
false ] -> [ days<k
days>0 ]
} else {
[ k=days
days>365 ]
days -= 365;
[ k-365=days
days-365>365 ] -> [ k-365=days
days0 ] -> [ days<k
year += 1;
[ days<k
days0 ]
}
[ days<k
days0 ]
}
[ true ]
days0 ]
84
Challenge: proving non-termination
• Write a rule for proving that a program does
not terminate when started with a
precondition P
• Prove that the buggy Zune calendar program
does not terminate
[while-ntp]
{b P}S{b}
{ P } while b do S { false }
85
conclusion
86
Extensions to axiomatic semantics
• Assertions for execution time
– Exact time
– Order of magnitude time
• Assertions for dynamic memory
– Separation Logic
• Assertions for parallelism
– Owicki-Gries
– Concurrent Separation Logic
– Rely-guarantee
87
Axiomatic verification conclusion
• Very powerful technique for reasoning about
programs
– Sound and complete
• Extendible
• Static analysis can be used to automatically
synthesize assertions and loop invariants
88
Next lecture:
static analysis
Download