Hoare Triple: when we want to prove P \to [\alpha]Q, we often write it as \{P\}\alpha\{Q\}. We assume:
Note that while quantifiers are allowed, allowing them might mean that our formulas might not be decidable.
Dynamic monitoring: track memory access and abort if unsafe.
Instrument it with guard: predict whether memory access would be unsafe.
Test: \textbf{ test } P is a program that checks whether P holds. If it does, it does nothing; if it doesn't, it loops forever.
Aborting programs is considered safe, because aborting is actually a well-defined operation that does no harm (except to the running program, but it is its own fault if it tries to execute an unsafe command)
We can make a program safe by replacing:
every allocation M := \textbf{ alloc } e with \textbf{ test } (e \geq 0) ; M := \textbf{ alloc } e
every read x := M[e] with \textbf{ test } (0 \leq e < |M|) ; x := M[e]
every write M[e_1] := e_2 with \textbf{ test } (0 \leq e_1 < |M|) ; M[e_1] := e_2
every division x := \textbf{ divides } e_1 \ e_2 with \textbf{ test } (e_2 \neq 0) ; x := \textbf{ divides } e_1 \ e_2
every assertion \textbf{ assert } P with \textbf{ test } P
Note that \textbf{ test } 0 \leq e < |M|; x := M[e] is different from t := e; \textbf{ test } 0 \leq t < |M|; x:= M[t]. Because we re-evaluated the expression in the first case.
Re-evaluation is fine in terms of correctness, but hurt performance.
Sufficient Precondition: If P \to [\alpha]Q, then pure formula P is a sufficient precondition.
Liberal Precondition: If P \to [\alpha]Q, then pure formula P is a liberal precondition since we do not need to prove termination (i.e. total correctness).
P is stronger than Q if P \to Q. So the weakest precondition is P = \top (since it says nothing) while the strongest precondition is P = \bot (since it can prove anything).
We use \text{ wlp } \ \alpha \ Q to denote the weakest liberal precondition of \alpha with respect to Q. It has the following properties:
\text{ wlp } \ \alpha \ Q \to [\alpha]Q (it is a precondition)
(P \to [\alpha]Q) \implies (P \to \text{ wlp } \ \alpha \ Q) (it is the weakest)
We can see \text{ wlp } \ \alpha \ Q \iff [\alpha]Q, but \text{ wlp } \ \alpha \ Q \neq [\alpha]Q because \text{ wlp } \ \alpha \ Q is a pure formula while [\alpha]Q is not pure.
For loops, we can construct a weakest liberal precondition with respect to the given loop invariants (from programmer).
Verification Conditions: Given a problem P \to [\alpha]Q, we can generate "verification conditions" by computing \text{ wlp } \ \alpha \ Q and then proving P \to \text{ wlp } \ \alpha \ Q. We call P \to \text{ wlp } \ \alpha \ Q the verification condition for proving P \to [\alpha]Q.
Recall the following needs fresh variables: x' because Q(x') might contain program definitions (e.g. x = x+1), but we don't have such problen with \text{ wlp } since Q is pure.
For loops, let's define white box:
Therefore we have
Note that \square P(x) prevent substitution.
Table of Content