<<

Spring 2016 Program Analysis and Verification

Lecture 3: Axiomatic I

Roman Manevich Ben-Gurion University Warm-up exercises

1. Define program state:

2. Define structural semantics configurations:

3. Define the form of structural semantics transitions:

2 Tentative syllabus

Abstract Program Program Analysis Interpretation Verification Analysis Basics Techniques fundamentals

Operational Control Flow Numerical Lattices semantics Graphs Domains

Axiomatic Equation Fixed-Points Alias analysis Verification Systems

Collecting Chaotic Interprocedural Semantics Iteration Analysis

Galois Shape Using Soot Connections Analysis

Domain CEGAR constructors

Widening/ Narrowing 3 Agenda

• Basic concepts of correctness • (pages 175-183) – Motivation – First-order logic reminder – Hoare Logic

4 program correctness

5 Program correctness concepts

• Specification = a certain relationship between

initial state and final state Main focus of this course • Partial correctness = specifications that hold if the program terminates

• Termination = program always terminates – i.e., for every input state partial correctness + termination = total correctness

Other correctness concepts exist: liveness, resource usage, … 6 Verifying factorial with structural semantics

7 Structural semantics for While

[asssos] x := a,   1 [x Aa]

[skipsos] skip,  1 

1 S1,  1 S1’, ’ [comp sos] S1; S2,  1 S1’; S2, 

2 S1,  1 ’ [comp sos] S1; S2,  1 S2, ’

tt [if sos] if b then S1 else S2,  1 S1,  if B b  = tt

ff [if sos] if b then S1 else S2,  1 S2,  if B b  = ff

while b do S,  1 [whilesos] if b then S; while b do S) else skip,  8 Factorial example

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1) • Factorial partial correctness specification = if the statement terminates then the final value of y will be the factorial of the initial value of x – What if  x < 0? • Formally, using structural semantics:

Sfac,  1* ’ implies ’ y = ( x)!

9 Factorial proof strategy

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1)

Lemma 1 Lemma 2 Lemma 3 • Lemma 1: if  x>1 then y:=y*x; x:=x–1,  1* ’ implies  y * ( x)! = ’ y * (’ x)! and ’ x1 • Lemma 2: if  x1 then while (x=1) do (y:=y*x; x:=x–1),  1* ’ implies  y * ( x)! = ’ y * (’ x)! and ’ x=1 • Lemma 3: if  x1 then Sfac,  1* ’ implies ’ y = ( x)!

10 Factorial example: lemma 1

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1)

• Lemma 1:

if  x>1 then y:=y*x; x:=x–1,  1 * ’ implies  y * ( x)! = ’ y * (’ x)! and ’ x1 • Proof: Assume  x>1

y:=y*x; x:=x–1,  1 x:=x–1, [y y* x] 1 [y y* x, xx–1] = ’ • Now ’ y * (’ x)! = ( y* x) * ( x–1)! =  y * ( x)! And since’ x =  x-1 we have that ’ x1 • QED

11 Factorial example: lemma 2

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1)

• Lemma 2:

if  x1 then while (x1) do (y:=y*x; x:=x–1),  1* ’ implies  y * ( x)! = ’ y * (’ x)! and ’ x=1 • Proof:

W,  1 if (x1) then (y:=y*x; x:=x–1); W) else skip,  – Case 1:  x=1 – Case 2:  x1 – meaning  x>1

12 Factorial example: lemma 2, case 1

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1)

• Lemma 2:

if  x1 then while (x1) do (y:=y*x; x:=x–1),  1* ’ implies  y * ( x)! = ’ y * (’ x)! and ’ x=1 • Proof:

W,  1 if (x1) then (y:=y*x; x:=x–1); W) else skip,  1 skip,  1  • Claim holds

13 Factorial example: lemma 2, case 2

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1)

• Lemma 2: if  x1 then while (x1) do (y:=y*x; x:=x–1),  1* ’ implies  y * ( x)! = ’ y * (’ x)! and ’ x=1 • Proof: W,  1 if (x1) then (y:=y*x; x:=x–1); W) else skip,  1 (y:=y*x; x:=x–1); while,  1* while, ’’ 1* ’ • From lemma 1 we have that  y * ( x)! = ’ y * (’’ x)! and ’’ x1 • Applying Lemma by induction (case 1 is the base case) gives us that ’’ y * (’’ x)! = ’ y * (’ x)! and ’ x=1 • Combining the two, we get ’ y * (’ x)! = ’’ y * (’’ x)! =  y * ( x)! • and ’ x=1 • QED

14 Factorial example: lemma 3

Sfac  y:=1; while (x1) do (y:=y*x; x:=x–1)

• Lemma 3: if  x1 then Sfac,  1* ’ implies ’ y = ( x)! • Proof: • Assume  x1

• Now y:=1; W,  1 W, [y1] and [y1] x =  x • Therefore, we can apply lemma 2 and obtain W,  1* ’ •  [y1] y * ( [y1] x)! = ’ y * (’ x)! and ’ x=1 • Simplifying this yields: • 1 * ( x)! = ’ y * 1! and ’ x=1 • Meaning: ’ y = ( x)! • QED

