DART: Directed Automated Random Testing - PowerPoint PPT Presentation

1 / 44
About This Presentation
Title:

DART: Directed Automated Random Testing

Description:

DART: Directed Automated Random Testing Koushik Sen University of Illinois Urbana-Champaign Joint work with Patrice Godefroid and Nils Klarlund Software Testing ... – PowerPoint PPT presentation

Number of Views:92
Avg rating:3.0/5.0
Slides: 45
Provided by: KSe55
Category:

less

Transcript and Presenter's Notes

Title: DART: Directed Automated Random Testing


1
DART Directed Automated Random Testing
  • Koushik Sen
  • University of Illinois Urbana-Champaign

Joint work with Patrice Godefroid and Nils
Klarlund
2
Software Testing
  • Testing accounts for 50 of software development
    cost
  • Software failure costs USA 60 billion annually
  • Improvement in software testing infrastructure
    can save one-third of this cost
  • The economic impacts of inadequate
    infrastructure for software testing, NIST, May,
    2002
  • Currently, software testing is mostly done
    manually

3
Simple C code
  • int double(int x)
  • return 2 x
  • void test_me(int x, int y)
  • int z double(x)
  • if(zy)
  • if(x ! y10)
  • printf(I am fine here)
  • else
  • printf(I should not reach here)
  • abort()

4
Automatic Extraction of Interface
  • Automatically determine (code parsing)
  • inputs to the program
  • arguments to the entry function
  • variables whose value depends on environment
  • external objects
  • function calls return value depends on the
    environment
  • external function calls
  • For simple C code
  • want to unit test the function test_me
  • int x and int y passed as an argument to
    test_me forms the external environment

5
Generate Random Test Driver
  • Generate a test driver automatically to simulate
    random environment of the extracted interface
  • most general environment
  • C code
  • Compile the program along with the test driver to
    create a closed executable.
  • Run the executable several times to see if
    assertion violates

6
Random test-driver
  • int double(int x)
  • return 2 x
  • void test_me(int x, int y)
  • int z double(x)
  • if(zy)
  • if(x ! y10)
  • printf(I am fine here)
  • else
  • printf(I should not reach here)
  • abort()

Random Test Driver
  • main()
  • int tmp1 randomInt()
  • int tmp2 randomInt()
  • test_me(tmp1,tmp2)

7
Random test-driver
  • int double(int x)
  • return 2 x
  • void test_me(int x, int y)
  • int z double(x)
  • if(zy)
  • if(x ! y10)
  • printf(I am fine here)
  • else
  • printf(I should not reach here)
  • abort()

Random Test Driver
  • main()
  • int tmp1 randomInt()
  • int tmp2 randomInt()
  • test_me(tmp1,tmp2)

Probability of reaching abort() is extrememly low
8
Limitations
  • Hard to hit the assertion violated with random
    values of x and y
  • there is an extremely low probability of hitting
    assertion violation
  • Can we do better?
  • Directed Automated Random Testing
  • White box assumption

9
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
10
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
11
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
12
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
13
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
14
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
15
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m ! n
16
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m ! n
17
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
solve 2m n m1, n2
2m ! n
18
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
19
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
20
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
21
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
22
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
23
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m n
24
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m n
m ! n10
25
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m n
m ! n10
26
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m n
m ! n10
27
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
solve 2m n and mn10 m -10, n -20
2m n
m ! n10
28
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
29
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
30
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
31
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
32
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
33
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m n
34
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
2m n
m n10
35
DART Approach
Concrete Execution
Symbolic Execution
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
Program Error
2m n
m n10
36
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) if(zy) if(x ! y10)
printf(I am fine here) else
printf(I should not reach here)
abort()
N
Y
N
Y
Error
37
DART in a Nutshell
  • Dynamically observe random execution and generate
    new test inputs to drive the next execution along
    an alternative path
  • do dynamic analysis on a random execution
  • collect symbolic constraints at branch points
  • negate one constraint at a branch point (say b)
  • call constraint solver to generate new test
    inputs
  • use the new test inputs for next execution to
    take alternative path at branch b
  • (Check that branch b is indeed taken next)

38
More details
  • Instrument the C program to do both
  • Concrete Execution
  • Actual Execution
  • Symbolic Execution and Lightweight theorem
    proving (path constraint solving)
  • Dynamic symbolic analysis
  • Interacts with concrete execution
  • Instrumentation also checks whether the next
    execution matches the last prediction.

39
Experiments
  • Tested a C implementation of a security protocol
    (Needham-Schroeder) with a known attack
  • 406 lines of code
  • Took less than 26 minutes on a 2GHz machine to
    discover middle-man attack
  • In contrast, a software model-checker (VeriSoft)
    and a hand-written nondeterministic model of the
    attacker took hours to discover the attack

40
Larger Experiment
  • oSIP (open-source session initiation protocol)
  • http//www.gnu.org/software/osip/osip.html
  • 30,000 lines of C code (version 2.0.9)
  • 600 externally visible functions
  • Results
  • crashed 65 of the externally visible functions
    within 1000 iterations
  • no nullity check for pointers
  • Focused on oSIP parser
  • can externally crash oSIP server
  • osip_message_parse() pass a buffer of size 2.5
    MB with no 0 or character
  • tries to copy the packet to stack using
    alloca(size)
  • this fails returns NULL pointer
  • this NULL pointer passed to another function
  • does not check for nullity and crashes

41
Advantage of Dynamic Analysis over Static Analysis
  • struct foo int i char c
  • bar (struct foo a)
  • if (a-gtc 0)
  • ((char )a sizeof(int)) 1
  • if (a-gtc ! 0)
  • abort()
  • Reasoning about dynamic data is easy
  • Due to limitation of alias analysis static
    analyzers cannot determine that a-gtc has
    been rewritten
  • BLAST would infer that the program is safe
  • DART finds the error
  • sound

42
Further advantages
  • 1 foobar(int x, int y)
  • 2 if (xxx gt 0)
  • 3 if (xgt0 y10)
  • 4 abort()
  • 5
  • 6 else
  • 7 if (xgt0 y20)
  • 8 abort()
  • 9
  • 10
  • 11
  • static analysis based model-checkers would
    consider both branches
  • both abort() statements are reachable
  • false alarm
  • Symbolic execution gets stuck at line number 2
  • DART finds the only error

43
Discussion
  • In comparison to existing testing tools, DART is
  • light-weight
  • 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 real C programs
  • completely automatic
  • Software model-checkers using abstraction (SLAM,
    BLAST)
  • starts with an abstraction with more behaviors
    gradually refines
  • static analysis approach false alarms
  • DART executes program systematically to explore
    feasible paths

44
Current Work CUTE at UIUC
  • CUTE A Concolic Unit Testing Engine (FSE05)
  • For C and Java
  • Handle pointers
  • Can test data-structures
  • Can handle heap
  • Bounded depth search
  • Use static analysis to find branches that can
    lead to assertion violation
  • use this info to prune search space
  • Concurrency Support
  • Probabilistic Search Mode
  • Find bugs in Cryptographic Protocols
  • 100 -1000 times faster than the DART
    implementation reported in PLDI05
Write a Comment
User Comments (0)
About PowerShow.com