CUTE: A Concolic Unit Testing Engine for C

Similar documents
DART: Directed Automated Random Testing

CUTE: A Concolic Unit Testing Engine for C

DART: Directed Automated Random Testing. CUTE: Concolic Unit Testing Engine. Slide Source: Koushik Sen from Berkeley

Automated Software Analysis Techniques For High Reliability: A Concolic Testing Approach. Moonzoo Kim

Applications of Logic in Software Engineering. CS402, Spring 2016 Shin Yoo

Software Testing CS 408. Lecture 6: Dynamic Symbolic Execution and Concolic Testing 1/30/18

Three Important Testing Questions

Symbolic Execution, Dynamic Analysis

Concolic Testing of Sequential and Concurrent Programs

Emblematic Execution for Software Testing based on DART AND CUTE

Automatic Software Verification

Symbolic and Concolic Execution of Programs

Automated Testing of Cloud Applications

DART: Directed Automated Random Testing

From Symbolic Execution to Concolic Testing. Daniel Paqué

Bullseye: A System for Targeted Test Generation

Analysis/Bug-finding/Verification for Security

Symbolic Evaluation/Execution

Comp Sci 1MD3 Mid-Term II 2003 answers

Automated Software Testing in the Absence of Specifications

Symbolic Execution. Wei Le April

Dynamic Test Generation to Find Bugs in Web Application

Reading Assignment. Symbolic Evaluation/Execution. Move from Dynamic Analysis to Static Analysis. Move from Dynamic Analysis to Static Analysis

Advanced Programming Methods. Introduction in program analysis

Lecture Notes on Memory Layout

CS558 Programming Languages

Automated Test-Input Generation

Automated Unit Testing of Large Industrial Embedded Software using Concolic Testing

A Gentle Introduction to Program Analysis

CSCE 548 Building Secure Software Software Analysis Basics

Combining Model Checking and Testing

TNT. Runtime Errors. Proving Non-Termination. Proving Non-Termination. Non-Termination Errors. TNT: Testing Non-Termination

CS 241 Data Organization Binary Trees

: Principles of Imperative Computation Victor Adamchik. Practice Exam - I

Lecture Notes on Binary Search Trees

Lecture Notes on Binary Search Trees

Static Analysis and Bugfinding

Having a BLAST with SLAM

Testing. ECE/CS 5780/6780: Embedded System Design. Why is testing so hard? Why do testing?

Timing Analysis of Event-Driven Programs with Directed Testing

Programm- & Systemverifikation

CS 430 Spring Mike Lam, Professor. Data Types and Type Checking

Lecture 15 Notes Binary Search Trees

Lecture 15 Binary Search Trees

Directed Random Testing*

Seminar in Software Engineering Presented by Dima Pavlov, November 2010

CSE 565 Computer Security Fall 2018

Lecture 10 Notes Linked Lists

Automated Whitebox Fuzz Testing. by - Patrice Godefroid, - Michael Y. Levin and - David Molnar

Lecture 8: Pointer Arithmetic (review) Endianness Functions and pointers

Static Program Analysis Part 1 the TIP language

Software Testing CS 408. Lecture 11: Review 2/20/18

Model Checking with Abstract State Matching

From Program to Logic: An Introduction

Verification & Validation of Open Source

Copyright 2008 CS655 System Modeling and Analysis. Korea Advanced Institute of Science and Technology

Testing & Symbolic Execution

Comp Sci 1MD3 Mid-Term II 2004 Dr. Jacques Carette

Profile-Guided Program Simplification for Effective Testing and Analysis

Software Model Checking. Xiangyu Zhang

Implementing an abstract datatype. Linked lists and queues

Symbolic Execu.on. Suman Jana

A CutEr Tool. Kostis Sagonas

n HW7 due in about ten days n HW8 will be optional n No CLASS or office hours on Tuesday n I will catch up on grading next week!

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

CS32 Discussion Week 3

Lecture 10 Notes Linked Lists

C Review. MaxMSP Developers Workshop Summer 2009 CNMAT

Research on Fuzz Testing Framework based on Concolic Execution

Symbolic Execution for Bug Detection and Automated Exploit Generation

Scalable Test Generation by Interleaving Concrete and Symbolic Execution

