Dynamic Symbolic Execution CS 8803 FPL Oct 31, 2012 (Slides adapted from Koushik Sen) 1.

Slides:



Advertisements
Similar presentations
Chapter 22 Implementing lists: linked implementations.
Advertisements

Automated Theorem Proving Lecture 1. Program verification is undecidable! Given program P and specification S, does P satisfy S?
Singly linked lists Doubly linked lists
Leonardo de Moura Microsoft Research. Z3 is a new solver developed at Microsoft Research. Development/Research driven by internal customers. Free for.
1 Symbolic Execution Kevin Wallace, CSE
Masahiro Fujita Yoshihisa Kojima University of Tokyo May 2, 2008
Symbolic Execution with Mixed Concrete-Symbolic Solving
PLDI’2005Page 1June 2005 Example (C code) int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); if (z==y) { if (y == x+10)
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)
Symbolic execution © Marcelo d’Amorim 2010.
Rigorous Software Development CSCI-GA Instructor: Thomas Wies Spring 2012 Lecture 13.
Hybrid Concolic Testing Rupak Majumdar Koushik Sen UC Los Angeles UC Berkeley.
CSE503: SOFTWARE ENGINEERING SYMBOLIC TESTING, AUTOMATED TEST GENERATION … AND MORE! David Notkin Spring 2011.
Synergy: A New Algorithm for Property Checking
PLDI’2005Page 1June 2005 DART: Directed Automated Random Testing Patrice Godefroid Nils Klarlund Koushik Sen Bell Labs Bell Labs UIUC.
DART Directed Automated Random Testing Patrice Godefroid, Nils Klarlund, and Koushik Sen Syed Nabeel.
Evaluation of DART DART: Directed Automated Random Testing Godefroid, Klarlund, Sen.
1 ES 314 Advanced Programming Lec 2 Sept 3 Goals: Complete the discussion of problem Review of C++ Object-oriented design Arrays and pointers.
19-Aug-15 Simple Recursive Algorithms. 2 A short list of categories Algorithm types we will consider include: Simple recursive algorithms Backtracking.
Software Testing Sudipto Ghosh CS 406 Fall 99 November 9, 1999.
Language Evaluation Criteria
DART: Directed Automated Random Testing Koushik Sen University of Illinois Urbana-Champaign Joint work with Patrice Godefroid and Nils Klarlund.
Tao Xie (North Carolina State University) Nikolai Tillmann, Jonathan de Halleux, Wolfram Schulte (Microsoft Research, Redmond WA, USA)
Symbolic Execution with Mixed Concrete-Symbolic Solving (SymCrete Execution) Jonathan Manos.
CUTE: A Concolic Unit Testing Engine for C Technical Report Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
CS 11 C track: lecture 5 Last week: pointers This week: Pointer arithmetic Arrays and pointers Dynamic memory allocation The stack and the heap.
CS4311 Spring 2011 Unit Testing Dr. Guoqiang Hu Department of Computer Science UTEP.
CS265: Program Analysis, Testing, and Debugging
Chapter 12 Recursion, Complexity, and Searching and Sorting
Computer Science Detecting Memory Access Errors via Illegal Write Monitoring Ongoing Research by Emre Can Sezer.
Testing Testing Techniques to Design Tests. Testing:Example Problem: Find a mode and its frequency given an ordered list (array) of with one or more integer.
Unit Testing 101 Black Box v. White Box. Definition of V&V Verification - is the product correct Validation - is it the correct product.
DATA STRUCTURE & ALGORITHMS (BCS 1223) NURUL HASLINDA NGAH SEMESTER /2014.
Symbolic Execution with Abstract Subsumption Checking Saswat Anand College of Computing, Georgia Institute of Technology Corina Păsăreanu QSS, NASA Ames.
An Undergraduate Course on Software Bug Detection Tools and Techniques Eric Larson Seattle University March 3, 2006.
Learning Symbolic Interfaces of Software Components Zvonimir Rakamarić.
CSV 889: Concurrent Software Verification Subodh Sharma Indian Institute of Technology Delhi Scalable Symbolic Execution: KLEE.
A System to Generate Test Data and Symbolically Execute Programs Lori A. Clarke Presented by: Xia Cheng.
Symbolic and Concolic Execution of Programs Information Security, CS 526 Omar Chowdhury 10/7/2015Information Security, CS 5261.
A Test Case + Mock Class Generator for Coding Against Interfaces Mainul Islam, Christoph Csallner Software Engineering Research Center (SERC) Computer.
CS265: Dynamic Partial Order Reduction Koushik Sen UC Berkeley.
(c) , University of Washington18a-1 CSC 143 Java Searching and Recursion N&H Chapters 13, 17.
Semantic Analysis II Type Checking EECS 483 – Lecture 12 University of Michigan Wednesday, October 18, 2006.
Recursion A recursive definition is one which uses the word or concept being defined in the definition itself Example: “A computer is a machine.
Static Techniques for V&V. Hierarchy of V&V techniques Static Analysis V&V Dynamic Techniques Model Checking Simulation Symbolic Execution Testing Informal.
CUTE: A Concolic Unit Testing Engine for C Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
/ PSWLAB Evidence-Based Analysis and Inferring Preconditions for Bug Detection By D. Brand, M. Buss, V. C. Sreedhar published in ICSM 2007.
Lazy Annotation for Program Testing and Verification (Supplementary Materials) Speaker: Chen-Hsuan Adonis Lin Advisor: Jie-Hong Roland Jiang December 3,
1 Validation of Security Protocols Joint work with Gul Agha, Michael Greenwald, Carl Gunter, Sanjeev Khanna, Darko Marinov, Jose Meseguer, Prasanna Thati,
Dynamic Symbolic Execution (aka, directed automated random testing, aka concolic execution) Slides by Koushik Sen.
Recursion ITI 1121 N. El Kadri. Reminders about recursion In your 1 st CS course (or its equivalent), you have seen how to use recursion to solve numerical.
Week 6 MondayTuesdayWednesdayThursdayFriday Testing III Reading due Group meetings Testing IVSection ZFR due ZFR demos Progress report due Readings out.
CSE 331 SOFTWARE DESIGN & IMPLEMENTATION SYMBOLIC TESTING Autumn 2011.
1 Compiler Construction Run-time Environments,. 2 Run-Time Environments (Chapter 7) Continued: Access to No-local Names.
Software Testing.
CS5123 Software Validation and Quality Assurance
A Test Case + Mock Class Generator for Coding Against Interfaces
Types of Testing Visit to more Learning Resources.
Teach A level Computing: Algorithms and Data Structures
DART and CUTE: Concolic Testing
Automated Software Analysis Techniques For High Reliability: A Concolic Testing Approach Moonzoo Kim.
White-Box Testing Using Pex
Software Testing (Lecture 11-a)
Dynamic Symbolic Execution
Elided to examples only
Automatic Test Generation SymCrete
Automated Software Analysis Techniques For High Reliability: A Concolic Testing Approach Moonzoo Kim.
Example (C code) int double(int x) { return 2 * x; }
CUTE: A Concolic Unit Testing Engine for C
Presentation transcript:

