shithub: puzzles

Download patch

ref: 150c05a2989ec5e50768718686c2c997b95af0df
parent: b107decdaf7a49e3cc4b6f6f37c004cd8e2b5119
author: Ben Harris <bjh21@bjh21.me.uk>
date: Sat Feb 18 06:59:08 EST 2023

Support Honggfuzz's persistent mode in fuzzpuzz

Unlike AFL, Honggfuzz's compiler wrapper doesn't provide a convenient
preprocessor macro, so we have to have CMake detect the existence of
HF_ITER.  Also the resulting program can't run outside of Honggfuzz, so
maybe some additional cleverness is called for there as well.  Still, it
makes Honggfuzz go ten times faster, which is nice.

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -275,10 +275,15 @@
 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)
 if(build_cli_programs)
+  write_generated_games_header()
+  include(CheckFunctionExists)
+  check_function_exists(HF_ITER HAVE_HF_ITER)
+  if(HAVE_HF_ITER)
+    add_definitions(-DHAVE_HF_ITER)
+  endif()
+  cliprogram(fuzzpuzz fuzzpuzz.c list.c ${puzzle_sources}
+    COMPILE_DEFINITIONS COMBINED)
   target_include_directories(fuzzpuzz PRIVATE ${generated_include_dir})
 endif()
 
--- a/fuzzpuzz.c
+++ b/fuzzpuzz.c
@@ -16,6 +16,13 @@
  * cmake --build build-afl --target fuzzpuzz
  * mkdir fuzz-in && ln icons/''*.sav fuzz-in
  * afl-fuzz -i fuzz-in -o fuzz-out -x fuzzpuzz.dict -- build-afl/fuzzpuzz
+ *
+ * Similarly with Honggfuzz:
+ *
+ * CC=hfuzz-cc cmake -B build-honggfuzz
+ * cmake --build build-honggfuzz --target fuzzpuzz
+ * mkdir fuzz-corpus && ln icons/''*.sav fuzz-corpus
+ * honggfuzz -s -i fuzz-corpus -w fuzzpuzz.dict -- build-honggfuzz/fuzzpuzz
  */
 
 #include <stdbool.h>
@@ -32,6 +39,10 @@
 __AFL_FUZZ_INIT();
 #endif
 
+#ifdef HAVE_HF_ITER
+extern int HF_ITER(unsigned char **, size_t *);
+#endif
+
 static const char *fuzz_one(bool (*readfn)(void *, void *, int), void *rctx,
                             void (*rewindfn)(void *),
                             void (*writefn)(void *, const void *, int),
@@ -118,6 +129,22 @@
     while (__AFL_LOOP(10000)) {
         if (in != NULL) fclose(in);
         in = fmemopen(__AFL_FUZZ_TESTCASE_BUF, __AFL_FUZZ_TESTCASE_LEN, "r");
+        if (in == NULL) {
+            fprintf(stderr, "fmemopen failed");
+            ret = 1;
+            continue;
+        }
+#elif defined(HAVE_HF_ITER)
+    /*
+     * Honggfuzz persistent mode.  Unlike AFL persistent mode, the
+     * resulting executable cannot be run outside of Honggfuzz.
+     */
+    while (true) {
+        unsigned char *testcase_buf;
+        size_t testcase_len;
+        if (in != NULL) fclose(in);
+        HF_ITER(&testcase_buf, &testcase_len);
+        in = fmemopen(testcase_buf, testcase_len, "r");
         if (in == NULL) {
             fprintf(stderr, "fmemopen failed");
             ret = 1;