Investigate a fuzzer-friendly serialization
http://llvm.org/devmtg/2017-10/slides/Serebryany-Structure-aware%20fuzzing%20for%20Clang%20and%20LLVM%20with%20libprotobuf-mutator.pdf https://github.com/google/libprotobuf-mutator
To some extent, we try to do this with DeepState_InputPath, seen here, which enables us to parse out a filename rather than read it out completely, and can be useful here when software under test consumes a filename input to create some type of structure.
/* .. what we can currently do in DeepState */
TEST(Test, SimpleMutationExample) {
const char * js_file = DeepState_InputPath();
JSObj *deser = ParseSourceToJS(js_file, ...);
ASSERT(deser.isValid() == 1);
deser.doStuff();
}
While this makes the framework kind of structure-aware, it's by no means as effective as using custom mutators with LLVM.
For improvements on the grammar/structure generation aspect of DeepState, we may want to take inspiration from binaryen and how it fuzzes WASM, where random AFL-generated input cases can act as seeds to a codegen routine (ie DeepState_Mutator), which then generates valid structured source in some shape or form.
/* .. what we may ideally want for better structure-awareness */
class MyMutator: DeepStateMutator {
using T = JSObj;
public:
/* some internal routine would store and parse a CFG */
std::string grammar_source("some_typeof_grammar.bnf");
/* once a structure is generated, user implements this to parse with library under test and validate it */
T ParseValidate() {}
private:
/* use DeepState input somehow as a sort-of RNG for how we will randomly recurse CFG. This
* would ideally be a default method in parent. */
void Map(unsigned char *seed, size_t max_size) {}
}
TEST(Test, BetterMutationExample) {
/* generates completely random input, assume no presence of dictionaries, etc. */
char *input = DeepState_C(input_size);
/* constructor would invoke all functionality of mutator, and return final deserialized object */
MyMutator m(input, source_size);
JSObj *deser = m.ParseValidate();
//ASSERT(deser.isValid() == 1);
deser.doStuff();
}