290 likes | 430 Views
Scalable Error Detection using Boolean Satisfiability. Yichen Xie and Alex Aiken Stanford University. Motivation. Requirements. Motivation. Scalability Millions of lines of code Precision Maximize bugs found Minimize false positives. unlock. lock. unlock. Error. Unlocked. Locked.
E N D
Scalable Error Detection using Boolean Satisfiability Yichen Xie and Alex Aiken Stanford University Scalable Error Detection using Boolean Satisfiability
Motivation Scalable Error Detection using Boolean Satisfiability
Requirements Motivation • Scalability • Millions of lines of code • Precision • Maximize bugs found • Minimize false positives Scalable Error Detection using Boolean Satisfiability
unlock lock unlock Error Unlocked Locked lock Code Example Flow Sensitivity 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); } result (&x->lock); spin_trylock (&y->lock); spin_lock Path Sensitivity (!result) Pointers & Heap (&x->lock); (&y->lock); spin_unlock Inter-procedural Scalable Error Detection using Boolean Satisfiability
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
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
x31 … x0 y31 … y0 Bitwise-AND x31y31 … x0y0 == Straight-line Code void f(int x, int y) { int z = x & y ; assert(z == x); } ; z y x & == R Scalable Error Detection using Boolean Satisfiability
Straight-line Code void f(int x, int y) { int z = x & y; assert(z == x); } Query: Is-Satisfiable( ) Answer: Yes x = [00…1] y = [00…0] Negated assertion is satisfiable. Therefore, the assertion may fail. R Scalable Error Detection using Boolean Satisfiability
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
Control Flow – Example • if (c) • x = a; • else • x = b; • res = x; • Merges • preserve path sensitivity • select bits based on the values of incoming guards G = c, x: [a31…a0] G = c, x: [b31…b0] G = cc, x: [v31…v0] where vi = (cai)(cbi) if (c) c c x = a; x = b; true res = x; Scalable Error Detection using Boolean Satisfiability
Pointers – Overview • May point to different locations… • Thus, use points-to sets p: { l1,…,ln } • … but only one at a time • Use guards on points-to relationships p: { (g1, l1), …, (gn, ln) } Scalable Error Detection using Boolean Satisfiability
Pointers – Example G = true, p: { (true, x) } • p = &x; • if (c) • p = &y; • res = *p; if (c) res = y; else if (c) res = x; G = c, p: { (true, y) } G = true, p: { (c, y); (c, x)} Scalable Error Detection using Boolean Satisfiability
Pointers – Recap • Guarded Location Sets { (g1, l1), …, (gn, ln) } • Guards • Condition under which points-to relationship holds • Mutually exclusive • Collected from statement guards • Pointer Dereference • Conditional Assignments Scalable Error Detection using Boolean Satisfiability
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
if (l->state == Unlocked) l->state = Locked; else l->state = Error; unlock if (l->state == Locked) l->state = Unlocked; else l->state = Error; lock unlock Error Locked Unlocked lock What can we do with Saturn? int f(lock_t *l) { lock(l); … unlock(l); } Scalable Error Detection using Boolean Satisfiability
General FSM Checking • Encode FSM in the program • State Integer • Transition Conditional Assignments • Check code behavior • SAT queries Scalable Error Detection using Boolean Satisfiability
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
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; } Function Summaries (1st try) Scalable Error Detection using Boolean Satisfiability
int f(lock_t *l) { lock(l); … if (err) return -1; … unlock(l); return 0; } 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 A Difficulty Scalable Error Detection using Boolean Satisfiability
FSM Function Summaries • Summary representation (simplified): { Pin, Pout, R } • User gives: • Pin: predicates on initial state • Pout: 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
int f(lock_t *l) { lock(l); … if (err) return -1; … unlock(l); return 0; } Output predicate: Pout = { (retval == 0) } Summary (R): 1. (retval == 0) *l: Unlocked Unlocked Locked Error 2. (retval == 0) *l: Unlocked Locked Locked Error Lock Summary (2nd try) Scalable Error Detection using Boolean Satisfiability
Lock checker for Linux • Parameters: • States: { Locked, Unlocked, Error } • Pin = {} • Pout = { (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
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
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
Bugs Previous Work: MC (31), CQual (18), <20% Bugs Scalable Error Detection using Boolean Satisfiability
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
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
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
Thank you! Project Web-page: http://glide.stanford.edu/saturn/ Or, Google: “Saturn, Boolean” Email: saturn@glide.stanford.edu Scalable Error Detection using Boolean Satisfiability