aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c4
-rw-r--r--src/afl-as.c2
-rw-r--r--src/afl-cc.c267
-rw-r--r--src/afl-common.c4
-rw-r--r--src/afl-forkserver.c163
-rw-r--r--src/afl-fuzz-bitmap.c75
-rw-r--r--src/afl-fuzz-init.c27
-rw-r--r--src/afl-fuzz-mutators.c80
-rw-r--r--src/afl-fuzz-one.c18
-rw-r--r--src/afl-fuzz-python.c39
-rw-r--r--src/afl-fuzz-queue.c86
-rw-r--r--src/afl-fuzz-run.c5
-rw-r--r--src/afl-fuzz-state.c9
-rw-r--r--src/afl-fuzz.c46
-rw-r--r--src/afl-ld-lto.c18
-rw-r--r--src/afl-sharedmem.c28
-rw-r--r--src/afl-showmap.c29
-rw-r--r--src/afl-tmin.c32
18 files changed, 676 insertions, 256 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index c8acebb3..2780deff 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -78,9 +78,9 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
static s32 dev_null_fd = -1; /* FD to /dev/null */
-static u8 edges_only, /* Ignore hit counts? */
+static bool edges_only, /* Ignore hit counts? */
use_hex_offsets, /* Show hex offsets? */
- use_stdin = 1; /* Use stdin for program input? */
+ use_stdin = true; /* Use stdin for program input? */
static volatile u8 stop_soon, /* Ctrl-C pressed? */
child_timed_out; /* Child timed out? */
diff --git a/src/afl-as.c b/src/afl-as.c
index 7d70bfcd..3d6f7d5e 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -27,7 +27,7 @@
utility has right now is to be able to skip them gracefully and allow the
compilation process to continue.
- That said, see examples/clang_asm_normalize/ for a solution that may
+ That said, see utils/clang_asm_normalize/ for a solution that may
allow clang users to make things work even with hand-crafted assembly. Just
note that there is no equivalent for GCC.
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 19dc9a6a..c43ac2c1 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -48,6 +48,7 @@
static u8 * obj_path; /* Path to runtime libraries */
static u8 **cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
+static u8 clang_mode; /* Invoked as afl-clang*? */
static u8 llvm_fullpath[PATH_MAX];
static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
static u8 compiler_mode, plusplus_mode, have_instr_env = 0;
@@ -105,7 +106,24 @@ u8 *getthecwd() {
}
-/* Try to find the runtime libraries. If that fails, abort. */
+/* Try to find a specific runtime we need, returns NULL on fail. */
+
+/*
+ in find_object() we look here:
+
+ 1. if obj_path is already set we look there first
+ 2. then we check the $AFL_PATH environment variable location if set
+ 3. next we check argv[0] if it has path information and use it
+ a) we also check ../lib/afl
+ 4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and
+ FreeBSD with procfs)
+ a) and check here in ../lib/afl too
+ 5. we look into the AFL_PATH define (usually /usr/local/lib/afl)
+ 6. we finally try the current directory
+
+ if all these attempts fail - we return NULL and the caller has to decide
+ what to do.
+*/
static u8 *find_object(u8 *obj, u8 *argv0) {
@@ -114,11 +132,9 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
if (afl_path) {
-#ifdef __ANDROID__
tmp = alloc_printf("%s/%s", afl_path, obj);
-#else
- tmp = alloc_printf("%s/%s", afl_path, obj);
-#endif
+
+ if (debug) DEBUGF("Trying %s\n", tmp);
if (!access(tmp, R_OK)) {
@@ -131,125 +147,139 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
}
- if (argv0) slash = strrchr(argv0, '/');
+ if (argv0) {
- if (slash) {
+ slash = strrchr(argv0, '/');
- u8 *dir;
+ if (slash) {
- *slash = 0;
- dir = ck_strdup(argv0);
- *slash = '/';
+ u8 *dir = ck_strdup(argv0);
-#ifdef __ANDROID__
- tmp = alloc_printf("%s/%s", dir, obj);
-#else
- tmp = alloc_printf("%s/%s", dir, obj);
-#endif
+ slash = strrchr(dir, '/');
+ *slash = 0;
- if (!access(tmp, R_OK)) {
+ tmp = alloc_printf("%s/%s", dir, obj);
- obj_path = dir;
- return tmp;
-
- }
+ if (debug) DEBUGF("Trying %s\n", tmp);
- ck_free(tmp);
- ck_free(dir);
+ if (!access(tmp, R_OK)) {
- }
+ obj_path = dir;
+ return tmp;
- tmp = alloc_printf("%s/%s", AFL_PATH, obj);
-#ifdef __ANDROID__
- if (!access(tmp, R_OK)) {
+ }
-#else
- if (!access(tmp, R_OK)) {
+ ck_free(tmp);
+ tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);
-#endif
+ if (debug) DEBUGF("Trying %s\n", tmp);
- obj_path = AFL_PATH;
- return tmp;
+ if (!access(tmp, R_OK)) {
- }
+ u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
+ obj_path = dir2;
+ ck_free(dir);
+ return tmp;
- ck_free(tmp);
- return NULL;
+ }
-}
+ ck_free(tmp);
+ ck_free(dir);
-/* Try to find the runtime libraries. If that fails, abort. */
+ }
-static void find_obj(u8 *argv0) {
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
+ defined(__ANDROID__) || defined(__NetBSD__)
+ #define HAS_PROC_FS 1
+#endif
+#ifdef HAS_PROC_FS
+ else {
+
+ char *procname = NULL;
+ #if defined(__FreeBSD__) || defined(__DragonFly__)
+ procname = "/proc/curproc/file";
+ #elif defined(__linux__) || defined(__ANDROID__)
+ procname = "/proc/self/exe";
+ #elif defined(__NetBSD__)
+ procname = "/proc/curproc/exe";
+ #endif
+ if (procname) {
- u8 *afl_path = getenv("AFL_PATH");
- u8 *slash, *tmp;
+ char exepath[PATH_MAX];
+ ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
+ if (exepath_len > 0 && exepath_len < PATH_MAX) {
- if (afl_path) {
+ exepath[exepath_len] = 0;
+ slash = strrchr(exepath, '/');
-#ifdef __ANDROID__
- tmp = alloc_printf("%s/afl-compiler-rt.so", afl_path);
-#else
- tmp = alloc_printf("%s/afl-compiler-rt.o", afl_path);
-#endif
+ if (slash) {
- if (!access(tmp, R_OK)) {
+ *slash = 0;
+ tmp = alloc_printf("%s/%s", exepath, obj);
- obj_path = afl_path;
- ck_free(tmp);
- return;
+ if (!access(tmp, R_OK)) {
- }
+ u8 *dir = alloc_printf("%s", exepath);
+ obj_path = dir;
+ return tmp;
- ck_free(tmp);
+ }
- }
+ ck_free(tmp);
+ tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);
- slash = strrchr(argv0, '/');
+ if (debug) DEBUGF("Trying %s\n", tmp);
- if (slash) {
+ if (!access(tmp, R_OK)) {
- u8 *dir;
+ u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
+ obj_path = dir;
+ return tmp;
- *slash = 0;
- dir = ck_strdup(argv0);
- *slash = '/';
+ }
-#ifdef __ANDROID__
- tmp = alloc_printf("%s/afl-compiler-rt.so", dir);
-#else
- tmp = alloc_printf("%s/afl-compiler-rt.o", dir);
-#endif
+ }
- if (!access(tmp, R_OK)) {
+ }
- obj_path = dir;
- ck_free(tmp);
- return;
+ }
}
- ck_free(tmp);
- ck_free(dir);
+#endif
+#undef HAS_PROC_FS
}
-#ifdef __ANDROID__
- if (!access(AFL_PATH "/afl-compiler-rt.so", R_OK)) {
+ tmp = alloc_printf("%s/%s", AFL_PATH, obj);
-#else
- if (!access(AFL_PATH "/afl-compiler-rt.o", R_OK)) {
+ if (debug) DEBUGF("Trying %s\n", tmp);
-#endif
+ if (!access(tmp, R_OK)) {
obj_path = AFL_PATH;
- return;
+ return tmp;
+
+ }
+
+ ck_free(tmp);
+
+ tmp = alloc_printf("./%s", obj);
+
+ if (debug) DEBUGF("Trying %s\n", tmp);
+
+ if (!access(tmp, R_OK)) {
+
+ obj_path = ".";
+ return tmp;
}
- FATAL(
- "Unable to find 'afl-compiler-rt.o' or 'afl-llvm-pass.so'. Please set "
- "AFL_PATH");
+ ck_free(tmp);
+
+ if (debug) DEBUGF("Trying ... giving up\n");
+
+ return NULL;
}
@@ -288,7 +318,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (compiler_mode >= GCC_PLUGIN) {
- alt_cxx = "g++";
+ if (compiler_mode == GCC) {
+
+ alt_cxx = clang_mode ? "clang++" : "g++";
+
+ } else {
+
+ alt_cxx = "g++";
+
+ }
} else {
@@ -313,7 +351,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (compiler_mode >= GCC_PLUGIN) {
- alt_cc = "gcc";
+ if (compiler_mode == GCC) {
+
+ alt_cc = clang_mode ? "clang" : "gcc";
+
+ } else {
+
+ alt_cc = "gcc";
+
+ }
} else {
@@ -337,12 +383,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = obj_path;
+ if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
+
}
if (compiler_mode == GCC_PLUGIN) {
- char *fplugin_arg =
- alloc_printf("-fplugin=%s", find_object("afl-gcc-pass.so", argvnull));
+ char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
cc_params[cc_par_cnt++] = fplugin_arg;
}
@@ -686,7 +733,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
- getenv("LAF_TRANSFORM_COMPARES") || lto_mode) {
+ getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") ||
+ lto_mode) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
@@ -843,6 +891,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
#endif
+ #ifdef USEMMAP
+ cc_params[cc_par_cnt++] = "-lrt";
+ #endif
+
}
#endif
@@ -934,7 +986,9 @@ int main(int argc, char **argv, char **envp) {
} else if (strncmp(callname, "afl-gcc", 7) == 0 ||
- strncmp(callname, "afl-g++", 7) == 0) {
+ strncmp(callname, "afl-g++", 7) == 0 ||
+
+ strncmp(callname, "afl-clang", 9) == 0) {
compiler_mode = GCC;
@@ -978,6 +1032,14 @@ int main(int argc, char **argv, char **envp) {
}
+ if (strncmp(callname, "afl-clang", 9) == 0) {
+
+ clang_mode = 1;
+
+ if (strncmp(callname, "afl-clang++", 11) == 0) { plusplus_mode = 1; }
+
+ }
+
for (i = 1; i < argc; i++) {
if (strncmp(argv[i], "--afl", 5) == 0) {
@@ -1030,7 +1092,7 @@ int main(int argc, char **argv, char **envp) {
if (instrument_mode == 0)
instrument_mode = INSTRUMENT_PCGUARD;
else if (instrument_mode != INSTRUMENT_PCGUARD)
- FATAL("you can not set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
+ FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
}
@@ -1048,8 +1110,7 @@ int main(int argc, char **argv, char **envp) {
if (instrument_mode == 0)
instrument_mode = INSTRUMENT_CFG;
else if (instrument_mode != INSTRUMENT_CFG)
- FATAL(
- "you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
+ FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
}
@@ -1403,9 +1464,15 @@ int main(int argc, char **argv, char **envp) {
if (have_llvm)
SAYF("afl-cc LLVM version %d with the the binary path \"%s\".\n",
LLVM_MAJOR, LLVM_BINDIR);
- if (have_lto || have_llvm) SAYF("\n");
#endif
+#ifdef USEMMAP
+ SAYF("Compiled with shm_open support (adds -lrt when linking).\n");
+#else
+ SAYF("Compiled with shmat support.\n");
+#endif
+ SAYF("\n");
+
SAYF(
"Do not be overwhelmed :) afl-cc uses good defaults if no options are "
"selected.\n"
@@ -1545,7 +1612,7 @@ int main(int argc, char **argv, char **envp) {
if (debug) {
- SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
+ DEBUGF("cd '%s';", getthecwd());
for (i = 0; i < argc; i++)
SAYF(" '%s'", argv[i]);
SAYF("\n");
@@ -1565,15 +1632,29 @@ int main(int argc, char **argv, char **envp) {
if (!be_quiet && cmplog_mode)
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
-#ifndef __ANDROID__
- find_obj(argv[0]);
+#ifdef __ANDROID__
+ ptr = find_object("afl-compiler-rt.so", argv[0]);
+#else
+ ptr = find_object("afl-compiler-rt.o", argv[0]);
#endif
+ if (!ptr) {
+
+ FATAL(
+ "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH "
+ "environment variable.");
+
+ }
+
+ if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
+
+ ck_free(ptr);
+
edit_params(argc, argv, envp);
if (debug) {
- SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
+ DEBUGF("cd '%s';", getthecwd());
for (i = 0; i < (s32)cc_par_cnt; i++)
SAYF(" '%s'", cc_params[i]);
SAYF("\n");
diff --git a/src/afl-common.c b/src/afl-common.c
index 8cf1a444..ed0b0e53 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -46,7 +46,7 @@ u8 be_quiet = 0;
u8 *doc_path = "";
u8 last_intr = 0;
-void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
+void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
u32 i = 0;
u8 cwd[PATH_MAX];
@@ -63,7 +63,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
- *use_stdin = 0;
+ *use_stdin = false;
if (prog_in[0] != 0) { // not afl-showmap special case
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 3814a77e..3afb94be 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -62,6 +62,8 @@ static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) {
execv(fsrv->target_path, argv);
+ WARNF("Execv failed in forkserver.");
+
}
/* Initializes the struct */
@@ -76,8 +78,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->dev_urandom_fd = -1;
/* Settings */
- fsrv->use_stdin = 1;
- fsrv->no_unlink = 0;
+ fsrv->use_stdin = true;
+ fsrv->no_unlink = false;
fsrv->exec_tmout = EXEC_TIMEOUT;
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
fsrv->mem_limit = MEM_LIMIT;
@@ -86,8 +88,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
/* exec related stuff */
fsrv->child_pid = -1;
fsrv->map_size = get_map_size();
- fsrv->use_fauxsrv = 0;
- fsrv->last_run_timed_out = 0;
+ fsrv->use_fauxsrv = false;
+ fsrv->last_run_timed_out = false;
+
+ fsrv->uses_crash_exitcode = false;
+ fsrv->uses_asan = false;
fsrv->init_child_func = fsrv_exec_child;
@@ -109,6 +114,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->dev_urandom_fd = from->dev_urandom_fd;
fsrv_to->out_fd = from->out_fd; // not sure this is a good idea
fsrv_to->no_unlink = from->no_unlink;
+ fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
+ fsrv_to->crash_exitcode = from->crash_exitcode;
// These are forkserver specific.
fsrv_to->out_dir_fd = -1;
@@ -348,9 +355,10 @@ static void report_error_and_exit(int error) {
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output) {
- int st_pipe[2], ctl_pipe[2];
- s32 status;
- s32 rlen;
+ int st_pipe[2], ctl_pipe[2];
+ s32 status;
+ s32 rlen;
+ char *ignore_autodict = getenv("AFL_NO_AUTODICT");
if (!be_quiet) { ACTF("Spinning up the fork server..."); }
@@ -520,8 +528,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
falling through. */
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
- fprintf(stderr, "Error: execv to target failed\n");
- exit(1);
+ FATAL("Error: execv to target failed\n");
}
@@ -607,7 +614,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
fsrv->use_shmem_fuzz = 1;
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
- if ((status & FS_OPT_AUTODICT) == 0) {
+ if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
@@ -660,100 +667,108 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
- if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
+ if (ignore_autodict) {
- // this is not afl-fuzz - or it is cmplog - we deny and return
- if (fsrv->use_shmem_fuzz) {
+ if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); }
- status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
+ } else {
- } else {
+ if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
- status = (FS_OPT_ENABLED);
+ // this is not afl-fuzz - or it is cmplog - we deny and return
+ if (fsrv->use_shmem_fuzz) {
- }
+ status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
- if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+ } else {
- FATAL("Writing to forkserver failed.");
+ status = (FS_OPT_ENABLED);
- }
+ }
- return;
+ if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
- }
+ FATAL("Writing to forkserver failed.");
- if (!be_quiet) { ACTF("Using AUTODICT feature."); }
+ }
- if (fsrv->use_shmem_fuzz) {
+ return;
- status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
+ }
- } else {
+ if (!be_quiet) { ACTF("Using AUTODICT feature."); }
- status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
+ if (fsrv->use_shmem_fuzz) {
- }
+ status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
- if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
+ } else {
- FATAL("Writing to forkserver failed.");
+ status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
- }
+ }
+
+ if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
- if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
+ FATAL("Writing to forkserver failed.");
- FATAL("Reading from forkserver failed.");
+ }
- }
+ if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
- if (status < 2 || (u32)status > 0xffffff) {
+ FATAL("Reading from forkserver failed.");
- FATAL("Dictionary has an illegal size: %d", status);
+ }
- }
+ if (status < 2 || (u32)status > 0xffffff) {
- u32 offset = 0, count = 0;
- u32 len = status;
- u8 *dict = ck_alloc(len);
- if (dict == NULL) {
+ FATAL("Dictionary has an illegal size: %d", status);
- FATAL("Could not allocate %u bytes of autodictionary memory", len);
+ }
- }
+ u32 offset = 0, count = 0;
+ u32 len = status;
+ u8 *dict = ck_alloc(len);
+ if (dict == NULL) {
- while (len != 0) {
+ FATAL("Could not allocate %u bytes of autodictionary memory", len);
- rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
- if (rlen > 0) {
+ }
- len -= rlen;
- offset += rlen;
+ while (len != 0) {
- } else {
+ rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
+ if (rlen > 0) {
+
+ len -= rlen;
+ offset += rlen;
- FATAL(
- "Reading autodictionary fail at position %u with %u bytes "
- "left.",
- offset, len);
+ } else {
+
+ FATAL(
+ "Reading autodictionary fail at position %u with %u bytes "
+ "left.",
+ offset, len);
+
+ }
}
- }
+ offset = 0;
+ while (offset < (u32)status &&
+ (u8)dict[offset] + offset < (u32)status) {
- offset = 0;
- while (offset < (u32)status &&
- (u8)dict[offset] + offset < (u32)status) {
+ fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
+ (u8)dict[offset]);
+ offset += (1 + dict[offset]);
+ count++;
- fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
- (u8)dict[offset]);
- offset += (1 + dict[offset]);
- count++;
+ }
- }
+ if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
+ ck_free(dict);
- if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
- ck_free(dict);
+ }
}
@@ -902,7 +917,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" estimate the required amount of virtual memory for the "
"binary.\n\n"
- " - the target was compiled with afl-clang-lto and a constructor "
+ " - The target was compiled with afl-clang-lto and a constructor "
"was\n"
" instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
"your \n"
@@ -945,6 +960,8 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
if (fsrv->shmem_fuzz) {
+ if (unlikely(len > MAX_FILE)) len = MAX_FILE;
+
*fsrv->shmem_fuzz_len = len;
memcpy(fsrv->shmem_fuzz, buf, len);
#ifdef _DEBUG
@@ -1055,6 +1072,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (fsrv->child_pid <= 0) {
if (*stop_soon_p) { return 0; }
+
+ if ((fsrv->child_pid & FS_OPT_ERROR) &&
+ FS_OPT_GET_ERROR(fsrv->child_pid) == FS_ERROR_SHM_OPEN)
+ FATAL(
+ "Target reported shared memory access failed (perhaps increase "
+ "shared memory available).");
+
FATAL("Fork server is misbehaving (OOM?)");
}
@@ -1127,10 +1151,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
- /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
- must use a special exit code. */
+ /* MSAN in uses_asan mode uses a special exit code as it doesn't support
+ abort_on_error.
+ On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */
- if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) {
+ if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
+ (fsrv->uses_crash_exitcode &&
+ WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) {
fsrv->last_kill_signal = 0;
return FSRV_RUN_CRASH;
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 2d14b04e..f1ca7400 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -425,8 +425,10 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
/* Construct a file name for a new test case, capturing the operation
that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
-u8 *describe_op(afl_state_t *afl, u8 hnb) {
+u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
+ size_t real_max_len =
+ MIN(max_description_len, sizeof(afl->describe_op_buf_256));
u8 *ret = afl->describe_op_buf_256;
if (unlikely(afl->syncing_party)) {
@@ -445,29 +447,66 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
- sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
+ if (afl->current_custom_fuzz &&
+ afl->current_custom_fuzz->afl_custom_describe) {
- if (afl->stage_cur_byte >= 0) {
+ /* We are currently in a custom mutator that supports afl_custom_describe,
+ * use it! */
- sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
+ size_t len_current = strlen(ret);
+ ret[len_current++] = ',';
+ ret[len_current] = '\0';
- if (afl->stage_val_type != STAGE_VAL_NONE) {
+ ssize_t size_left = real_max_len - len_current - strlen(",+cov") - 2;
+ if (unlikely(size_left <= 0)) FATAL("filename got too long");
- sprintf(ret + strlen(ret), ",val:%s%+d",
- (afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
- afl->stage_cur_val);
+ const char *custom_description =
+ afl->current_custom_fuzz->afl_custom_describe(
+ afl->current_custom_fuzz->data, size_left);
+ if (!custom_description || !custom_description[0]) {
+
+ DEBUGF("Error getting a description from afl_custom_describe");
+ /* Take the stage name as description fallback */
+ sprintf(ret + len_current, "op:%s", afl->stage_short);
+
+ } else {
+
+ /* We got a proper custom description, use it */
+ strncat(ret + len_current, custom_description, size_left);
}
} else {
- sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
+ /* Normal testcase descriptions start here */
+ sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
+
+ if (afl->stage_cur_byte >= 0) {
+
+ sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
+
+ if (afl->stage_val_type != STAGE_VAL_NONE) {
+
+ sprintf(ret + strlen(ret), ",val:%s%+d",
+ (afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
+ afl->stage_cur_val);
+
+ }
+
+ } else {
+
+ sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
+
+ }
}
}
- if (hnb == 2) { strcat(ret, ",+cov"); }
+ if (new_bits == 2) { strcat(ret, ",+cov"); }
+
+ if (unlikely(strlen(ret) >= max_description_len))
+ FATAL("describe string is too long");
return ret;
@@ -540,7 +579,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(len == 0)) { return 0; }
u8 *queue_fn = "";
- u8 hnb = '\0';
+ u8 new_bits = '\0';
s32 fd;
u8 keeping = 0, res;
u64 cksum = 0;
@@ -566,7 +605,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* Keep only if there are new bits in the map, add to queue for
future fuzzing, etc. */
- if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
+ if (!(new_bits = has_new_bits(afl, afl->virgin_bits))) {
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
return 0;
@@ -575,8 +614,9 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
- queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
- afl->queued_paths, describe_op(afl, hnb));
+ queue_fn = alloc_printf(
+ "%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
+ describe_op(afl, new_bits, NAME_MAX - strlen("id:000000,")));
#else
@@ -619,7 +659,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#endif
- if (hnb == 2) {
+ if (new_bits == 2) {
afl->queue_top->has_new_cov = 1;
++afl->queued_with_cov;
@@ -742,7 +782,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
- afl->unique_hangs, describe_op(afl, 0));
+ afl->unique_hangs,
+ describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
#else
@@ -787,7 +828,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
afl->unique_crashes, afl->fsrv.last_kill_signal,
- describe_op(afl, 0));
+ describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
#else
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 0360cdb0..6707340b 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -868,7 +868,19 @@ void perform_dry_run(afl_state_t *afl) {
if (skip_crashes) {
- WARNF("Test case results in a crash (skipping)");
+ if (afl->fsrv.uses_crash_exitcode) {
+
+ WARNF(
+ "Test case results in a crash or AFL_CRASH_EXITCODE %d "
+ "(skipping)",
+ (int)(s8)afl->fsrv.crash_exitcode);
+
+ } else {
+
+ WARNF("Test case results in a crash (skipping)");
+
+ }
+
q->cal_failed = CAL_CHANCES;
++cal_failures;
break;
@@ -954,7 +966,18 @@ void perform_dry_run(afl_state_t *afl) {
#undef MSG_ULIMIT_USAGE
#undef MSG_FORK_ON_APPLE
- WARNF("Test case '%s' results in a crash, skipping", fn);
+ if (afl->fsrv.uses_crash_exitcode) {
+
+ WARNF(
+ "Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, "
+ "skipping",
+ fn, (int)(s8)afl->fsrv.crash_exitcode);
+
+ } else {
+
+ WARNF("Test case '%s' results in a crash, skipping", fn);
+
+ }
/* Remove from fuzzing queue but keep for splicing */
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 1d14f657..0c85458e 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -151,7 +151,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
/* Mutator */
/* "afl_custom_init", optional for backward compatibility */
mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
- if (!mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
+ if (!mutator->afl_custom_init) {
+
+ FATAL("Symbol 'afl_custom_init' not found.");
+
+ }
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@@ -161,49 +165,74 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
- if (!mutator->afl_custom_fuzz)
+ if (!mutator->afl_custom_fuzz) {
+
WARNF("Symbol 'afl_custom_mutator' not found.");
+ }
+
}
/* "afl_custom_introspection", optional */
#ifdef INTROSPECTION
mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
- if (!mutator->afl_custom_introspection)
+ if (!mutator->afl_custom_introspection) {
+
ACTF("optional symbol 'afl_custom_introspection' not found.");
+
+ }
+
#endif
/* "afl_custom_fuzz_count", optional */
mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
- if (!mutator->afl_custom_fuzz_count)
+ if (!mutator->afl_custom_fuzz_count) {
+
ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
+ }
+
/* "afl_custom_deinit", optional for backward compatibility */
mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
- if (!mutator->afl_custom_deinit)
+ if (!mutator->afl_custom_deinit) {
+
FATAL("Symbol 'afl_custom_deinit' not found.");
+ }
+
/* "afl_custom_post_process", optional */
mutator->afl_custom_post_process = dlsym(dh, "afl_custom_post_process");
- if (!mutator->afl_custom_post_process)
+ if (!mutator->afl_custom_post_process) {
+
ACTF("optional symbol 'afl_custom_post_process' not found.");
+ }
+
u8 notrim = 0;
/* "afl_custom_init_trim", optional */
mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
- if (!mutator->afl_custom_init_trim)
+ if (!mutator->afl_custom_init_trim) {
+
ACTF("optional symbol 'afl_custom_init_trim' not found.");
+ }
+
/* "afl_custom_trim", optional */
mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
- if (!mutator->afl_custom_trim)
+ if (!mutator->afl_custom_trim) {
+
ACTF("optional symbol 'afl_custom_trim' not found.");
+ }
+
/* "afl_custom_post_trim", optional */
mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
- if (!mutator->afl_custom_post_trim)
+ if (!mutator->afl_custom_post_trim) {
+
ACTF("optional symbol 'afl_custom_post_trim' not found.");
+ }
+
if (notrim) {
mutator->afl_custom_init_trim = NULL;
@@ -217,31 +246,54 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
/* "afl_custom_havoc_mutation", optional */
mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation");
- if (!mutator->afl_custom_havoc_mutation)
+ if (!mutator->afl_custom_havoc_mutation) {
+
ACTF("optional symbol 'afl_custom_havoc_mutation' not found.");
+ }
+
/* "afl_custom_havoc_mutation", optional */
mutator->afl_custom_havoc_mutation_probability =
dlsym(dh, "afl_custom_havoc_mutation_probability");
- if (!mutator->afl_custom_havoc_mutation_probability)
+ if (!mutator->afl_custom_havoc_mutation_probability) {
+
ACTF("optional symbol 'afl_custom_havoc_mutation_probability' not found.");
+ }
+
/* "afl_custom_queue_get", optional */
mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
- if (!mutator->afl_custom_queue_get)
+ if (!mutator->afl_custom_queue_get) {
+
ACTF("optional symbol 'afl_custom_queue_get' not found.");
+ }
+
/* "afl_custom_queue_new_entry", optional */
mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry");
- if (!mutator->afl_custom_queue_new_entry)
+ if (!mutator->afl_custom_queue_new_entry) {
+
ACTF("optional symbol 'afl_custom_queue_new_entry' not found");
+ }
+
+ /* "afl_custom_describe", optional */
+ mutator->afl_custom_describe = dlsym(dh, "afl_custom_describe");
+ if (!mutator->afl_custom_describe) {
+
+ ACTF("Symbol 'afl_custom_describe' not found.");
+
+ }
+
OKF("Custom mutator '%s' installed successfully.", fn);
/* Initialize the custom mutator */
- if (mutator->afl_custom_init)
+ if (mutator->afl_custom_init) {
+
mutator->data = mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
+ }
+
mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
mutator->stacked_custom_prob =
6; // like one of the default mutations in havoc
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 0adc3719..e6fa6064 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -445,8 +445,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (unlikely(afl->not_on_tty)) {
- ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...",
- afl->current_entry, afl->queued_paths, afl->unique_crashes);
+ ACTF(
+ "Fuzzing test case #%u (%u total, %llu uniq crashes found, "
+ "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...",
+ afl->current_entry, afl->queued_paths, afl->unique_crashes,
+ afl->queue_cur->perf_score, afl->queue_cur->exec_us,
+ likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
+ afl->queue_cur->bitmap_size);
fflush(stdout);
}
@@ -1790,11 +1795,16 @@ custom_mutator_stage:
afl->current_custom_fuzz = el;
- if (el->afl_custom_fuzz_count)
+ if (el->afl_custom_fuzz_count) {
+
afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
- else
+
+ } else {
+
afl->stage_max = saved_max;
+ }
+
has_custom_fuzz = true;
afl->stage_short = el->name_short;
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index 9ac4403b..8760194c 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -111,6 +111,37 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
}
+static const char *custom_describe_py(void * py_mutator,
+ size_t max_description_len) {
+
+ PyObject *py_args, *py_value;
+
+ py_args = PyTuple_New(1);
+
+ PyLong_FromSize_t(max_description_len);
+
+ /* add_buf */
+ py_value = PyLong_FromSize_t(max_description_len);
+ if (!py_value) {
+
+ Py_DECREF(py_args);
+ FATAL("Failed to convert arguments");
+
+ }
+
+ PyTuple_SetItem(py_args, 0, py_value);
+
+ py_value = PyObject_CallObject(
+ ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DESCRIBE], py_args);
+
+ Py_DECREF(py_args);
+
+ if (py_value != NULL) { return PyBytes_AsString(py_value); }
+
+ return NULL;
+
+}
+
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
(void)afl;
@@ -156,6 +187,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
+ py_functions[PY_FUNC_DESCRIBE] =
+ PyObject_GetAttrString(py_module, "describe");
py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count");
if (!py_functions[PY_FUNC_FUZZ])
@@ -342,6 +375,12 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
+ if (py_functions[PY_FUNC_DESCRIBE]) {
+
+ mutator->afl_custom_describe = custom_describe_py;
+
+ }
+
if (py_functions[PY_FUNC_POST_PROCESS]) {
mutator->afl_custom_post_process = post_process_py;
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index f35b4f57..54afa17c 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -42,11 +42,39 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
}
+double compute_weight(afl_state_t *afl, struct queue_entry *q,
+ double avg_exec_us, double avg_bitmap_size) {
+
+ u32 hits;
+
+ if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+
+ hits = afl->n_fuzz[q->n_fuzz_entry];
+ if (hits == 0) { hits = 1; }
+
+ } else {
+
+ hits = 1;
+
+ }
+
+ double weight = 1.0;
+ weight *= avg_exec_us / q->exec_us;
+ weight *= log(q->bitmap_size) / avg_bitmap_size;
+ weight /= log10(hits) + 1;
+
+ if (q->favored) weight *= 5;
+
+ return weight;
+
+}
+
/* create the alias table that allows weighted random selection - expensive */
void create_alias_table(afl_state_t *afl) {
- u32 n = afl->queued_paths, i = 0, a, g;
+ u32 n = afl->queued_paths, i = 0, a, g;
+ double sum = 0;
afl->alias_table =
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
@@ -65,22 +93,60 @@ void create_alias_table(afl_state_t *afl) {
memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
- double sum = 0;
+ if (likely(afl->schedule < RARE)) {
- for (i = 0; i < n; i++) {
+ double avg_exec_us = 0.0;
+ double avg_bitmap_size = 0.0;
+ for (i = 0; i < n; i++) {
- struct queue_entry *q = afl->queue_buf[i];
+ struct queue_entry *q = afl->queue_buf[i];
+ avg_exec_us += q->exec_us;
+ avg_bitmap_size += log(q->bitmap_size);
- if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
+ }
- sum += q->perf_score;
+ avg_exec_us /= afl->queued_paths;
+ avg_bitmap_size /= afl->queued_paths;
- }
+ for (i = 0; i < n; i++) {
+
+ struct queue_entry *q = afl->queue_buf[i];
+
+ if (!q->disabled) {
- for (i = 0; i < n; i++) {
+ q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size);
+ q->perf_score = calculate_score(afl, q);
- struct queue_entry *q = afl->queue_buf[i];
- P[i] = (q->perf_score * n) / sum;
+ }
+
+ sum += q->weight;
+
+ }
+
+ for (i = 0; i < n; i++) {
+
+ P[i] = (afl->queue_buf[i]->weight * n) / sum;
+
+ }
+
+ } else {
+
+ for (i = 0; i < n; i++) {
+
+ struct queue_entry *q = afl->queue_buf[i];
+
+ if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
+
+ sum += q->perf_score;
+
+ }
+
+ for (i = 0; i < n; i++) {
+
+ struct queue_entry *q = afl->queue_buf[i];
+ P[i] = (q->perf_score * n) / sum;
+
+ }
}
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 95b3ee8a..5948d83a 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -79,7 +79,8 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
s32 doc_fd;
char fn[PATH_MAX];
snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir,
- afl->document_counter++, describe_op(afl, 0));
+ afl->document_counter++,
+ describe_op(afl, 0, NAME_MAX - strlen("000000000:")));
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
@@ -484,7 +485,7 @@ void sync_fuzzers(afl_state_t *afl) {
DIR * sd;
struct dirent *sd_ent;
u32 sync_cnt = 0, synced = 0, entries = 0;
- u8 path[PATH_MAX + 256];
+ u8 path[PATH_MAX + 1 + NAME_MAX];
sd = opendir(afl->sync_dir);
if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 489d4e53..9c51a3ef 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -87,7 +87,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->w_end = 0.3;
afl->g_max = 5000;
afl->period_pilot_tmp = 5000.0;
- afl->schedule = EXPLORE; /* Power schedule (default: EXPLORE) */
+ afl->schedule = FAST; /* Power schedule (default: FAST) */
afl->havoc_max_mult = HAVOC_MAX_MULT;
afl->clear_screen = 1; /* Window resized? */
@@ -394,6 +394,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_statsd_tags_flavor =
(u8 *)get_afl_env(afl_environment_variables[i]);
+ } else if (!strncmp(env, "AFL_CRASH_EXITCODE",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_crash_exitcode =
+ (u8 *)get_afl_env(afl_environment_variables[i]);
+
}
} else {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 1008f28c..391d4c4f 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -26,6 +26,7 @@
#include "afl-fuzz.h"
#include "cmplog.h"
#include <limits.h>
+#include <stdlib.h>
#ifndef USEMMAP
#include <sys/mman.h>
#include <sys/stat.h>
@@ -40,7 +41,7 @@ extern u64 time_spent_working;
static void at_exit() {
- int i;
+ s32 i, pid1 = 0, pid2 = 0;
char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
char *ptr;
@@ -48,10 +49,10 @@ static void at_exit() {
if (ptr && *ptr) unlink(ptr);
ptr = getenv("__AFL_TARGET_PID1");
- if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
+ if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) kill(pid1, SIGTERM);
ptr = getenv("__AFL_TARGET_PID2");
- if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
+ if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) kill(pid2, SIGTERM);
i = 0;
while (list[i] != NULL) {
@@ -75,6 +76,9 @@ static void at_exit() {
}
+ if (pid1 > 0) { kill(pid1, SIGKILL); }
+ if (pid2 > 0) { kill(pid2, SIGKILL); }
+
}
/* Display usage hints. */
@@ -162,6 +166,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
"AFL_BENCH_JUST_ONE: run the target just once\n"
"AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
+ "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
@@ -184,6 +189,7 @@ static void usage(u8 *argv0, int more_help) {
" used. Defaults to 200.\n"
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
+ "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
@@ -224,6 +230,12 @@ static void usage(u8 *argv0, int more_help) {
SAYF("Compiled without python module support\n");
#endif
+#ifdef USEMMAP
+ SAYF("Compiled with shm_open support.\n");
+#else
+ SAYF("Compiled with shmat support.\n");
+#endif
+
#ifdef ASAN_BUILD
SAYF("Compiled with ASAN_BUILD\n\n");
#endif
@@ -248,7 +260,7 @@ static void usage(u8 *argv0, int more_help) {
SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS\n\n");
#endif
- SAYF("For additional help please consult %s/README.md\n\n", doc_path);
+ SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
exit(1);
#undef PHYTON_SUPPORT
@@ -698,7 +710,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'N': /* Unicorn mode */
if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
- afl->fsrv.no_unlink = afl->no_unlink = 1;
+ afl->fsrv.no_unlink = (afl->no_unlink = true);
break;
@@ -909,7 +921,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!mem_limit_given && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
+ if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
"Eißfeldt, Andrea Fioraldi and Dominik Maier");
@@ -1131,6 +1143,23 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->afl_env.afl_crash_exitcode) {
+
+ long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
+ if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+ exitcode < -127 || exitcode > 128) {
+
+ FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+ afl->afl_env.afl_crash_exitcode);
+
+ }
+
+ afl->fsrv.uses_crash_exitcode = true;
+ // WEXITSTATUS is 8 bit unsigned
+ afl->fsrv.crash_exitcode = (u8)exitcode;
+
+ }
+
if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
@@ -1482,9 +1511,12 @@ int main(int argc, char **argv_orig, char **envp) {
cull_queue(afl);
- if (!afl->pending_not_fuzzed)
+ if (!afl->pending_not_fuzzed) {
+
FATAL("We need at least on valid input seed that does not crash!");
+ }
+
show_init_stats(afl);
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 771e2d0d..16feaa80 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -182,12 +182,12 @@ static void edit_params(int argc, char **argv) {
instrim = 1;
if (debug)
- SAYF(cMGN "[D] " cRST
- "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
- "inst_present=%s rt_present=%s rt_lto_present=%s\n",
- passthrough ? "true" : "false", instrim, gold_pos,
- gold_present ? "true" : "false", inst_present ? "true" : "false",
- rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
+ DEBUGF(
+ "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
+ "inst_present=%s rt_present=%s rt_lto_present=%s\n",
+ passthrough ? "true" : "false", instrim, gold_pos,
+ gold_present ? "true" : "false", inst_present ? "true" : "false",
+ rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
for (i = 1; i < argc; i++) {
@@ -280,7 +280,7 @@ int main(int argc, char **argv) {
if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
- SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd);
+ DEBUGF("cd \"%s\";", thecwd);
for (i = 0; i < argc; i++)
SAYF(" \"%s\"", argv[i]);
SAYF("\n");
@@ -315,7 +315,7 @@ int main(int argc, char **argv) {
if (debug) {
- SAYF(cMGN "[D]" cRST " cd \"%s\";", thecwd);
+ DEBUGF("cd \"%s\";", thecwd);
for (i = 0; i < ld_param_cnt; i++)
SAYF(" \"%s\"", ld_params[i]);
SAYF("\n");
@@ -333,7 +333,7 @@ int main(int argc, char **argv) {
if (pid < 0) PFATAL("fork() failed");
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
- if (debug) SAYF(cMGN "[D] " cRST "linker result: %d\n", status);
+ if (debug) DEBUGF("linker result: %d\n", status);
if (!just_version) {
diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c
index 6eb63949..3e671df5 100644
--- a/src/afl-sharedmem.c
+++ b/src/afl-sharedmem.c
@@ -248,22 +248,26 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
}
- shm_str = alloc_printf("%d", shm->shm_id);
+ if (!non_instrumented_mode) {
- /* If somebody is asking us to fuzz instrumented binaries in non-instrumented
- mode, we don't want them to detect instrumentation, since we won't be
- sending fork server commands. This should be replaced with better
- auto-detection later on, perhaps? */
+ shm_str = alloc_printf("%d", shm->shm_id);
+
+ /* If somebody is asking us to fuzz instrumented binaries in
+ non-instrumented mode, we don't want them to detect instrumentation,
+ since we won't be sending fork server commands. This should be replaced
+ with better auto-detection later on, perhaps? */
- if (!non_instrumented_mode) { setenv(SHM_ENV_VAR, shm_str, 1); }
+ setenv(SHM_ENV_VAR, shm_str, 1);
- ck_free(shm_str);
+ ck_free(shm_str);
- if (shm->cmplog_mode) {
+ }
+
+ if (shm->cmplog_mode && !non_instrumented_mode) {
shm_str = alloc_printf("%d", shm->cmplog_shm_id);
- if (!non_instrumented_mode) { setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); }
+ setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1);
ck_free(shm_str);
@@ -274,6 +278,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
if (shm->map == (void *)-1 || !shm->map) {
shmctl(shm->shm_id, IPC_RMID, NULL); // do not leak shmem
+
if (shm->cmplog_mode) {
shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); // do not leak shmem
@@ -291,11 +296,8 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
if (shm->cmp_map == (void *)-1 || !shm->cmp_map) {
shmctl(shm->shm_id, IPC_RMID, NULL); // do not leak shmem
- if (shm->cmplog_mode) {
- shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); // do not leak shmem
-
- }
+ shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); // do not leak shmem
PFATAL("shmat() failed");
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 69527007..34a4f30d 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -287,6 +287,8 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
afl_fsrv_write_to_testcase(fsrv, mem, len);
+ if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
+
if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
FSRV_RUN_ERROR) {
@@ -667,6 +669,8 @@ static void usage(u8 *argv0) {
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
"inputs\n"
"AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
+ "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
+ "crash\n"
"AFL_DEBUG: enable extra developer output\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
"size\n"
@@ -709,6 +713,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'C':
collect_coverage = 1;
+ quiet_mode = 1;
break;
case 'i':
@@ -815,7 +820,6 @@ int main(int argc, char **argv_orig, char **envp) {
case 'q':
- if (quiet_mode) { FATAL("Multiple -q options not supported"); }
quiet_mode = 1;
break;
@@ -904,7 +908,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_DEBUG")) {
- SAYF(cMGN "[D]" cRST);
+ DEBUGF("");
for (i = 0; i < argc; i++)
SAYF(" %s", argv[i]);
SAYF("\n");
@@ -1066,7 +1070,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) {
int i = optind;
- SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path);
+ DEBUGF("%s:", fsrv->target_path);
while (argv[i] != NULL) {
SAYF(" \"%s\"", argv[i++]);
@@ -1090,6 +1094,23 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (getenv("AFL_CRASH_EXITCODE")) {
+
+ long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
+ if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+ exitcode < -127 || exitcode > 128) {
+
+ FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+ getenv("AFL_CRASH_EXITCODE"));
+
+ }
+
+ fsrv->uses_crash_exitcode = true;
+ // WEXITSTATUS is 8 bit unsigned
+ fsrv->crash_exitcode = (u8)exitcode;
+
+ }
+
afl_fsrv_start(fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") ||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
@@ -1170,7 +1191,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!quiet_mode) {
+ if (!quiet_mode || collect_coverage) {
if (!tcnt) { FATAL("No instrumentation detected" cRST); }
OKF("Captured %u tuples (highest value %u, total values %llu) in "
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index e4fb068d..b9045551 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -51,6 +51,7 @@
#include <signal.h>
#include <dirent.h>
#include <fcntl.h>
+#include <limits.h>
#include <sys/wait.h>
#include <sys/time.h>
@@ -841,17 +842,17 @@ static void usage(u8 *argv0) {
"For additional tips, please consult %s/README.md.\n\n"
"Environment variables used:\n"
- "TMPDIR: directory to use for temporary input files\n"
- "ASAN_OPTIONS: custom settings for ASAN\n"
- " (must contain abort_on_error=1 and symbolize=0)\n"
- "MSAN_OPTIONS: custom settings for MSAN\n"
- " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
+ "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
+ "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
- "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
-
+ "ASAN_OPTIONS: custom settings for ASAN\n"
+ " (must contain abort_on_error=1 and symbolize=0)\n"
+ "MSAN_OPTIONS: custom settings for MSAN\n"
+ " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
+ "TMPDIR: directory to use for temporary input files\n"
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
exit(1);
@@ -1122,6 +1123,23 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (getenv("AFL_CRASH_EXITCODE")) {
+
+ long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
+ if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+ exitcode < -127 || exitcode > 128) {
+
+ FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+ getenv("AFL_CRASH_EXITCODE"));
+
+ }
+
+ fsrv->uses_crash_exitcode = true;
+ // WEXITSTATUS is 8 bit unsigned
+ fsrv->crash_exitcode = (u8)exitcode;
+
+ }
+
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
/* initialize cmplog_mode */