Spring 2015 Program Analysis and Verification Lecture 6: Axiomatic Semantics III Roman Manevich Ben-Gurion University Tentative syllabus Semantics Static Analysis Abstract Interpretation fundamentals Analysis Techniques Crafting your own Natural Semantics Automating Hoare Logic Lattices Numerical Domains Soot Structural semantics Control Flow Graphs Fixed-Points Alias analysis From proofs to abstractions Axiomatic Verification Equation Systems Chaotic Iteration Interprocedural Analysis Systematically developing transformers Collecting Semantics Galois Connections Shape Analysis Domain constructors CEGAR Widening/ Narrowing 2 Previously • Hoare logic – Inference system – Annotated programs – Soundness and completeness • Weakest precondition calculus • Strongest postcondition calculus 3 Weakest (liberal) precondition rules 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) = where {b }S{ } and b Q Use consequence rule here 4 Strongest postcondition rules 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 Use consequence rule here 5 Warm-up 6 Proof of swap by WP { t { x { y { y=b := x y=b := y x=b := t x=b x=a } t=a } t=a } y=a } 7 Prove swap via SP { y=b t := x { x=a } } x := y { } y := t { x=b y=a } 8 Prove swap via SP Quantifier elimination (a very trivial one) Quantifier elimination Quantifier elimination { 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 } 9 Proof of absolute value via WP { 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) } } } } } } 10 Prove absolute value by SP { x=v } { if x<0 then { x := -x { else { skip { { { x=|v| } } } } } } } 11 Proof of absolute value via WP { 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| } 12 Agenda • Some useful rules • Extension for memory • Proving termination 13 Making the proof system more practical 14 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 15 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 16 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 17 Strongest postcondition calculus practice By Vadim Plessky (http://svgicons.sourceforge.net/) [see page for license], via Wikimedia Commons 18 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 { ? } 19 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 20 “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} 21 “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} 22 “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} 23 “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} 24 Prove using strongest postcondition { x=a t := x y=b } x := y y := t { x=b y=a } 25 Prove using strongest postcondition { x=a t := x { x=a y=b } y=b t=a } x := y y := t { x=b y=a } 26 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 } 27 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 28 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 } 29 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 } 30 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 } 31 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 32 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) } 33 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) } 34 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) } 35 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) } 36 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) } 37 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) } 38 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) } 39 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 } 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) } 40 Buggy sum program 1 • 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+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) } 41 Buggy sum program 2 { 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 } 42 Handling data structures 43 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? 44 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 Assignment • A different approach: heaps as arrays • Really successful approach for heaps is based on Separation Logic 47 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 • Re-define program states State = • Define operational semantics x := y[a], y[a] := x, 48 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 } { zx y[x a](z) = y(z) } 49 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 } 50 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} 51 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) } 52 practice proving programs with arrays 53 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 } 54 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 } 55 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 56 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 } 57 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 } 58 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 } 59 Proving termination By Noble0 (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons 60 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 61 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 t0 [ P ] while b do S [ b P ] [ P’ ] S [ Q’ ] [P]S[Q] if P P’ and Q’ Q 62 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[ ] 63 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 ] 64 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 [ ? ] 65 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 ] 66 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-x0 ] if nums[x] > res then res := nums[x] x := x + 1 // [ N-x<k N-x0 ] [ true ] 67 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-x00 ] if nums[x] > res then res := nums[x] x := x + 1 // [ N-x<k N-x0 ] [ true ] 68 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-x00 ] if nums[x] > res then res := nums[x] [ x=x0 x0<N N-x0=k N-x00 ] // Frame x := x + 1 // [ N-x<k N-x0 ] [ true ] 69 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-x00 ] if nums[x] > res then res := nums[x] [ x=x0 x0<N N-x0=k N-x00 ] // Frame x := x + 1 [ x=x0+1 x0<N N-x0=k N-x00 ] // [ N-x<k N-x0 ] [ true ] 70 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-x00 ] if nums[x] > res then res := nums[x] [ x=x0 x0<N N-x0=k N-x00 ] // Frame x := x + 1 [ x=x0+1 x0<N N-x0=k N-x00 ] [ N-x<k N-x0 ] // cons [ true ] 71 Zune calendar bug 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 days0 ] if (IsLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } else { break; [ false ] } } else { days -= 365; year += 1; } // [ days0 days<k ] } [ true ] Let’s model break by a small cheat – assume execution never gets past it 76 Fixed code – proving termination [ true ] Variant = [ t=days ] while (days > 365) { [ days0 k=days days>365 ] -> [ days0 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 days366 ] 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 days0 ] -> [ days<k year += 1; [ days<k days0 ] } [ days<k days0 ] } [ true ] days0 ] 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 [while-ntp] {b P}S{b} { P } while b do S { false } 78 conclusion 79 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 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