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

1

Symbolic Execution for Model Checking and Testing

Corina Păsăreanu (Kestrel)

Joint work with Sarfraz Khurshid (MIT) and Willem Visser (RIACS)

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

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.

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

3

Motivation

void Executive::startExecutive(){ runThreads(); …}void Executive::executePlan(…) { while(!empty) executeCurrentPlanNode();} …

Rover ExecutiveFuture 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

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

4

Our symbolic execution framework

Extends model checking • to programs that have complex inputs with unbounded (very large) dataAutomates 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

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

5

Symbolic Execution

Code:

(PC=“path condition”)

- “Simulate” the code using symbolic values instead of program numeric data

Symbolic execution tree: x:X,y:YPC: true

x:X,y:YPC: X>Y

x:X,y:YPC: X<=Y

true false

x:X+Y,y:YPC: X>Y

x:X+Y,y:XPC: X>Y

x:Y,y:XPC: X>Y

x:Y,y:XPC: X>Y Y-X>0

x:Y,y:XPC: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); }

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

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}

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

7

Generalized Symbolic Execution

E0

next

E1next

t

E2next

...

Code:

( = “unknown yet”)

E0next

E1next

t

E0

next

E1next

t

E2next

PC: E0-E1>0 PC: E0-E1<=0

truefalse

...

-“Simulate” the code using symbolic values instead of program numeric data.-Enumerate input structures lazily.

Symbolic execution tree:E0

nextPC: true

Precondition: acyclic list!

E0next

null E0next

E1next

E0

next ......

E0next

E1next

t

null E0next

E1next

t

E2next

E0next

E1

t next

E0next

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; } }

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

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

E0next

null

E0next

E1next

E0

next

E0next

E1next

null

E0next

E1next

E2next

E0next

E1

next

E0next

E1

next

Input list + Constraint Output list

E0>E1

none

E0≤E1

none

E0>E1

E0>E1

E0>E1

E1next

E0next

E2next

E1next

E0

next

E1next

E0

next

E1next

E0next

null

E0next

E1next

E0

next

E0next

null

Null pointer exception!

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

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:

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

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)

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

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; } }

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

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]

• ...

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

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

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

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; }}

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

15

Problem: convergence

Symbolic execution tree:

void test(int n) { int x = 0; while(x < n) x = x + 1; }

Code:n:SPC:true

n:S,x:0PC:true

n:S,x:1PC:0<S

n:S,x:0PC:0<S

n:S,x:0PC:0>=S

n:S,x:1PC:0<S & 1>=S

n:S,x:1PC:0<S & 1<S

....