A SAT characterization of boolean-program correctness K. Rustan M. Leino Microsoft Research,...

Preview:

Citation preview

A SAT characterization of A SAT characterization of boolean-program boolean-program

correctnesscorrectness

K. Rustan M. LeinoK. Rustan M. LeinoMicrosoft Research, Redmond, WAMicrosoft Research, Redmond, WA

14 Nov 2002IFIP WG 2.4 meeting, Schloβ Dagstuhl, Germany

MotivationMotivation

This program has performed an illegal operation.If the problem persists, please contact the vendor.

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

The SLAM toolkitThe SLAM toolkitTom Ball, Sriram Rajamani, et al., Microsoft Research

Device driver (C program)

Abstraction (boolean program)

y := false;

x := true;

x := x y;

assert x;

Properties of interest: x “resource is locked” y t > 0

Predicate abstraction

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

The SLAM toolkitThe SLAM toolkitTom Ball, Sriram Rajamani, et al., Microsoft Research

Device driver (C program)

Abstraction (boolean program)

y := false;

x := true;

x := x y;

assert x;assert x

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

The SLAM toolkitThe SLAM toolkitTom Ball, Sriram Rajamani, et al., Microsoft Research

Device driver (C program)

Abstraction (boolean program)

y := false;

x := true;

x := x y;

assert x;assert x

real error

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

The SLAM toolkitThe SLAM toolkitTom Ball, Sriram Rajamani, et al., Microsoft Research

Device driver (C program)

Abstraction (boolean program)

y := false;

x := true;

x := x y;

assert x;

infeasible path

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

APIERR DevGetStatus(LPSTATUS status){

unsigned int t;struct _Info info;for (i = 0; i < 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->result = 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->huwMagi < 10){

fChanged = FALSE;}else{

err = DevReleaseColumn(pinfo);}

} while (fChanged);return DevReleaseColumn(pinfo);

}

The SLAM toolkitThe SLAM toolkitTom Ball, Sriram Rajamani, et al., Microsoft Research

Device driver (C program)

Abstraction (boolean program)

y := false;

x := true;

x := x y;

assert x;

Predicate abstraction

Properties of interest: x “resource is locked” y t > 0 z p≠ NULL

z := true;

if (z) …Predicate abstraction

Boolean programsBoolean programs Prog ::= Prog ::= varvar Id* ; Block* Id* ; Block* Block ::= LabelId : Stmt* Block ::= LabelId : Stmt* gotogoto

LabelId*LabelId* Stmt ::=Stmt ::= Id := ExprId := Expr

|| assertassert Expr Expr|| assumeassume Expr Expr

Expr ::= false | true | Id | Expr ::= false | true | Id | ExprExpr|| Expr Expr Expr | Expr Expr | Expr Expr Expr

ExampleExample varvar x, y; x, y;

A:A: x := true; x := true; gotogoto B BB:B: assertassert x; x := x x; x := x y; y; gotogoto B B oror C CC:C:

A: x := true

B: assert x;x := x y

C:

Semantics: Weakest Semantics: Weakest preconditionspreconditions

For any statement S and For any statement S and postcondition Q, wp(S,Q) postcondition Q, wp(S,Q) characterizes those pre-states from characterizes those pre-states from which execution is guaranteed:which execution is guaranteed: not to go wrong, andnot to go wrong, and either the execution doesn’t terminate either the execution doesn’t terminate

or it terminates in a state satisfying Qor it terminates in a state satisfying QS

Q

wp(S,Q)

Semantics: Weakest Semantics: Weakest preconditionspreconditions

wp(x := E, Q) = Q[x:=E]wp(x := E, Q) = Q[x:=E]wp(wp(assertassert E, Q) = E E, Q) = E Q Qwp(wp(assumeassume E, Q) = E E, Q) = E Q Q

wp(wp(skipskip, Q) = Q, Q) = Qwp(S;T, Q) = wp(S, wp(T,Q))wp(S;T, Q) = wp(S, wp(T,Q))

wp(wp(gotogoto labelslabels, Q) =, Q) =(( L L labelslabels :: wp(L,Q)) :: wp(L,Q))

