SAT & SMT. Software Verification & Testing SAT & SMT Test case generation Predicate Abstraction Verifying Compilers.

Slides:



Advertisements
Similar presentations
Advanced programming tools at Microsoft
Advertisements

Demand-driven inference of loop invariants in a theorem prover
Writing specifications for object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 21 Jan 2005 Invited talk, AIOOL 2005 Paris,
Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Challenges in increasing tool support for programming K. Rustan M. Leino Microsoft Research, Redmond, WA, USA 23 Sep 2004 ICTAC Guiyang, Guizhou, PRC joint.
Leonardo de Moura Microsoft Research. Z3 is a new solver developed at Microsoft Research. Development/Research driven by internal customers. Free for.
The Dafny program verifier
Using SMT solvers for program analysis Shaz Qadeer Research in Software Engineering Microsoft Research.
Semantics Static semantics Dynamic semantics attribute grammars
Finding bugs: Analysis Techniques & Tools Symbolic Execution & Constraint Solving CS161 Computer Security Cho, Chia Yuan.
Masahiro Fujita Yoshihisa Kojima University of Tokyo May 2, 2008
Satisfiability Modulo Theories (An introduction)
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
Software Engineering & Automated Deduction Willem Visser Stellenbosch University With Nikolaj Bjorner (Microsoft Research, Redmond) Natarajan Shankar (SRI.
1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)
Chair of Software Engineering Software Verification Stephan van Staden Lecture 10: Model Checking.
Leonardo de Moura and Nikolaj Bjørner Microsoft Research.
ISBN Chapter 3 Describing Syntax and Semantics.
Verification of parameterised systems
Using Programmer-Written Compiler Extensions to Catch Security Holes Authors: Ken Ashcraft and Dawson Engler Presented by : Hong Chen CS590F 2/7/2007.
Leonardo de Moura Microsoft Research. Verification/Analysis tools need some form of Symbolic Reasoning.
Leonardo de Moura Microsoft Research. Satisfiability Modulo Theories: A Calculus of Computation Verification/Analysis tools need some form of Symbolic.
Formal Methods of Systems Specification Logical Specification of Hard- and Software Prof. Dr. Holger Schlingloff Institut für Informatik der Humboldt.
Johannes Kepler University Linz, Austria 2008 Leonardo de Moura and Nikolaj Bjørner Microsoft Research.
Nikolaj Bjørner Microsoft Research Lecture 3. DayTopicsLab 1Overview of SMT and applications. SAT solving, Z3 Encoding combinatorial problems with Z3.
Synergy: A New Algorithm for Property Checking
1 Predicate Abstraction of ANSI-C Programs using SAT Edmund Clarke Daniel Kroening Natalia Sharygina Karen Yorav (modified by Zaher Andraus for presentation.
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond, WA part 0 Summer School on Logic and Theorem-Proving in Programming.
Yeting Ge Leonardo de Moura New York University Microsoft Research.
CS 267: Automated Verification Lectures 14: Predicate Abstraction, Counter- Example Guided Abstraction Refinement, Abstract Interpretation Instructor:
Automatically Validating Temporal Safety Properties of Interfaces Thomas Ball and Sriram K. Rajamani Software Productivity Tools, Microsoft Research Presented.
ECI 2007: Specification and Verification of Object- Oriented Programs Lecture 1.
Software Reliability Methods Sorin Lerner. Software reliability methods: issues What are the issues?
Predicate Abstraction for Software and Hardware Verification Himanshu Jain Model checking seminar April 22, 2005.
Program Exploration with Pex Nikolai Tillmann, Peli de Halleux Pex
Nikolaj Bjørner Microsoft Research FSE &. *Title of Bradley & Manna’s book At the core of every software analysis engine is invariably a component using.
Nikolaj Bjørner Leonardo de Moura Nikolai Tillmann Microsoft Research August 11’th 2008.
Chair of Software Engineering Automatic Verification of Computer Programs.
Describing Syntax and Semantics
K. Rustan M. Leino Research in Software Engineering (RiSE) Microsoft Research, Redmond Caltech Pasadena, CA 12 November 2009.
Automatic Predicate Abstraction of C Programs Thomas BallMicrosoft Rupak MajumdarUC Berkeley Todd MillsteinU Washington Sriram K. RajamaniMicrosoft
Automating Software Testing Using Program Analysis -Patrice Godefroid, Peli de Halleux, Aditya V. Nori, Sriram K. Rajamani,Wolfram Schulte, and Nikolai.
Nikolaj Bjørner and Leonardo de Moura Microsoft Research Microsoft Corporation McMaster University, November 28, 2007.
Leonardo de Moura Microsoft Research. Quantifiers in Satisfiability Modulo Theories Logic is “The Calculus of Computer Science” (Z. Manna). High computational.
Towards Scalable Modular Checking of User-defined Properties Thomas Ball, MSR Brian Hackett, Mozilla Shuvendu Lahiri, MSR Shaz Qadeer, MSR Julien Vanegue,
Software Engineering Prof. Dr. Bertrand Meyer March 2007 – June 2007 Chair of Software Engineering Static program checking and verification Slides: Based.
Leonardo de Moura and Nikolaj Bjørner Microsoft Research.
272: Software Engineering Fall 2012 Instructor: Tevfik Bultan Lecture 3: Modular Verification with Magic, Predicate Abstraction.
Rule Checking SLAM Checking Temporal Properties of Software with Boolean Programs Thomas Ball, Sriram K. Rajamani Microsoft Research Presented by Okan.
Leonardo de Moura Microsoft Research. Satisfiability Modulo Theories: An Appetizer Verification/Analysis tools need some form of Symbolic Reasoning.
Ethan Jackson, Nikolaj Bjørner and Wolfram Schulte Research in Software Engineering (RiSE), Microsoft Research 1. A FORMULA for Abstractions and Automated.
ISBN Chapter 3 Describing Semantics -Attribute Grammars -Dynamic Semantics.
CS 363 Comparative Programming Languages Semantics.
Code Contracts Parameterized Unit Tests Tao Xie. Example Unit Test Case = ? Outputs Expected Outputs Program + Test inputs Test Oracles 2 void addTest()
Leonardo de Moura Microsoft Research. SATTheoriesSMT Arithmetic Bit-vectors Arrays …
Integrating high-level constructs into programming languages Language extensions to make programming more productive Underspecified programs –give assertions,
Automatically Validating Temporal Safety Properties of Interfaces Thomas Ball, Sriram K. MSR Presented by Xin Li.
Leonardo de Moura Microsoft Research. Quantifiers in Satisfiability Modulo Theories Logic is “The Calculus of Computer Science” (Z. Manna). High computational.
Semantics In Text: Chapter 3.
Leonardo de Moura Microsoft Research. Verification/Analysis tools need some form of Symbolic Reasoning.
CSV 889: Concurrent Software Verification Subodh Sharma Indian Institute of Technology Delhi Scalable Symbolic Execution: KLEE.
Symbolic and Concolic Execution of Programs Information Security, CS 526 Omar Chowdhury 10/7/2015Information Security, CS 5261.
Welcome to CS 477 Formal Methods in Software Development Spring 2011 Madhusudan Parthasarathy ( Madhu )
Leonardo de Moura Microsoft Research. Applications and Challenges in Satisfiability Modulo Theories Verification/Analysis tools need some form of Symbolic.
1 Automatically Validating Temporal Safety Properties of Interfaces - Overview of SLAM Parts of the slides are from
Lazy Annotation for Program Testing and Verification (Supplementary Materials) Speaker: Chen-Hsuan Adonis Lin Advisor: Jie-Hong Roland Jiang December 3,
Logic Engines as a Service Leonardo de Moura and Nikolaj Bjørner Microsoft Research.
The Zoo of Software Security Techniques
Predicate Abstraction
Course: CS60030 Formal Systems
Presentation transcript:

SAT & SMT

Software Verification & Testing SAT & SMT Test case generation Predicate Abstraction Verifying Compilers

Software Verification & Testing SATTheoriesSMT Arithmetic Bit-vectors Arrays …

Software Verification & Testing SMT Test case generation Predicate Abstraction Verifying Compilers

unsigned GCD(x, y) { requires(y > 0); while (true) { unsigned m = x % y; if (m == 0) return y; x = y; y = m; } Software Verification & Testing We want a trace where the loop is executed twice. (y 0 > 0) and (m 0 = x 0 % y 0 ) and not (m 0 = 0) and (x 1 = y 0 ) and (y 1 = m 0 ) and (m 1 = x 1 % y 1 ) and (m 1 = 0) model x 0 = 2 y 0 = 4 m 0 = 2 x 1 = 4 y 1 = 2 m 1 = 0 SSASSA SMTSolverSMTSolver

Software Verification & Testing Test (correctness + usability) is 95% of the deal: Dev/Test is 1-1 in products. Developers are responsible for unit tests. Tools: File Fuzzing Unit test case generation

Security is critical Software Verification & Testing Security bugs can be very expensive: Cost of each MS Security Bulletin: $600k to $Millions. Cost due to worms: $Billions. Most security exploits are initiated via files or packets. Ex: Internet Explorer parses dozens of file formats. Security testing: hunting for million dollar bugs Write A/V Read A/V Null pointer dereference Division by zero

Two main techniques used by “black hats”: Code inspection (of binaries). Black box fuzz testing. Black box fuzz testing: A form of black box random testing. Randomly fuzz (=modify) a well formed input. Grammar-based fuzzing: rules to encode how to fuzz. Heavily used in security testing At MS: several internal tools. Conceptually simple yet effective in practice Software Verification & Testing

Execution Path Run Test and Monitor Path Condition Solve seed New input Test Inputs Constraint System Known Paths SMTSolverSMTSolver

Software Verification & Testing Unit x Application Trade off between performance and precision Execution path mutation: existing execution path new path Concretization x = y * z  x = 128 (if y = 2 and z = 64 in the existing path)

PEX Implements DART for.NET. SAGE Implements DART for x86 binaries. YOGI Implements DART to check the feasibility of program paths generated statically using a SLAM-like tool. Vigilante Partially implements DART to dynamically generate worm filters. Software Verification & Testing

Test input generator Pex starts from parameterized unit tests Generated tests are emitted as traditional unit tests Visual Studio Plugin Software Verification & Testing

class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } }

