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 } { zx 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 t0 [ 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-x0 ] if nums[x] > res then res := nums[x] x := x + 1 // [ N-x<k N-x0 ] [ 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-x00 ] if nums[x] > res then res := nums[x] x := x + 1 // [ N-x<k N-x0 ] [ 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-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 ] 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-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 ] 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-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 ] 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 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 83 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 ] 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