CSE507 Computer-Aided Reasoning for Software Symbolic Execution courses.cs.washington.edu/courses/cse507/14au/ Emina Torlak emina@cs.washington.edu
Today 2
Today Last lecture • Bounded verification: forward VCG for finitized programs 2
Today Last lecture • Bounded verification: forward VCG for finitized programs Today • Symbolic execution: a path-based translation • Concolic testing 2
The spectrum of program validation tools Static Analysis Verification Extended Static Bounded Verification Confidence Checking & Symbolic Execution Concolic Testing & Whitebox Fuzzing Ad-hoc Testing Cost (programmer effort, time, expertise) 3
The spectrum of program validation tools Static Analysis Verification Extended Static Bounded Verification Confidence Checking & Symbolic Execution E.g., JPF, Klee Concolic Testing & Whitebox Fuzzing E.g., SAGE, Pex, CUTE, DART Ad-hoc Testing Cost (programmer effort, time, expertise) 3
Symbolic execution 1976: A system to generate test data and symbolically execute programs (Lori Clarke) 1976: Symbolic execution and program testing (James King) 2005-present: practical symbolic execution • Using SMT solvers • Heuristics to control exponential explosion • Heap modeling and reasoning about pointers • Environment modeling • Dealing with solver limitations 4
Classic symbolic execution def f (x, y): if (x > y): x = x + y y = x - y x = x - y if (x - y > 0): assert false return (x, y) 5
Classic symbolic execution def f (x, y): if (x > y): x = x + y y = x - y x = x - y if (x - y > 0): assert false return (x, y) Execute the program on symbolic values . 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): if (x > y): x = x + y y = x - y x = x - y if (x - y > 0): assert false return (x, y) Execute the program on symbolic values . Symbolic state maps variables to symbolic values. 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ Y if (x > y): x = x + y x ↦ X y = x - y y ↦ Y x = x - y if (x - y > 0): assert false return (x, y) Execute the program on symbolic values . Symbolic state maps variables to symbolic values. Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch decisions taken so far. 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ Y if (x > y): x = x + y x ↦ X y = x - y y ↦ Y x = x - y if (x - y > 0): feasible assert false return (x, y) Execute the program on symbolic values . Symbolic state maps variables to symbolic values. Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch decisions taken so far. All paths in the program form its execution tree , in which some paths are feasible and some are infeasible . 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): feasible assert false return (x, y) Execute the program on symbolic values . Symbolic state maps variables to symbolic values. Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch decisions taken so far. All paths in the program form its execution tree , in which some paths are feasible and some are infeasible . 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): true feasible assert false x ↦ X + Y return (x, y) y ↦ X Execute the program on symbolic values . Symbolic state maps variables to symbolic values. Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch decisions taken so far. All paths in the program form its execution tree , in which some paths are feasible and some are infeasible . 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): true feasible assert false x ↦ X + Y return (x, y) y ↦ X Execute the program on symbolic values . true Symbolic state maps variables to symbolic values. x ↦ Y y ↦ X Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch decisions taken so far. All paths in the program form its execution tree , in which some paths are feasible and some are infeasible . 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): true feasible assert false x ↦ X + Y return (x, y) y ↦ X Execute the program on symbolic values . true Symbolic state maps variables to symbolic values. x ↦ Y y ↦ X Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch Y - X ≤ 0 decisions taken so far. x ↦ Y All paths in the program form its execution tree , y ↦ X in which some paths are feasible and some are infeasible . 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): true feasible assert false x ↦ X + Y return (x, y) y ↦ X Execute the program on symbolic values . true Symbolic state maps variables to symbolic values. x ↦ Y y ↦ X Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch Y - X ≤ 0 decisions taken so far. x ↦ Y All paths in the program form its execution tree , y ↦ X in which some paths are feasible and some are infeasible . feasible 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): true feasible assert false x ↦ X + Y return (x, y) y ↦ X Execute the program on symbolic values . true Symbolic state maps variables to symbolic values. x ↦ Y y ↦ X Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch Y - X ≤ 0 Y - X > 0 decisions taken so far. x ↦ Y x ↦ Y All paths in the program form its execution tree , y ↦ X y ↦ X in which some paths are feasible and some are infeasible . feasible 5
Classic symbolic execution x ↦ X y ↦ Y def f (x, y): X ≤ X > Y Y if (x > y): x = x + y x ↦ X + x ↦ X Y y = x - y y ↦ Y y ↦ Y x = x - y if (x - y > 0): true feasible assert false x ↦ X + Y return (x, y) y ↦ X Execute the program on symbolic values . true Symbolic state maps variables to symbolic values. x ↦ Y y ↦ X Path condition is a quantifier-free formula over the symbolic inputs that encodes all branch Y - X ≤ 0 Y - X > 0 decisions taken so far. x ↦ Y x ↦ Y All paths in the program form its execution tree , y ↦ X y ↦ X in which some paths are feasible and some are infeasible . infeasible feasible 5
Classic symbolic execution: practical issues 6
Classic symbolic execution: practical issues Loops and recursion: infinite execution trees 6
Classic symbolic execution: practical issues Loops and recursion: infinite execution trees Path explosion: exponentially many paths 6
Classic symbolic execution: practical issues Loops and recursion: infinite execution trees Path explosion: exponentially many paths Heap modeling: symbolic data structures and pointers 6
Classic symbolic execution: practical issues Loops and recursion: infinite execution trees Path explosion: exponentially many paths Heap modeling: symbolic data structures and pointers Solver limitations: dealing with complex PCs 6
Classic symbolic execution: practical issues Loops and recursion: infinite execution trees Path explosion: exponentially many paths Heap modeling: symbolic data structures and pointers Solver limitations: dealing with complex PCs Environment modeling: dealing with native / system / library calls 6
Classic symbolic execution: practical issues Loops and recursion: infinite execution trees Path explosion: exponentially many paths Heap modeling: symbolic data structures and pointers Solver limitations: dealing with complex PCs Environment modeling: dealing with native / system / library calls 6
Loops and recursion Dealing with infinite execution trees: • Finitize paths by limiting the size of PCs (bounded verification) • Use loop invariants (verification) 7
Loops and recursion Dealing with infinite execution trees: • Finitize paths by limiting the size of PCs (bounded verification) • Use loop invariants (verification) init; while (C) { I B; } assert P; 7
Loops and recursion Dealing with infinite execution trees: • Finitize paths by limiting the size of PCs (bounded verification) • Use loop invariants (verification) init; assert I; makeSymbolic(targets(B)); init; assume I; while (C) { if (C) { I B; B; } assert I; assert P; } else assert P; 7
Path explosion Achieving good coverage in the presence of exponentially many paths: • Select next branch at random • Select next branch based on coverage • Interleave symbolic execution with random testing 8
Recommend
More recommend