Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 6: Axiomatic Semantics III Roman Manevich Ben-Gurion University.

Slides:



Advertisements
Similar presentations
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Advertisements

Program Analysis and Verification
ICE1341 Programming Languages Spring 2005 Lecture #6 Lecture #6 In-Young Ko iko.AT. icu.ac.kr iko.AT. icu.ac.kr Information and Communications University.
Reasoning About Code; Hoare Logic, continued
Hoare’s Correctness Triplets Dijkstra’s Predicate Transformers
Rigorous Software Development CSCI-GA Instructor: Thomas Wies Spring 2012 Lecture 11.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 1: Introduction Roman Manevich Ben-Gurion University.
David Evans CS655: Programming Languages University of Virginia Computer Science Lecture 19: Minding Ps & Qs: Axiomatic.
Axiomatic Verification I Prepared by Stephen M. Thebaut, Ph.D. University of Florida Software Testing and Verification Lecture 17.
Predicate Transformers
1/22 Programs : Semantics and Verification Charngki PSWLAB Programs: Semantics and Verification Mordechai Ben-Ari Mathematical Logic for Computer.
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 5: Axiomatic Semantics II Roman Manevich Ben-Gurion University.
1 Operational Semantics Mooly Sagiv Tel Aviv University Textbook: Semantics with Applications.
ESC Java. Static Analysis Spectrum Power Cost Type checking Data-flow analysis Model checking Program verification AutomatedManual ESC.
Software Verification Bertrand Meyer Chair of Software Engineering Lecture 2: Axiomatic semantics.
Operational Semantics Semantics with Applications Chapter 2 H. Nielson and F. Nielson
Floyd Hoare Logic. Semantics A programming language specification consists of a syntactic description and a semantic description. Syntactic description:symbols.
Proving Program Correctness The Axiomatic Approach.
Program Analysis and Verification Noam Rinetzky Lecture 3: Axiomatic Semantics 1 Slides credit: Roman Manevich, Mooly Sagiv, Eran Yahav.
Program Analysis and Verification
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 7: Static Analysis I Roman Manevich Ben-Gurion University.
Reading and Writing Mathematical Proofs
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 2: Operational Semantics I Roman Manevich Ben-Gurion University.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 14: Numerical Abstractions Roman Manevich Ben-Gurion University.
1 Formal Semantics of Programming Languages “Program testing can be used to show the presence of bugs, but never to show their absence!” --Dijkstra.
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 14: Numerical Abstractions Roman Manevich Ben-Gurion University.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 9: Abstract Interpretation I Roman Manevich Ben-Gurion University.
CS 363 Comparative Programming Languages Semantics.
Program Analysis and Verification
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 4: Axiomatic Semantics I Roman Manevich Ben-Gurion University.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 12: Abstract Interpretation IV Roman Manevich Ben-Gurion University.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 4: Axiomatic Semantics I Roman Manevich Ben-Gurion University.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 13: Abstract Interpretation V Roman Manevich Ben-Gurion University.
Compiler Principles Fall Compiler Principles Lecture 7: Lowering Correctness Roman Manevich Ben-Gurion University of the Negev.
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 12: Abstract Interpretation IV Roman Manevich Ben-Gurion University.
Operational Semantics Mooly Sagiv Tel Aviv University Textbook: Semantics with Applications Chapter.
Cs7100(Prasad)L18-9WP1 Axiomatic Semantics Predicate Transformers.
Program Analysis and Verification Noam Rinetzky Lecture 5: Abstract Interpretation 1 Slides credit: Roman Manevich, Mooly Sagiv, Eran Yahav.
Roman Manevich Ben-Gurion University Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 16: Shape Analysis.
Program Analysis and Verification
Operational Semantics Mooly Sagiv Tel Aviv University Sunday Scrieber 8 Monday Schrieber.
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 8: Static Analysis II Roman Manevich Ben-Gurion University.
Operational Semantics Mooly Sagiv Reference: Semantics with Applications Chapter 2 H. Nielson and F. Nielson
Program Analysis and Verification Spring 2014 Program Analysis and Verification Lecture 6: Axiomatic Semantics III Roman Manevich Ben-Gurion University.
CORRECTNESS ISSUES AND LOOP INVARIANTS Lecture 8 CS2110 – Fall 2014.
Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 8: Static Analysis II Roman Manevich Ben-Gurion University.
Program Analysis and Verification Spring 2016 Program Analysis and Verification Lecture 5: Axiomatic Semantics II Roman Manevich Ben-Gurion University.
Spring 2017 Program Analysis and Verification
Spring 2017 Program Analysis and Verification
Spring 2016 Program Analysis and Verification
Spring 2017 Program Analysis and Verification
Spring 2016 Program Analysis and Verification
Spring 2016 Program Analysis and Verification
Warm-up exercises Define program state: Define state predicate:
Formal Methods in Software Engineering 1
Program Analysis and Verification
Predicate Transforms II
Hoare-style program verification
Spring 2017 Program Analysis and Verification Operational Semantics
Lecture 5 Floyd-Hoare Style Verification
Program Analysis and Verification
Programming Languages and Compilers (CS 421)
Predicate Transformers
Formal Methods in software development
Spring 2016 Program Analysis and Verification
Predicate Transforms II
Program correctness Axiomatic semantics
Spring 2016 Program Analysis and Verification Operational Semantics
Programming Languages and Compilers (CS 421)
Strongest postcondition rules
Presentation transcript:

