130 likes | 271 Vues
This project presents concolic testing as a powerful white-box technique that improves upon traditional random testing by dynamically observing program inputs during execution. By generating new inputs to traverse different execution paths, concolic testing enhances the detection of program correctness, abstraction violations, and implementation dependencies. The project showcases practical examples, including managing dynamic memory and enforcing type constraints, highlighting how such techniques effectively reduce error occurrences and enhance modularity in software systems.
E N D
Concolic Modularity Testing Derrick Coetzee University of California, Berkeley CS 265 Final Project Presentation
Concolic Testing • A white-box improvement on random testing • Observe how inputs are used at runtime • Compute new inputs designed to force program to execute a different path • Effective in testing program correctness on a variety of inputs
More than correctness • Analogy with type systems: • Some types prevent bad inputs • Some types prevent abstraction violations • Can concolic testing also detect abstraction violations? • Detect implementation dependence • Find portability issues • Help enforce modularity
Detect implementation dependence • Forgetting to check for error return codes • e.g. Assuming malloc() never returns NULL • Relying on the behavior of a particular implementation • e.g. Assuming result of malloc() is always word-aligned • Not coping with improbable events • e.g. Assuming hash functions always return distinct values on distinct inputs.
A simple approach • Introduce a new symbolic variable whenever the function is invoked • Depending on its value, modify the result void* my_malloc(size_t size) { void* result = malloc(size); intsimulate_out_of_memory; CREST_int(simulate_out_of_memory); if (simulate_out_of_memory) { result = NULL; } return result; }
A simple approach • Doesn’t always work • May lead to an infeasible sequence of results intmy_hash(char* s) { int result; CREST_int(result); return result; } my_hash("hello") → 0 /* OK */ my_hash("world") → 0 /* OK */ my_hash("hello") → 1 /* Not OK */
Generalizing the approach • In general, the behavior of functions is constrained by their specification • e.g. Hash functions must be pure • With concolic testing, invariants can be enforced directly in the source language • e.g. By adding an input/output history
Generalizing the approach string_int_maphistory; intmy_hash(char* s) { if (contains_key(history, s)) { return lookup(history, s); } else { int result; CREST_int(result); add_pair(history, s, result); return result; } }
A more complex example • A sort function invokes a comparator (≤,=) • Comparator is constrained to be a total order • a = a • if a = b then b = a • if a = b and b = c then a = c • if a ≤ b and b ≤ a then a = b • if a ≤ b and b ≤ c then a ≤ c • Can use input/output history to enforce all these properties in the source language
Liveness properties • Specifications may constrain sequences of operations • e.g. if malloc() returns NULL, it will continue to return NULL for arguments of the same size or larger until free() is called • Easy to support by maintaining state across calls • May even help reduce the search space
Experiments: malloc test • Took the CREST grep 2.2 example • Instrumented all malloc() calls • Possibly return NULL • CREST enumerated 5621 tests • 2 were real bugs • Adding the liveness constraint: • Reduced the number of tests to 2869 (49% less) • Still found the 2 bugs
Experiments: sort • Selection sort using a comparator function • The comparator was constrained only to represent a total order • For a list of 5 elements, CREST enumerated 541 different comparators • If any of the constraints are removed, CREST finds an explicit comparator function that causes the sort to fail
Experiments: hash • grep 2.2 uses an internal hash function for fast state matching • Constrained hash function only to be pure • Enumerated 1472 tests on test input • grep was robust against hash collisions • Removing pure constraint did not produce errors but produced extra states