15 How easy was that?

• Proof is very laborious – Need to connect all transitions and argue about relationships between their states – Reason: too closely connected to semantics of programming • Proof is long – Makes it hard to find possible mistakes • How did we know to find this proof? – Is there a methodology?

16 Can you I’ll use prove my operational program semantics correct?

Better use axiomatic verification

17 One of the oldest surviving fragments of Euclid's Elements, a textbook used for millennia to teach proof-writing techniques. The diagram accompanies Book II, Proposition 5

"P. Oxy. I 29" by Euclid - http://www.math.ubc.ca/~cass/Euclid/papyrus/tha.jpg. Licensed under Public Domain via Wikimedia Commons - http://commons.wikimedia.org/wiki/File:P._Oxy._I_29.jpg#/media/File:P._Oxy._I_29.jpg

18 A systematic approach to program verification

19 Axiomatic verification approach

• What do we need in order to prove that the program does what it supposed to do? • A language to express specifications • Compare the behavior with the one obtained by the • Develop a proof system for showing that the program satisfies the specification • Mechanically use the proof system to show correctness

20 Axiomatic semantics contributors

Robert Floyd C.A.R. Hoare Edsger W. Dijkstra

1967: use assertions 1969: use Floyd’s ideas Predicate transformer as foundation for static to define axiomatic semantics: weakest correctness proofs semantics precondition and “An axiomatic basis for strongest postcondition computer programming”

21 Assertions, a.k.a Hoare triples { P } C { Q }

statement precondition a.k.a command postcondition • P and Q are state predicates expressed as logical formulas – Example: x>0 • If P holds in the initial state, and if execution of C terminates on that state, then Q will hold in the state in which C halts • C is not required to always terminate {true} while true do skip {false}

22 Total correctness assertions [ P ] C [ Q ]

• If P holds in the initial state, execution of C must terminate on that state, and Q will hold in the state in which C halts

23 Specifying correctness of factorial

24 Factorial example: specify precondition/postcondition

{ ? } y := 1; while (x=1) do (y := y*x; x := x–1) { ? }

25 First attempt

We need a way to “remember” value of x before execution { x>0 } y := 1; while (x=1) do (y := y*x; x := x–1) { y=x! }

Holds only for value of x at state after execution finishes

26 Fixed assertion

A logical variable, must not appear in statements – immutable. Also called a ghost variable. { x=n } y := 1; while (x=1) do (y := y*x; x := x–1) { y=n!  n>0 }

27 The proof outline

Background axiom { x>0  x=n } { n!=n*(n-1)! } y := 1; { x>0  y*x!=n!  nx } while (x=1) do { x-1>0  (y*x)*(x-1)!=n!  n(x-1) } y := y*x; { x-1>0  y*(x-1)!=n!  n(x-1) } x := x–1 { y*x!=n!  n>0  x=1 }

28 Factorial spec and proof in Dafny online function Factorial(n: int): int requires n >= 1 { if n == 1 then 1 else n * Factorial(n - 1) }

method ComputeFactorial(n: int) returns (y: int) requires n >= 1 ensures y == Factorial(n) { var x := n; y := 1; while x != 1 invariant y * Factorial(x) == Factorial(n) decreases x { y := y * x; x := x - 1; } } 29 Formalizing partial correctness via hoare logic

30 States and predicates  •  – program states (State)  – undefined P • A state predicate P is a (possibly infinite) set of states •   P  – P holds in state 

31 Formalizing Hoare triples

’ if C,  1*’ Q Ssos C  =  else P C(P)  C ’ • { P } C { Q }

– , ’   . (  P  C,  1* ’)  ’  Q alternatively – Convention:   P for all P    .   P  SsosC  Q

32 How do we express predicates?

• Extensional approach – Abstract mathematical functions P : State  {tt, ff}

• Intensional approach – via language of formulae

33 An assertion language

• Bexp is not expressive enough to express predicates needed for many proofs – Extend Bexp • Allow quantification – z. … – z. … • z. z = kn • Import well-known mathematical concepts – n!  n  (n-1)   2  1

34 An assertion language

Either a program variables or a logical variable a ::= n | x | a1 + a2 | a1  a2 | a1 – a2 A ::= true | false

| a1 = a2 | a1  a2 | A | A1  A2 | A1  A2 | A1  A2 | z. A | z. A

35 Some FO logic definitions before we get to the rules

36 Free/bound variables

• A variable is said to be bound in a formula when it occurs in the scope of a quantifier Otherwise it is said to be free – i. k=im – (i+10077)i. j+1=i+3) • FV(A)  the free variables of A • Defined inductively on the abstract syntax tree of A

37 Computing free variables

FV(n)  {} FV(x)  {x}

FV(a1+a2)  FV(a1a2)  FV(a1-a2)  FV(a1)  FV(a2)

FV(true)  FV(false) {}