CS61C Machine Structures. Lecture 3 Introduction to the C Programming Language. 1/23/2006 John Wawrzynek. www-inst.eecs.berkeley.

Symbolic Execution for Software Testing: Three Decades Later

Applications of Program analysis in Model-Based Design

1 A Brief Introduction To GDB

MEMORY MANAGEMENT TEST-CASE GENERATION OF C PROGRAMS USING BOUNDED MODEL CHECKING

speller.c dictionary contains valid words, one per line 1. calls load on the dictionary file

CS558 Programming Languages

Low level security. Andrew Ruef

CSCI 171 Chapter Outlines

(Section : Computer Science)

Targeted Test Input Generation Using Symbolic Concrete Backward Execution

CSCI-243 Exam 1 Review February 22, 2015 Presented by the RIT Computer Science Community

Lecture Notes on Binary Search Trees

CS61, Fall 2012 Section 2 Notes

CONTENTS. PART 1 Structured Programming 1. 1 Getting started 3. 2 Basic programming elements 17

Bounded Model Checking Of C Programs: CBMC Tool Overview

Agenda. Peer Instruction Question 1. Peer Instruction Answer 1. Peer Instruction Question 2 6/22/2011

THE GOOD, BAD AND UGLY ABOUT POINTERS. Problem Solving with Computers-I

// Initially NULL, points to the dynamically allocated array of bytes. uint8_t *data;

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Recitation: Cache Lab & C

Having a BLAST with SLAM

Software Security: Vulnerability Analysis

CS 11 C track: lecture 5

Types and Type Inference

Lecture Notes on Contracts