class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } Inputs

(0,null) class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } }

InputsObserved Constraints (0,null)!(c<0) class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } c < 0  false

InputsObserved Constraints (0,null)!(c<0) && 0==c class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } 0 == c  true

InputsObserved Constraints (0,null)!(c<0) && 0==c class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } item == item  true This is a tautology, i.e. a constraint that is always true, regardless of the chosen values. We can ignore such constraints.

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } SMTSolverSMTSolver

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c(1,null) class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } SMTSolverSMTSolver

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c(1,null)!(c<0) && 0!=c class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } 0 == c  false

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c(1,null)!(c<0) && 0!=c c<0 class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } SMTSolverSMTSolver

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c(1,null)!(c<0) && 0!=c c<0(-1,null) class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } SMTSolverSMTSolver

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c(1,null)!(c<0) && 0!=c c<0(-1,null)c<0 class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } } c < 0  true

Constraints to solve InputsObserved Constraints (0,null)!(c<0) && 0==c !(c<0) && 0!=c(1,null)!(c<0) && 0!=c c<0(-1,null)c<0 class ArrayList { object[] items; int count; ArrayList(int capacity) { if (capacity < 0) throw...; items = new object[capacity]; } void Add(object item) { if (count == items.Length) ResizeArray(); items[this.count++] = item; }... class ArrayListTest { [PexMethod] void AddItem(int c, object item) { var list = new ArrayList(c); list.Add(item); Assert(list[0] == item); } }

Apply DART to large applications (not units). Start with well-formed input (not random). Combine with generational search (not DFS). Negate 1-by-1 each constraint in a path constraint. Generate many children for each parent run. Software Verification & Testing parent generation 1

SAGE is very effective at finding bugs Works on large applications Fully automated Easy to deploy (x86 analysis – any language) Used in various groups inside Microsoft Found > 100 security bugs in Windows 7 Gold medal in an internal file fuzzing competition Powered by SMT Software Verification & Testing

Trade off between precision and performance Scalability Machine arithmetic (aka Bitvectors) Floating point arithmetic. FP operations are: Concretized in SAGE Approximated using rational numbers in Pex Software Verification & Testing

SMT Test case generation Predicate Abstraction Verifying Compilers

SLAM/SDV is a software model checker. Application domain: device drivers. Architecture: c2bp C program → boolean program (predicate abstraction). bebop Model checker for boolean programs. newton Model refinement (check for path feasibility) SMT solvers are used to perform predicate abstraction and to check path feasibility. c2bp makes several calls to the SMT solver. The formulas are relatively small.

Given a C program P and F = {p 1, …, p n }. Produce a Boolean program B(P, F) Same control flow structure as P. Boolean variables {b 1, …, b n } to match {p 1, …, p n }. Properties true in B(P, F) are true in P. Each p i is a pure Boolean expression. Each p i represents set of states for which p i is true. Performs modular abstraction. Software Verification & Testing

do { KeAcquireSpinLock(); nPacketsOld = nPackets; if(request){ request = request->Next; KeReleaseSpinLock(); nPackets++; } } while (nPackets != nPacketsOld); KeReleaseSpinLock(); Do this code obey the looking rule?

do { KeAcquireSpinLock(); if(*){ KeReleaseSpinLock(); } } while (*); KeReleaseSpinLock(); Model checking Boolean program U U L L L L L L L L U U L L U U U U U U E E

do { KeAcquireSpinLock(); nPacketsOld = nPackets; if(request){ request = request->Next; KeReleaseSpinLock(); nPackets++; } } while (nPackets != nPacketsOld); KeReleaseSpinLock(); Is error path feasible? U U L L L L L L L L U U L L U U U U U U E E

do { KeAcquireSpinLock(); nPacketsOld = nPackets; if(request){ request = request->Next; KeReleaseSpinLock(); nPackets++; } } while (nPackets != nPacketsOld); KeReleaseSpinLock(); Add new predicate to Boolean program b: (nPacketsOld == nPackets) Add new predicate to Boolean program b: (nPacketsOld == nPackets) U U L L L L L L L L U U L L U U U U U U E E b = true; b = b ? false : *; !b

do { KeAcquireSpinLock(); b = true; if(*){ KeReleaseSpinLock(); b = b ? false : *; } } while (!b); KeReleaseSpinLock(); Model Checking Refined Program b: (nPacketsOld == nPackets) Model Checking Refined Program b: (nPacketsOld == nPackets) U U L L L L L L L L U U L L U U U U U U E E b b b b b b !b

do { KeAcquireSpinLock(); b = true; if(*){ KeReleaseSpinLock(); b = b ? false : *; } } while (!b); KeReleaseSpinLock(); Model Checking Refined Program b: (nPacketsOld == nPackets) Model Checking Refined Program b: (nPacketsOld == nPackets) U U L L L L L L L L U U L L U U U U b b b b b b !b

do { KeAcquireSpinLock(); b = true; if(*){ KeReleaseSpinLock(); b = b ? false : *; } } while (!b); KeReleaseSpinLock(); Model Checking Refined Program b: (nPacketsOld == nPackets) Model Checking Refined Program b: (nPacketsOld == nPackets) U U L L L L L L L L U U L L U U U U b b b b b b !b

Implies F (e) Best Boolean function over F that implies e. ImpliedBy F (e) Best Boolean function over F that is implied by e. ImpliedBy F (e) = not Implies F (not e) Software Verification & Testing

minterm m = l 1 ∧... ∧ l n, where l i = p i, or l i = not p i. Implies F (e): disjunction of all minterms that imply e. Naive approach Generate all 2 n possible minterms. For each minterm m, use SMT solver to check validity of m ⇒ e. Many possible optimizations Software Verification & Testing

F = { x < y, x = 2} e : y > 1 Minterms over F !x 1 x 1 !x 1 x 1 Implies F (y>1) = x<y  x=2 Implies F (y>1) = b 1  b 2 Software Verification & Testing

Given an error path p in the Boolean program B. Is p a feasible path of the corresponding C program? Yes: found a bug. No: find predicates that explain the infeasibility. Execute path symbolically. Check conditions for inconsistency using SMT Solver. Software Verification & Testing

All-SAT Better (more precise) Predicate Abstraction Unsatisfiable cores Why the abstract path is not feasible? Fast Predicate Abstraction Interpolants Software Verification & Testing

Let S be an unsatisfiable set of formulas. S’  S is an unsatisfiable core of S if: S’ is also unsatisfiable, and There is no S’’  S’ that is also unsatisfiable. Computing Implies F (e) with F = {p 1, p 2, p 3, p 4 } Assume p 1, p 2, p 3, p 4  e is valid That is p 1, p 2, p 3, p 4,  e is unsat Now assume p 1, p 3,  e is the unsatisfiable core Then it is unnecessary to check: p 1,  p 2, p 3, p 4  e p 1,  p 2, p 3,  p 4  e p 1, p 2, p 3,  p 4  e

Software Verification & Testing SMT Test case generation Predicate Abstraction Verifying Compilers

A verifying compiler uses automated reasoning to check the correctness of a program that is compiles. Correctness is specified by types, assertions,... and other redundant annotations that accompany the program. Tony Hoare 2004

Source Language C# + goodies = Spec# Specifications method contracts, invariants, field and type annotations. Program Logic: Dijkstra’s weakest preconditions. Automatic Verification type checking, verification condition generation (VCG), SMT Spec# (annotated C#) Boogie PL Spec# Compiler VC Generator Formulas SMT Solver

class C { private int a, z; invariant z > 0 public void M() requires a != 0 { z = 100/a; }

VCC translates an annotated C program into a Boogie PL program. A C-ish memory model Abstract heaps Bit-level precision Microsoft Hypervisor: verification grand challenge. Software Verification & Testing

Quantifiers, quantifiers, quantifiers, … Modeling the runtime  h,o,f: IsHeap(h)  o ≠ null  read(h, o, alloc) = t  read(h,o, f) = null  read(h, read(h,o,f),alloc) = t Software Verification & Testing

Quantifiers, quantifiers, quantifiers, … Modeling the runtime Frame axioms  o, f: o ≠ null  read(h 0, o, alloc) = t  read(h 1,o,f) = read(h 0,o,f)  (o,f)  M Software Verification & Testing

Quantifiers, quantifiers, quantifiers, … Modeling the runtime Frame axioms User provided assertions  i,j: i  j  read(a,i)  read(b,j) Software Verification & Testing

Quantifiers, quantifiers, quantifiers, … Modeling the runtime Frame axioms User provided assertions Theories  x: p(x,x)  x,y,z: p(x,y), p(y,z)  p(x,z)  x,y: p(x,y), p(y,x)  x = y Software Verification & Testing

Quantifiers, quantifiers, quantifiers, … Modeling the runtime Frame axioms User provided assertions Theories Solver must be fast in satisfiable instances. Software Verification & Testing We want to find bugs!

Undecidable “False positives” Very fragile Software Verification & Testing

E-matching Complete instantiation Decidable fragments Model checking Superposition Calculus Software Verification & Testing

SMT is hot at Microsoft (> 15 projects) Many applications Cryptography Scheduling Optimization Many challenges Thank You!