DART Directed Automated Random Testing Patrice Godefroid, Nils Klarlund, and Koushik Sen Syed Nabeel.

Slides:



Advertisements
Similar presentations
1 Verification by Model Checking. 2 Part 1 : Motivation.
Advertisements

Cristian Cadar, Peter Boonstoppel, Dawson Engler RWset: Attacking Path Explosion in Constraint-Based Test Generation TACAS 2008, Budapest, Hungary ETAPS.
A Survey of Approaches for Automated Unit Testing
Masahiro Fujita Yoshihisa Kojima University of Tokyo May 2, 2008
Symbolic Execution with Mixed Concrete-Symbolic Solving
A System to Generate Test Data and Symbolically Execute Programs Lori A. Clarke September 1976.
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.
Finding bugs: Analysis Techniques & Tools Comparison of Program Analysis Techniques CS161 Computer Security Cho, Chia Yuan.
Fuzzing and Patch Analysis: SAGEly Advice. Introduction.
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 From Program slicing to Abstract Interpretation Dr. Manuel Oriol.
1/20 Generalized Symbolic Execution for Model Checking and Testing Charngki PSWLAB Generalized Symbolic Execution for Model Checking and Testing.
Hybrid Concolic Testing Rupak Majumdar Koushik Sen UC Los Angeles UC Berkeley.
Dynamic Symbolic Execution CS 8803 FPL Oct 31, 2012 (Slides adapted from Koushik Sen) 1.
The Software Model Checker BLAST by Dirk Beyer, Thomas A. Henzinger, Ranjit Jhala and Rupak Majumdar Presented by Yunho Kim Provable Software Lab, KAIST.
CSE503: SOFTWARE ENGINEERING SYMBOLIC TESTING, AUTOMATED TEST GENERATION … AND MORE! David Notkin Spring 2011.
Precise Inter-procedural Analysis Sumit Gulwani George C. Necula using Random Interpretation presented by Kian Win Ong UC Berkeley.
Synergy: A New Algorithm for Property Checking
ECE Synthesis & Verification1 ECE 667 Spring 2011 Synthesis and Verification of Digital Systems Verification Introduction.
PLDI’2005Page 1June 2005 DART: Directed Automated Random Testing Patrice Godefroid Nils Klarlund Koushik Sen Bell Labs Bell Labs UIUC.
CUTE Homework CS Assignment Due Noon 02/06/2009 Arrange to give me a demo on Monday 02/09/2009 after 1 pm Your Program: Trace -> Input You must.
Synthesis of Interface Specifications for Java Classes Rajeev Alur University of Pennsylvania Joint work with P. Cerny, G. Gupta, P. Madhusudan, W. Nam,
16/27/2015 3:38 AM6/27/2015 3:38 AM6/27/2015 3:38 AMTesting and Debugging Testing The process of verifying the software performs to the specifications.
Program Analysis Mooly Sagiv Tel Aviv University Sunday Scrieber 8 Monday Schrieber.
Automating Software Testing Using Program Analysis -Patrice Godefroid, Peli de Halleux, Aditya V. Nori, Sriram K. Rajamani,Wolfram Schulte, and Nikolai.
Dr. Pedro Mejia Alvarez Software Testing Slide 1 Software Testing: Building Test Cases.
CREST Internal Yunho Kim Provable Software Laboratory CS Dept. KAIST.
DART: Directed Automated Random Testing Koushik Sen University of Illinois Urbana-Champaign Joint work with Patrice Godefroid and Nils Klarlund.
Symbolic Execution with Mixed Concrete-Symbolic Solving (SymCrete Execution) Jonathan Manos.
Modular Programming Chapter Value and Reference Parameters t Function declaration: void computesumave(float num1, float num2, float& sum, float&
CUTE: A Concolic Unit Testing Engine for C Technical Report Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
1 A Static Analysis Approach for Automatically Generating Test Cases for Web Applications Presented by: Beverly Leung Fahim Rahman.
Aditya V. Nori, Sriram K. Rajamani Microsoft Research India.
Type Systems CS Definitions Program analysis Discovering facts about programs. Dynamic analysis Program analysis by using program executions.
Parameterized Unit Tests By Nikolai Tillmann and Wolfram Schulte Proc. of ESEC/FSE 2005 Presented by Yunho Kim Provable Software Lab, KAIST TexPoint fonts.
Introduction to Problem Solving. Steps in Programming A Very Simplified Picture –Problem Definition & Analysis – High Level Strategy for a solution –Arriving.
Symbolic Execution with Abstract Subsumption Checking Saswat Anand College of Computing, Georgia Institute of Technology Corina Păsăreanu QSS, NASA Ames.
Xusheng Xiao North Carolina State University CSC 720 Project Presentation 1.
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.
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.
CUTE: A Concolic Unit Testing Engine for C Koushik SenDarko MarinovGul Agha University of Illinois Urbana-Champaign.
Dynamic Testing.
( = “unknown yet”) Our novel symbolic execution framework: - extends model checking to programs that have complex inputs with unbounded (very large) data.
/ 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,
Dynamic Symbolic Execution (aka, directed automated random testing, aka concolic execution) Slides by Koushik Sen.
Week 6 MondayTuesdayWednesdayThursdayFriday Testing III Reading due Group meetings Testing IVSection ZFR due ZFR demos Progress report due Readings out.
Symbolic Execution in Software Engineering By Xusheng Xiao Xi Ge Dayoung Lee Towards Partial fulfillment for Course 707.
CSE 331 SOFTWARE DESIGN & IMPLEMENTATION SYMBOLIC TESTING Autumn 2011.
CS223: Software Engineering Lecture 26: Software Testing.
Willem Visser Stellenbosch University
Verification and Testing
Automated Pattern Based Mobile Testing
A Test Case + Mock Class Generator for Coding Against Interfaces
DART and CUTE: Concolic Testing
Symbolic Implementation of the Best Transformer
All You Ever Wanted to Know About Dynamic Taint Analysis & Forward Symbolic Execution (but might have been afraid to ask) Edward J. Schwartz, Thanassis.
Elided to examples only
Automatic Test Generation SymCrete
Software Verification and Validation
Software Verification and Validation
Section 5: HW6 and Interfaces
Example (C code) int double(int x) { return 2 * x; }
CUTE: A Concolic Unit Testing Engine for C
The Zoo of Software Security Techniques
Software Verification and Validation
Presentation transcript:

DART Directed Automated Random Testing Patrice Godefroid, Nils Klarlund, and Koushik Sen Syed Nabeel

Motivation ► ► Software Testing emerges as one of the most important aspects in Software Engineering ► ► Unit Testing ► ► Limitations in Unit Testing ► ► DART a novel approach to counter limitations in Unit Testing

Unit Testing Testing small portions of programs, such as methods, groups of methods, or classes. ► ► a sequence of calls to the units (for e.g. methods) ► ► BEFORE the calls some code to generate parameters for the methods ► ► AFTER the calls some code checking whether the method has performed correctly.

Goals of Unit Testing ► ► Detect Errors in the components logic ► ► Check ALL corner cases ► ► Provide 100% code coverage

Question What are some limitations of Unit Testing?

Limitations of Unit Testing ► Requires test driver and harness code which is representative of ALL external environment ► Expensive and hard to perform manually (rarely done properly)

DART To The Rescue Automates unit testing removing need for writing test drivers Automates unit testing removing need for writing test drivers ► Automated extraction of the program interface by static code parsing ► Automatic generation of test driver for this interface that performs random testing ► Dynamic Analysis of the program behavior to generate specific test inputs for the direction of program execution through alternate program paths

Execution Model For DART ► Concrete Execution: based on a memory model M that maps addresses to values ► Symbolic Execution: based on symbolic memory S that maps addresses to expressions

Directed Testing by Constraint Building ► Progressively constraints are built as branches are encountered ► Linear constraints are solved to explore various execution paths ► In case of getting stuck or non linear constraints symbolic execution falls back to concrete execution

Consider An Example …. int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10){ printf(“I am fine here”); printf(“I am fine here”); } else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}}

