241 likes | 770 Vues
Symbolic Execution and Program Testing. James C.King IBM Thomas J.Watson Research Center. Table of Contents. Introduction Symbolic Execution Examples Symbolic Execution Tree Examples An Interactive Symbolic Executor – EFFIGY Symbolic Execution and Program Testing Conclusion.
E N D
Symbolic Execution and Program Testing James C.King IBM Thomas J.Watson Research Center
Table of Contents • Introduction • Symbolic Execution • Examples • Symbolic Execution Tree • Examples • An Interactive Symbolic Executor – EFFIGY • Symbolic Execution and Program Testing • Conclusion
Introduction • Testing vs. Formal analysis • Testing • A programmer can be assured that sample test runs work correctly by checking the results • But the correct execution for inputs not in the sample is still in doubt • Formal analysis • Proving the correctness of programs by formal analysis shows great promise • Fundamental problems in reducing the theory to practice are not likely to be solved in the immediate future • So let’s take a practical approach between these two extremes – Symbolic Execution !
Symbolic Execution (1/8) • What is symbolic execution ? • Instead of supplying the normal inputs to a program, symbolic execution supplies symbols representing arbitrary values • ex) int f(1, 2) int f(α1 , α2) • The execution proceeds as in a normal execution except that values may be symbolic formulae over the input symbols • A program is symbolically executed for a set of classes of inputs, so each symbolic execution result may be equivalent to a large number of normal test cases
Symbolic Execution (2/8) Normal execution result of ADD(1,3,5) • Simple Example • Function ADD 1 : int ADD(int a, int b, int c) { 2 : int x = a + b; 3: int y = b + c; 4: int z = x + y – b; 5: return z; 6: } Symbolic execution result of ADD(α1, α2,α3)
Symbolic Execution (3/8) • Language syntax and the individual programs written in the language need not be changed • The only opportunity to introduce symbolic data is as input to the program • Assignment and Branch statement must be extended to handle symbolic values • Assignment statement • Right-hand side of the statement may be polynomial • Branch statement • Symbolic execution of the IF statement requires path condition(pc) • pc is a boolean expression over the symbolic input
Symbolic Execution (4/8) • IF statement (1/2) • The symbolic execution of an IF statement begins in a fashion similar to its normal execution • Since the values of variables are polynomial, the condition is an expression of the form: R ≥ 0, where R is a polynomial • Path Condition • Initial value of pc is true • Using the current path condition(pc), we have two following expressions • (a) pcq (q is a condition expression) (b) pc ~q
Symbolic Execution (5/8) • IF statement (2/2) • nonforking execution (either of expression is true) • In case that (a) is true, pass control to THEN part In case that (b) is true, pass control to ELSE part • forking execution (neither expressions are true) • Since each alternative is possible in this case, the only complete approach is to explore both control paths • In choosing THEN alternative, the inputs are assumed to satisfy q, this information is recorded in pc by doing assignment pc:= pc ∧ q • Similarly choosing the ELSE alternative leads to pc:= pc ∧ ~q
Symbolic Execution (6/8) • Example • Function POWER(x, y) 1: int POWER(x, y) 2: { 3: int z = 1; 4: int j = 1; 5: while ( y ≥ j ) 6: { 7: z = z * x; 8: j++; 9: } 10: return z; 11: }
Symbolic Execution (7/8) • Example • Function POWER(x, y) 1: int POWER(x, y) 2: { 3: int z = 1; 4: int j = 1; 5: while ( y ≥ j ) 6: { 7: z = z * x; 8: j++; 9: } 10: return z; 11: }
Symbolic Execution (8/8) • Commutativity • The result which is computed by normal execution with specific integer inputs is same as executing the program symbolically and then instantiating the symbolic result • ex) • Normal execution • ADD(3, 5) = 8 • Symbolic execution • ADD(α1, α2) = α1 + α2 • Instantiate the symbolic result α1 = 3, α2 = 5 3 + 5 = 8
Symbolic Execution Tree (1/3) • We can generate symbolic execution tree characterizing the execution paths followed during the symbolic execution • Associate a node with each statement executed • Associate a directed arc connecting the associated nodes with each transition between statements • For IF statement execution, the associated node has two arcs leaving the node which are labeled “T” and “F” for the true and false part, respectively • Associate the complete current execution state, i.e. variable values, statement counter, and pc with each node
Symbolic Execution Tree (2/3) • Example • Function POWER(x, y) 1 2 3 1: int POWER(x, y) 2: { 3: int z = 1; 4: int j = 1; 5: while ( y ≥ j ) 6: { 7: z = z * x; 8: j++; 9: } 10: return z; 11: } 4 F Case pc is (α2<1) : return 1 5 10 11 T 6 7 8 9 F Case pc is (α2= 1) : return α1 5 10 11 T 6
Symbolic Execution Tree (3/3) • Properties • For each terminal leaf in the symbolic execution tree there exists a particular nonsymbolic input to the program • pc’s associated with any two terminal leaves are distinct • ex) F pc is ~(α1 > 5) return 0 1 3 4 1: if (x > 5) 2: return 1 3: else 4: return 0 T 2 pc is α1 > 5 return 1
An Interactive Symbolic Executer – EFFIGY (1/2) • EFFIGY (1/2) • Debugger for symbolic program execution • Basic debugging and testing facilities are provided for symbolic program execution • EFFIGY treats normal execution as a special case • Interactive debugging facilities are available, including: • Tracing • The user can request to see the statement number, the computational results • Breakpoints • The user can insert breakpoints before or after any statement • State saving • SAVE, RESTORE
An Interactive Symbolic Executer – EFFIGY (2/2) • EFFIGY (2/2) • Testing facilities • Test manager • Test manager is available for exploring the alternatives presented in the symbolic execution tree • Program verifier • Check if the program is running correctly • ASSUME(P) • pc := pc∧ P • PROVE(P) • Check if pc P is true
Symbolic Execution and Program Testing (1/2) • To prove the correctness of a program, the programmer supplies an input predicate and an output predicate with the program • The program is correct if for all inputs which satisfy the input predicate the results produced by the program satisfy the output predicate
Symbolic Execution and Program Testing (2/2) • We can prove the correctness of each path by executing it symbolically as follows: • Place ASSUME at the beginning of the path and PROVE at the end of the path • Execute the path symbolically • If the PROVE at the end of the path displays true, the path is correct, otherwise it is not
Conclusion • Symbolic execution offers the advantage that one symbolic execution may represent a large class of normal executions • EFFIGY system embodies symbolic execution in a general purpose interactive debugging system • Test manager and program verifier are powerful for program testing