Seyed Masoud Hosseini · Overview · Study log · Weekly summaries · Ideas · Search · Transcript · RSS feed

Computer Security · Lecture 9 of 22 · 1:22:16

Lecture 10: Symbolic Execution

10. Symbolic Execution on YouTube

Study guide

What this lecture covers

Guest lecturer Armando Solar-Lezama (MIT CSAIL) introduces symbolic execution, a program analysis technique used in tools like Microsoft's SAGE to find security bugs by reasoning about entire classes of inputs rather than testing one input at a time. The lecture builds up from ordinary concrete execution to symbolic execution, explains how program paths turn into logical formulas, and then explains how SAT and SMT solvers decide whether those formulas have a solution.

After watching, you can explain why symbolic execution can prove a branch unreachable when testing cannot, describe how a path condition is built while walking a control-flow path, and outline how SAT solvers propagate assignments and learn conflict clauses, and how SMT solvers extend SAT with theories like bit-vectors and arrays to model integers and heap memory.

Key ideas

  • Symbolic execution: instead of running a program on one concrete input, it tracks each variable as a symbolic formula over the unknown inputs, letting a single run reason about many (or infinite) concrete inputs at once.
  • Path condition: the set of constraints (from branch decisions and assumptions) that must hold for execution to reach a given point along a specific path; if the path condition is unsatisfiable, that path is provably unreachable.
  • Precondition / contract: an assumption about valid inputs to a function; without it, symbolic execution may report failures on inputs the function was never meant to handle.
  • SAT solver: given a Boolean formula in conjunctive normal form, it tries variable assignments, propagates their consequences, and on a contradiction derives a new conflict clause, until it finds a satisfying assignment or proves none exists.
  • SMT (satisfiability modulo theories) solver: builds on a SAT solver by separating a formula's Boolean structure from domain-specific reasoning (theories such as bit-vectors, linear arithmetic, arrays, or uninterpreted functions), going back and forth between the SAT solver and theory solvers.
  • Theory of bit-vectors: models machine integers with a fixed width, which matters because machine integers can overflow in ways mathematical integers cannot.
  • Theory of arrays: models heap memory as one large array from addresses to values, which is how symbolic execution handles pointers and heap-allocated data.
  • Path-by-path exploration: because it does not scale to explore all paths of a large program simultaneously, most symbolic execution tools generate a separate, simpler formula for each path and prune paths early once a path condition becomes unsatisfiable.

Walkthrough

Why symbolic execution matters (1:00)

Symbolic execution is described as a workhorse of modern program analysis, used at Microsoft in a tool called SAGE to find security bugs across products like PowerPoint and Windows. Compared to random testing, it can reason about effectively infinite sets of inputs; compared to purely static analysis, when it finds a bug it produces a concrete input and trace that reproduces the failure, so developers can distinguish real bugs from false positives.

From concrete to symbolic execution (5:33)

Using a small program with an assert false guarded by branches, the lecture first runs it with concrete inputs (x=4, y=4 and x=2, y=2), showing that individual test runs say nothing about other inputs. Symbolic execution instead tracks each variable as a symbolic value (a formula), and at a branch where the direction is unknown, both branches are followed, merging the resulting formula for a variable like t into a single expression (t0) with logical conditions describing when it equals each branch's value. Solving the resulting equation shows the assertion is unreachable. The lecture also discusses preconditions: a branch that looks reachable in isolation may be provably unreachable once a function's documented assumptions about its inputs are added as constraints.

SMT solvers and theories (24:52)

An SMT solver takes a logical formula and returns a satisfying assignment, a proof of unsatisfiability, or (for hard cases) "I don't know" - many of the underlying problems are NP-complete or worse. The "modulo theories" part means solvers can be extended with domain-specific theories: fixed-width bit-vectors (which force a choice of bit width and capture overflow behavior), linear integer arithmetic (efficient but not overflow-aware), and uninterpreted functions (used when only input/output consistency of a function like sin matters, not its actual behavior).

How SAT solvers work (34:41)

SMT solvers rely on SAT solvers to handle formulas in conjunctive normal form. A SAT solver picks a variable, guesses a value, propagates the logical consequences through the remaining clauses, and repeats. When it hits a contradiction (a variable forced both true and false), it analyzes which assignments caused it and records a new conflict clause so it never repeats that mistake, continuing until every variable is assigned or a top-level contradiction is proven.

Combining SAT with theory solvers (40:49)

An SMT solver splits a formula's Boolean skeleton from its theory-specific subformulas (such as x > 5), asks the SAT solver for a candidate assignment to the Boolean skeleton, and checks that assignment against a theory solver (for example, a linear arithmetic solver). If the theory solver rejects the assignment, it returns a summary constraint (a conflict) that the SAT solver incorporates before trying again. This back-and-forth continues until a jointly satisfying assignment is found or proven impossible.

From programs to formulas: paths and the heap (54:52)

Because exploring all paths simultaneously does not scale well with modern solvers, most tools explore one path at a time: for a chosen path through the control-flow graph, they build up a symbolic state and an accumulating path condition, checking early whether that condition is still satisfiable so infeasible paths can be pruned without further exploration. The lecture then extends this to programs with heap-allocated memory and pointers, modeling memory as one large array from addresses (just integers) to values, so pointer reads, writes, and arithmetic become array operations that SMT solvers' theory of arrays can reason about directly. A simplified malloc model that ignores freeing and safety regions is shown as a common trade-off between analysis precision and scalability - richer models of library functions catch more bug classes but cost more performance.

