Scalable Error Detection using Boolean Satisfiability 1 Yichen Xie and Alex Aiken Stanford University
Scalable Error Detection using Boolean Satisfiability 2 Motivation
Scalable Error Detection using Boolean Satisfiability 3 Requirements Motivation Scalability –Millions of lines of code Precision –Maximize bugs found –Minimize false positives
Scalable Error Detection using Boolean Satisfiability 4 void f(state *x, state *y) { result = spin_trylock( & x->lock); spin_lock( & y->lock); … if (!result) spin_unlock( & x->lock); spin_unlock( & y->lock); } Code Example Path Sensitivity result (!result) Pointers & Heap ( & x->lock); ( & y->lock); Inter- procedural Flow Sensitivity spin_trylock spin_lock spin_unlock Locked Unlocked Error unlock lock unlock lock
Scalable Error Detection using Boolean Satisfiability 5 Saturn What? –SAT-based approach to static bug detection How? –SAT-based approach –Program constructs Boolean constraints –Inference SAT solving Why SAT? –Program states naturally expressed as bits –The theory for bits is SAT –Efficient solvers widely available
Scalable Error Detection using Boolean Satisfiability 6 Outline Motivation and goals Next: Technical discussion –Straight-line code –Control flow –Pointers Checking with Saturn Experimental results Related work and conclusion
Scalable Error Detection using Boolean Satisfiability 7 Straight-line Code void f(int x, int y) { int z = x & y ; assert(z == x); } x 31 …x0x0 y 31 …y0y0 == x 31 y 31 … x0y0x0y0 Bitwise-AND R y & x z == ;
Scalable Error Detection using Boolean Satisfiability 8 Straight-line Code void f(int x, int y) { int z = x & y; assert(z == x); } R Query: Is-Satisfiable( ) Answer: Yes x = [00…1] y = [00…0] Negated assertion is satisfiable. Therefore, the assertion may fail.
Scalable Error Detection using Boolean Satisfiability 9 Control Flow – Preparation Our Approach –Assumes loop free program –Unroll loops, drop backedges May miss errors that are deeply buried –Bug finding, not verification –Many errors surface in a few iterations Advantages –Simplicity, reduces false positives
Scalable Error Detection using Boolean Satisfiability 10 if (c) Control Flow – Example Merges –preserve path sensitivity –select bits based on the values of incoming guards G = c, x: [a 31 …a 0 ] G = c, x: [b 31 …b 0 ] G = c c, x: [v 31 …v 0 ] where v i = (c a i ) ( c b i ) c x = a; x = b; res = x; cc if (c) x = a; else x = b; res = x; true
Scalable Error Detection using Boolean Satisfiability 11 Pointers – Overview May point to different locations… –Thus, use points-to sets p: { l 1,…,l n } … but only one at a time –Use guards on points-to relationships p: { (g 1, l 1 ), …, (g n, l n ) }
Scalable Error Detection using Boolean Satisfiability 12 G = c, p: { (true, y) } Pointers – Example G = true, p: { (true, x) } p = & x; if (c) p = & y; res = *p; G = true, p: { (c, y); ( c, x)} if (c) res = y; else if ( c) res = x;
Scalable Error Detection using Boolean Satisfiability 13 Pointers – Recap Guarded Location Sets { (g 1, l 1 ), …, (g n, l n ) } Guards –Condition under which points-to relationship holds –Mutually exclusive –Collected from statement guards Pointer Dereference –Conditional Assignments
Scalable Error Detection using Boolean Satisfiability 14 Not Covered in the Talk Other Constructs –Structs, … Modeling of the environment Optimizations –several to reduce size of formulas –some form of program slicing important See paper...
Scalable Error Detection using Boolean Satisfiability 15 What can we do with Saturn? int f(lock_t *l) { lock(l); … unlock(l); } if (l->state == Unlocked) l->state = Locked; else l->state = Error; if (l->state == Locked) l->state = Unlocked; else l->state = Error; Locked Unlocked Error unlock lock unlock lock
Scalable Error Detection using Boolean Satisfiability 16 General FSM Checking Encode FSM in the program –State Integer –Transition Conditional Assignments Check code behavior –SAT queries
Scalable Error Detection using Boolean Satisfiability 17 How are we doing so far? Precision: Scalability: –SAT limit is 1M clauses –About 10 functions Solution: –Divide and conquer –Function Summaries
Scalable Error Detection using Boolean Satisfiability 18 Function Summaries (1 st try) Function behavior can be summarized with a set of state transitions Summary: * l: Unlocked Unlocked Locked Error int f(lock_t *l) { lock(l); … unlock(l); return 0; }
Scalable Error Detection using Boolean Satisfiability 19 int f(lock_t *l) { lock(l); … if (err) return -1; … unlock(l); return 0; } A Difficulty Problem –two possible output states –distinguished by return value (retval == 0)… Summary 1. (retval == 0) *l: Unlocked Unlocked Locked Error 2. (retval == 0) *l: Unlocked Locked Locked Error
Scalable Error Detection using Boolean Satisfiability 20 FSM Function Summaries Summary representation (simplified): { P in, P out, R } User gives: –P in : predicates on initial state –P out : predicates on final state –Express interprocedural path sensitivity Saturn computes: –R: guarded state transitions –Used to simulate function behavior at call site
Scalable Error Detection using Boolean Satisfiability 21 int f(lock_t *l) { lock(l); … if (err) return -1; … unlock(l); return 0; } Lock Summary (2 nd try) Output predicate: –P out = { (retval == 0) } Summary (R): 1. (retval == 0) *l: Unlocked Unlocked Locked Error 2. (retval == 0) *l: Unlocked Locked Locked Error
Scalable Error Detection using Boolean Satisfiability 22 Lock checker for Linux Parameters: –States: { Locked, Unlocked, Error } –P in = {} –P out = { (retval == 0) } Experiment: –Linux Kernel 2.6.5: 4.8MLOC –~40 lock/unlock/trylock primitives –20 hours to analyze 3.0GHz Pentium IV, 1GB memory
Scalable Error Detection using Boolean Satisfiability 23 Double Locking/Unlocking static void sscape_coproc_close(…) { spin_lock_irqsave(&devc->lock, flags); if (…) sscape_write(devc, DMAA_REG, 0x20); … } static void sscape_write(struct … *devc, …) { spin_lock_irqsave(&devc->lock, flags); … }
Scalable Error Detection using Boolean Satisfiability 24 Ambiguous Return State int i2o_claim_device(…) { down(&i2o_configuration_lock); if (d->owner) { up(&i2o_configuration_lock); return –EBUSY; } if (…) { return –EBUSY; } … }
Scalable Error Detection using Boolean Satisfiability 25 Bugs TypeBugsFalse Pos.% Bugs Double Locking % Ambiguous State % Total % Previous Work: MC (31), CQual (18), <20% Bugs
Scalable Error Detection using Boolean Satisfiability 26 Function Summary Database 63,000 functions in Linux – More than 23,000 are lock related – 17,000 with locking constraints on entry – Around 9,000 affects more than one lock – 193 lock wrappers – 375 unlock wrappers – 36 with return value/lock state correlation
Scalable Error Detection using Boolean Satisfiability 27 Why SAT? (Retrospect) Moore’s Law Uniform modeling of constructs as bits Constraints –Local specification –Global solution Incremental SAT solving –makes multiple queries efficient
Scalable Error Detection using Boolean Satisfiability 28 Related Work Bug Detection Tools –SLAM (Ball & Rajamani, MSR) –BLAST (Henzinger et. al., UCB) –MC (Engler et. al., Stanford) –ESP (Das et. al., MSR) –PREfix (Bush & Pincus, MSR) –CQual (Foster & Aiken, UCB) SAT-based tools –CBMC (Clarke et. al., CMU) –Magic (Chaki et. al., CMU)
Scalable Error Detection using Boolean Satisfiability 29 Thank you! Project Web-page: Or, Google: “Saturn, Boolean”