1 / 34

A SAT characterization of boolean-program correctness

A SAT characterization of boolean-program correctness. K. Rustan M. Leino Microsoft Research, Redmond, WA. 14 Nov 2002 IFIP WG 2.4 meeting, Schlo β Dagstuhl, Germany. Motivation. This program has performed an illegal operation. If the problem persists, please contact the vendor.

maurilio
Download Presentation

A SAT characterization of boolean-program correctness

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. A SAT characterization of boolean-program correctness K. Rustan M. LeinoMicrosoft Research, Redmond, WA 14 Nov 2002IFIP WG 2.4 meeting, Schloβ Dagstuhl, Germany

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

  3. The SLAM toolkit Tom Ball, Sriram Rajamani, et al., Microsoft Research Properties of interest: x  “resource is locked” y  t > 0 Device driver (C program) Abstraction (boolean program) 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);} y := false; assert x; x := true; x := x  y; Predicate abstraction

  4. The 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 < 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);} y := false; assert x assert x; x := true; x := x  y;

  5. The 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 < 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);} y := false; assert x assert x; x := true; x := x  y; real error

  6. The 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 < 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);} y := false; assert x; x := true; x := x  y; infeasible path

  7. The SLAM toolkit Tom Ball, Sriram Rajamani, et al., Microsoft Research Properties of interest: x  “resource is locked” y  t > 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 < 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);} y := false; assert x; x := true; z := true; Predicate abstraction x := x  y; Predicate abstraction if (z) …

  8. Boolean 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

  9. Example • var x, y;A: x := true; goto BB: assert x; x := x  y; goto B or CC: A: x := true B: assert x; x := x  y C:

  10. Semantics: 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 doesn’t terminate or it terminates in a state satisfying Q Q S wp(S,Q)

  11. Semantics: Weakest preconditions • wp(x := E, Q) = Q[x:=E]wp(assert E, Q) = E  Qwp(assume E, Q) = E  Q • wp(skip, Q) = Qwp(S;T, Q) = wp(S, wp(T,Q)) • wp(gotolabels, Q) = ( L  labels :: wp(L,Q))

  12. Semantics 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))) )

  13. Example • 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:

  14. Equations 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

  15. Weakest 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

  16. Weakest 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)

  17. Weakest 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) F G(A,B,C) G H(A,B,C) H Weakest fixpoint of F,G,H

  18. Program 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

  19. Equations 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

  20. Point functions • A function: f(w) = f(false)  f(w)can be expressed as two point functions : ffalse = ffalse  ffalse ftrue = ffalse  ftrue

  21. Point-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

  22. A 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 ) 

  23. Computing 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 other—weakest fixpoint of F

  24. Computing 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

  25. Multiple 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

  26. Special instance • Lattice of booleans has height 1 • If F returns a boolean, then F’s fixpoint depth is at most 1 • and so F’s weakest fixpoint is F(T)

  27. Back 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

  28. Back 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

  29. Leibniz constraints • Being a function means, for any f: (w,w’ :: (w=w’)  (f(w)=f(w’)))“Leibniz’s rule” • So when we have: Btrue,y = … By,y = …we also generate the following Leibniz constraint : (true=y)  (y=y)  (Btrue,y = By,y)

  30. SAT formula • From the closed set of terms:Ax,y = Btrue,yBtrue,y = true  Btruey,y  Ctruey,yBy,y = y  true  Cyy,yCy,y = true we produce the following SAT equations: a a = b b = true  b’  c b’ = y  true  c c = true y  (b=b’) a b b’ c negated start symbol: A(x,y) Leibniz constraint

  31. Summary • 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?

  32. Complexity • 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 N·2K·2K 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 2K·N·2K different terms  Symbolic checking:  Explicit-state checking:

  33. Symbolic 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))

  34. Summary • 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?

More Related