Program Analysis and Verification Spring 2015 Program Analysis and Verification Lecture 6: Axiomatic Semantics III Roman Manevich Ben-Gurion University

Tentative syllabus Semantics Natural Semantics Structural semantics Axiomatic Verification Static Analysis Automating Hoare Logic Control Flow Graphs Equation Systems Collecting Semantics Abstract Interpretation fundamentals LatticesFixed-Points Chaotic Iteration Galois Connections Domain constructors Widening/ Narrowing Analysis Techniques Numerical Domains Alias analysis Interprocedural Analysis Shape Analysis CEGAR Crafting your own Soot From proofs to abstractions Systematically developing transformers 2

Previously Hoare logic – Inference system – Annotated programs – Soundness and completeness Weakest precondition calculus Strongest postcondition calculus 3

Weakest (liberal) precondition rules 1.wlp( skip, Q) = Q 2.wlp( x := a, Q) = Q[a/ x ] 3.wlp(S 1 ; S 2, Q) = wlp(S 1, wlp(S 2, Q)) 4.wlp( if b then S 1 else S 2, Q) = (b  wlp(S 1, Q))  (  b  wlp(S 2, Q)) 5.wlp( while b do {  } S, Q) =  where {b   } S {  } and  b    Q 4 Use consequence rule here

Strongest postcondition rules 1.sp( skip, P) = P 2.sp( x := a, P) =  v. x=a[v/x]  P[v/x] 3.sp(S 1 ; S 2, P) = sp(S 2, sp(S 1, P)) 4.sp( if b then S 1 else S 2, P) = sp(S 1, b  P)  sp(S 2,  b  P) 5.sp( while b do {  } S, P) =    b where {b   } S {  } and P   b   5 Use consequence rule here

Warm-up 6

Proof of swap by WP 7 { y=b  x=a } t := x { y=b  t=a } x := y { x=b  t=a } y := t { x=b  y=a }

Prove swap via SP 8 { y=b  x=a } t := x { } x := y {} y := t { x=b  y=a }

Prove swap via SP 9 { y=b  x=a } t := x {  v. t=x  y=b  x=a } x := y {  v. x=y  t=v  y=b  v=a } { x=y  y=b   v. t=v  v=a } { x=y  y=b  t=a } y := t {  v. y=t  x=v  v=b  t=a } { y=t  t=a   v. x=v  v=b } { y=t  t=a  x=b } { x=b  y=a } Quantifier elimination (a very trivial one) Quantifier elimination

