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

Download Report

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

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
– 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?
Theorem Proving and Software
Semantics
Program
Meets spec/Found Bug
Specification
Validity
VC
generation
Provability
(theorem proving)
Theorem
in a logic
• Soundness:
– If the theorem is valid then the program
meets specification
– If the theorem is provable then it is valid
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
– If the 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
{A} s1 {C}
{C} s2 {B}
{ A } s1; s2 {B}
{A Æ E} s1 {B}
{A Æ :E} s2 {B}
{A} if E then s1 else s2 {B}
{I Æ E} s {I}
IÆ:E)B
{ I} while E do s {B}
Hoare Rules: Assignment
• Example: { A } x := x + 2 {x >= 5 }. What is A?
• General rule:
{ B[E/x] } x := E {B}
• Surprising how simple the rule is !
• The key is to compute “backwards” the precondition
from the postcondition
• Forward rule is more complicated:
{ A } x := E {9 x’. A[x’/x] Æ x = E[x’/x] }
Weakest preconditions
Dijkstra’s idea: To verify that { A } s { B}
a) 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)
Predicate lattice
false
)
Pre(s, B)
strong
A
weakest
precondition: WP(s, B)
true
weak
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
S
else
c := b
}
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 ?
Not quite weakest preconditions
• Recall what we are trying to do:
false
)
Pre(s, B)
strong
weakest
A precondition: WP(s, B)
verification
condition: VC(s, B)
true
weak
• 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))
I holds
on entry
Æ
I is preserved in
an arbitrary iteration
(:E ) B)) )[T0/T]
B holds when the
loop terminates
• I is the loop invariant (provided by the programmer)
• T is the set of loop targets (can be approximated by
scanning the loop body)
Example
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
A
while (t > 0) {
L
c := c + 1
B
t := t - 1
}
}
Conjecture to be proved:
b  0  VC(A, c = a + b)
VC(B, t  0  c = a + b - t) 
t - 1  0  c + 1 = a + b – (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)
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)
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
VC(f)  pre  VC(S, post)
• What is the decision procedure for
proving validity of VC(f)?
• Depends on the logic in which VC(f) is
expressed
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
S
else
c := b
}
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
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
A
while (t > 0) {
L
c := c + 1
B
t := t - 1
}
}
Conjecture to be proved:
b  0  VC(A, c = a + b)
VC(B, t  0  c = a + b - t) 
t - 1  0  c + 1 = a + b – (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)
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)
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