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.
GCC warns about that character sequence in a comment. I shouldn't have
assumed that having only edited a comment meant I could get away without
a test build.
There's now a function, fuzz_one(), that processes a single save file,
and main() arranges to call this a suitable number of times depending
on whether we're in AFL persistent mode or not. This makes things a
bit cleaner, and will probably make adding good support for other
fuzzers, or just switching entirely to the horrible but popular
libFuzzer interface, simpler.
Now if the input save file loads correctly, fuzzpuzz asks the back-end
to draw the puzzle. All the drawing operations are no-ops, but this
tests the drawing code in the back-end.
When reporting that the game name in a save file isn't recognised,
don't include the name from the save file in the error message, partly
to avoid the complexity of freeing it properly on two different code
paths and partly because including unsanitized data from a
fuzzer-supplied save file in the error message just seems dangerous.
And properly sanitising it would waste the fuzzer's time exploring the
sanitising code.
Thanks to Ben Hutchings for reporting the bug.
Now there's a single version of the main loop that runs once in normal
mode and repeatedly in AFL++ persistent mode. In persistent mode,
fmemopen() allows the loop to read the shared-memory buffer as though
it were a stdio stream. fmemopen() is POSIX-only, but so is AFL++.
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.