From 53a1faa0d758c86c5bc77808c4265129d627be1b Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 7 Jan 2023 18:57:48 +0000 Subject: [PATCH] Add a fuzzing harness for Puzzles This just feeds save files into the loading code, but because of how Puzzles is structured that actually exercises most of its parsers. --- CMakeLists.txt | 5 ++++ fuzzpuzz.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 fuzzpuzz.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e8d96f..5e7992c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,4 +275,9 @@ cliprogram(penrose-vector-test penrose.c COMPILE_DEFINITIONS TEST_VECTORS) cliprogram(sort-test sort.c COMPILE_DEFINITIONS SORT_TEST) cliprogram(tree234-test tree234.c COMPILE_DEFINITIONS TEST) +write_generated_games_header() +cliprogram(fuzzpuzz fuzzpuzz.c list.c ${puzzle_sources} + COMPILE_DEFINITIONS COMBINED) +target_include_directories(fuzzpuzz PRIVATE ${generated_include_dir}) + build_extras() diff --git a/fuzzpuzz.c b/fuzzpuzz.c new file mode 100644 index 0000000..4ee523f --- /dev/null +++ b/fuzzpuzz.c @@ -0,0 +1,65 @@ +/* + * fuzzpuzz.c: Fuzzing frontend to all puzzles. + */ + +/* + * The idea here is that this front-end supports all back-ends and can + * feed them save files. This tests the deserialiser, the code for + * loading game descriptions, and the processing of move strings, + * without all the tedium of actually rendering anything. + */ + +#include +#include +#include +#include + +#include "puzzles.h" + +static bool savefile_read(void *wctx, void *buf, int len) +{ + FILE *fp = (FILE *)wctx; + int ret; + + ret = fread(buf, 1, len, fp); + return (ret == len); +} + +int main(int argc, char **argv) +{ + const char *err; + char *gamename; + int i; + const game * ourgame = NULL; + midend *me; + + if (argc != 1) { + fprintf(stderr, "usage: %s\n", argv[0]); + exit(1); + } + + err = identify_game(&gamename, savefile_read, stdin); + if (err != NULL) { + fprintf(stderr, "%s\n", err); + exit(1); + } + + for (i = 0; i < gamecount; i++) + if (strcmp(gamename, gamelist[i]->name) == 0) + ourgame = gamelist[i]; + if (ourgame == NULL) { + fprintf(stderr, "Game '%s' not recognised\n", gamename); + exit(1); + } + + me = midend_new(NULL, ourgame, NULL, NULL); + + rewind(stdin); + err = midend_deserialise(me, savefile_read, stdin); + if (err != NULL) { + fprintf(stderr, "%s\n", err); + exit(1); + } + midend_free(me); + return 0; +}