For any block:For any block:var w;var w;……L: S; goto labelsL: S; goto labels……

introduce a boolean function L, such introduce a boolean function L, such that:that:

What I write:

L(w) =L(w) = wp(S, (wp(S, (GGlabels :: labels :: G(w)))G(w)))

Semantics of blocksSemantics of blocks

((w ::w :: L(w) =L(w) = wp(S, (wp(S, (GGlabels :: labels :: G(w))) )G(w))) )

L = (L = (λλw ::w :: wp(S, (wp(S, (GGlabels :: labels :: G(w))) )G(w))) )

What I really mean:

or equivalently:

ExampleExample

A(x,y) = wp(x := true, B(x,y))A(x,y) = wp(x := true, B(x,y))

B(x,y) = wp(B(x,y) = wp(assertassert x; x := x x; x := x y, y,

B(x,y) B(x,y) C(x,y)) C(x,y))

C(x,y) = wp(C(x,y) = wp(skipskip, true), true)A: x := true

B: assert x;x := x y

C:

A(x,y) = B(true,y)A(x,y) = B(true,y)

B(x,y) = x B(x,y) = x B(x B(x y, y) y, y) C(x C(x y, y) y, y)

C(x,y) = trueC(x,y) = true

Equations with multiple Equations with multiple solutionssolutions

The unknownsSolution 0:

A(x,y) = falseB(x,y) = falseC(x,y) = true

Solution 1:

A(x,y) = yB(x,y) = x yC(x,y) = true

We want the weakest solution

A, B, C :A, B, C : A(x,y) = B(true, y)A(x,y) = B(true, y)

B(x,y) = x B(x,y) = x B(x B(xy, y) y, y) C(x C(xy, y,

y)y)

C(x,y) = trueC(x,y) = true

Weakest solutionWeakest solution

A,B,C :A,B,C : A(x,y) = B(true, y)A(x,y) = B(true, y)B(x,y) = x B(x,y) = x B(x B(xy, y) y, y) C(x C(xy, y,

y)y)C(x,y) = trueC(x,y) = true

Weakest solutionWeakest solution

F(A,B,C) G(A,B,C) H(A,B,C)

A,B,C :A,B,C : A = (A = (λλx,y :: B(true, y))x,y :: B(true, y))B = (B = (λλx,y :: x x,y :: x B(x B(xy, y) y, y) C(x C(xy, y,

y))y))C = (C = (λλx,y :: true)x,y :: true)

F(A,B,C) G(A,B,C) H(A,B,C)

A,B,C :A,B,C : A = F(A,B,C) A = F(A,B,C) B = G(A,B,C)B = G(A,B,C)C = H(A,B,C)C = H(A,B,C)

wherewhere F = ( F = (λλx,y :: B(true, y))x,y :: B(true, y)) G = ( G = (λλx,y :: x x,y :: x B(x B(xy, y) y, y) C(x C(xy, y))y, y)) H = ( H = (λλx,y :: true)x,y :: true)

((λλx,y :: x x,y :: x B(x B(xy, y) y, y) C(x C(xy, y))y, y))((λλx,y :: true)x,y :: true)

Weakest solution/fixpointWeakest solution/fixpoint

F G H

Weakest solution of A,B,C

((λλx,y :: B(true, y))x,y :: B(true, y))

Weakest fixpoint of F,G,H

Program correctnessProgram correctness A program with variables w and start A program with variables w and start

block A is correct iff:block A is correct iff:

((w :: A(w))w :: A(w))

That is, the program has an error iff:That is, the program has an error iff:

A(w)A(w)

is satisfiable.is satisfiable.

boolean equations, satisfiability

functions, weakest solutions

SAT

SAT

Equations over a closed set of Equations over a closed set of “terms”“terms”

Using the definitions:Using the definitions:A(x,y) = B(true, y)A(x,y) = B(true, y)B(x,y) = x B(x,y) = x B(x B(xy, y) y, y) C(x C(xy, y)y, y)C(x,y) = trueC(x,y) = true

We produce:We produce: A(x,y) = B(true, y)A(x,y) = B(true, y) B(true, y) = true B(true, y) = true B(true B(truey, y) y, y) C(true C(truey, y)y, y) B(trueB(truey, y) = truey, y) = truey y B(true B(trueyyy, y) y, y) C(true C(trueyyy, y,

y)y) C(trueC(truey, y) = truey, y) = true