for (i=1; i<=100000; i++) { x = sqrt (y); // square root function cout << x+i << endl; }

Static Analysis in C/C++ code with Polyspace

Static program checking and verification

Transcription:

CUTE: A Concolic Unit Testing Engine for C Koushik Sen Darko Marinov Gul Agha University of Illinois Urbana-Champaign

Goal Automated Scalable Unit Testing of real-world C Programs Generate test inputs Execute unit under test on generated test inputs so that all reachable ments are executed Any assertion violation gets caught 2

Goal Automated Scalable Unit Testing of real-world C Programs Generate test inputs Execute unit under test on generated test inputs so that all reachable ments 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 ments are executed 3

Paths of a Program Can be seen as a binary tree with possibly infinite depth Computation tree 0 Each node represents the execution of a if then else ment 0 0 Each edge represents the execution of a sequence of non-conditional ments 0 Each path in the tree represents an equivalence class of inputs 0 4

Example of Computation Tree void test_me(int x int y) { if(2*x==y){ if(x!= y+0){ printf( I am fine here ); else { printf( I should not reach here ); ERROR; N 2*x==y N Y x!=y+0 Y ERROR 5

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

Existing Approach II Symbolic 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%0)*4!=7){ ERROR; else { ERROR; Symbolic execution will say both branches are reachable: False positive 7

Approach Combine concrete and symbolic execution for unit testing Concrete + Symbolic = Concolic In a nutshell Use concrete execution over a concrete input to guide symbolic execution Concrete execution helps Symbolic execution to simplify complex and unmanageable symbolic expressions by replacing symbolic values by concrete values Achieves Scalability Higher branch coverage than random testing No false positives or scalability issue like in symbolic execution based testing 8

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

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

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

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

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

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

CUTE Approach typedef struct cell { int v; struct cell *next; cell; Concrete concrete symbolic solve: x 0 >0 and p 0 NULL Symbolic constraints int f(int v) { return 2*v + ; x 0 =236 p 0 NULL int testme(cell *p int x) { if (x > 0) if (p!= NULL) if (f(x) == p->v) if (p->next == p) return 0; p x=236 634 p=p 0 x=x 0 x 0 >0 p 0 =NULL NULL 5

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

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

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

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

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

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

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

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

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

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

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

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

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

CUTE Approach typedef struct cell { int v; struct cell *next; cell; int f(int v) { return 2*v + ; concrete Concrete symbolic solve: x 0 >0 and p 0 NULL and 2x 0 +=v 0 and n 0 =p 0 Symbolic constraints int testme(cell *p int x) { if (x > 0) if (p!= NULL) if (f(x) == p->v) if (p->next == p) return 0; p 3 NULL x=. p=p 0 x=x 0 p->v =v 0 p->next=n 0 x 0 >0 p 0 NULL 2x 0 +=v 0 n 0 p 0 29

CUTE Approach typedef struct cell { int v; struct cell *next; cell; int f(int v) { return 2*v + ; concrete Concrete symbolic solve: x 0 >0 and p 0 NULL and 2x 0 +=v 0 and n 0 =p 0 Symbolic constraints int testme(cell *p int x) { if (x > 0) if (p!= NULL) if (f(x) == p->v) if (p->next == p) return 0; p 3 NULL x= x 0 = p 0 3 p=p 0 x=x 0 p->v =v 0 p->next=n 0 x 0 >0 p 0 NULL 2x 0 +=v 0 n 0 p 0 30

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

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

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

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

CUTE Approach typedef struct cell { int v; struct cell *next; cell; concrete Concrete symbolic Symbolic constraints int f(int v) { return 2*v + ; int testme(cell *p int x) { if (x > 0) if (p!= NULL) if (f(x) == p->v) if (p->next == p) return 0; p 3 Program Error x= p=p 0 x=x 0 p->v =v 0 p->next=n 0 x 0 >0 p 0 NULL 2x 0 +=v 0 n 0 =p 0 35

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 37

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 38

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 39

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 40

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 4

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 42

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 43

Explicit Path (not State) Model Checking Traverse all execution paths one by one to detect errors 0 check for assertion violations 0 0 check for program crash combine with valgrind to discover memory leaks 0 detect invariants 0 44

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

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 46

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 47

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 48

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 49

Testing Data-structures of CUTE itself Unit tested several non-standard datastructures 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 expressions) Discovered a few memory leaks and a couple of segmentation faults these errors did not show up in other uses of CUTE for memory leaks we used CUTE in conjunction with Valgrind 50

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

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver 52

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 take then branch with constraint x*x*x+ 3*x*x+9!= y 53

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 take then branch with constraint x*x*x+ 3*x*x+9!= y solve x*x*x+ 3*x*x+9 = y to take else branch Don t know how to solve!! Stuck? 54

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 take then branch with constraint x*x*x+ 3*x*x+9!= y solve x*x*x+ 3*x*x+9 = y to take else branch Don t know how to solve!! Stuck? NO : CUTE handles this smartly 55

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver 56

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 cannot handle symbolic value of z 57

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 cannot handle symbolic value of z make symbolic z = 9 and proceed 58

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 cannot handle symbolic value of z make symbolic z = 9 and proceed take then branch with constraint 9!= y 59

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 cannot handle symbolic value of z make symbolic z = 9 and proceed take then branch with constraint 9!= y solve 9 = y to take else branch execute next run with x = -3 and y= 9 got error (reaches abort) 60

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); Replace symbolic expression by concrete value when symbolic expression becomes unmanageable (i.e. non-linear) Let initially x = -3 and y = 7 generated by random testdriver concrete z = 9 symbolic z = x*x*x + 3*x*x+9 cannot handle symbolic value of z make symbolic z = 9 and proceed take then branch with constraint 9!= y solve 9 = y to take else branch execute next run with x = -3 and y= 9 got error (reaches abort) 6

Simultaneous Symbolic & Concrete void again_test_me(int xint y){ z = x*x*x + 3*x*x + 9; if(z!= y){ printf( Good branch ); else { printf( Bad branch ); void again_test_me(int xint y){ z = black_box_fun(x); if(z!= y){ printf( Good branch ); else { printf( Bad branch ); 62

Related Work DART: Directed Automated Random Testing by Patrice Godefroid Nils Klarlund and Koushik Sen (PLDI 05) handles only arithmetic constraints CUTE Supports C with pointers data-structures Highly efficient constraint solver 00-000 times faster arithmetic pointers Provides Bounded Depth-First Search and Random Search strategies Publicly available tool that works on ALL C programs 63

Discussion CUTE is dynamic analysis (compare with static analysis) ensures no false alarms concrete execution and symbolic execution run simultaneously symbolic execution consults concrete execution whenever dynamic analysis becomes intractable real tool that works on all C programs Requires actual code that can be fully compiled Can (sometimes) reduce to Random Testing System calls (I/O) in tests not supported Supporting concurrency is hard Complementary to Static Analysis Tools 64