Before you watch

  • This is a guest lecture within MIT 6.858 on program analysis for security; no earlier lecture is a strict prerequisite, but familiarity with basic programming (branches, pointers, control flow) and discrete math (Boolean logic, conjunctive normal form) helps.
  • Some background in what a control-flow graph is will make the path-exploration discussion easier to follow.

Check your understanding

  1. Why can testing a program on a handful of concrete inputs never prove a branch is unreachable, while symbolic execution sometimes can?
  2. What is a path condition, and why does an unsatisfiable path condition let a tool prune that path without exploring it further?
  3. How does an SMT solver divide labor between a SAT solver and a theory solver, and what happens when the theory solver rejects a candidate assignment?
  4. Why does choosing between the theory of bit-vectors and the theory of linear integer arithmetic involve a trade-off, particularly with respect to integer overflow?
  5. How does modeling the heap as a single large array let symbolic execution reason about pointer reads and writes, and why might a simplified malloc model miss certain classes of bugs?

Vocabulary

symbolic execution (noun)
A way of running a program where inputs are treated as unknown formulas instead of fixed numbers.
Symbolic execution can reason about all possible inputs at once.
concrete execution (noun)
Running a program with one specific, fixed set of input values.
Concrete execution with x=4 only tells you about that one case.
reason about (phrasal verb)
To think through and analyze something logically.
The tool can reason about infinite sets of possible inputs.
branch (noun)
A point in a program where execution can go one of two or more ways.
At each branch, symbolic execution explores both directions.
path (noun)
One specific sequence of branch decisions through a program.
Each path through the program gets its own formula.
path condition (noun)
The set of logical requirements that must be true for a specific path to be taken.
If the path condition is unsatisfiable, that path can never run.
assertion (noun)
A statement in code that claims something must be true at that point.
The assert false statement should never be reached.
reachable (adjective)
Able to be reached or arrived at during execution.
The tool proves the failing branch is not reachable.
false positive (noun)
A result that wrongly reports a problem that doesn't actually exist.
A concrete trace helps developers tell real bugs from false positives.
precondition (noun)
An assumption about valid inputs that must hold before a function is called.
Without the precondition, the tool reports impossible failures.
contract (noun)
A formal agreement about what a function expects and guarantees.
A function's contract states what inputs are considered valid.
formula (noun)
A logical or mathematical expression built from variables and operators.
Each symbolic variable is tracked as a formula.
satisfiable (adjective)
Able to be made true by some assignment of values.
A satisfiable formula has at least one solution.
unsatisfiable (adjective)
Impossible to make true no matter what values are chosen.
An unsatisfiable path condition means that path can be skipped.
SAT solver (noun)
A program that decides whether a logical formula can be made true.
The SAT solver tries different variable assignments.
SMT solver (noun)
A tool that extends a SAT solver with reasoning about things like numbers and arrays.
An SMT solver can handle formulas about real program data.
conjunctive normal form (noun)
A standard way of writing a logical formula as a group of OR-clauses joined by AND.
SAT solvers expect input in conjunctive normal form.
propagate (verb)
To pass an effect forward through connected parts.
The solver propagates the consequences of each guess.
contradiction (noun)
A situation where two things cannot both be true.
A contradiction forces the solver to backtrack.
conflict clause (noun)
A new rule the solver learns from a contradiction, to avoid repeating the same mistake.
The solver records a conflict clause after each failed guess.
theory (in logic) (noun)
A specialized set of rules for reasoning about a particular kind of data, like numbers.
The theory of bit-vectors models fixed-size integers.
bit-vector (noun)
A fixed-width sequence of bits used to represent an integer in a computer.
Bit-vectors can capture how integers overflow.
overflow (noun)
When a calculation produces a result too large to fit in its storage size.
Machine integers can overflow in ways real numbers cannot.
linear arithmetic (noun)
A branch of math dealing with equations where variables aren't multiplied together.
Linear arithmetic is efficient but ignores overflow.
uninterpreted function (noun)
A function treated only by its input-output consistency, without knowing what it actually computes.
sin can be modeled as an uninterpreted function when its exact behavior doesn't matter.
heap (noun)
The area of memory used for dynamically allocated data during a program's run.
The heap is modeled as one large array of addresses to values.
pointer (noun)
A variable that stores the memory address of another value.
Pointer reads and writes become array operations in the model.
prune (verb)
To cut away and stop exploring an unneeded part.
Infeasible paths can be pruned early.
trade-off (noun)
A balance where gaining one benefit means giving up another.
A simplified malloc model is a trade-off between precision and speed.
scalability (noun)
The ability of a method to keep working well as size or complexity grows.
Exploring all paths at once does not scale well.

Chapters

From the YouTube description

MIT 6.858 Computer Systems Security, Fall 2014
View the complete course: http://ocw.mit.edu/6-858F14
Instructor: Armando Solar-Lezama

In this lecture, Professor Solar-Lezama from MIT CSAIL presents the concept of symbolic execution.

License: Creative Commons BY-NC-SA
More information at http://ocw.mit.edu/terms
More courses at http://ocw.mit.edu

← Lecture 9: Securing Web Applications · Lecture 11: Ur/Web →