Point functionsPoint functions A function:A function:

f(w) = f(false) f(w) = f(false) f(w) f(w)

can be expressed as two can be expressed as two point point functions functions ::

fffalsefalse = f = ffalsefalse f ffalsefalse

fftruetrue = f = ffalsefalse f ftruetrue

Point-function equationsPoint-function equations A set of equations:A set of equations:

f :f : f(w) = f(false) f(w) = f(false) f(w) f(w)

can be expressed as:can be expressed as:

fffalsefalse, f, ftruetrue : : fffalsefalse = f = ffalsefalse f ffalsefalse

fftruetrue = f = ffalsefalse f ftruetrue

A fixpoint theoremA fixpoint theorem Given a function F on a complete Given a function F on a complete

lattice,lattice,if F is continuous, then its weakest if F is continuous, then its weakest fixpoint exists and is given by:fixpoint exists and is given by:

FFkk( T )( T )

for some natural number k.for some natural number k.

k is the k is the fixpoint depthfixpoint depth of F of F

fixpoint depth fixpoint depth lattice height lattice height

T

F F k k ( T )( T )

latt

ice

heig

ht

Computing fixpoints: Computing fixpoints: outwardoutward

TT{ apply F }{ apply F }

F(F(TT)){ apply F }{ apply F }

F(F(F(T)F(T))){ apply F }{ apply F }

F(F(F(F(T))F(F(T)))){ apply F }{ apply F }

F(F(F(F(F(T)))F(F(F(T)))))

equal to each other—weakest fixpoint of F

Suppose fixpoint depth of F is 3

produced in previous step

Computing fixpoints: inwardComputing fixpoints: inward { replace { replace with F( with F() }) }

F(F()){ replace { replace with F( with F() }) }

F(F(F(F()))){ replace { replace with F( with F() }) }

F(F(F(F(F(F()))))){ replace { replace with T } with T }

F(F(F(F(F(F(TT)))))) weakest fixpoint of F

no need for further applications of F

Suppose fixpoint depth of F is 3

produced in previous step

Multiple unknownsMultiple unknowns a,b :a,b :a = F(a,b)a = F(a,b)

b = G(a,b)b = G(a,b) Suppose fixpoint depths of F,G are 2,1Suppose fixpoint depths of F,G are 2,1 Weakest solution for a is:Weakest solution for a is:

aa0000

F(aF(a10 10 , b, b10 10 )) F(F(aF(F(a2020, b, b20 20 ), G(a), G(a11 11 , b, b1111)))) F(F(T , G(aF(F(T , G(a2121, b, b2121)), G(F(a)), G(F(a2121, b, b2121), T ))), T )) F(F(T , G(T , T F(F(T , G(T , T )), G(F(T , T )), G(F(T , T ), T ))), T ))

Number of enclosing applications of G

Number of enclosing applications of F

Special instanceSpecial instance Lattice of booleans has height 1Lattice of booleans has height 1 If F returns a boolean, then F’s If F returns a boolean, then F’s

fixpoint depth is at most 1fixpoint depth is at most 1 and so F’s weakest fixpoint is F(T)and so F’s weakest fixpoint is F(T)

Back to our problemBack to our problem Using the definitions:Using the definitions:

A(x,y) = B(true, y)A(x,y) = B(true, y)B(x,y) = x B(x,y) = x B(x B(xy, y) y, y) C(x C(xy, y)y, y)C(x,y) = trueC(x,y) = true

We produce:We produce: AAx,yx,y = B = Btrue,ytrue,y

BBtrue,ytrue,y = true = true B Btruetruey,yy,y C Ctruetruey,yy,y

BBy,yy,y = y = y B Byyy,yy,y C Cyyy,yy,y

true

Using the definitions:Using the definitions:A(x,y) = B(true, y)A(x,y) = B(true, y)B(x,y) = x B(x,y) = x B(x B(xy, y) y, y) C(x C(xy, y)y, y)C(x,y) = trueC(x,y) = true