Random Testing int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10){ printf(“I am fine here”); printf(“I am fine here”); } else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} main(){ int tmp1 = randomInt(); int tmp2 = randomInt(); test_me(tmp1,tmp2);}

Random Testing int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10){ printf(“I am fine here”); printf(“I am fine here”); } else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} main(){ int tmp1 = randomInt(); int tmp2 = randomInt(); test_me(tmp1,tmp2);} Evident Problem: Probability of Reaching Abort is very low

DART Approach main(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Full example taken from Presentation by Koushik at

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=36t1=m

DART Approach Concrete Execution concrete state symbolic stateconstraints t1=36, t2=-7t1=m, t2=nmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=36, t2=-7t1=m, t2=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=36, y=-7x=m, y=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=36, y=-7, z=72x=m, y=n, z=2m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=36, y=-7, z=72x=m, y=n, z=2m 2m != n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution 2m != n x=36, y=-7, z=72x=m, y=n, z=2m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution solve: 2m = n m=1, n=2 solve: 2m = n m=1, n=2 2m != n x=36, y=-7, z=72x=m, y=n, z=2m

Question Which portion of code identifies a new constraint ?

The Example Again main(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}}

The Example Again main(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}}

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=1t1=m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=1, t2=2t1=m, t2=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=1, t2=2t1=m, t2=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=1, y=2x=m, y=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=1, y=2x=m, y=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=1, y=2x=m, y=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=1, y=2x=m, y=n 2m = n m != n+10

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution 2m = n m != n+10 x=1, y=2, z=2x=m, y=n, z=2m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution 2m = n m != n+10 x=1, y=2, z=2x=m, y=n, z=2m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution solve: 2m = n m=1, n=2 solve: 2m = n and m=n+10 m= -10, n= -20 2m = n x=36, y=-7, z=72x=m, y=n, z=2m m != n+10

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=-10t1=m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=-10, t2=-20t1=m, t2=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution t1=-10, t2=-20t1=m, t2=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=-10, y=-20x=m, y=n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=-10, y=-20, z=-20x=m, y=n, z=2m

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=-10, y=-20, z=-20 x=m, y=n, z=2m2m = n

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution x=-10, y=-20, z=-20 x=m, y=n, z=2m 2m = n m = n+10