Proof of absolute value via WP 10 { x=v } { (-x=|v|  x<0)  (x=|v|  x  0) } if x<0 then { -x=|v| } x := -x { x=|v| } else { x=|v| } skip { x=|v| } { x=|v| }

Prove absolute value by SP 11 { x=v } {} if x<0 then {} x := -x {} else { } skip {} { } { x=|v| }

Proof of absolute value via WP 12 { x=v } if x<0 then { x=v  x<0 } x := -x {  w. x=-w  w=v  w<0 } { x=-v  v<0 } else { x=v  x  0 } skip { x=v  x  0 } { x=-v  v<0  x=v  x  0 } { x=|v| }

Agenda Some useful rules Extension for memory Proving termination 13

Making the proof system more practical 14

Conjunction rule 15 Allows breaking up proofs into smaller, easier to manage, sub-proofs

More useful rules 16 { P } C { Q } { P’ } C { Q’ } { P  P’ } C {Q  Q’ } [disj p ] { P } C { Q } {  v. P } C {  v. Q } [exist p ] v  FV( C) { P } C { Q } {  v. P } C {  v. Q } [univ p ] v  FV(C ) { F } C { F } Mod(C)  FV(F)={} [Inv p ] Mod(C) = set of variables assigned to in sub-statements of C FV(F) = free variables of F Breaks if C is non- deterministic

Invariance + Conjunction = Constancy 17 Mod(C) = set of variables assigned to in sub-statements of C FV(F) = free variables of F { P } C { Q } { F  P } C { F  Q } [constancy p ] Mod(C)  FV(F)={}

Strongest postcondition calculus practice 18 By Vadim Plessky ( [see page for license], via Wikimedia Commons

Floyd’s strongest postcondition rule Example { z=x } x:=x+1 { ?} 19 { P } x := a {  v. x=a[v/x]  P[v/x] } where v is a fresh variable [ass Floyd ] The value of x in the pre-state

Floyd’s strongest postcondition rule 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 20 { P } x := a {  v. x=a[v/x]  P[v/x] } where v is a fresh variable [ass Floyd ] meaning: {x=z+1}

“Small” assignment axiom 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} [exist p ] {  n. x=n} x:=y+1 {  n. x=y+1} therefore {true} x:=y+1 {x=y+1} [constancy p ] {z=9} x:=y+1 {z=9  x=y+1} 21 { x=v } x:=a { x=a[v/x] } where v  FV(a) [ass floyd ] First evaluate a in the precondition state (as a may access x) Then assign the resulting value to x Create an explicit Skolem variable in precondition

“Small” assignment axiom 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} [exist p ] {  n. x=n} x:=y+1 {  n. x=y+1} therefore {true} x:=y+1 {x=y+1} [constancy p ] {z=9} x:=y+1 {z=9  x=y+1} 22 { x=v } x:=a { x=a[v/x] } where v  FV(a) [ass floyd ]

“Small” assignment axiom 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} [exist p ] {  n. x=n} x:=y+1 {  n. x=y+1} therefore {true} x:=y+1 {x=y+1} [constancy p ] {z=9} x:=y+1 {z=9  x=y+1} 23 { x=v } x:=a { x=a[v/x] } where v  FV(a) [ass floyd ]

“Small” assignment axiom 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} [exist p ] {  n. x=n} x:=y+1 {  n. x=y+1} therefore {true} x:=y+1 {x=y+1} [constancy p ] {z=9} x:=y+1 {z=9  x=y+1} 24 { x=v } x:=a { x=a[v/x] } where v  FV(a) [ass floyd ]

Prove using strongest postcondition 25 { x=a  y=b } t := x x := y y := t { x=b  y=a }

Prove using strongest postcondition 26 { x=a  y=b } t := x { x=a  y=b  t=a } x := y y := t { x=b  y=a }

Prove using strongest postcondition 27 { x=a  y=b } t := x { x=a  y=b  t=a } x := y { x=b  y=b  t=a } y := t { x=b  y=a }

