diff options
| author | Ben Harris <bjh21@bjh21.me.uk> | 2023-01-08 01:03:17 +0000 |
|---|---|---|
| committer | Ben Harris <bjh21@bjh21.me.uk> | 2023-01-12 22:21:45 +0000 |
| commit | 69924f376bd58932c7c3aa3234b9f12eb1866edc (patch) | |
| tree | b2167afcfe147608dc25c17df6bcfd1902e5f0aa /fuzzpuzz.c | |
| parent | 53a1faa0d758c86c5bc77808c4265129d627be1b (diff) | |
| download | puzzles-69924f376bd58932c7c3aa3234b9f12eb1866edc.zip puzzles-69924f376bd58932c7c3aa3234b9f12eb1866edc.tar.gz puzzles-69924f376bd58932c7c3aa3234b9f12eb1866edc.tar.bz2 puzzles-69924f376bd58932c7c3aa3234b9f12eb1866edc.tar.xz | |
AFL-specific shared-memory fuzzing mode
Rather than a save file from standard input and then exiting, this reads
it from a shared memory buffer and then loops. This makes fuzzing
_much_ faster: one core on my laptop can now load about 30,000 save
files per second.
Diffstat (limited to 'fuzzpuzz.c')
| -rw-r--r-- | fuzzpuzz.c | 71 |
1 files changed, 71 insertions, 0 deletions
@@ -16,6 +16,75 @@ #include "puzzles.h" +#ifdef __AFL_FUZZ_TESTCASE_LEN +/* + * AFL persistent mode, where we fuzz from a RAM buffer provided by + * AFL in a loop. This version can still be run standalone if + * necessary, for instance to diagnose a crash. + */ +#include <unistd.h> + +__AFL_FUZZ_INIT(); + +struct memfile { + unsigned char *buf; + int off; + int len; +}; + +static bool memfile_read(void *wctx, void *buf, int len) +{ + struct memfile *mem = (struct memfile *)wctx; + + if (mem->len - mem->off < len) return false; + memcpy(buf, mem->buf + mem->off, min(len, mem->len - mem->off)); + mem->off += len; + return true; +} + +int main(int argc, char **argv) +{ + const char *err; + char *gamename; + int i; + const game * ourgame = NULL; + midend *me; + struct memfile mem; + +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + + mem.buf = __AFL_FUZZ_TESTCASE_BUF; + while (__AFL_LOOP(10000)) { + + mem.off = 0; + mem.len = __AFL_FUZZ_TESTCASE_LEN; + + err = identify_game(&gamename, memfile_read, &mem); + if (err != NULL) continue; + + for (i = 0; i < gamecount; i++) + if (strcmp(gamename, gamelist[i]->name) == 0) + ourgame = gamelist[i]; + if (ourgame == NULL) continue; + + me = midend_new(NULL, ourgame, NULL, NULL); + + mem.off = 0; + + err = midend_deserialise(me, memfile_read, &mem); + midend_free(me); + } + return 0; +} + +#else + +/* + * Standard mode, where we process a single save file from stdin. + */ + static bool savefile_read(void *wctx, void *buf, int len) { FILE *fp = (FILE *)wctx; @@ -63,3 +132,5 @@ int main(int argc, char **argv) midend_free(me); return 0; } + +#endif |