DART Approach Concrete Execution concrete state symbolic stateconstraintsmain(){ int t1 = randomInt(); int t2 = randomInt(); test_me(t1,t2);} int double(int x) { return 2 * x; } void test_me(int x, int y) { int z = double(x); int z = double(x); if(z==y){ if(z==y){ if(x != y+10) { printf(“I am fine here”); printf(“I am fine here”); } else { else { printf(“I should not reach here”); printf(“I should not reach here”); abort(); abort();}} Symbolic Execution Program Error x=-10, y=-20, z=-20 x=m, y=n, z=2m 2m = n m = n+10

Properties of DART ► Sound w.r.t errors found (no false positives) ► Complete (in a limited sense) If DART terminates without reporting a bug, no bug exists If DART terminates without reporting a bug, no bug exists

Advantages: ► Dynamic Data Analysis ► Sound Errors

Dynamic Data Analysis struct foo { int i; char c; } bar (struct foo *a) { if (a->c == 0) { *((char *)a + sizeof(int)) = 1; if (a->c != 0) abort(); }

Dynamic Data Analysis ► Static Analyzers would not be able to detect the change in the value of a->c and declare the program to be safe ► DART locates the error by means of satisfying the constraint a->c==0

Sound Errors foobar(int x, int y){ if (x*x*x > 0){ if (x>0 && y==10) abort(); } else { if (x>0 && y==20) abort(); }

Sound Errors ► Static analysis using predicate abstraction state that both aborts may be reachable ► Test-generation using symbolic execution get stuck at first conditional ► DART detects first abort with high probability

DART For C ► Interface Extraction done by light weight static parsing of source code ► Test Driver Generation involves initialization of external variables with random values, stubs for external functions ► Directed Search comprises of implementation of constraint satisfaction, parsing and analysis of C code

Discussion