Prove using strongest postcondition 28 { x=a  y=b } t := x { x=a  y=b  t=a } x := y { x=b  y=b  t=a } y := t { x=b  y=a  t=a } { x=b  y=a } // cons

Prove using strongest postcondition 29 { x=v } if x 0 } else { x=v  x  0 } skip { x=v  x  0 } { v<0  x=-v  v  0  x=v } { x=|v| }

Prove using strongest postcondition 30 { x=v } if x 0 } else { x=v  x  0 } skip { x=v  x  0 } { v<0  x=-v  v  0  x=v } { x=|v| }

Sum program – specify Define Sum(0, n) = 0+1+…+n 31 {?} 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

Sum program – specify Define Sum(0, n) = 0+1+…+n 32 { 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

Sum program – prove Define Sum(0, n) = 0+1+…+n 33 { y  0 } x := 0 res := 0 Inv = 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) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 34 { 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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 35 { 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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 36 { 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 res := res+x x := x+1 { res = Sum(0, y) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 37 { 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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 38 { 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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 39 { 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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Sum program – prove Define Sum(0, n) = 0+1+…+n 40 { 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 } 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=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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Buggy sum program 1 Define Sum(0, n) = 0+1+…+n 41 { 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+n  x=n+1  m=Sum(0, n)  n<y } { y  0  res=Sum(0, n)+n  x=n+1  n<y }  { 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) } { x=Sum(0, n) } { y=n+1 } { x+y=Sum(0, n+1) }

Buggy sum program 2 42 { 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)  x>y }  {res = Sum(0, y) }

Handling data structures 43

Problems with Hoare logic and heaps { P[a/ x ] } x := a { P } Consider the annotated program { y=5 } y := 5; { y=5 } x := &y; { y=5 } *x := 7; { y=5 } Is it correct? 44 The rule works on a syntactic level unaware of possible aliasing between different terms (y and *x in our case)

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? 45

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 46

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 AssignmentA General Axiom of Assignment A different approach: heaps as arrays Really successful approach for heaps is based on Separation Logic Separation Logic 47

Axiomatizing data types 48 We added a new type of variables – array variables – Model array variable as a function y : Z  Z Re-define program states State = Define operational semantics  x := y [ a ],    y [ a ] := x,   S ::= x := a | x := y [ a ] | y [ a ] := x | skip | S 1 ; S 2 | if b then S 1 else S 2 | while b do S

Axiomatizing data types 49 We added a new type of variables – array variables – Model array variable as a function y : Z  Z We need the two following axioms: S ::= x := a | x := y [ a ] | y [ a ] := x | skip | S 1 ; S 2 | if b then S 1 else S 2 | while b do S { y[x  a](x) = a } { z  x  y[x  a](z) = y(z) }

Array update rules (wlp) 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) 50 S ::= x := a | x := y [ a ] | y [ a ] := x | skip | S 1 ; S 2 | if b then S 1 else S 2 | while b do S [array-update] { P[y[a  x]/y] } y[a] := x { P } [array-load] { P[y(a)/x] } x := y[a] { P } A very general approach – allows handling many data types

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) 51 [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}

Array update rules (sp) 52 [array-update F ] { x=v  y=g  a=b } y[a] := x { y=g[b  v] } [array-load F ] { y=g  a=b } x := y[a] { x=g(b) } In both rules v, g, and b are fresh

practice proving programs with arrays 53

Array-max program – specify 54 nums : array N : int // N stands for num’s length { N  0  nums=orig_nums } x := 0 res := nums[0] while x res then res := nums[x] x := x { x=N } 2.{  m. (m  0  m<N)  nums(m)  res } 3.{  m. m  0  m<N  nums(m)=res } 4.{ nums=orig_nums }

Array-max program 55 nums : array N : int // N stands for num’s length { N  0  nums=orig_nums } x := 0 res := nums[0] while x res then res := nums[x] x := x + 1 Post 1 : { x=N } Post 2 : { nums=orig_nums } Post 3 : {  m. 0  m<N  nums(m)  res } Post 4 : {  m. 0  m<N  nums(m)=res }

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  nums=orig_nums} C {x=N  nums=orig_nums} We can refer to assertions from earlier proofs in writing new proofs 56

Array-max example: Post 1 57 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 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 }

Array-max example: Post 2 58 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 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 }

