Static Techniques for V&V
Hierarchy of V&V techniques Static Analysis V&V Dynamic Techniques Model Checking Simulation Symbolic Execution Testing Informal Analysis Formal Analysis Static Techniques Proofs Review Inspection Walkthrough
Analysis Different from experimenting (testing). – Based on a model –Source code or abstracted source code –Not the actual product (executable).
Analysis Can be subject to failure itself (wrong proof) –Similar to mathematical proofs –Start with conjecture –Try to show it is a theorem Find either
Informal Analysis Reviews Inspections Walkthroughs
Code Reviews: Read. If you can’t read it, neither can the people trying to maintain it Do this for any artifact This is a team effort
Walk-through: Simulate by hand, pick test cases, generalize Looking for any bugs Keep size small (3-5) Players get documentation ahead of time Meeting is restricted to a few hours
Code Inspections: Looking for specific bugs Common bugs: –Un-initialized variables –Jumps into loops –Incompatible assignments (type errors) –Non-termination –Out-of-bounds –Memory leaks –Parameter mismatches
(Semi) Formal Analysis Techniques Proofs Static checking –Code analysis: syntax errors and simple error patterns (i.e. Pointer problems) –Structure checking: CFGs with structural error detection (dead code, logic errors)
Formal correctness proofs {true} Begin read (a); read (b); x = a + b; write (x) end; {output = input1 + input2} Precondition Post condition
Proof Step 1 {true} Begin read (a); read (b); x = a + b; write (x) end; {output = input1 + input2} Due to the semantics of write(), the post condition holds iff {x=input1 + input2} holds
Proof Step 2 {true} Begin read (a); read (b); x = a + b; write (x) end; {output = input1 + input2} {x=input1 + input2} holds iff {a+b = input1 + input2}
Proof Step 3 {true} Begin read (a); read (b); x = a + b; write (x) end; {output = input1 + input2} Since the semantics of read(a) and read(b) assign input1 to a and input2 to b, {a+b = input1 + input2} holds
Basic Idea For any postcondition POST on program variables, and For any assignment statement x = expr, –expr is an expression containing variables POST holds after the assignment iff POST’ holds before the assignment
Basic Idea We want to show that whenever the preconditions hold, the postconditions must hold, that is –Pre -> Post We can take post conditions and derive necessary and sufficient conditions, then show the preconditions match these.
Notes We assume there are no side effects in expr.
Consider examples {x = 5} x = x + 1 {x = 6} {z-43 > y + 7} x = z – 43 {x > y + 7}
Sequences Suppose you have shown {F1} S1 {F2} and {F2} S2 {F3} You can deduce –{F1} S1;S2 {F3}
Consider conditional: {true} if x >= y then max = x else max = y; { (max = x or max = y) AND (max >= x and max >= y) }
Proof informally by cases: assume x >= y. then { (x = x or x = y) AND (x >= x and x >= y) }, which is true.
Rules of inference, conditional: Given {pre and condition} s1 {post} and {pre and not condition} s2 {post} Infer {pre} if condition then s1 else s2 {post}
Loop invariants I is a loop invariant cond is the loop condition (while loop) S is the body of the loop
Loop example: {x > y} while (x <> 0) x = x –2 y = y –2 end while {x > y and x = 0} Invariant
Loop example: {x > y} while (x <> 0) x = x –2 y = y –2 end while {x > y and x = 0} Note: Loop is not guaranteed to terminate
Loops example: Can easily show that if x > y at exit, it must have been so at entry. Might need induction to do these in general. Notice, this loop does not end if x is odd on entry.
Example {input1>0 and input2>0} begin read(x); read(y); div=0; while x>=y loop div = div + 1; x = x – y; end loop; write (div); write (x); end {input1 = output1*input2 + output2 and 0<=output2<input2}
Notes: Formal proofs may be more complex than the program Proofs are error prone if done by hand Proofs require mathematical sophistication Proofs may be overwhelming to do
Notes 2: Proofs rely on a semantic model of the environment (language, processor): They only provide assurance under this model Proofs may depend on continuous systems, not discrete systems Are they useful? –only for very small parts of the code. –they can be automated (PVS, for example) Many research issues here
Notes 3 Automated Theorem Provers: ACL2, HOL, Isabelle, Clam/Oyster –Theorem proving frameworks for software Outline:
Symbolic execution Similar to testing, but instead of individual test cases, you have symbolic generalization each test is a test of an entire class of tests. (testing, one element of equiv class. symbolic, entire class). Plan: try to get path coverage. How? In general, abstract the source code with respect to some property. Then do symbolic execution of every path through abstracted code. Research problem.
Model Checking Exhaustive search through state space of program (complete state space expansion) Form of symbolic execution Problem: state space
Model Checker Model software as FSA (what’s that?) Model properties in some logic, usually temporal logic (LTL, CTL) Represent FSA as a graph (what’s that?) Traverse graph (how?) Show properties hold in each node of graph
Model Checking What does it mean if an assertion does not hold in the model? What does it mean if the assertion does hold in the model?
Automated Programming Automatically generate programs from specifications Deductive Synthesis: extract a program from a proof
Cleanroom Build software in such a way as to prevent defects from being introduced. No testing. Specify system. Refine specification systematically, proving that the refinement meets the specification
Transformational Programming Take an input string and rewrite it: –aBc => axyc –Rules can have conditions –Rules can have procedural attachment or be higher order Formal, stepwise refinement of specification to program Can check each step individually “correct” by construction