Merge the two versions of fuzzpuzz back together

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++.
This commit is contained in:
Ben Harris
2023-01-12 10:12:26 +00:00
parent 69924f376b
commit 311d227ba6

View File

@ -13,78 +13,16 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __AFL_FUZZ_TESTCASE_LEN
# include <unistd.h> /* read() is used by __AFL_FUZZ_TESTCASE_LEN. */
#endif
#include "puzzles.h" #include "puzzles.h"
#ifdef __AFL_FUZZ_TESTCASE_LEN #ifdef __AFL_FUZZ_INIT
/*
* 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(); __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 #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) static bool savefile_read(void *wctx, void *buf, int len)
{ {
FILE *fp = (FILE *)wctx; FILE *fp = (FILE *)wctx;
@ -98,39 +36,66 @@ int main(int argc, char **argv)
{ {
const char *err; const char *err;
char *gamename; char *gamename;
int i; int i, ret = -1;
const game * ourgame = NULL; const game *ourgame = NULL;
midend *me; midend *me;
FILE *in = NULL;
if (argc != 1) { if (argc != 1) {
fprintf(stderr, "usage: %s\n", argv[0]); fprintf(stderr, "usage: %s\n", argv[0]);
exit(1); exit(1);
} }
err = identify_game(&gamename, savefile_read, stdin); #ifdef __AFL_HAVE_MANUAL_CONTROL
if (err != NULL) { __AFL_INIT();
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;
}
#endif #endif
#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.
*/
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;
}
#else
in = stdin;
while (ret == -1) {
#endif
err = identify_game(&gamename, savefile_read, in);
if (err != NULL) {
fprintf(stderr, "%s\n", err);
ret = 1;
continue;
}
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);
ret = 1;
continue;
}
me = midend_new(NULL, ourgame, NULL, NULL);
rewind(in);
err = midend_deserialise(me, savefile_read, in);
if (err != NULL) {
fprintf(stderr, "%s\n", err);
ret = 1;
continue;
}
midend_free(me);
ret = 0;
}
return ret;
}