Dynamic Symbolic Execution CS 8803 FPL Oct 31, 2012 (Slides adapted from Koushik Sen) 1

2 Today, QA is mostly testing “50% of my company employees are testers, and the rest spends 50% of their time testing!” Bill Gates 1995

3 Software Reliability Importance Software is pervading every aspects of life  Software everywhere Software failures were estimated to cost the US economy about $60 billion annually [NIST 2002]  Improvements in software testing infrastructure may save one- third of this cost Testing accounts for an estimated 50%-80% of the cost of software development [Beizer 1990]

4 Big Picture Safe Programming Languages and Type systems Static Program Analysis Dynamic Program Analysis Model Based Software Development and Analysis Model Checking and Theorem Proving Runtime Monitoring Testing

5 Big Picture Safe Programming Languages and Type systems Model Checking and Theorem Proving Runtime Monitoring Model Based Software Development and Analysis Static Program Analysis Dynamic Program Analysis Testing

6 A Familiar Program: QuickSort void quicksort (int[] a, int lo, int hi) { int i=lo, j=hi, h; int x=a[(lo+hi)/2]; // partition do { while (a[i]<x) i++; while (a[j]>x) j--; if (i<=j) { h=a[i]; a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // recursion if (lo<j) quicksort(a, lo, j); if (i<hi) quicksort(a, i, hi); }

7 A Familiar Program: QuickSort void quicksort (int[] a, int lo, int hi) { int i=lo, j=hi, h; int x=a[(lo+hi)/2]; // partition do { while (a[i]<x) i++; while (a[j]>x) j--; if (i<=j) { h=a[i]; a[i]=a[j]; a[j]=h; i++; j--; } } while (i<=j); // recursion if (lo<j) quicksort(a, lo, j); if (i<hi) quicksort(a, i, hi); } Test QuickSort  Create an array  Initialize the elements of the array  Execute the program on this array How much confidence do I have in this testing method? Is my test suite *Complete*? Can someone generate a small and *Complete* test suite for me?

8 Automated Test Generation Studied since 70’s  King 76, Myers years have passed, and yet no effective solution What Happened?

9 Automated Test Generation Studied since 70’s  King 76, Myers years have passed, and yet no effective solution What Happened?  Program-analysis techniques were expensive  Automated theorem proving and constraint solving techniques were not efficient

10 Automated Test Generation Studied since 70’s  King 76, Myers years have passed, and yet no effective solution What Happened?  Program-analysis techniques were expensive  Automated theorem proving and constraint solving techniques were not efficient Recent years have seen remarkable strides in static analysis and constraint solving  SLAM, BLAST, ESP, Bandera, Saturn, MAGIC

11 Automated Test Generation Studied since 70’s  King 76, Myers years have passed, and yet no effective solution What Happened?  Program analysis techniques were expensive  Automated theorem proving and constraint solving techniques were not efficient Recent years have seen remarkable strides in static analysis and constraint solving  SLAM, BLAST, ESP, Bandera, Saturn, MAGIC Question: Can we use similar techniques in Automated Testing?

12 Systematic Automated Testing Testing Static Analysis Automated Theorem Proving Model-Checking and Formal Methods Constraint Solving

13 CUTE and DART Combine random testing (concrete execution) and symbolic testing (symbolic execution) [PLDI’05, FSE’05, FASE’06, CAV’06,ISSTA’07, ICSE’07] Concrete + Symbolic = Concolic

14 Goal Automated Unit Testing of real-world C and Java Programs  Generate test inputs  Execute unit under test on generated test inputs so that all reachable statements are executed  Any assertion violation gets caught

15 Goal Automated Unit Testing of real-world C and Java Programs  Generate test inputs  Execute unit under test on generated test inputs so that all reachable statements are executed  Any assertion violation gets caught Our Approach:  Explore all execution paths of an Unit for all possible inputs Exploring all execution paths ensure that all reachable statements are executed

16 Execution Paths of a Program Can be seen as a binary tree with possibly infinite depth  Computation tree Each node represents the execution of a “if then else” statement Each edge represents the execution of a sequence of non-conditional statements Each path in the tree represents an equivalence class of inputs

17 Example of Computation Tree void test_me(int x, int y) { if(2*x==y){ if(x != y+10){ printf(“I am fine here”); } else { printf(“I should not reach here”); ERROR; } 2*x==y x!=y+10 NY NY ERROR

18 Concolic Testing: Finding Security and Safety Bugs Divide by 0 Error x = 3 / i; Buffer Overflow a[i] = 4;

19 Concolic Testing: Finding Security and Safety Bugs Divide by 0 Error if (i !=0) x = 3 / i; else ERROR; Buffer Overflow if (0<=i && i < a.length) a[i] = 4; else ERROR; Key: Add Checks Automatically and Perform Concolic Testing

20 Existing Approach I Random testing  generate random inputs  execute the program on generated inputs Probability of reaching an error can be astronomically less test_me(int x){ if(x==94389){ ERROR; } Probability of hitting ERROR = 1/2 32

21 Existing Approach II Symbolic Execution  use symbolic values for input variables  execute the program symbolically on symbolic input values  collect symbolic path constraints  use theorem prover to check if a branch can be taken Does not scale for large programs test_me(int x) { if ((x%10)*4!=17) { ERROR; } else { ERROR; } Symbolic execution will say both branches are reachable: False positive

22 Existing Approach II Symbolic Execution  use symbolic values for input variables  execute the program symbolically on symbolic input values  collect symbolic path constraints  use theorem prover to check if a branch can be taken Does not scale for large programs test_me(int x) { if (bbox(x)!=17) { ERROR; } else { ERROR; } Symbolic execution will say both branches are reachable: False positive

23 Concolic Testing Approach Random Test Driver:  random values for x and y Probability of reaching ERROR is extremely low int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; }

24 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7x = x 0, y = y 0

25 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7, z = 14 x = x 0, y = y 0, z = 2*y 0

26 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7, z = 14 x = x 0, y = y 0, z = 2*y 0 2*y 0 != x 0

27 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition 2*y 0 != x 0 Solve: 2*y 0 == x 0 Solution: x 0 = 2, y 0 = 1 x = 22, y = 7, z = 14 x = x 0, y = y 0, z = 2*y 0

28 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 2, y = 1x = x 0, y = y 0

29 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 2, y = 1, z = 2 x = x 0, y = y 0, z = 2*y 0

30 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 2, y = 1, z = 2 x = x 0, y = y 0, z = 2*y 0 2*y 0 == x 0

31 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 2, y = 1, z = 2 x = x 0, y = y 0, z = 2*y 0 2*y 0 == x 0 x 0 <= y 0 +10

32 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 2, y = 1, z = 2 x = x 0, y = y 0, z = 2*y 0 Solve: (2*y 0 == x 0 ) and (x 0 > y ) Solution: x 0 = 30, y 0 = 15 2*y 0 == x 0 x 0 <= y 0 +10

33 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 30, y = 15x = x 0, y = y 0

34 Concolic Testing Approach int double (int v) { return 2*v; } void testme (int x, int y) { z = double (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 30, y = 15x = x 0, y = y 0 2*y 0 == x 0 x 0 > y Program Error

35 Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors  assertion violations  program crash  uncaught exceptions combine with valgrind to discover memory errors F T FF F F T T T T T T

36 Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors  assertion violations  program crash  uncaught exceptions combine with valgrind to discover memory errors F T FF F F T T T T T T

37 Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors  assertion violations  program crash  uncaught exceptions combine with valgrind to discover memory errors F T FF F F T T T T T T

38 Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors  assertion violations  program crash  uncaught exceptions combine with valgrind to discover memory errors F T FF F F T T T T T T

39 Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors  assertion violations  program crash  uncaught exceptions combine with valgrind to discover memory errors F T FF F F T T T T T T

40 Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors  assertion violations  program crash  uncaught exceptions combine with valgrind to discover memory errors F T FF F F T T T T T T

41 Novelty: Simultaneous Concrete and Symbolic Execution int foo (int v) { return (v*v) % 50; } void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7x = x 0, y = y 0

42 int foo (int v) { return (v*v) % 50; } void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7, z = 49 x = x 0, y = y 0, z = (y 0 *y 0 )%50 (y 0 *y 0 )%50 !=x 0 Solve: (y 0 *y 0 )%50 == x 0 Don’t know how to solve! Stuck? Novelty: Simultaneous Concrete and Symbolic Execution

43 void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7, z = 49 x = x 0, y = y 0, z = foo (y 0 ) foo (y 0 ) !=x 0 Novelty: Simultaneous Concrete and Symbolic Execution Solve: foo (y 0 ) == x 0 Don’t know how to solve! Stuck?

44 int foo (int v) { return (v*v) % 50; } void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7, z = 49 x = x 0, y = y 0, z = (y 0 *y 0 )%50 (y 0 *y 0 )%50 !=x 0 Solve: (y 0 *y 0 )%50 == x 0 Don’t know how to solve! Not Stuck! Use concrete state Replace y 0 by 7 (sound) Novelty: Simultaneous Concrete and Symbolic Execution

45 int foo (int v) { return (v*v) % 50; } void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 22, y = 7, z = 48 x = x 0, y = y 0, z = !=x 0 Solve: 49 == x 0 Solution : x 0 = 49, y 0 = 7 Novelty: Simultaneous Concrete and Symbolic Execution

46 int foo (int v) { return (v*v) % 50; } void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 49, y = 7x = x 0, y = y 0 Novelty: Simultaneous Concrete and Symbolic Execution

47 int foo (int v) { return (v*v) % 50; } void testme (int x, int y) { z = foo (y); if (z == x) { if (x > y+10) { ERROR; } Concrete Execution Symbolic Execution concrete state symbolic state path condition x = 49, y = 7, z = 49 x = x 0, y = y 0, z = 49 2*y 0 == x 0 x 0 > y Program Error Novelty: Simultaneous Concrete and Symbolic Execution

48 Concolic Testing: A Middle Approach + Complex programs + Efficient - Less coverage + No false positive - Simple programs - Not efficient + High coverage - False positive Random Testing Symbolic Testing Concolic Testing + Complex programs +/- Somewhat efficient + High coverage + No false positive

49 Implementations DART and CUTE for C programs jCUTE for Java programs  Goto for CUTE and jCUTE binarieshttp://srl.cs.berkeley.edu/~ksen/ MSR has four implementations  SAGE, PEX, YOGI, Vigilante Similar tool: EXE at Stanford Easiest way to use and to develop on top of CUTE  Implement concolic testing yourself

50 Another Example: Testing Data Structures typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Random Test Driver: random memory graph reachable from p random value for x Probability of reaching abort( ) is extremely low

51 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0 p, x=236 NULL

52 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0 p, x=236 NULL

53 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p=p 0, x=x 0 p, x=236 NULL

54 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p=p 0, x=x 0 p, x=236 NULL !(p 0 !=NULL )

55 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p=p 0, x=x 0 p, x=236 NULL p 0 =NULL solve: x 0 >0 and p 0  NULL

56 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p=p 0, x=x 0 p, x=236 NULL p 0 =NULL solve: x 0 >0 and p 0  NULL x 0 =236, p NULL

57 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634

58 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634 x 0 >0

59 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634 x 0 >0 p 0  NULL

60 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634 x 0 >0 p 0  NULL 2x 0 +1  v 0

61 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634 x 0 >0 p 0  NULL 2x 0 +1  v 0

62 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634 x 0 >0 p 0  NULL 2x 0 +1  v 0 solve: x 0 >0 and p 0  NULL and 2x 0 +1=v 0

63 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=236 NULL 634 x 0 >0 p 0  NULL 2x 0 +1  v 0 solve: x 0 >0 and p 0  NULL and 2x 0 +1=v 0 x 0 =1, p 0 3 NULL

64 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3

65 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0

66 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0 p 0  NULL

67 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0 p 0  NULL 2x 0 +1=v 0

68 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0 p 0  NULL 2x 0 +1=v 0 n0p0n0p0

69 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0 p 0  NULL 2x 0 +1=v 0 n0p0n0p0

70 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints solve: x 0 >0 and p 0  NULL and 2x 0 +1=v 0 and n 0 =p 0 p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0 p 0  NULL 2x 0 +1=v 0 n0p0n0p0

71 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints solve: x 0 >0 and p 0  NULL and 2x 0 +1=v 0 and n 0 =p 0 x 0 =1, p 0 3 p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 NULL 3 x 0 >0 p 0  NULL 2x 0 +1=v 0 n0p0n0p0

72 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 3

73 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 3

74 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p 0  NULL p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 3

75 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p 0  NULL 2x 0 +1=v 0 p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 3

76 CUTE Approach typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; } Concrete Execution Symbolic Execution concrete state symbolic state constraints x 0 >0 p 0  NULL 2x 0 +1=v 0 n0=p0n0=p0 p=p 0, x=x 0, p->v=v 0, p->next=n 0 p, x=1 3 Program Error

77 Pointer Inputs: Input Graph typedef struct cell { int v; struct cell *next; } cell; int f(int v) { return 2*v + 1; } int testme(cell *p, int x) { if (x > 0) if (p != NULL) if (f(x) == p->v) if (p->next == p) abort(); return 0; }

78 CUTE in a Nutshell Generate concrete inputs one by one  each input leads program along a different path

79 CUTE in a Nutshell Generate concrete inputs one by one  each input leads program along a different path On each input execute program both concretely and symbolically

80 CUTE in a Nutshell Generate concrete inputs one by one  each input leads program along a different path On each input execute program both concretely and symbolically  Both cooperate with each other concrete execution guides the symbolic execution

81 CUTE in a Nutshell Generate concrete inputs one by one  each input leads program along a different path On each input execute program both concretely and symbolically  Both cooperate with each other concrete execution guides the symbolic execution concrete execution enables symbolic execution to overcome incompleteness of theorem prover  replace symbolic expressions by concrete values if symbolic expressions become complex  resolve aliases for pointer using concrete values  handle arrays naturally

82 CUTE in a Nutshell Generate concrete inputs one by one  each input leads program along a different path On each input execute program both concretely and symbolically  Both cooperate with each other concrete execution guides the symbolic execution concrete execution enables symbolic execution to overcome incompleteness of theorem prover  replace symbolic expressions by concrete values if symbolic expressions become complex  resolve aliases for pointer using concrete values  handle arrays naturally symbolic execution helps to generate concrete input for next execution  increases coverage

83 Instrumentation

84 Instrumented Program Maintains a symbolic state  maps each memory location used by the program to symbolic expressions over symbolic input variables Maintains a path constraint  a sequence of constraints C 1, C 2,…, C k such that C i s are symbolic constraints over symbolic input variables C 1 ∧ C 2 ∧ … ∧ C k holds over the path currently executed by the program

85 Instrumented Program Maintains a symbolic state  maps each memory location used by the program to symbolic expressions over symbolic input variables Maintains a path constraint  a sequence of constraints C 1, C 2,…, C k such that C i s are symbolic constraints over symbolic input variables C 1 ∧ C 2 ∧ … ∧ C k holds over the path currently executed by the program Arithmetic Expressions a 1 x 1 +…+a n x n +c Pointer Expressions x

86 Instrumented Program Maintains a symbolic state  maps each memory location used by the program to symbolic expressions over symbolic input variables Maintains a path constraint  a sequence of constraints C 1, C 2,…, C k such that C i s are symbolic constraints over symbolic input variables C 1 ∧ C 2 ∧ … ∧ C k holds over the path currently executed by the program Arithmetic Expressions a 1 x 1 +…+a n x n +c Pointer Expressions x Arithmetic Constraints a 1 x 1 +…+a n x n ¸ 0 Pointer Constraints x=y x  y x=NULL x  NULL

87 Constraint Solving Path constraint C 1 ∧ C 2 ∧ … ∧ C k ∧ … ∧ C n

88 Constraint Solving Path constraint C 1 ∧ C 2 ∧ … ∧ C k ∧ … ∧ C n Solve C 1 ∧ C 2 ∧ … ∧ !C k to generate next input

89 Constraint Solving Path constraint C 1 ∧ C 2 ∧ … ∧ C k ∧ … ∧ C n Solve C 1 ∧ C 2 ∧ … ∧ !C k to generate next input If C k is pointer constraint then invoke pointer solver C i1 ∧ C i2 ∧ … ∧ !C k where ij in [1..k-1] and C ij is pointer constraint If C k is arithmetic constraint then invoke linear solver C i1 ∧ C i2 ∧ … ∧ !C k where ij in [1..k-1] and C ij is arithmetic constraint

90 SGLIB: popular library for C data-structures Used in Xrefactory a commercial tool for refactoring C/C++ programs Found two bugs in sglib  reported them to authors  fixed in sglib Bug 1:  doubly-linked list library segmentation fault occurs when a non-zero length list is concatenated with a zero-length list discovered in 140 iterations ( < 1second) Bug 2:  hash-table an infinite loop in hash table is member function 193 iterations (1 second)

91 SGLIB: popular library for C data-structures Name Run time in seconds # of Iterations # of Branches Explored % Branch Coverage # of Functions Tested # of Bugs Found Array Quick Sort Array Heap Sort Linked List Sorted List Doubly Linked List Hash Table Red Black Tree 26291,000,

92 Experiments: Needham-Schroeder Protocol Tested a C implementation of a security protocol (Needham-Schroeder) with a known attack  600 lines of code  Took less than 13 seconds on a machine with 1.8GHz Xeon processor and 2 GB RAM to discover middle-man attack In contrast, a software model-checker (VeriSoft) took 8 hours

93 Testing Data-structures of CUTE itself Unit tested several non-standard data- structures implemented for the CUTE tool  cu_depend (used to determine dependency during constraint solving using graph algorithm)  cu_linear (linear symbolic expressions)  cu_pointer (pointer symbolic expresiions) Discovered a few memory leaks and a copule of segmentation faults  these errors did not show up in other uses of CUTE  for memory leaks we used CUTE in conjunction with Valgrind