Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)

Similar presentations


Presentation on theme: "1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)"— Presentation transcript:

1 1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)

2 2 Paper Khurshid, S., Pasareanu, C.S., and Vissser, W., “Generalized Symbolic Execution for Model Checking and Testing”, in Proc. of the 9th International Conference on Tools and Algorithms for the Construction and Analysis of Systems (TACAS 2003). April 2003, Warsaw, Poland.

3 3 Motivation void Executive:: startExecutive(){ runThreads(); …} void Executive:: executePlan(…) { while(!empty) executeCurrentPlanNode(); } … Rover Executive Future mission software: - concurrent - complex, dynamically allocated data structures (e.g., lists or trees) - highly interactive: - with complex inputs - large environment - should be extremely reliable Input plan complex input structure concurrency, dynamic data (lists, trees) execute action environment/ rover status Current practice in checking complex software: large environment data Mars Rover Testing: - requires manual input - typically done for a few nominal input cases - not good at finding concurrency bugs - not good at dealing with complex data structures Model checking: - automatic, good at finding concurrency bugs - not good at dealing with complex data structures - feasible only with a small environment - and a small set of input values

4 4 Our symbolic execution framework Extends model checking to programs that have complex inputs with unbounded (very large) data Automates test input generation Provides: A novel symbolic execution algorithm Handles dynamic data (e.g., lists and trees), concurrency Uses lazy initialization: –Initializes the components of the program’s inputs on an ``as-needed'' basis –No a priori bound on input sizes –Uses preconditions to initialize inputs only with valid values A source to source translation to instrument a program Enables standard model checkers to perform symbolic execution of the program Uses “off-the-shelf” decision procedures

5 5 Symbolic Execution Code: (PC=“path condition”) - “Simulate” the code using symbolic values instead of program numeric data Symbolic execution tree: x:X,y:Y PC: true x:X,y:Y PC: X>Y x:X,y:Y PC: X<=Y true false x:X+Y,y:Y PC: X>Y x:X+Y,y:X PC: X>Y x:Y,y:X PC: X>Y x:Y,y:X PC: X>Y  Y-X>0 x:Y,y:X PC:X>Y  Y-X<=0 true false FALSE! Not reachable int x, y; if (x > y) { x = x + y; y = x - y; x = x - y; if (x – y > 0) assert (false); }

6 6 Algorithm: Lazy Initialization To symbolically execute method m of class C: create a new object, o, of class C set all its fields to uninitialized values invoke o.m() when m accesses field f if (f is uninitialized) { if (f is reference field of type T) { non-deterministically initialize f to –null –a new object of class T (with un-initialized field values) –a previously initialized object of class T } if (f is numeric (string) field) initialize f to a new symbolic value }

7 7 Generalized Symbolic Execution E0 next E1 next t E2 next... Code: ( = “unknown yet”) E0 next E1 next t E0 next E1 next t E2 next PC: E0-E1>0PC: E0-E1<=0 truefalse... -“Simulate” the code using symbolic values instead of program numeric data. -Enumerate input structures lazily. Symbolic execution tree: E0 next PC: true Precondition: acyclic list! E0 next null E0 next E1 next E0 next... E0 next E1 next t null E0 next E1 next t E2 next E0 next E1 tnext E0 next E1 next t... class Node { int elem; Node next; Node swapNode() { if (next != null) if (elem – next.elem > 0) { Node t = next; next = t.next; t.next = this; return t; } return this; } }

8 8 class Node { int elem; Node next; Node swapNode() { if (next != null) if (elem – next.elem > 0) { Node t = next; next = t.next; t.next = this; return t; } return this; } } Code: Results of Analysis E0 next null E0 next E1 next E0 next E0 next E1 next null E0 next E1 next E2 next E0 next E1 next E0 next E1 next Input list +ConstraintOutput list E0>E1 none E0≤E1 none E0>E1 E1 next E0 next E2 next E1 next E0 next E1 next E0 next E1 next E0 next null E0 next E1 next E0 next E0 next null Null pointer exception!

9 9 Framework Model checking Program instrumentation Decision procedures Instrumented program Correctness specification continue/ backtrack Counterexample(s)/ test suite [heap+constraint+thread scheduling] Source program Path condition (data) Heap configuration Thread scheduling State:

10 10 Implementation for Java Uses Korat (MIT) for program instrumentation Uses Java PathFinder model checker toolset Uses Omega library as a decision procedure –for integer linear constraints Framework: Can be used as a symbolic execution tool with backtracking –Handles multithreaded programs No state matching –Un-decidable in general Good for finding counter-examples to safety properties –Programs with loops can have infinite execution trees –Uses breadth first search or depth first search with limited depth Used to –check for null pointer exceptions, rich properties in multithreaded programs –generate test inputs for code coverage of an Altitude Switch used in flight control software (~ 2000 Java lines)

11 11 Code Instrumentation Code: class Expression { static PathCondition _pc; Expression_minus(Expression e) { … } } class PathCondition { … Constraints c; boolean _updateGT (Expression e1, Expression e2) { boolean result = choose_boolean(); if (result) c.add_constraintGT(e1,e2)); else c.add_constraintLE(e1,e2)); if (! c.is_satisfiable()) backtrack(); return result; } class Node { Expression elem; boolean _elem_is_initialized; Node next; boolean _next_is_initialized; Node swapNode() { if (_get_next() != null) if (Expression._pc._updateGT(_get_elem()._minus(_get_next(). _get_elem() ), new IntegerConstant(0) ) { Node t = _get_next() ; _set_next (t._get_next() ); t._set_next (this); return t; } return this; } } class Node { int elem; Node next; Node swapNode() { if (next != null) if (elem – next.elem > 0) { Node t = next; next = t.next; t.next = this; return t; } return this; } }

12 12 Related work Symbolic execution and program testing –EFFIGY [King’76] Static analysis –ESC [Detlefs et al’98] –TVLA [Sagiv et al’98] Software model checking –VeriSoft [Godefroid’97] –JPF [Visser et al’00] –Bandera (KSU), SLAM (Microsoft) Specification-based testing –Korat [ISSTA ’02]...

13 13 Conclusions Framework for symbolic execution –Handles dynamic data and concurrency –Program instrumentation enables any model checker to perform symbolic execution –Used for checking rich properties of multithreaded programs with complex inputs and for test input generation Future work: –Investigate Widening and abstraction techniques to help termination Different decision procedures and constraint solvers (to handle non-linear constraints and floats) –Case studies

14 14 Demo class List { Node header; static class Node { int elem; Node next; } void swap2() { // swaps the first two nodes if (header == null) return; if (header.next == null) return; Node t = header; header = header.next; t.next = t.next.next; header.next = t; }

15 15 Problem: convergence Symbolic execution tree: void test(int n) { int x = 0; while(x < n) x = x + 1; } Code: n:S PC:true n:S,x:0 PC:true n:S,x:1 PC:0<S n:S,x:0 PC:0<S n:S,x:0 PC:0>=S n:S,x:1 PC:0 =S n:S,x:1 PC:0<S & 1<S....


Download ppt "1 Symbolic Execution for Model Checking and Testing Corina Păsăreanu (Kestrel) Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)"

Similar presentations


Ads by Google