Universal Symbolic Execution and Its Application to Likely Data Structure Invariant Generation

Universal Symbolic Execution and Its Application to Likely Data Structure Invariant Generation

Universal Symbolic Execution and its Application to Likely Data Structure Invariant Generation Yamini Kannan Koushik Sen EECS, UC Berkeley EECS, UC Berkeley [email protected] [email protected] ABSTRACT a large class of data structures [19]. This paper explores a novel We consider the problem of automatically inferring likely program technique, called KRYSTAL, to infer likely local data structure in- invariants from execution traces. In this paper, we focus on in- variants using a variant of symbolic execution [15, 3, 4, 27, 14, 26, ference of invariants that hold over data structures in the program. 16, 29], called universal symbolic execution. Properties of data structures can be specified by means of local ax- There are three important contributions of this work. First, we ioms asserted over a bounded fragment of a data structure around propose universal symbolic execution, that helps us to symbolically a memory cell. These include predicates over scalar fields, pointer track data flow for all memory locations along an execution even if equalities, and pointer disequalities. It has been shown that such lo- input values do not flow directly into those memory locations. In cal invariants are both natural and sufficient for describing a large universal symbolic execution, we execute a program concretely on class of data structures. This paper explores a novel technique, test inputs, while simultaneously performing symbolic execution of the program. However, unlike traditional symbolic execution, we called KRYSTAL, to infer likely local data structure invariants us- ing a variant of symbolic execution, called universal symbolic ex- create a fresh symbolic variable for every read of a lvalue that has ecution. Universal symbolic execution is like traditional symbolic no mapping in the symbolic state rather than creating a symbolic execution except the fact that we create a fresh symbolic variable variable only for inputs. For example, universal symbolic execu- for every read of a lvalue that has no mapping in the symbolic state tion of the following code rather than creating a symbolic variable only for inputs. This helps x = 1; universal symbolic execution to symbolically track data flow for all y = x + 1; memory locations along an execution even if input values do not z = x − 1; flow directly into those memory locations. We have implemented creates a symbolic memory where x maps to a fresh symbolic vari- our algorithm and applied it to several data structure implementa- able, say x0, y maps to x0 + 1, and z maps to x0 − 1. Note that tions in Java. Our experimental results show that we can infer many we have introduced a symbolic variable x0 despite the fact that the interesting local invariants for these data structures. code has no input. In contrast, traditional symbolic execution of Categories and Subject Descriptors: D.2.4 [Software Engi- the code creates a memory map where x maps to 1, y maps to 2, neering]: Software/Program Verification, D.2.5 [Software Engi- and z maps to 0. The advantage of universal symbolic execution is neering]: Testing and Debugging that now we can relate y and z by simply looking at the symbolic General Terms: Reliability, Design, Documentation memory, i.e. we can infer y − 1 = z + 1. This crucial observa- Keywords: Program invariants, symbolic execution, dynamic tion is central to our invariant generation algorithm. Specifically, analysis, execution traces, logical inference. we use symbolic memory maps and symbolic path conditions and equate the symbolic variables present in them to generate symbolic relations among various memory cells. 1. INTRODUCTION Second, we show how the results of universal symbolic execu- Local data structure invariants are an important class of invari- tion can be refined and generalized to generate likely local data ants that can express interesting properties of data structures. An structure invariants. Specifically, universal symbolic execution of a example of such an invariant for a sorted doubly-linked list is “for program on a test input generates a symbolic memory and a set of all nodes M of the list, if M 6= null and M:next 6= null, then path conditions, where the symbolic memory is a map from pro- M:next:prev = M and M:value ≤ M:next:value.” Such proper- gram addresses to symbolic expressions and each path condition is ties are asserted over a bounded fragment of a data structure around a symbolic predicate generated by the execution of a conditional a distinguished node M of the data structure. It has been shown that statement. The symbolic memory and the path condition set are such local invariants are both natural and sufficient for describing then used to generate a set of symbolic predicates that hold along the test execution. Subsequently, local predicates, i.e. predicates involving a single symbolic variable, are derived from the set of predicates through variable elimination. These local predicates are Permission to make digital or hard copies of all or part of this work for then generalized and simplified across all test executions to infer personal or classroom use is granted without fee provided that copies are a set of likely local invariant templates. The templates that hold not made or distributed for profit or commercial advantage and that copies on all nodes of the data structure along all test executions are then bear this notice and the full citation on the first page. To copy otherwise, to output as likely local data structure invariants. republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Third, we evaluate KRYSTAL on a number of data structure im- ISSTA’08, July 20–24, 2008, Seattle, Washington, USA. plementations in Java. Our experimental results are encouraging. Copyright 2008 ACM 978-1-59593-904-3/08/07 ...$5.00. class NODE { int key; // data field int depth; // depth of the node from the root 3#4&5&67 !"#$%&'!"#$%& Node left, right, parent; 0$!&, 5&7 ($)&'!"#$%& } #*+,&'!"#$%& -.// class BINARYSEARCHTREE { '()&*+&,#-"..".-& NODE root; /!&#0#12+"/. void INSERT(int data){ `0:NODE node = new NODE(); : node.key = data; `1 3#4&5&67 3#4&5&67 ` : node.left = node.right = node.parent= null; 2 0$!&, 5&7 0$!&, 5&7 `3: if (root == null) { `4: root = node; node.depth = 0; return;} 3#4&5&< 3#4&5&< 3#4&5&6< `5:NODE current = root; 0$!&, 5&6 0$!&, 5&6 0$!&, 5&6 `6: if (current.key < data) `7: if (current.right == null) { ` : current.right = node; goto l ;} 8 15 80*9:$#&6;& 80*9:$#&=;& else { // loop again '()&*+&8.%&/!&#0#12+"/. '()&*+&8.%&/!&#0#12+"/. `9: current = current.right; goto l6;} `10: if (current.key > data) Figure 3: Structure of the binary search tree at the beginning `11: if (current.left == null) { and end of a test execution `12: current.left = node; goto l15;} else { // loop again `13: current = current.left; goto l6;} 1.K RYSTAL assumes that there is a test harness and a set of ` : return; //data already present in the tree 14 test inputs for the given data structure. KRYSTAL performs a ` : node.parent = current; 15 variant of symbolic execution, called universal symbolic exe- `16: node.depth = current.depth + 1; } cution, along each test execution path to compute a symbolic } memory and a symbolic path condition set. Figure 1: Binary search tree and insert class BSTHARNESS { 2.K RYSTAL uses the symbolic memory and the symbolic path static BINARYSEARCHTREE bst condition set to generate a set of local symbolic predicates, = new BINARYSEARCHTREE(); i.e. a set of predicates each of which is an expression over a public static void TESTBST(int input){ single symbolic variable. A local symbolic predicate in the bst.INSERT(input); set represents a local property that holds over a specific data } } structure node along the test execution. Figure 2: Test harness for the binary search tree 3.K RYSTAL simplifies “similar” (defined in Section 3.4) local predicates in the set by taking conjunctions of similar local predicates. The simplified local predicates are then used to We show that KRYSTAL can infer interesting local invariants for generate local invariant templates. A local invariant template these data structures in a few seconds. We also argue that many of denotes a predicate that could potentially hold on any node these invariants cannot be inferred by existing techniques. in the data structure. 2. OVERVIEW 4.K RYSTAL collects local invariant templates across test ex- We informally present KRYSTAL on a binary search tree example ecutions and further simplifies them by taking disjunctions shown in Figure 1. The example defines two classes NODE and of “similar” (defined in Section 3.4) templates. The resul- BINARYSEARCHTREE and the method INSERT. An instance of tant templates are then relaxed by incorporating implicit con- the class BINARYSEARCHTREE holds a reference to the root of a straints (such as dereferencing a null object is illegal.) Col- binary search tree. The nodes of the tree are instances of the class lecting templates across executions helps to ensure that the NODE. The INSERT method takes as input an integer data, creates set of templates contains all potential local data structure in- a new node for data, and computes the correct position for node variants. in the tree. If data is absent from the tree, INSERT adds the node 5.K RYSTAL then validates each template, by checking if it into the tree by setting fields in appropriate nodes. The class NODE holds on every node of the data structure at the end of each defines a field depth that holds the current depth of the node from test execution. The templates that hold for all nodes along the root node in the tree.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    11 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us