Array-max example: Post 3 59 nums : array { N  0  0  m res then { nums(x)>oRes  res=oRes  x=k  0  m 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} [univ p ] {  m. 0  m<N  nums(m)  res }

Proving termination 60 By Noble0 (Own work) [CC BY-SA 3.0 ( via Wikimedia Commons

Total correctness semantics for While 61 [ P[a/ x ] ] x := a [ P ] [ass p ] [ P ] skip [ P ] [skip p ] [ P ] S 1 [ Q ],[ Q ] S 2 [ R ] [ P ] S 1 ; S 2 [ R ] [comp p ] [ b  P ] S 1 [ Q ], [  b  P ] S 2 [ Q ] [ P ] if b then S 1 else S 2 [ Q ] [if p ] [ P’ ] S [ Q’ ] [ P ] S [ Q ] [cons p ] if P  P’ and Q’  Q [while p ] [ P(z+1) ] S [ P(z) ] [  z. P(z) ] while b do S [ P(0) ] P(z+1)  b P(0)   b

Total correctness semantics for While 62 [ P[a/ x ] ] x := a [ P ] [ass p ] [ P ] skip [ P ] [skip p ] [ P ] S 1 [ Q ],[ Q ] S 2 [ R ] [ P ] S 1 ; S 2 [ R ] [comp p ] [ b  P ] S 1 [ Q ], [  b  P ] S 2 [ Q ] [ P ] if b then S 1 else S 2 [ Q ] [if p ] [ P’ ] S [ Q’ ] [ P ] S [ Q ] [cons p ] if P  P’ and Q’  Q [while p ] [ b  P  t=k ] S [ P  t<k ] [ P ] while b do S [  b  P ] P  t0P  t0 Rank, or Loop variant

Proving termination There is a more general rule based on well- founded 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 [] 63

Proving termination There is a more general rule based on well- founded 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 ] 64

Array-max – specify termination 65 nums : array N : int // N stands for num’s length x := 0 res := nums[0] Variant = [?] while x res then res := nums[x] x := x + 1 [?]

Array-max – specify termination 66 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 ]

Array-max – prove loop variant 67 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 ]

Array-max – prove loop variant 68 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 := x + 1 // [ N-x<k  N-x  0 ] [ true ] Capture initial value of x, since it changes in the loop

Array-max – prove loop variant 69 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 ]

Array-max – prove loop variant 70 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 ]

Array-max – prove loop variant 71 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 ]

Zune calendar bugbug while (days > 365) { if (IsLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } } else { days -= 365; year += 1; } 72

Fixed code while (days > 365) { if (IsLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } else { break; } } else { days -= 365; year += 1; } 73

Fixed code – specify termination [ ? ] while (days > 365) { if (IsLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } else { break; } } else { days -= 365; year += 1; } [ ? ] 74

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 ] 75

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 ] 76 Let’s model break by a small cheat – assume execution never gets past it

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 0 ] } else { [ k=days  days>365 ] days -= 365; [ k-365=days  days-365>365 ] -> [ k-365=days  days  0 ] -> [ days<k  days  0 ] year += 1; [ days<k  days  0 ] } [ days<k  days  0 ] } [ true ] 77

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 78 { b  P } S { b } { P } while b do S { false } [while-nt p ]

conclusion 79

Extensions to axiomatic semantics Assertions for execution time – Exact time – Order of magnitude time Assertions for dynamic memory – Separation Logic Separation Logic Assertions for parallelism – Owicki-Gries Owicki-Gries – Concurrent Separation Logic – Rely-guarantee 80

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 81

Next lecture: static analysis