Exploring Symbolic vs Concrete Testing and Program Paths

symbolic vs concrete testing n.w
1 / 40
Embed
Share

"Discover the differences between symbolic and concrete testing, the concept of program paths, infeasible paths, and the role of symbolic executions in real programs. Learn about symbolic testing tools and techniques for finding infeasible paths in software testing methodologies."

  • Symbolic Testing
  • Concrete Testing
  • Program Paths
  • Infeasible Paths
  • Software Testing

Uploaded on | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Symbolic vs. Concrete Testing Mooly Sagiv

  2. Program Path Program Path A path in the control flow of the program Can start and end at any point Appropriate for imperative programs Feasible program path There exists an input that leads to the execution of this path Infeasible program path No input that leads to the execution

  3. Infeasible Paths A void grade(int score) { A: if (score <45) { B: printf( fail ); } else C: printf( pass ); } D: if (score > 85) { E: printf( with honors ); } F: } B C D E F

  4. Concrete vs. Symbolic Executions Real programs have many infeasible paths Ineffective concrete testing Symbolic execution aims to find rare errors

  5. Symbolic Testing Tools EFFIGY [King, IBM 76] PEX [MSR] SAGE [MSR] SATURN[Stanford] KLEE[Stanford] Java pathfinder[NASA] Bitscope [Berkeley] Cute [UIUC, Berkeley] Calysto [UBC]

  6. Finding Infeasible Paths Via SMT A void grade(int score) { A: if (score <45) { B: printf( fail ); } else C: printf( pass ); } D: if (score > 85) { E: printf( with honors ); } F: } score < 45 score > 85 B C D E UNSAT F

  7. Plan Random Testing Symbolic Testing Concolic Testing

  8. Fuzzing [Miller 1990] Test programs on random unexpected data Can be realized using black/white testing Can be quite effective Operating Systems Networks Usually implemented via instrumentation Tricky to scale for programs with many paths If (x == 10001) { int f(int *p) { . if (f(*y) == *z) { . if (p !=NULL) { return q ; }

  9. Symbolic Exploration Execute a program on symbolic inputs Track set of values symbolically Update symbolic states when instructions are executed Whenever a branch is encountered check if the path is feasible using a theorem prover call

  10. Symbolic Execution Tree The constructed symbolic execution paths Nodes Symbolic Program States Edges Potential Transitions Constructed during symbolic evaluation Each edge requires a theorem prover call

  11. Simple Example 1)int x, y; 2)if (x > y) { 3) x = x + y; 4) y = x y; 5) x = x y; 6) if (x > y) 7) assert false; 8)} pc=1, x =s1, y=s2 pc=2, x =s1, y=s2 pc=8, x =s1, y=s2, s1 s2 pc=3, x =s1, y=s2, s1>s2 x = x + y pc=4, x =s1+s2, y=s2, s1>s2 y = x - y pc=5, x =s1+s2, y=s1, s1>s2 x = x - y x y pc=6, x =s2, y=s1, s1>s2 pc=8, x =s2, y=s1, s1>s2

  12. Another Example int f(int x) { return 2 * x ;} int h(int x, int y) { 1)if (x!= y) { 2) if (f(x) == x +10) { 3) abort() // * error */ } } 4) return 0; pc=1, x =s1, y=s2 pc=2, x =s1, y=s2, s1 s2 pc=4, x =s1, y=s2, s1=s2 pc=4, x=s1, y=s2, s1 s2, 2*s1 s2+10 pc=3, x =s1, y=s2, s1 s2, 2*s1 =s2+10

  13. Pointers struct foo {int i; char c;} bar(struct foo *a) { 1) if (a->c == 0) { 2) *((char *)a + sizeof(int)) = 1 ; 3) if (a->c !=0) { 4) abort(); } } 5) }

  14. Non-Deterministic Behavior int x; y; 1) if (nondet()) { 2) x = 7; } else { 3) x = 19 ; } 4)

  15. Loops 1) int i; 2) while i < n { i = i + 1; } 3) if (n ==106) { 4) abort(); 5) }

  16. Scaling Issues for Symbolic Exploration

  17. Challenge 1: Limitations of Theorem Provers foobar(int x, int y) { 1) if (x * x * x > 0) { 2) if (x>0 && y ==10) { 3) abort() ; } 4) } 5) else { 6) if (x > 0 && y == 20) { 7) abort ;} 8) } 9) }

  18. Challenge 2: External Calls 1) 2) 3) 4) 5) 6) 7) 8) FILE *fp; fp = fopen( test.txt", w"); if (fp) { struct stat buffer; if (stat ( text.txt , &buffer) != 0) { abort(); } }

  19. Challenge 3: #Theorem prover calls 1) int i = 0; 2) while i < n { i = i + 1; } 3) if (n==106) { 4) abort(); 5) }

  20. Concolic Testing Concrete + Symbolic = Concolic Combine concrete testing (concrete execution) and symbolic testing (symbolic execution) Trade coverage (miss bugs) for scalability Reduce the number of theorem prover calls Reduce the complexity of path formulas Can cope with external calls

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

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

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

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

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

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

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

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

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

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

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

  32. The Concolic Testing Algorithm Classify input variables into symbolic / concrete Instrument to record symbolic vars and path conditions Choose an arbitrary input Execute the program Symbolically re-execute the program Negate the unexplored last path condition F T Is there an input satisfying constraint

  33. Interesting Example Concolic Testing foobar(int x, int y) { 1) if (x * x * x > 0) { 2) if (x>0 && y ==10) { 3) abort() ; } 4) } 5) else { 6) if (x > 0 && y == 20) { 7) abort ;} 8) } 9) }

  34. Pointers struct foo {int i; char c;} bar(struct foo *a) { 1) if (a->c == 0) { 2) *((char *)a + sizeof(int)) = 1 ; 3) if (a->c !=0) { 4) abort(); } } 5) }

  35. Loops 1) int i= 0; 2) while i < n { i = i + 1; } 3) if (n ==106) { 4) abort(); 5) }

  36. Handling External Calls 1) 2) 3) 4) 5) 6) 7) 8) FILE *fp; fp = fopen( test.txt", w"); if (fp) { struct stat buffer; if (stat ( text.txt , &buffer) != 0) { abort(); } }

  37. Concolic Testing Techniques Linear underapproximation Modeling System call models Simple heuristics Two possible values for pointers Efficient instrumentation Interface extraction Generating random inputs of arbitrary types

  38. Original DART Approach [PLDI05] Tailored for C Three types of functions Program functions External functions handled non-deterministically Library functions handled as black-box (concrete only)

  39. SAGE: Whitebox Fuzzing for Security Testing Check correctness of Win 7, Win 8 200+ machine years 1 Billion+ SMT constraints 100s of apps, 100s of bugs 1/3 of all Win7 WEX security bugs found Millions of dollars saved

  40. Summary Concolic testing is powerful Scaling is an issue Future progress in symbolic reasoning can help Example: handling dynamically allocated memory

Related


More Related Content