aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c225
-rw-r--r--src/afl-cc.c33
-rw-r--r--src/afl-common.c2
-rw-r--r--src/afl-forkserver.c10
-rw-r--r--src/afl-fuzz-bitmap.c13
-rw-r--r--src/afl-fuzz-init.c132
-rw-r--r--src/afl-fuzz-mutators.c1
-rw-r--r--src/afl-fuzz-one.c13
-rw-r--r--src/afl-fuzz-queue.c9
-rw-r--r--src/afl-fuzz-redqueen.c98
-rw-r--r--src/afl-fuzz-run.c24
-rw-r--r--src/afl-fuzz-state.c9
-rw-r--r--src/afl-fuzz-stats.c68
-rw-r--r--src/afl-fuzz.c31
-rw-r--r--src/afl-showmap.c189
-rw-r--r--src/afl-tmin.c11
16 files changed, 496 insertions, 372 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index aabdbf1a..a5cad03c 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -55,12 +55,7 @@
#include <sys/types.h>
#include <sys/resource.h>
-static s32 child_pid; /* PID of the tested program */
-
-static u8 *trace_bits; /* SHM with instrumentation bitmap */
-
-static u8 *in_file, /* Analyzer input test case */
- *prog_in; /* Targeted program input file */
+static u8 *in_file; /* Analyzer input test case */
static u8 *in_data; /* Input data for analysis */
@@ -73,20 +68,19 @@ static u64 orig_cksum; /* Original checksum */
static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
-static s32 dev_null_fd = -1; /* FD to /dev/null */
-
static bool edges_only, /* Ignore hit counts? */
use_hex_offsets, /* Show hex offsets? */
use_stdin = true; /* Use stdin for program input? */
-static volatile u8 stop_soon, /* Ctrl-C pressed? */
- child_timed_out; /* Child timed out? */
+static volatile u8 stop_soon; /* Ctrl-C pressed? */
static u8 *target_path;
static u8 frida_mode;
static u8 qemu_mode;
static u32 map_size = MAP_SIZE;
+static afl_forkserver_t fsrv = {0}; /* The forkserver */
+
/* Constants used for describing byte behavior. */
#define RESP_NONE 0x00 /* Changing byte is a no-op. */
@@ -156,7 +150,7 @@ static void classify_counts(u8 *mem) {
static inline u8 anything_set(void) {
- u32 *ptr = (u32 *)trace_bits;
+ u32 *ptr = (u32 *)fsrv.trace_bits;
u32 i = (map_size >> 2);
while (i--) {
@@ -173,7 +167,7 @@ static inline u8 anything_set(void) {
static void at_exit_handler(void) {
- unlink(prog_in); /* Ignore errors */
+ unlink(fsrv.out_file); /* Ignore errors */
}
@@ -205,116 +199,29 @@ static void read_initial_file(void) {
}
-/* Write output file. */
-
-static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
-
- s32 ret;
-
- unlink(path); /* Ignore errors */
-
- ret = open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
-
- if (ret < 0) { PFATAL("Unable to create '%s'", path); }
-
- ck_write(ret, mem, len, path);
-
- lseek(ret, 0, SEEK_SET);
-
- return ret;
-
-}
-
/* Execute target application. Returns exec checksum, or 0 if program
times out. */
-static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
-
- static struct itimerval it;
- int status = 0;
-
- s32 prog_in_fd;
- u64 cksum;
-
- memset(trace_bits, 0, map_size);
- MEM_BARRIER();
-
- prog_in_fd = write_to_file(prog_in, mem, len);
-
- child_pid = fork();
-
- if (child_pid < 0) { PFATAL("fork() failed"); }
-
- if (!child_pid) {
-
- struct rlimit r;
-
- if (dup2(use_stdin ? prog_in_fd : dev_null_fd, 0) < 0 ||
- dup2(dev_null_fd, 1) < 0 || dup2(dev_null_fd, 2) < 0) {
-
- *(u32 *)trace_bits = EXEC_FAIL_SIG;
- PFATAL("dup2() failed");
-
- }
-
- close(dev_null_fd);
- close(prog_in_fd);
-
- if (mem_limit) {
-
- r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
-
-#ifdef RLIMIT_AS
-
- setrlimit(RLIMIT_AS, &r); /* Ignore errors */
-
-#else
-
- setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
+static u32 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
-#endif /* ^RLIMIT_AS */
+ afl_fsrv_write_to_testcase(&fsrv, mem, len);
+ fsrv_run_result_t ret = afl_fsrv_run_target(&fsrv, exec_tmout, &stop_soon);
- }
-
- r.rlim_max = r.rlim_cur = 0;
- setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
-
- execv(target_path, argv);
-
- *(u32 *)trace_bits = EXEC_FAIL_SIG;
- exit(0);
-
- }
-
- close(prog_in_fd);
-
- /* Configure timeout, wait for child, cancel timeout. */
-
- child_timed_out = 0;
- it.it_value.tv_sec = (exec_tmout / 1000);
- it.it_value.tv_usec = (exec_tmout % 1000) * 1000;
+ if (ret == FSRV_RUN_ERROR) {
- setitimer(ITIMER_REAL, &it, NULL);
+ FATAL("Error in forkserver");
- if (waitpid(child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
+ } else if (ret == FSRV_RUN_NOINST) {
- child_pid = 0;
- it.it_value.tv_sec = 0;
- it.it_value.tv_usec = 0;
+ FATAL("Target not instrumented");
- setitimer(ITIMER_REAL, &it, NULL);
+ } else if (ret == FSRV_RUN_NOBITS) {
- MEM_BARRIER();
-
- /* Clean up bitmap, analyze exit condition, etc. */
-
- if (*(u32 *)trace_bits == EXEC_FAIL_SIG) {
-
- FATAL("Unable to execute '%s'", argv[0]);
+ FATAL("Failed to run target");
}
- classify_counts(trace_bits);
+ classify_counts(fsrv.trace_bits);
total_execs++;
if (stop_soon) {
@@ -326,21 +233,19 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
/* Always discard inputs that time out. */
- if (child_timed_out) {
+ if (fsrv.last_run_timed_out) {
exec_hangs++;
return 0;
}
- cksum = hash64(trace_bits, map_size, HASH_CONST);
+ u64 cksum = hash64(fsrv.trace_bits, fsrv.map_size, HASH_CONST);
- /* We don't actually care if the target is crashing or not,
- except that when it does, the checksum should be different. */
+ if (ret == FSRV_RUN_CRASH) {
- if (WIFSIGNALED(status) ||
- (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
- (WIFEXITED(status) && WEXITSTATUS(status))) {
+ /* We don't actually care if the target is crashing or not,
+ except that when it does, the checksum should be different. */
cksum ^= 0xffffffff;
@@ -604,7 +509,7 @@ static void dump_hex(u32 len, u8 *b_data) {
/* Actually analyze! */
-static void analyze(char **argv) {
+static void analyze() {
u32 i;
u32 boring_len = 0, prev_xff = 0, prev_x01 = 0, prev_s10 = 0, prev_a10 = 0;
@@ -630,16 +535,16 @@ static void analyze(char **argv) {
code. */
in_data[i] ^= 0xff;
- xor_ff = analyze_run_target(argv, in_data, in_len, 0);
+ xor_ff = analyze_run_target(in_data, in_len, 0);
in_data[i] ^= 0xfe;
- xor_01 = analyze_run_target(argv, in_data, in_len, 0);
+ xor_01 = analyze_run_target(in_data, in_len, 0);
in_data[i] = (in_data[i] ^ 0x01) - 0x10;
- sub_10 = analyze_run_target(argv, in_data, in_len, 0);
+ sub_10 = analyze_run_target(in_data, in_len, 0);
in_data[i] += 0x20;
- add_10 = analyze_run_target(argv, in_data, in_len, 0);
+ add_10 = analyze_run_target(in_data, in_len, 0);
in_data[i] -= 0x10;
/* Classify current behavior. */
@@ -712,7 +617,7 @@ static void handle_stop_sig(int sig) {
(void)sig;
stop_soon = 1;
- if (child_pid > 0) { kill(child_pid, SIGKILL); }
+ afl_fsrv_killall();
}
@@ -724,10 +629,10 @@ static void set_up_environment(char **argv) {
char *afl_preload;
char *frida_afl_preload = NULL;
- dev_null_fd = open("/dev/null", O_RDWR);
- if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
+ fsrv.dev_null_fd = open("/dev/null", O_RDWR);
+ if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
- if (!prog_in) {
+ if (!fsrv.out_file) {
u8 *use_dir = ".";
@@ -738,10 +643,17 @@ static void set_up_environment(char **argv) {
}
- prog_in = alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid());
+ fsrv.out_file =
+ alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid());
}
+ unlink(fsrv.out_file);
+ fsrv.out_fd =
+ open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
+
+ if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); }
+
/* Set sane defaults... */
x = get_afl_env("ASAN_OPTIONS");
@@ -977,9 +889,9 @@ int main(int argc, char **argv_orig, char **envp) {
case 'f':
- if (prog_in) { FATAL("Multiple -f options not supported"); }
- use_stdin = 0;
- prog_in = optarg;
+ if (fsrv.out_file) { FATAL("Multiple -f options not supported"); }
+ fsrv.use_stdin = 0;
+ fsrv.out_file = ck_strdup(optarg);
break;
case 'e':
@@ -1000,6 +912,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!strcmp(optarg, "none")) {
mem_limit = 0;
+ fsrv.mem_limit = 0;
break;
}
@@ -1038,6 +951,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ fsrv.mem_limit = mem_limit;
+
}
break;
@@ -1057,6 +972,17 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ fsrv.exec_tmout = exec_tmout;
+
+ break;
+
+ case 'O': /* FRIDA mode */
+
+ if (frida_mode) { FATAL("Multiple -O options not supported"); }
+
+ frida_mode = 1;
+ fsrv.frida_mode = frida_mode;
+
break;
case 'O': /* FRIDA mode */
@@ -1073,6 +999,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (!mem_limit_given) { mem_limit = MEM_LIMIT_QEMU; }
qemu_mode = 1;
+ fsrv.mem_limit = mem_limit;
+ fsrv.qemu_mode = qemu_mode;
break;
case 'U':
@@ -1081,6 +1009,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!mem_limit_given) { mem_limit = MEM_LIMIT_UNICORN; }
unicorn_mode = 1;
+ fsrv.mem_limit = mem_limit;
break;
case 'W': /* Wine+QEMU mode */
@@ -1090,6 +1019,8 @@ int main(int argc, char **argv_orig, char **envp) {
use_wine = 1;
if (!mem_limit_given) { mem_limit = 0; }
+ fsrv.qemu_mode = qemu_mode;
+ fsrv.mem_limit = mem_limit;
break;
@@ -1108,6 +1039,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !in_file) { usage(argv[0]); }
map_size = get_map_size();
+ fsrv.map_size = map_size;
use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX");
@@ -1117,14 +1049,15 @@ int main(int argc, char **argv_orig, char **envp) {
/* initialize cmplog_mode */
shm.cmplog_mode = 0;
- trace_bits = afl_shm_init(&shm, map_size, 0);
+
atexit(at_exit_handler);
setup_signal_handlers();
set_up_environment(argv);
- target_path = find_binary(argv[optind]);
- detect_file_args(argv + optind, prog_in, &use_stdin);
+ fsrv.target_path = find_binary(argv[optind]);
+ fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
+ detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
if (qemu_mode) {
@@ -1148,14 +1081,31 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF("\n");
+ if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
+
+ s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
+ if (forksrv_init_tmout < 1) {
+
+ FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
+
+ }
+
+ fsrv.init_tmout = (u32)forksrv_init_tmout;
+
+ }
+
+ fsrv.kill_signal =
+ parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
+
read_initial_file();
ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
mem_limit, exec_tmout, edges_only ? ", edges only" : "");
- analyze_run_target(use_argv, in_data, in_len, 1);
+ afl_fsrv_start(&fsrv, use_argv, &stop_soon, false);
+ analyze_run_target(in_data, in_len, 1);
- if (child_timed_out) {
+ if (fsrv.last_run_timed_out) {
FATAL("Target binary times out (adjusting -t may help).");
@@ -1167,13 +1117,14 @@ int main(int argc, char **argv_orig, char **envp) {
}
- analyze(use_argv);
+ analyze();
OKF("We're done here. Have a nice day!\n");
- if (target_path) { ck_free(target_path); }
-
afl_shm_deinit(&shm);
+ afl_fsrv_deinit(&fsrv);
+ if (fsrv.target_path) { ck_free(fsrv.target_path); }
+ if (in_data) { ck_free(in_data); }
exit(0);
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 486f7468..6a60fb85 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -315,7 +315,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0,
- have_c = 0;
+ have_c = 0, partial_linking = 0;
cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
@@ -514,14 +514,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
unsetenv("AFL_LD");
unsetenv("AFL_LD_CALLER");
+
if (cmplog_mode) {
if (lto_mode && !have_c) {
cc_params[cc_par_cnt++] = alloc_printf(
- "-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path);
- cc_params[cc_par_cnt++] = alloc_printf(
- "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path);
+ "-Wl,-mllvm=-load=%s/cmplog-switches-pass.so", obj_path);
+
cc_params[cc_par_cnt++] = alloc_printf(
"-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
@@ -531,13 +531,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] =
- alloc_printf("%s/cmplog-routines-pass.so", obj_path);
-
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
+ alloc_printf("%s/cmplog-switches-pass.so", obj_path);
// reuse split switches from laf
cc_params[cc_par_cnt++] = "-Xclang";
@@ -746,6 +740,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = afllib;
+#ifdef __APPLE__
+ cc_params[cc_par_cnt++] = "-undefined";
+ cc_params[cc_par_cnt++] = "dynamic_lookup";
+#endif
+
}
continue;
@@ -767,6 +766,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!strcmp(cur, "-x")) x_set = 1;
if (!strcmp(cur, "-E")) preprocessor_only = 1;
if (!strcmp(cur, "-shared")) shared_linking = 1;
+ if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
+ if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
+ if (!strcmp(cur, "-r")) partial_linking = 1;
+ if (!strcmp(cur, "--relocatable")) partial_linking = 1;
if (!strcmp(cur, "-c")) have_c = 1;
if (!strncmp(cur, "-O", 2)) have_o = 1;
@@ -996,7 +999,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
switch (bit_mode) {
case 0:
- if (!shared_linking)
+ if (!shared_linking && !partial_linking)
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-compiler-rt.o", obj_path);
if (lto_mode)
@@ -1005,7 +1008,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
break;
case 32:
- if (!shared_linking) {
+ if (!shared_linking && !partial_linking) {
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-compiler-rt-32.o", obj_path);
@@ -1026,7 +1029,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
break;
case 64:
- if (!shared_linking) {
+ if (!shared_linking && !partial_linking) {
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-compiler-rt-64.o", obj_path);
@@ -1049,7 +1052,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
#if !defined(__APPLE__) && !defined(__sun)
- if (!shared_linking)
+ if (!shared_linking && !partial_linking)
cc_params[cc_par_cnt++] =
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
#endif
diff --git a/src/afl-common.c b/src/afl-common.c
index c61ce3d8..9ca2b3e8 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -751,6 +751,8 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
}
+/* Get unix time in milliseconds */
+
u64 get_cur_time(void) {
struct timeval tv;
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 3d472b36..8fb8a75a 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -90,6 +90,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
/* exec related stuff */
fsrv->child_pid = -1;
fsrv->map_size = get_map_size();
+ fsrv->real_map_size = fsrv->map_size;
fsrv->use_fauxsrv = false;
fsrv->last_run_timed_out = false;
fsrv->debug = false;
@@ -110,6 +111,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->init_tmout = from->init_tmout;
fsrv_to->mem_limit = from->mem_limit;
fsrv_to->map_size = from->map_size;
+ fsrv_to->real_map_size = from->real_map_size;
fsrv_to->support_shmem_fuzz = from->support_shmem_fuzz;
fsrv_to->out_file = from->out_file;
fsrv_to->dev_urandom_fd = from->dev_urandom_fd;
@@ -691,15 +693,15 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
- if (unlikely(tmp_map_size % 64)) {
+ fsrv->real_map_size = tmp_map_size;
+
+ if (tmp_map_size % 64) {
- // should not happen
- WARNF("Target reported non-aligned map size of %u", tmp_map_size);
tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
}
- if (!be_quiet) { ACTF("Target map size: %u", tmp_map_size); }
+ if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); }
if (tmp_map_size > fsrv->map_size) {
FATAL(
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 97f10e6f..0a9242a5 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -551,19 +551,18 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
- if (cksum)
- afl->queue_top->exec_cksum = cksum;
- else
- cksum = afl->queue_top->exec_cksum =
- hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
-
- if (afl->schedule >= FAST && afl->schedule <= RARE) {
+ /* AFLFast schedule? update the new queue entry */
+ if (cksum) {
afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
}
+ /* due to classify counts we have to recalculate the checksum */
+ cksum = afl->queue_top->exec_cksum =
+ hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
/* Try to calibrate inline; this also calls update_bitmap_score() when
successful. */
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 88b5bc02..5e4f1585 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -480,13 +480,22 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
for (iter = 0; iter < afl->foreign_sync_cnt; iter++) {
- if (afl->foreign_syncs[iter].dir != NULL &&
- afl->foreign_syncs[iter].dir[0] != 0) {
+ if (afl->foreign_syncs[iter].dir && afl->foreign_syncs[iter].dir[0]) {
if (first) ACTF("Scanning '%s'...", afl->foreign_syncs[iter].dir);
time_t mtime_max = 0;
- u8 * name = strrchr(afl->foreign_syncs[iter].dir, '/');
- if (!name) { name = afl->foreign_syncs[iter].dir; }
+
+ u8 *name = strrchr(afl->foreign_syncs[iter].dir, '/');
+ if (!name) {
+
+ name = afl->foreign_syncs[iter].dir;
+
+ } else {
+
+ ++name;
+
+ }
+
if (!strcmp(name, "queue") || !strcmp(name, "out") ||
!strcmp(name, "default")) {
@@ -701,96 +710,103 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
- for (i = 0; i < (u32)nl_cnt; ++i) {
+ if (nl_cnt) {
- struct stat st;
+ i = nl_cnt;
+ do {
- u8 dfn[PATH_MAX];
- snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
- nl[i]->d_name);
- u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
+ --i;
- u8 passed_det = 0;
+ struct stat st;
+ u8 dfn[PATH_MAX];
+ snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
+ nl[i]->d_name);
+ u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
- if (lstat(fn2, &st) || access(fn2, R_OK)) {
+ u8 passed_det = 0;
- PFATAL("Unable to access '%s'", fn2);
+ if (lstat(fn2, &st) || access(fn2, R_OK)) {
- }
+ PFATAL("Unable to access '%s'", fn2);
- /* obviously we want to skip "descending" into . and .. directories,
- however it is a good idea to skip also directories that start with
- a dot */
- if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
+ }
- free(nl[i]); /* not tracked */
- read_testcases(afl, fn2);
- ck_free(fn2);
- continue;
+ /* obviously we want to skip "descending" into . and .. directories,
+ however it is a good idea to skip also directories that start with
+ a dot */
+ if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
- }
+ free(nl[i]); /* not tracked */
+ read_testcases(afl, fn2);
+ ck_free(fn2);
+ continue;
- free(nl[i]);
+ }
- if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
+ free(nl[i]);
- ck_free(fn2);
- continue;
+ if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
- }
+ ck_free(fn2);
+ continue;
- if (st.st_size > MAX_FILE) {
+ }
- WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
- stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
- stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
+ if (st.st_size > MAX_FILE) {
- }
+ WARNF("Test case '%s' is too big (%s, limit is %s), partial reading",
+ fn2,
+ stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
+ stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
- /* Check for metadata that indicates that deterministic fuzzing
- is complete for this entry. We don't want to repeat deterministic
- fuzzing when resuming aborted scans, because it would be pointless
- and probably very time-consuming. */
+ }
- if (!access(dfn, F_OK)) { passed_det = 1; }
+ /* Check for metadata that indicates that deterministic fuzzing
+ is complete for this entry. We don't want to repeat deterministic
+ fuzzing when resuming aborted scans, because it would be pointless
+ and probably very time-consuming. */
- add_to_queue(afl, fn2, st.st_size >= MAX_FILE ? MAX_FILE : st.st_size,
- passed_det);
+ if (!access(dfn, F_OK)) { passed_det = 1; }
- if (unlikely(afl->shm.cmplog_mode)) {
+ add_to_queue(afl, fn2, st.st_size >= MAX_FILE ? MAX_FILE : st.st_size,
+ passed_det);
- if (afl->cmplog_lvl == 1) {
+ if (unlikely(afl->shm.cmplog_mode)) {
- if (!afl->cmplog_max_filesize ||
- afl->cmplog_max_filesize < st.st_size) {
+ if (afl->cmplog_lvl == 1) {
- afl->cmplog_max_filesize = st.st_size;
+ if (!afl->cmplog_max_filesize ||
+ afl->cmplog_max_filesize < st.st_size) {
- }
+ afl->cmplog_max_filesize = st.st_size;
- } else if (afl->cmplog_lvl == 2) {
+ }
+
+ } else if (afl->cmplog_lvl == 2) {
- if (!afl->cmplog_max_filesize ||
- afl->cmplog_max_filesize > st.st_size) {
+ if (!afl->cmplog_max_filesize ||
+ afl->cmplog_max_filesize > st.st_size) {
- afl->cmplog_max_filesize = st.st_size;
+ afl->cmplog_max_filesize = st.st_size;
+
+ }
}
}
- }
+ /*
+ if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
- /*
- if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size,
+ HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
+ afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
- u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size,
- HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
- afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
+ }
- }
+ */
- */
+ } while (i > 0);
}
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index e27d6fae..79a47744 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -393,6 +393,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
+ classify_counts(&afl->fsrv);
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
}
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index c3ce2edd..1bc5854e 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -73,7 +73,7 @@ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) {
/* Helper to choose random block len for block operations in fuzz_one().
Doesn't return zero, provided that max_len is > 0. */
-static u32 choose_block_len(afl_state_t *afl, u32 limit) {
+static inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
u32 min_value, max_value;
u32 rlim = MIN(afl->queue_cycle, (u32)3);
@@ -2057,7 +2057,7 @@ havoc_stage:
temp_len = new_len;
if (out_buf != custom_havoc_buf) {
- afl_realloc(AFL_BUF_PARAM(out), temp_len);
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len);
if (unlikely(!afl->out_buf)) { PFATAL("alloc"); }
memcpy(out_buf, custom_havoc_buf, temp_len);
@@ -2102,9 +2102,9 @@ havoc_stage:
case 8 ... 9: {
- /* Set word to interesting value, randomly choosing endian. */
+ case 8 ... 9: {
- if (temp_len < 2) { break; }
+ /* Set word to interesting value, little endian. */
#ifdef INTROSPECTION
snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
@@ -2136,9 +2136,9 @@ havoc_stage:
case 12 ... 13: {
- /* Set dword to interesting value, randomly choosing endian. */
+ case 12 ... 13: {
- if (temp_len < 4) { break; }
+ /* Set dword to interesting value, little endian. */
#ifdef INTROSPECTION
snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
@@ -2862,6 +2862,7 @@ abandon_entry:
--afl->pending_not_fuzzed;
afl->queue_cur->was_fuzzed = 1;
+ afl->reinit_table = 1;
if (afl->queue_cur->favored) { --afl->pending_favored; }
}
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 811e805c..b759532c 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -58,7 +58,8 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
weight *= (log(q->bitmap_size) / avg_bitmap_size);
weight *= (1 + (q->tc_ref / avg_top_size));
- if (unlikely(q->favored)) weight *= 5;
+ if (unlikely(q->favored)) { weight *= 5; }
+ if (unlikely(!q->was_fuzzed)) { weight *= 2; }
return weight;
@@ -198,6 +199,8 @@ void create_alias_table(afl_state_t *afl) {
while (nS)
afl->alias_probability[S[--nS]] = 1;
+ afl->reinit_table = 0;
+
/*
#ifdef INTROSPECTION
u8 fn[PATH_MAX];
@@ -1132,12 +1135,10 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
do_once = 1;
// release unneeded memory
- u8 *ptr = ck_realloc(
+ afl->q_testcase_cache = ck_realloc(
afl->q_testcase_cache,
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
- if (ptr) { afl->q_testcase_cache = (struct queue_entry **)ptr; }
-
}
/* Cache full. We neet to evict one or more to map one.
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 22fd0621..268f726c 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -252,7 +252,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
u64 start_time = get_cur_time();
#endif
- u32 screen_update = 1000000 / afl->queue_cur->exec_us;
+ u32 screen_update;
u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@@ -261,6 +261,24 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
afl->stage_max = (len << 1);
afl->stage_cur = 0;
+ if (likely(afl->queue_cur->exec_us)) {
+
+ if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
+
+ screen_update = 100000 / afl->queue_cur->exec_us;
+
+ } else {
+
+ screen_update = 1;
+
+ }
+
+ } else {
+
+ screen_update = 100000;
+
+ }
+
// in colorization we do not classify counts, hence we have to calculate
// the original checksum.
if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
@@ -905,17 +923,16 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..."
s64 diff = pattern - b_val;
s64 o_diff = o_pattern - o_b_val;
- /*
- fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
- h->shape + 1, o_pattern, o_b_val, o_diff);
- fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
- b_val, diff);*/
+ /* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
+ h->shape + 1, o_pattern, o_b_val, o_diff);
+ fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
+ b_val, diff); */
if (diff == o_diff && diff) {
// this could be an arithmetic transformation
u64 new_repl = (u64)((s64)repl - diff);
- // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
+ // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@@ -935,15 +952,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
diff = pattern ^ b_val;
s64 o_diff = o_pattern ^ o_b_val;
- /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
- idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr,
- "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/
+ /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
+ idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+ fprintf(stderr,
+ "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
+ */
if (diff == o_diff && diff) {
// this could be a XOR transformation
u64 new_repl = (u64)((s64)repl ^ diff);
- // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
+ // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@@ -982,15 +1001,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
- idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr,
- "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/
+ /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
+ idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+ fprintf(stderr,
+ "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
+ */
if (o_diff && diff) {
// this could be a lower to upper
u64 new_repl = (repl & (0x5f5f5f5f5f5f5f5f & mask));
- // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
+ // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@@ -1029,15 +1050,17 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
- idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr,
- "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/
+ /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
+ idx, h->shape + 1, o_pattern, o_b_val, o_diff);
+ fprintf(stderr,
+ "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
+ */
if (o_diff && diff) {
// this could be a lower to upper
u64 new_repl = (repl | (0x2020202020202020 & mask));
- // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
+ // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
@@ -1383,7 +1406,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- //#endif /* CMPLOG_SOLVE_ARITHMETIC
+ //#endif /*
+ // CMPLOG_SOLVE_ARITHMETIC
return 0;
@@ -2152,7 +2176,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
memcpy(buf + idx, tmp, i + 1);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
- // fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex, *status);
+ // fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex,
+ // *status);
}
@@ -2235,7 +2260,8 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
for (j = 0; j <= i; j++)
buf[idx + j] = repl[j] - arith_val[j];
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
- // fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith, *status);
+ // fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith,
+ // *status);
}
@@ -2328,16 +2354,17 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
/*
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
- fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
- h->shape, h->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x",
- o->v0[j]); fprintf(stderr, " v1="); for (j = 0; j < 8; j++) fprintf(stderr,
- "%02x", o->v1[j]); fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u
- o0=", hh->hits, hh->id, hh->shape, hh->attribute); for (j = 0; j < 8; j++)
- fprintf(stderr, "%02x", orig_o->v0[j]);
- fprintf(stderr, " o1=");
- for (j = 0; j < 8; j++)
- fprintf(stderr, "%02x", orig_o->v1[j]);
- fprintf(stderr, "\n");
+ fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits,
+ h->id, h->shape, h->attribute);
+ for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]);
+ fprintf(stderr, " v1=");
+ for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]);
+ fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=",
+ hh->hits, hh->id, hh->shape, hh->attribute);
+ for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]);
+ fprintf(stderr, " o1=");
+ for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]);
+ fprintf(stderr, "\n");
*/
t = taint;
@@ -2663,7 +2690,12 @@ exit_its:
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
- ck_free(afl->queue_cur->cmplog_colorinput);
+ if (afl->queue_cur->cmplog_colorinput) {
+
+ ck_free(afl->queue_cur->cmplog_colorinput);
+
+ }
+
while (taint) {
t = taint->next;
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 2c3e8a1b..fb81522e 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -314,7 +314,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
++q->cal_failed;
afl->stage_name = "calibration";
- afl->stage_max = afl->fast_cal ? 3 : CAL_CYCLES;
+ afl->stage_max = afl->afl_env.afl_cal_fast ? 3 : CAL_CYCLES;
/* Make sure the forkserver is up before we do anything, and let's not
count its spin-up time toward binary calibration. */
@@ -333,7 +333,6 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) {
- unsetenv(SHM_FUZZ_ENV_VAR);
afl_shm_deinit(afl->shm_fuzz);
ck_free(afl->shm_fuzz);
afl->shm_fuzz = NULL;
@@ -356,6 +355,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+ if (unlikely(afl->debug)) {
+
+ DEBUGF("calibration stage %d/%d\n", afl->stage_cur + 1, afl->stage_max);
+
+ }
+
u64 cksum;
write_to_testcase(afl, use_mem, q->len);
@@ -403,6 +408,21 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
+ if (unlikely(!var_detected)) {
+
+ // note: from_queue seems to only be set during initialization
+ if (afl->afl_env.afl_no_ui || from_queue) {
+
+ WARNF("instability detected during calibration");
+
+ } else if (afl->debug) {
+
+ DEBUGF("instability detected during calibration\n");
+
+ }
+
+ }
+
var_detected = 1;
afl->stage_max = afl->fast_cal ? CAL_CYCLES : CAL_CYCLES_LONG;
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 0658070e..b832c11e 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -96,8 +96,6 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->splicing_with = -1; /* Splicing with which test case? */
afl->cpu_to_bind = -1;
afl->havoc_stack_pow2 = HAVOC_STACK_POW2;
- afl->cal_cycles = CAL_CYCLES;
- afl->cal_cycles_long = CAL_CYCLES_LONG;
afl->hang_tmout = EXEC_TIMEOUT;
afl->exit_on_time = 0;
afl->stats_update_freq = 1;
@@ -341,6 +339,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_cal_fast =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_FAST_CAL",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_cal_fast =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_STATSD",
afl_environment_variable_len)) {
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 4884b942..c2294f7c 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -264,6 +264,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"peak_rss_mb : %lu\n"
"cpu_affinity : %d\n"
"edges_found : %u\n"
+ "total_edges : %u\n"
"var_byte_count : %u\n"
"havoc_expansion : %u\n"
"testcache_size : %llu\n"
@@ -303,10 +304,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
#else
-1,
#endif
- t_bytes, afl->var_byte_count, afl->expand_havoc,
- afl->q_testcase_cache_size, afl->q_testcase_cache_count,
- afl->q_testcase_evictions, afl->use_banner,
- afl->unicorn_mode ? "unicorn" : "",
+ t_bytes, afl->fsrv.real_map_size, afl->var_byte_count,
+ afl->expand_havoc, afl->q_testcase_cache_size,
+ afl->q_testcase_cache_count, afl->q_testcase_evictions,
+ afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
afl->fsrv.qemu_mode ? "qemu " : "",
afl->non_instrumented_mode ? " non_instrumented " : "",
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
@@ -326,7 +327,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
u32 i = 0;
fprintf(f, "virgin_bytes :");
- for (i = 0; i < afl->fsrv.map_size; i++) {
+ for (i = 0; i < afl->fsrv.real_map_size; i++) {
if (afl->virgin_bits[i] != 0xff) {
@@ -338,7 +339,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
fprintf(f, "\n");
fprintf(f, "var_bytes :");
- for (i = 0; i < afl->fsrv.map_size; i++) {
+ for (i = 0; i < afl->fsrv.real_map_size; i++) {
if (afl->var_bytes[i]) { fprintf(f, " %u", i); }
@@ -520,7 +521,7 @@ void show_stats(afl_state_t *afl) {
/* Do some bitmap stats. */
t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
- t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.map_size;
+ t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.real_map_size;
if (likely(t_bytes) && unlikely(afl->var_byte_count)) {
@@ -766,9 +767,9 @@ void show_stats(afl_state_t *afl) {
" uniq hangs : " cRST "%-6s" bSTG bV "\n",
time_tmp, tmp);
- SAYF(bVR bH bSTOP cCYA
- " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
- " map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
+ SAYF(bVR bH bSTOP cCYA
+ " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA
+ " map coverage" bSTG bHT bH20 bH2 bVL "\n");
/* This gets funny because we want to print several variable-length variables
together, but then cram them into a fixed-width field - so we need to
@@ -778,13 +779,13 @@ void show_stats(afl_state_t *afl) {
afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level,
((double)afl->current_entry * 100) / afl->queued_paths);
- SAYF(bV bSTOP " now processing : " cRST "%-16s " bSTG bV bSTOP, tmp);
+ SAYF(bV bSTOP " now processing : " cRST "%-18s " bSTG bV bSTOP, tmp);
sprintf(tmp, "%0.02f%% / %0.02f%%",
- ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.map_size,
+ ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.real_map_size,
t_byte_ratio);
- SAYF(" map density : %s%-21s" bSTG bV "\n",
+ SAYF(" map density : %s%-19s" bSTG bV "\n",
t_byte_ratio > 70
? cLRD
: ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST),
@@ -793,23 +794,23 @@ void show_stats(afl_state_t *afl) {
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_paths),
((double)afl->cur_skipped_paths * 100) / afl->queued_paths);
- SAYF(bV bSTOP " paths timed out : " cRST "%-16s " bSTG bV, tmp);
+ SAYF(bV bSTOP " paths timed out : " cRST "%-18s " bSTG bV, tmp);
sprintf(tmp, "%0.02f bits/tuple", t_bytes ? (((double)t_bits) / t_bytes) : 0);
- SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp);
+ SAYF(bSTOP " count coverage : " cRST "%-19s" bSTG bV "\n", tmp);
- SAYF(bVR bH bSTOP cCYA
- " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
- " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
+ SAYF(bVR bH bSTOP cCYA
+ " stage progress " bSTG bH10 bH5 bH2 bH2 bH2 bX bH bSTOP cCYA
+ " findings in depth " bSTG bH10 bH5 bH2 bVL "\n");
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
((double)afl->queued_favored) * 100 / afl->queued_paths);
/* Yeah... it's still going on... halp? */
- SAYF(bV bSTOP " now trying : " cRST "%-20s " bSTG bV bSTOP
- " favored paths : " cRST "%-22s" bSTG bV "\n",
+ SAYF(bV bSTOP " now trying : " cRST "%-22s " bSTG bV bSTOP
+ " favored paths : " cRST "%-20s" bSTG bV "\n",
afl->stage_name, tmp);
if (!afl->stage_max) {
@@ -824,12 +825,12 @@ void show_stats(afl_state_t *afl) {
}
- SAYF(bV bSTOP " stage execs : " cRST "%-21s" bSTG bV bSTOP, tmp);
+ SAYF(bV bSTOP " stage execs : " cRST "%-23s" bSTG bV bSTOP, tmp);
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov),
((double)afl->queued_with_cov) * 100 / afl->queued_paths);
- SAYF(" new edges on : " cRST "%-22s" bSTG bV "\n", tmp);
+ SAYF(" new edges on : " cRST "%-20s" bSTG bV "\n", tmp);
sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_crashes),
u_stringify_int(IB(1), afl->unique_crashes),
@@ -837,14 +838,14 @@ void show_stats(afl_state_t *afl) {
if (afl->crash_mode) {
- SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
- " new crashes : %s%-22s" bSTG bV "\n",
+ SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP
+ " new crashes : %s%-20s" bSTG bV "\n",
u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp);
} else {
- SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
- " total crashes : %s%-22s" bSTG bV "\n",
+ SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP
+ " total crashes : %s%-20s" bSTG bV "\n",
u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp);
}
@@ -856,12 +857,12 @@ void show_stats(afl_state_t *afl) {
sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
- SAYF(bV bSTOP " exec speed : " cLRD "%-20s ", tmp);
+ SAYF(bV bSTOP " exec speed : " cLRD "%-22s ", tmp);
} else {
sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec));
- SAYF(bV bSTOP " exec speed : " cRST "%-20s ", tmp);
+ SAYF(bV bSTOP " exec speed : " cRST "%-22s ", tmp);
}
@@ -869,13 +870,16 @@ void show_stats(afl_state_t *afl) {
u_stringify_int(IB(1), afl->unique_tmouts),
(afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
- SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-22s" bSTG bV "\n", tmp);
+ SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-20s" bSTG bV "\n", tmp);
/* Aaaalmost there... hold on! */
- SAYF(bVR bH cCYA bSTOP
- " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
- " path geometry " bSTG bH5 bH2 bVL "\n");
+ SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH2 bHT bH10 bH2
+ bH bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n");
+
+ if (unlikely(afl->custom_only)) {
+
+ strcpy(tmp, "disabled (custom-mutator-only mode)");
if (unlikely(afl->custom_only)) {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 5bdb4c8d..0c7b6e42 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -125,7 +125,7 @@ static void usage(u8 *argv0, int more_help) {
"entering the\n"
" pacemaker mode (minutes of no new paths). 0 = "
"immediately,\n"
- " -1 = immediately and together with normal mutation).\n"
+ " -1 = immediately and together with normal mutation.\n"
" See docs/README.MOpt.md\n"
" -c program - enable CmpLog by specifying a binary compiled for "
"it.\n"
@@ -143,7 +143,7 @@ static void usage(u8 *argv0, int more_help) {
" -x dict_file - fuzzer dictionary (see README.md, specify up to 4 "
"times)\n\n"
- "Testing settings:\n"
+ "Test settings:\n"
" -s seed - use a fixed seed for the RNG\n"
" -V seconds - fuzz for a specified time then terminate\n"
" -E execs - fuzz for an approx. no. of total executions then "
@@ -158,7 +158,7 @@ static void usage(u8 *argv0, int more_help) {
" -F path - sync to a foreign fuzzer queue directory (requires "
"-M, can\n"
" be specified up to %u times)\n"
- " -d - skip deterministic fuzzing in -M mode\n"
+ // " -d - skip deterministic fuzzing in -M mode\n"
" -T text - text banner to show on the screen\n"
" -I command - execute this command/script when a new crash is "
"found\n"
@@ -575,7 +575,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
afl->sync_id = ck_strdup(optarg);
- afl->skip_deterministic = 0; // force deterministic fuzzing
afl->old_seed_selection = 1; // force old queue walking seed selection
afl->disable_trim = 1; // disable trimming
@@ -1206,6 +1205,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ setenv("__AFL_OUT_DIR", afl->out_dir, 1);
+
if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
@@ -1275,7 +1276,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
- if (get_afl_env("AFL_FAST_CAL")) { afl->fast_cal = 1; }
if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
if (afl->afl_env.afl_autoresume) {
@@ -1488,14 +1488,6 @@ int main(int argc, char **argv_orig, char **envp) {
check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
- if (afl->afl_env.afl_cal_fast) {
-
- /* Use less calibration cycles, for slow applications */
- afl->cal_cycles = 3;
- afl->cal_cycles_long = 5;
-
- }
-
if (afl->afl_env.afl_custom_mutator_only) {
/* This ensures we don't proceed to havoc/splice */
@@ -1919,7 +1911,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
afl->start_time = get_cur_time();
- if (afl->in_place_resume || afl->afl_env.afl_autoresume) load_stats_file(afl);
+ if (afl->in_place_resume || afl->afl_env.afl_autoresume) {
+
+ load_stats_file(afl);
+
+ }
+
write_stats_file(afl, 0, 0, 0, 0);
maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
@@ -2157,7 +2154,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (likely(!afl->old_seed_selection)) {
- if (unlikely(prev_queued_paths < afl->queued_paths)) {
+ if (unlikely(prev_queued_paths < afl->queued_paths ||
+ afl->reinit_table)) {
// we have new queue entries since the last run, recreate alias table
prev_queued_paths = afl->queued_paths;
@@ -2283,13 +2281,10 @@ stop_fuzzing:
destroy_queue(afl);
destroy_extras(afl);
destroy_custom_mutators(afl);
- unsetenv(SHM_ENV_VAR);
- unsetenv(CMPLOG_SHM_ENV_VAR);
afl_shm_deinit(&afl->shm);
if (afl->shm_fuzz) {
- unsetenv(SHM_FUZZ_ENV_VAR);
afl_shm_deinit(afl->shm_fuzz);
ck_free(afl->shm_fuzz);
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 96b72dd9..5278c839 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -67,6 +67,8 @@ static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
*out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
+static u8 outfile[PATH_MAX];
+
static u8 *in_data, /* Input data */
*coverage_map; /* Coverage map */
@@ -230,7 +232,11 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"),
caa = !!getenv("AFL_CMIN_ALLOW_ANY");
- if (!outfile) { FATAL("Output filename not set (Bug in AFL++?)"); }
+ if (!outfile || !*outfile) {
+
+ FATAL("Output filename not set (Bug in AFL++?)");
+
+ }
if (cmin_mode &&
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
@@ -394,7 +400,28 @@ static u32 read_file(u8 *in_file) {
if (fstat(fd, &st) || !st.st_size) {
- WARNF("Zero-sized input file '%s'.", in_file);
+ if (!be_quiet && !quiet_mode) {
+
+ WARNF("Zero-sized input file '%s'.", in_file);
+
+ }
+
+ }
+
+ if (st.st_size > MAX_FILE) {
+
+ if (!be_quiet && !quiet_mode) {
+
+ WARNF("Input file '%s' is too large, only reading %u bytes.", in_file,
+ MAX_FILE);
+
+ }
+
+ in_len = MAX_FILE;
+
+ } else {
+
+ in_len = st.st_size;
}
@@ -692,6 +719,96 @@ static void setup_signal_handlers(void) {
}
+u32 execute_testcases(u8 *dir) {
+
+ struct dirent **nl;
+ s32 nl_cnt, subdirs = 1;
+ u32 i, done = 0;
+ u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
+
+ if (!be_quiet) { ACTF("Scanning '%s'...", dir); }
+
+ /* We use scandir() + alphasort() rather than readdir() because otherwise,
+ the ordering of test cases would vary somewhat randomly and would be
+ difficult to control. */
+
+ nl_cnt = scandir(dir, &nl, NULL, alphasort);
+
+ if (nl_cnt < 0) { return 0; }
+
+ for (i = 0; i < (u32)nl_cnt; ++i) {
+
+ struct stat st;
+
+ u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
+
+ if (lstat(fn2, &st) || access(fn2, R_OK)) {
+
+ PFATAL("Unable to access '%s'", fn2);
+
+ }
+
+ /* obviously we want to skip "descending" into . and .. directories,
+ however it is a good idea to skip also directories that start with
+ a dot */
+ if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
+
+ free(nl[i]); /* not tracked */
+ done += execute_testcases(fn2);
+ ck_free(fn2);
+ continue;
+
+ }
+
+ if (!S_ISREG(st.st_mode) || !st.st_size) {
+
+ free(nl[i]);
+ ck_free(fn2);
+ continue;
+
+ }
+
+ if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) {
+
+ WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
+ stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
+ stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
+
+ }
+
+ if (!collect_coverage)
+ snprintf(outfile, sizeof(outfile), "%s/%s", out_file, nl[i]->d_name);
+
+ free(nl[i]);
+
+ if (read_file(fn2)) {
+
+ if (wait_for_gdb) {
+
+ fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
+ fprintf(stderr, "exec: kill -CONT %d\n", getpid());
+ kill(0, SIGSTOP);
+
+ }
+
+ showmap_run_target_forkserver(fsrv, in_data, in_len);
+ ck_free(in_data);
+ ++done;
+
+ if (collect_coverage)
+ analyze_results(fsrv);
+ else
+ tcnt = write_results_to_file(fsrv, outfile);
+
+ }
+
+ }
+
+ free(nl); /* not tracked */
+ return done;
+
+}
+
/* Show banner. */
static void show_banner(void) {
@@ -710,7 +827,7 @@ static void usage(u8 *argv0) {
"\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
"Required parameters:\n"
- " -o file - file to write the trace data to\n\n"
+ " -o file - file to write the trace data to\n\n"
"Execution control settings:\n"
" -t msec - timeout for each run (none)\n"
@@ -722,19 +839,19 @@ static void usage(u8 *argv0) {
" (Not necessary, here for consistency with other afl-* "
"tools)\n\n"
"Other settings:\n"
- " -i dir - process all files in this directory, must be combined "
+ " -i dir - process all files below this directory, must be combined "
"with -o.\n"
- " With -C, -o is a file, without -C it must be a "
+ " With -C, -o is a file, without -C it must be a "
"directory\n"
- " and each bitmap will be written there individually.\n"
- " -C - collect coverage, writes all edges to -o and gives a "
+ " and each bitmap will be written there individually.\n"
+ " -C - collect coverage, writes all edges to -o and gives a "
"summary\n"
- " Must be combined with -i.\n"
- " -q - sink program's output and don't show messages\n"
- " -e - show edge coverage only, ignore hit counts\n"
- " -r - show real tuple values instead of AFL filter values\n"
- " -s - do not classify the map\n"
- " -c - allow core dumps\n\n"
+ " Must be combined with -i.\n"
+ " -q - sink program's output and don't show messages\n"
+ " -e - show edge coverage only, ignore hit counts\n"
+ " -r - show real tuple values instead of AFL filter values\n"
+ " -s - do not classify the map\n"
+ " -c - allow core dumps\n\n"
"This tool displays raw tuple data captured by AFL instrumentation.\n"
"For additional help, consult %s/README.md.\n\n"
@@ -1000,6 +1117,11 @@ int main(int argc, char **argv_orig, char **envp) {
check_environment_vars(envp);
+ if (getenv("AFL_NO_FORKSRV")) { /* if set, use the fauxserver */
+ fsrv->use_fauxsrv = true;
+
+ }
+
if (getenv("AFL_DEBUG")) {
DEBUGF("");
@@ -1177,7 +1299,7 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
- if ((coverage_map = (u8 *)malloc(map_size)) == NULL)
+ if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
FATAL("coult not grab memory");
edges_only = false;
raw_instr_output = true;
@@ -1260,44 +1382,7 @@ int main(int argc, char **argv_orig, char **envp) {
continue; // skip anything that starts with '.'
- }
-
-#if defined(DT_REG) /* Posix and Solaris do not know d_type and DT_REG */
- if (dir_ent->d_type != DT_REG) {
-
- continue; // only regular files
-
- }
-
-#endif
-
- snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name);
-
-#if !defined(DT_REG) /* use stat() */
- if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
-#endif
-
- if (!collect_coverage)
- snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
-
- if (read_file(infile)) {
-
- if (wait_for_gdb) {
-
- fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
- fprintf(stderr, "exec: kill -CONT %d\n", getpid());
- kill(0, SIGSTOP);
-
- }
-
- showmap_run_target_forkserver(fsrv, in_data, in_len);
- ck_free(in_data);
- if (collect_coverage)
- analyze_results(fsrv);
- else
- tcnt = write_results_to_file(fsrv, outfile);
-
- }
+ FATAL("could not read input testcases from %s", in_dir);
}
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 6656712a..2d80abe4 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -877,12 +877,13 @@ static void usage(u8 *argv0) {
" 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_NO_FORKSRV: run target via execve instead of using the forkserver\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);
+ "TMPDIR: directory to use for temporary input files\n",
+ argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
exit(1);
@@ -1104,6 +1105,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !in_file || !output_file) { usage(argv[0]); }
check_environment_vars(envp);
+
+ if (getenv("AFL_NO_FORKSRV")) { /* if set, use the fauxserver */
+ fsrv->use_fauxsrv = true;
+
+ }
+
setenv("AFL_NO_AUTODICT", "1", 1);
/* initialize cmplog_mode */