FV(a1=a2)  FV(a1a2)  FV(a1)  FV(a2) FV(A)  FV(A) FV(A1  A2)  FV(A1  A2)  FV(A1  A2)  FV(a1)  FV(a2)

FV(z. A)  FV(z. A)  FV(A) \ {z}

38 Substitution

• An expression t is pure (a term) if it does not contain quantifiers • A[t/z] denotes the assertion A’ which is the same as A, except that all instances of the free variable z are replaced by t • A  i. k=im A[5/k] = …? A[5/i] = …?

39 Calculating substitutions n[t/z] = n x[t/z] = x x[t/x] = t

(a1 + a2)[t/z] = a1[t/z] + a2[t/z] (a1  a2)[t/z] = a1[t/z]  a2[t/z] (a1 - a2)[t/z] = a1[t/z] - a2[t/z]

40 Calculating substitutions true[t/x] = true false[t/x] = false

(a1 = a2)[t/z] = a1[t/z] = a2[t/z] (a1  a2)[t/z]= a1[t/z]  a2[t/z] (A)[t/z] = (A[t/z])

(A1  A2)[t/z] = A1[t/z]  A2[t/z] (A1  A2)[t/z] = A1[t/z]  A2[t/z] (A1  A2)[t/z] = A1[t/z]  A2[t/z]

(z. A)[t/z] = z. A (z. A)[t/y] = z. A[t/y] ( z. A)[t/z] =  z. A ( z. A)[t/y] =  z. A[t/y] 41 Equivalence in FO logic

• We write A  B if for all states  if   A then   B – { |   A }  { |   B } – For every predicate A: false  A  true • We write A  B if A  B and B  A – false  5=7 • In writing Hoare-style proofs, we will often replace a predicate A with A’ such that A  A’ and A’ is “simpler”

42 six are completely enough and now… the rules

43 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 }

{ b  P } S { P } What’s different [while ] about this rule? p { P } while b do S {b  P }

{ P’ } S { Q’ } [cons ] if P P’ and Q’ Q p { P } S { Q }   44 Assignment rule

[assp] { P[a/x] } x := a { P }

• A “backwards” rule • x := a always finishes [xAa]  P • Why is this true? – Recall operational semantics:

[ass] x:= a,  1 [xAa]

• { | [xAa  P} 1 {[xAa | [xAa  P}

45 Practice with Dafny

Ghost methods do not get ghost method AssignRuleTest1() { compiled to code var x, y, z; assume ???; { } x:=y*z {x<9} Filters out states that do x := y * z; not satisfy the predicate assert x < 9; }

A proof obligation ghost method AssignRuleTest2() { var x: int, y: int , z: int; assume ???; x := x + 1; { } x:=x+1 {x>8} assert x > 8; }

ghost method AssignRuleTest3() { var x: int, y: int , z: int , w: int; assume ???; { } x:=y*z {w=5} x := y * z; assert w == 5; }

46 skip rule

[skipp] { P } skip { P }

48 Composition rule

{ P } S1 { Q }, { Q } S2 { R } [compp] { P } S1; S2 { R }

S ,   * ’, S , ’  * ’’ Lemma: 1 1 2 1 S1; S2,  1* ’’

• Holds when S1 terminates in every state where P holds and then Q holds and S2 terminates in every state where Q holds and then R holds

49 Practice with Dafny ghost method CompositionRuleTest() { { x < 9 } var x: int; assume x < 9; x := x + 1 x := x + 1; { } assert ???; x := x * 2; x := x * 2; { x < 20 } assert x < 20; }

50 Condition rule

{ b  P } S1 { Q }, { b  P } S2 { Q } [ifp] { P } if b then S1 else S2 { Q } • Intuitively, it means: – Split cases on either b holds or not – For each case make sure Q holds – Conclude that Q holds on both cases

51 Practice with Dafny ghost method ConditionRuleTest() { var x: int, y: int; assume x > 8 || x < -8; if x > 0 { y := x; } else { y := -1 * x; } assert ???; }

52 Loop rule

{ b  P } S { P } [while ] p { P } while b do S {b  P }

• Here P is called an invariant for the loop – Holds before and after each loop iteration – Finding loop invariants – most challenging part of proofs • When loop finishes, b is false

53 Example: write a specification

{ } while (timer  0) do timer := timer – 1 { }

• “The program should count to zero”

54 Practice with Dafny ghost method Timer(x: int) returns (timer: int) requires x >= 0; ensures timer == 0; { timer := x; while (timer != 0) invariant timer >= 0; { timer := timer - 1; } }

55 Rule of consequence

{ P’ } S { Q’ } [cons ] if PP’ and Q’Q p { P } S { Q }

• Allows strengthening the precondition and weakening the postcondition • The only rule that is not related to a statement

56 Rule of consequence

{ P’ } S { Q’ } [cons ] if PP’ and Q’Q p { P } S { Q }

• Why do we need it? • Allows the following {y*z<9} x:=y*z {x<9} {y*z<9w=5} x:=y*z {x<9}

57 See you next time

58