We produce:We produce: AAx,yx,y = B = Btrue,ytrue,y

BBtrue,ytrue,y = true = true B Btruetruey,yy,y C Ctruetruey,yy,y

BBy,yy,y = y = y true true C Cyyy,yy,y

CCy,yy,y = true = true

Back to our problemBack to our problem

Leibniz constraintsLeibniz constraints Being a function means, for any f:Being a function means, for any f:

((w,w’ :: (w=w’) w,w’ :: (w=w’) (f(w)=f(w’))) (f(w)=f(w’)))

“Leibniz’s rule”“Leibniz’s rule”

So when we have:So when we have:BBtrue,ytrue,y = … = …

BBy,yy,y = … = …

we also generate the following we also generate the following Leibniz constraint Leibniz constraint ::

(true=y) (true=y) (y=y) (y=y) (B (Btrue,ytrue,y = B = By,yy,y))

SAT formulaSAT formula From the closed set of terms:From the closed set of terms:

AAx,yx,y = B = Btrue,ytrue,y

BBtrue,ytrue,y = true = true B Btruetruey,yy,y C Ctruetruey,yy,y

BBy,yy,y = y = y true true C Cyyy,yy,y

CCy,yy,y = true = true

we produce the following SAT equations:we produce the following SAT equations:aaa = ba = bb = true b = true b’ b’ c cb’ = y b’ = y true true c cc = truec = truey y (b=b’) (b=b’)

Leibniz constraint

negated start symbol:

A(x,y)

abb’c

SummarySummary Boolean program, whose semantics is defined Boolean program, whose semantics is defined

by weakest solution of weakest-precondition by weakest solution of weakest-precondition equationsequations

Translate to SAT problem:Translate to SAT problem: Instantiate equations to get a closed set of termsInstantiate equations to get a closed set of terms Replace nested recursive instantiations by trueReplace nested recursive instantiations by true Conjoin negated start symbol and Leibniz constraintsConjoin negated start symbol and Leibniz constraints Write point functions as propositional variablesWrite point functions as propositional variables Check for satisfiabilityCheck for satisfiability

Performance? Heuristics?Performance? Heuristics? Are Leibniz constraints really needed?Are Leibniz constraints really needed? Better encoding of procedures?Better encoding of procedures?

ComplexityComplexity With N blocks and K variables:With N blocks and K variables:

each boolean function has K arguments, each boolean function has K arguments, each a boolean expressioneach a boolean expression

there are 2there are 222KK different boolean expressions different boolean expressions

So, there are N·2So, there are N·2KK··22KK different terms different terms

Suppose each of the 2Suppose each of the 2KK initial states initial states were considered individually:were considered individually: each boolean-function argument can then each boolean-function argument can then

be folded into one of the 2 boolean be folded into one of the 2 boolean constantsconstants

Then, there are only 2Then, there are only 2KK·N·2·N·2KK different terms different terms

Explicit-state checking:

Symbolic checking:

Symbolic vs. explicit-state Symbolic vs. explicit-state checkingchecking

The following equality (and others?) The following equality (and others?) can be exploited heuristically to try can be exploited heuristically to try to get a good balance:to get a good balance:

f(P, Q, R)f(P, Q, R)==(P (P f(true, Q, R)) f(true, Q, R)) ( (P P f(false, Q, R)) f(false, Q, R))

SummarySummary Boolean program, whose semantics is defined by Boolean program, whose semantics is defined by

weakest solution of weakest-precondition weakest solution of weakest-precondition equationsequations

Translate to SAT problem:Translate to SAT problem: Instantiate equations to get a closed set of termsInstantiate equations to get a closed set of terms Replace nested recursive instantiations by trueReplace nested recursive instantiations by true Conjoin negated start symbol and Leibniz constraintsConjoin negated start symbol and Leibniz constraints Write point functions as propositional variablesWrite point functions as propositional variables Check for satisfiabilityCheck for satisfiability

Performance heuristics: symbolic vs. explicit-Performance heuristics: symbolic vs. explicit-statestate

Other heuristics?Other heuristics? Are Leibniz constraints really needed?Are Leibniz constraints really needed? Better encoding of procedures?Better encoding of procedures?

Recommended