350 likes | 856 Views
Automated Theorem Proving Lecture 1. Given program P and specification S, does P satisfy S?. Program verification is undecidable!. The model checking approach. Create a model of the program in a decidable formalism Verify the model algorithmically Difficulties
E N D
Given program P and specification S, does P satisfy S? Program verification is undecidable!
The model checking approach • Create a model of the program in a decidable formalism • Verify the model algorithmically • Difficulties • Model creation is burden on programmer • The model might be incorrect. • If verification fails, is the problem in the model or the program?
The axiomatic approach • Add auxiliary specifications to the program to decompose the verification task into a set of local verification tasks • Verify each local verification problem • Difficulties • Auxiliary spec is burden on programmer • Auxiliary spec might be incorrect. • If verification fails, is the problem with the auxiliary specification or the program?
Semantics Program VC generation Provability (theorem proving) Validity Specification Theorem in a logic Theorem Proving and Software • Soundness: • If the theorem is valid then the program meets specification • If the theorem is provable then it is valid Meets spec/Found Bug
Overview of the Next Few Lectures • From programs to theorems • Verification condition generation • From theorems to proofs • Theorem provers • Decision procedures
Programs ! Theorems = Axiomatic Semantics • Consists of: • A language for making assertions about programs • Rules for establishing when assertions hold • Typical assertions: • During the execution, only non-null pointers are dereferenced • This program terminates with x = 0 • Partial vs. total correctness assertions • Safety vs. liveness properties • Usually focus on safety (partial correctness)
Hoare Triples • Partial correctness: { A } s { B} • When you start s in any state that satisfies A • Ifthe execution of s terminates • It does so in a state that satisfies B • Total correctness: [ A ] s [ B ] • When you start s in any state that satisfies A • The execution of s terminates and • It does so in a state that satisfies B • Defined inductively on the structure of statements
Hoare Rules: Assignment • Example: { A } x := x + 2 {x >= 5 }. What is A? • General rule: • Surprising how simple the rule is ! • The key is to compute “backwards” the precondition from the postcondition • Forward rule is more complicated:
Weakest preconditions • Dijkstra’s idea: To verify that { A } s { B} • Let Pre(s, B) = {A’ | { A’} s { B} } • b) (Pre(s,B), )) is a lattice • - false Pre(s,B) • - if Pre(s,B) and Pre(s,B), then Pre(s,B) • - if Pre(s,B) and Pre(s,B), then Pre(s,B) • c) WP(s, B) = lub(Pre(s, B)) • d) Compute WP(s, B) and prove A WP(s, B)
) false true weak strong weakest precondition: WP(s, B) A Predicate lattice Pre(s, B)
Weakest preconditions • WP(x := E, B) = B[E/x] • WP(s1; s2, B) = WP(s1, WP(s2, B)) • WP(if E then s1 else s2, B) = E ) WP(s1, B) Æ: E ) WP(s2, B) • WP(assert E, B) = E B
Example returns c requires true ensures c = a b bool or(bool a, bool b) { if (a) c := true else c := b } S WP(S, c = a b) = (a true = a b) (a b = a b) Conjecture to be proved: true (a true = a b) (a b = a b)
Weakest preconditions (Contd.) • What about loops? • Define a family of weakest preconditions • WPk(while E do S, B) = weakest precondition from which if the loop terminates in k or fewer iterations, then it terminates in B WP0 = : E ) B WPi+1 = WPi (E ) WP(s, WPi)) • WP(while E do S, B) = Æk ¸ 0 WPk = glb {WPk | k ¸ 0} • Hard to compute • Can we find something easier yet sufficient ?
verification condition: VC(s, B) Not quite weakest preconditions • Recall what we are trying to do: ) false true Pre(s, B) weak strong weakest precondition: WP(s, B) A • We shall construct a verification condition: VC(s, B) • The loops are annotated with loop invariants ! • VC is guaranteed stronger than WP • But hopefully still weaker than A: A ) VC(s, B) ) WP(s, B)
Verification condition generation • Computed in a manner similar to WP • Except the rule for while: VC(whileI,T E do s, B) = I Æ ( I ((E ) VC(s, I)) Æ (:E ) B)) )[T0/T] • I is the loop invariant (provided by the programmer) • T is the set of loop targets (can be approximated by scanning the loop body) I is preserved in an arbitrary iteration I holds on entry B holds when the loop terminates
Example VC(B, t 0 c = a + b - t) t - 1 0 c + 1 = a + b – (t – 1) returns c requires b >= 0 ensures c = a + b int add(int a, int b) { int t; t := b c := a invariant t 0 c = a + b - t while (t > 0) { c := c + 1 t := t - 1 } } VC(L, c = a + b) t 0 c = a + b – t (t 0 c = a + b – t t > 0 t - 1 0 c + 1 = a + b – (t - 1) t 0 c = a + b)[c0/c,t0/t] VC(L, c = a + b) t 0 c = a + b – t (t0 0 c0 = a + b – t0 t0 > 0 t0 - 1 0 c0 + 1 = a + b – (t0 - 1) t0 0 c0 = a + b) A L B VC(A, c = a + b) b 0 a = a + b – b (t0 0 c0 = a + b – t0 t0 > 0 t0 - 1 0 c0 + 1 = a + b – (t0 - 1) t0 0 c0 = a + b) Conjecture to be proved: b 0 VC(A, c = a + b)
Invariants Are Not Easy • Consider the following code from QuickSort int partition(int *a, int L0, int H0, int pivot) { int L = L0, H = H0; while(L < H) { while(a[L] < pivot) L ++; while(a[H] > pivot) H --; if(L < H) { swap a[L] and a[H] } L++; } return L } • Consider verifying only memory safety • What is the loop invariant for the outer loop ?
Verification conditions (Contd.) • What about procedure calls? • Annotate each procedure with a precondition pre and a postcondition post • VC(f(), B) = pre (post B)
Program verification • Annotate each procedure with a precondition and a postcondition and each loop with an invariant • Verify each procedure separately requires pre ensures post f() { S; } Verify that the formula VC(f) pre VC(S, post) is valid
Proving verification conditions • What is the decision procedure for proving validity of VC(f)? • Depends on the logic in which VC(f) is expressed VC(f) pre VC(S, post)
Verification condition logic VC(f) pre VC(S, post) • Atoms connected by boolean operators • , , , • Atoms depend on the program variables and operations on them • boolean, integer, memory • Atoms depend on the language of assertions, i.e., program assertions, loop invariants, preconditions and postconditions • quantification, reachability predicate
Assume each assertion is a quantifier-free boolean combination of expressions over program variables. • VC(f) is a boolean combination of atoms • Each atom is a relation over terms • Each term is built using functions and logical constants • Logical constants are different from program variables • program variables change over time • logical constants are fixed • The logical constants in VC(f) refer to the values of program variables at the beginning of f.
Case I: Boolean programs • Boolean-valued variables and boolean operations • Formula := A | | A Atom := b b SymBoolConst
Example returns c requires true ensures c = a b bool or(bool a, bool b) { if (a) c := true else c := b } S VC(S, c = a b) = (a true = a b) (a b = a b) Conjecture to be proved: true (a true = a b) (a b = a b)
Case II: Arithmetic programs • In addition, integer-valued variables with affine operations • Formula := A | | A Atom := b | t = 0 | t < 0 | t 0 t Term := c | x | t + t | t – t | ct b SymBoolConst x SymIntConst c {…,-1,0,1,…}
Example VC(B, t 0 c = a + b - t) t - 1 0 c + 1 = a + b – (t – 1) returns c requires b >= 0 ensures c = a + b int add(int a, int b) { int t; t := b c := a invariant t 0 c = a + b - t while (t > 0) { c := c + 1 t := t - 1 } } VC(L, c = a + b) t 0 c = a + b – t (t 0 c = a + b – t t > 0 t - 1 0 c + 1 = a + b – (t - 1) t 0 c = a + b)[c0/c,t0/t] VC(L, c = a + b) t 0 c = a + b – t (t0 0 c0 = a + b – t0 t0 > 0 t0 - 1 0 c0 + 1 = a + b – (t0 - 1) t0 0 c0 = a + b) A L B VC(A, c = a + b) b 0 a = a + b – b (t0 0 c0 = a + b – t0 t0 > 0 t0 - 1 0 c0 + 1 = a + b – (t0 - 1) t0 0 c0 = a + b) Conjecture to be proved: b 0 VC(A, c = a + b)
Case III: Memory programs • In addition, a memory with read and write operations • an unbounded set of objects • a finite set of fields in each object • each field contains a boolean value, an integer value, or a reference to an object • For each field f, two operations Select and Update • Select(f,o) is the content of the memory at object o and field f • Update(f,o,v) is a new memory obtained by updating field f of object o to v
Memory axioms for all objects o and o’, and memories m: o = o’ Select(Update(m,o,v),o’) = v o o’ Select(Update(m,o,v),o’) = Select(m,o’)
Modeling memory operations Treat each field f as a map variable: a = b.f a = Select(f,b) a.f = b f = Update(f,a,b) { ? } a.f = 5 { a.f + b.f = 10 } WP(a.f = 5, a.f + b.f = 10) WP(f = Update(f,a,5), Select(f,a) + Select(f,b) = 10) Select(Update(f,a,5),a) + Select(Update(f,a,5),b) = 10
Simplify using memory axiom Select(Update(f,a,5),a) + Select(Update(f,a,5),b) = 10 iff 5 + Select(Update(f,a,5),b) = 10 iff Select(Update(f,a,5),b) = 5 iff a = b 5 = 5 a b Select(f,b) = 5 iff a b Select(f,b) = 5
Formula := A | | A Atom := b | t = 0 | t < 0 | t 0 t Term := c | x | t + t | t – t | ct | Select(m,t) m MemTerm := f | Update(m,t,t) b SymBoolConst x SymIntConst c {…,-1,0,1,…}
Decision procedures • Boolean programs • Propositional satisfiability • Arithmetic programs • Propositional satisfiability modulo theory of linear arithmetic • Memory programs • Propositional satisfiability modulo theory of linear arithmetic + arrays