shithub: puzzles

Download patch

ref: 69924f376bd58932c7c3aa3234b9f12eb1866edc
parent: 53a1faa0d758c86c5bc77808c4265129d627be1b
author: Ben Harris <bjh21@bjh21.me.uk>
date: Sat Jan 7 20:03:17 EST 2023

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.

--- a/fuzzpuzz.c
+++ b/fuzzpuzz.c
@@ -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 @@
     midend_free(me);
     return 0;
 }
+
+#endif