Title: A SAT characterization of boolean-program correctness
1A SAT characterization of boolean-program
correctness
- K. Rustan M. LeinoMicrosoft Research, Redmond, WA
14 Nov 2002IFIP WG 2.4 meeting, Schloß Dagstuhl,
Germany
2Motivation
This program has performed an illegal
operation. If the problem persists, please
contact the vendor.
3The SLAM toolkit
Tom Ball, Sriram Rajamani, et al., Microsoft
Research
Properties of interest x ?? resource is
locked y ? t gt 0
Device driver (C program)
Abstraction (boolean program)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
y false
assert ??x
x true
x x ? y
Predicate abstraction
4The SLAM toolkit
Tom Ball, Sriram Rajamani, et al., Microsoft
Research
Device driver (C program)
Abstraction (boolean program)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
y false
assert ??x
assert ??x
x true
x x ? y
5The SLAM toolkit
Tom Ball, Sriram Rajamani, et al., Microsoft
Research
Device driver (C program)
Abstraction (boolean program)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
y false
assert ??x
assert ??x
x true
x x ? y
real error
6The SLAM toolkit
Tom Ball, Sriram Rajamani, et al., Microsoft
Research
Device driver (C program)
Abstraction (boolean program)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
y false
assert ??x
x true
x x ? y
infeasible path
7The SLAM toolkit
Tom Ball, Sriram Rajamani, et al., Microsoft
Research
Properties of interest x ?? resource is
locked y ? t gt 0 z ? p?? NULL
Device driver (C program)
Abstraction (boolean program)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
APIERR DevGetStatus(LPSTATUS status) unsigned
int t struct _Info info for (i 0 i lt
SPIGOT_COUNT i) APIERR err info.cbSize
sizeof(struct _Info) info.iSpigot i err
W_GetStatus(info) if (err !
APIERR_Success) return err t
info.fStatus SPIGOT_ALIVE status-gtresult
t 0x2055 return APIERR_Success APIERR
W_GetStatus(struct _Info pinfo) APIERR
err bool fChanged TRUE do err
DevRegisterColumn(pinfo, TRUE) if (err !
APIERR_Success) return err if
(pinfo-gthuwMagi lt 10) fChanged
FALSE else err DevReleaseColumn(pi
nfo) while (fChanged) return
DevReleaseColumn(pinfo)
y false
assert ??x
x true
z true
x x ? y
Predicate abstraction
Predicate abstraction
if (z)
8Boolean programs
- Prog var Id Block
- Block LabelId Stmt goto LabelId
- Stmt Id Expr assert Expr assume Expr
- Expr false true Id ?Expr Expr ? Expr
Expr ? Expr
9Example
- var x, yA x true goto BB assert x x
x ? y goto B or CC
A x true
B assert x x x ? y
C
10Semantics Weakest preconditions
- For any statement S and postcondition Q, wp(S,Q)
characterizes those pre-states from which
execution is guaranteed - not to go wrong, and
- either the execution doesnt terminate or it
terminates in a state satisfying Q
Q
S
wp(S,Q)
11Semantics Weakest preconditions
- wp(x E, Q) QxEwp(assert E, Q) E ?
Qwp(assume E, Q) E ? Q - wp(skip, Q) Qwp(ST, Q) wp(S, wp(T,Q))
- wp(goto labels, Q) (? L ? labels wp(L,Q))
12Semantics of blocks
What I write
- For any block var w L S goto
labels introduce a boolean function L, such
that
What I really mean
L(w) wp(S, (?G?labels G(w)))
(?w L(w) wp(S, (?G?labels G(w))) )
or equivalently
L (?w wp(S, (?G?labels G(w))) )
13Example
- A(x,y) wp(x true, B(x,y))B(x,y)
wp(assert x x x ? y,
B(x,y) ? C(x,y))C(x,y) wp(skip, true)
- A(x,y) B(true,y)B(x,y) x ? B(x ? y, y) ?
C(x ? y, y)C(x,y) true
A x true
B assert x x x ? y
C
14Equations with multiple solutions
- A, B, C A(x,y) B(true, y) B(x,y) x ?
B(x?y, y) ? C(x?y, y) C(x,y) true
The unknowns
Solution 0 A(x,y) false B(x,y)
false C(x,y) true
Solution 1 A(x,y) y B(x,y) x ?
y C(x,y) true
We want the weakest solution
15Weakest solution
- A,B,C A(x,y) B(true, y) B(x,y) x ?
B(x?y, y) ? C(x?y, y) C(x,y) true
16Weakest solution
- A,B,C A (?x,y B(true, y)) B (?x,y x
? B(x?y, y) ? C(x?y, y)) C (?x,y true)
F(A,B,C)
G(A,B,C)
H(A,B,C)
17Weakest solution/fixpoint
- A,B,C A F(A,B,C) B G(A,B,C) C
H(A,B,C) - where F (?x,y B(true, y)) G (?x,y
x ? B(x?y, y) ? C(x?y, y)) H (?x,y true)
(?x,y B(true, y))
(?x,y x ? B(x?y, y) ? C(x?y, y))
Weakest solution of A,B,C
(?x,y true)
F(A,B,C)
G(A,B,C)
H(A,B,C)
F
G
H
Weakest fixpoint of F,G,H
18Program correctness
- A program with variables w and start block A is
correct iff (?w A(w)) - That is, the program has an error
iff ?A(w)is satisfiable.
boolean equations, satisfiability
SAT
SAT
functions, weakest solutions
19Equations over a closed set of terms
- Using the definitions A(x,y) B(true,
y) B(x,y) x ? B(x?y, y) ? C(x?y, y) C(x,y)
true - We produce
- A(x,y) B(true, y)
- B(true, y) true ? B(true?y, y) ? C(true?y, y)
- B(true?y, y) true?y ? B(true?y?y, y) ?
C(true?y?y, y) - C(true?y, y) true
20Point functions
- A function f(w) f(false) ? f(w)can be
expressed as two point functions ffalse
ffalse ? ffalse ftrue ffalse ? ftrue
21Point-function equations
- A set of equations f f(w) f(false) ?
f(w)can be expressed as ffalse, ftrue
ffalse ffalse ? ffalse ftrue ffalse
? ftrue
22A fixpoint theorem
- Given a function F on a complete lattice,if F is
continuous, then its weakest fixpoint exists and
is given by Fk( T )for some natural number
k. - k is the fixpoint depth of F
- fixpoint depth ? lattice height
T
lattice height
F k ( T )
?
23Computing fixpoints outward
- T
- apply F
- F(T)
- apply F
- F(F(T))
- apply F
- F(F(F(T)))
- apply F
- F(F(F(F(T))))
Suppose fixpoint depth of F is 3
produced in previous step
equal to each otherweakest fixpoint of F
24Computing fixpoints inward
- ?
- replace ? with F(?)
- F(?)
- replace ? with F(?)
- F(F(?))
- replace ? with F(?)
- F(F(F(?)))
- replace ? with T
- F(F(F(T)))
Suppose fixpoint depth of F is 3
produced in previous step
no need for further applications of F
weakest fixpoint of F
25Multiple unknowns
- a,b a F(a,b) b G(a,b)
- Suppose fixpoint depths of F,G are 2,1
- Weakest solution for a is
- a00
- F(a10 , b10
) - F(F(a20, b20 ), G(a11
, b11)) - F(F(T , G(a21, b21)), G(F(a21, b21), T ))
- F(F(T , G(T , T )), G(F(T , T ), T ))
Number of enclosing applications of G
Number of enclosing applications of F
26Special instance
- Lattice of booleans has height 1
- If F returns a boolean, then Fs fixpoint depth
is at most 1 - and so Fs weakest fixpoint is F(T)
27Back to our problem
- Using the definitions A(x,y) B(true,
y) B(x,y) x ? B(x?y, y) ? C(x?y, y) C(x,y)
true - We produce
- Ax,y Btrue,y
- Btrue,y true ? Btrue?y,y ? Ctrue?y,y
- By,y y ? By?y,y ? Cy?y,y
true
28Back to our problem
- Using the definitions A(x,y) B(true,
y) B(x,y) x ? B(x?y, y) ? C(x?y, y) C(x,y)
true - We produce
- Ax,y Btrue,y
- Btrue,y true ? Btrue?y,y ? Ctrue?y,y
- By,y y ? true ? Cy?y,y
- Cy,y true
29Leibniz constraints
- Being a function means, for any f (?w,w
(ww) ? (f(w)f(w)))Leibnizs rule - So when we have Btrue,y By,y we
also generate the following Leibniz constraint
(truey) ? (yy) ? (Btrue,y By,y)
30SAT formula
- From the closed set of terms Ax,y
Btrue,y Btrue,y true ? Btrue?y,y ?
Ctrue?y,y By,y y ? true ? Cy?y,y Cy,y
true - we produce the following SAT equations ?a a
b b true ? b ? c b y ? true ? c c
true y ? (bb)
a b b c
negated start symbol ?A(x,y)
Leibniz constraint
31Summary
- Boolean program, whose semantics is defined by
weakest solution of weakest-precondition
equations - Translate to SAT problem
- Instantiate equations to get a closed set of
terms - Replace nested recursive instantiations by true
- Conjoin negated start symbol and Leibniz
constraints - Write point functions as propositional variables
- Check for satisfiability
- Performance? Heuristics?
- Are Leibniz constraints really needed?
- Better encoding of procedures?
32Complexity
- With N blocks and K variables
- each boolean function has K arguments, each a
boolean expression - there are 22K different boolean expressions
- So, there are N2K2K different terms
- Suppose each of the 2K initial states were
considered individually - each boolean-function argument can then be folded
into one of the 2 boolean constants - Then, there are only 2KN2K different terms
?? Symbolic checking
? Explicit-state checking
33Symbolic vs. explicit-state checking
- The following equality (and others?) can be
exploited heuristically to try to get a good
balance - f(P, Q, R)(P ? f(true, Q, R)) ? (?P ?
f(false, Q, R))
34Summary
- Boolean program, whose semantics is defined by
weakest solution of weakest-precondition
equations - Translate to SAT problem
- Instantiate equations to get a closed set of
terms - Replace nested recursive instantiations by true
- Conjoin negated start symbol and Leibniz
constraints - Write point functions as propositional variables
- Check for satisfiability
- Performance heuristics symbolic vs.
explicit-state - Other heuristics?
- Are Leibniz constraints really needed?
- Better encoding of procedures?