aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-forkserver.c18
-rw-r--r--src/afl-fuzz-bitmap.c8
-rw-r--r--src/afl-fuzz-init.c2
-rw-r--r--src/afl-fuzz-queue.c135
-rw-r--r--src/afl-fuzz-run.c33
-rw-r--r--src/afl-fuzz-state.c14
-rw-r--r--src/afl-fuzz-stats.c8
-rw-r--r--src/afl-fuzz.c383
-rw-r--r--src/afl-performance.c2
9 files changed, 554 insertions, 49 deletions
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 71d8570d..cec91f76 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -252,6 +252,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->uses_crash_exitcode = false;
fsrv->uses_asan = false;
+#ifdef __AFL_CODE_COVERAGE
+ fsrv->persistent_trace_bits = NULL;
+#endif
+
fsrv->init_child_func = fsrv_exec_child;
list_append(&fsrv_list, fsrv);
@@ -278,12 +282,19 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal;
fsrv_to->debug = from->debug;
+#ifdef __AFL_CODE_COVERAGE
+ fsrv_to->persistent_trace_bits = from->persistent_trace_bits;
+#endif
+
// These are forkserver specific.
fsrv_to->out_dir_fd = -1;
fsrv_to->child_pid = -1;
fsrv_to->use_fauxsrv = 0;
fsrv_to->last_run_timed_out = 0;
+ fsrv_to->late_send = from->late_send;
+ fsrv_to->custom_data_ptr = from->custom_data_ptr;
+
fsrv_to->init_child_func = from->init_child_func;
// Note: do not copy ->add_extra_func or ->persistent_record*
@@ -1944,6 +1955,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
+ if (unlikely(fsrv->late_send)) {
+
+ fsrv->late_send(fsrv->custom_data_ptr, fsrv->custom_input,
+ fsrv->custom_input_len);
+
+ }
+
exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout,
stop_soon_p);
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 03bc5d6c..97ccd3d3 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -75,9 +75,13 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
}
+#if __has_builtin(__builtin_popcount)
+ ret += __builtin_popcount(v);
+#else
v -= ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24;
+#endif
}
@@ -459,7 +463,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
- if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv);
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
@@ -485,7 +489,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* Generating a hash on every input is super expensive. Bad idea and should
only be used for special schedules */
- if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
classify_counts(&afl->fsrv);
classified = 1;
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 7310e49f..98de26dd 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -1019,7 +1019,7 @@ void perform_dry_run(afl_state_t *afl) {
}
- if (!q->was_fuzzed) {
+ if (unlikely(!q->was_fuzzed)) {
q->was_fuzzed = 1;
afl->reinit_table = 1;
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index f4cb930d..999929a1 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -123,7 +123,7 @@ void create_alias_table(afl_state_t *afl) {
double weight = 1.0;
{ // inline does result in a compile error with LTO, weird
- if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
@@ -133,39 +133,127 @@ void create_alias_table(afl_state_t *afl) {
if (likely(afl->schedule < RARE)) {
double t = q->exec_us / avg_exec_us;
+
if (likely(t < 0.1)) {
// nothing
- } else if (likely(t <= 0.25))
+ } else if (likely(t <= 0.25)) {
+
+ weight *= 0.95;
+
+ } else if (likely(t <= 0.5)) {
+
+ // nothing
+
+ } else if (likely(t <= 0.75)) {
+
+ weight *= 1.05;
+
+ } else if (likely(t <= 1.0)) {
- weight *= 0.9;
- else if (likely(t <= 0.5)) {
+ weight *= 1.1;
+
+ } else if (likely(t < 1.25)) {
+
+ weight *= 0.2; // WTF ??? makes no sense
+
+ } else if (likely(t <= 1.5)) {
// nothing
- } else if (likely(t < 1.0))
+ } else if (likely(t <= 2.0)) {
+
+ weight *= 1.1;
+
+ } else if (likely(t <= 2.5)) {
+
+ } else if (likely(t <= 5.0)) {
weight *= 1.15;
- else if (unlikely(t > 2.5 && t < 5.0))
+
+ } else if (likely(t <= 20.0)) {
+
weight *= 1.1;
- // else nothing
+ // else nothing
+
+ }
}
double l = q->len / avg_len;
- if (likely(l < 0.1))
- weight *= 0.75;
- else if (likely(l < 0.25))
- weight *= 1.1;
- else if (unlikely(l >= 10))
- weight *= 1.1;
+ if (likely(l < 0.1)) {
+
+ weight *= 0.5;
+
+ } else if (likely(l <= 0.5)) {
+
+ // nothing
+
+ } else if (likely(l <= 1.25)) {
+
+ weight *= 1.05;
+
+ } else if (likely(l <= 1.75)) {
+
+ // nothing
+
+ } else if (likely(l <= 2.0)) {
+
+ weight *= 0.95;
+
+ } else if (likely(l <= 5.0)) {
+
+ // nothing
+
+ } else if (likely(l <= 10.0)) {
+
+ weight *= 1.05;
+
+ } else {
+
+ weight *= 1.15;
+
+ }
double bms = q->bitmap_size / avg_bitmap_size;
- if (likely(bms < 0.5))
- weight *= (1.0 + ((bms - 0.5) / 2));
- else if (unlikely(bms > 1.33))
- weight *= 1.1;
+ if (likely(bms < 0.1)) {
+
+ weight *= 0.01;
+
+ } else if (likely(bms <= 0.25)) {
+
+ weight *= 0.55;
+
+ } else if (likely(bms <= 0.5)) {
+
+ // nothing
+
+ } else if (likely(bms <= 0.75)) {
+
+ weight *= 1.2;
+
+ } else if (likely(bms <= 1.25)) {
+
+ weight *= 1.3;
+
+ } else if (likely(bms <= 1.75)) {
+
+ weight *= 1.25;
+
+ } else if (likely(bms <= 2.0)) {
+
+ // nothing
+
+ } else if (likely(bms <= 2.5)) {
+
+ weight *= 1.3;
+
+ } else {
+
+ weight *= 0.75;
+
+ }
if (unlikely(!q->was_fuzzed)) { weight *= 2.5; }
if (unlikely(q->fs_redundant)) { weight *= 0.75; }
@@ -401,7 +489,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
} else {
- if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); }
+ if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/
+
+ }
}
@@ -699,12 +789,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
void destroy_queue(afl_state_t *afl) {
- u32 i;
+ u32 i;
+ struct queue_entry *q;
for (i = 0; i < afl->queued_items; i++) {
- struct queue_entry *q;
-
q = afl->queue_buf[i];
ck_free(q->fname);
ck_free(q->trace_mini);
@@ -740,7 +829,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
u64 fav_factor;
u64 fuzz_p2;
- if (likely(afl->schedule >= FAST && afl->schedule < RARE)) {
+ if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
fuzz_p2 = 0; // Skip the fuzz_p2 comparison
@@ -776,7 +865,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
u64 top_rated_fav_factor;
u64 top_rated_fuzz_p2;
- if (likely(afl->schedule >= FAST && afl->schedule < RARE)) {
+ if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 6a0da6ab..2f244a1d 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -60,6 +60,27 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon);
+#ifdef __AFL_CODE_COVERAGE
+ if (unlikely(!fsrv->persistent_trace_bits)) {
+
+ // On the first run, we allocate the persistent map to collect coverage.
+ fsrv->persistent_trace_bits = (u8 *)malloc(fsrv->map_size);
+ memset(fsrv->persistent_trace_bits, 0, fsrv->map_size);
+
+ }
+
+ for (u32 i = 0; i < fsrv->map_size; ++i) {
+
+ if (fsrv->persistent_trace_bits[i] != 255 && fsrv->trace_bits[i]) {
+
+ fsrv->persistent_trace_bits[i]++;
+
+ }
+
+ }
+
+#endif
+
/* If post_run() function is defined in custom mutator, the function will be
called each time after AFL++ executes the target program. */
@@ -173,7 +194,17 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
if (el->afl_custom_fuzz_send) {
- el->afl_custom_fuzz_send(el->data, *mem, new_size);
+ if (!afl->afl_env.afl_custom_mutator_late_send) {
+
+ el->afl_custom_fuzz_send(el->data, *mem, new_size);
+
+ } else {
+
+ afl->fsrv.custom_input = *mem;
+ afl->fsrv.custom_input_len = new_size;
+
+ }
+
sent = 1;
}
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index fbe6d32a..eead3e50 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -286,6 +286,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_no_sync =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_NO_FASTRESUME",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_no_fastresume =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY",
afl_environment_variable_len)) {
@@ -293,6 +300,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_custom_mutator_only =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_LATE_SEND",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_custom_mutator_late_send =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_CMPLOG_ONLY_NEW",
afl_environment_variable_len)) {
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 3a71e158..a20c46d0 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -76,7 +76,13 @@ char *get_fuzzing_state(afl_state_t *afl) {
void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
- u8 fn[PATH_MAX];
+ u8 fn[PATH_MAX], fn2[PATH_MAX];
+
+ snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir);
+ FILE *f2 = create_ffile(fn2);
+ fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path));
+ fclose(f2);
+
snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir);
FILE *f = create_ffile(fn);
u32 i;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index a7ddef6e..8a84d447 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -36,6 +36,67 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
+#ifdef HAVE_ZLIB
+
+ #define ck_gzread(fd, buf, len, fn) \
+ do { \
+ \
+ s32 _len = (s32)(len); \
+ s32 _res = gzread(fd, buf, _len); \
+ if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \
+ \
+ } while (0)
+
+ #define ck_gzwrite(fd, buf, len, fn) \
+ do { \
+ \
+ if (len <= 0) break; \
+ s32 _written = 0, _off = 0, _len = (s32)(len); \
+ \
+ do { \
+ \
+ s32 _res = gzwrite(fd, (buf) + _off, _len); \
+ if (_res != _len && (_res > 0 && _written + _res != _len)) { \
+ \
+ if (_res > 0) { \
+ \
+ _written += _res; \
+ _len -= _res; \
+ _off += _res; \
+ \
+ } else { \
+ \
+ RPFATAL(_res, "Short write to %s (%d of %d bytes)", fn, _res, \
+ _len); \
+ \
+ } \
+ \
+ } else { \
+ \
+ break; \
+ \
+ } \
+ \
+ } while (1); \
+ \
+ \
+ \
+ } while (0)
+
+ #include <zlib.h>
+ #define ZLIBOPEN gzopen
+ #define ZLIBREAD ck_gzread
+ #define NZLIBREAD gzread
+ #define ZLIBWRITE ck_gzwrite
+ #define ZLIBCLOSE gzclose
+ #define ZLIB_EXTRA "9"
+#else
+ #define ZLIBOPEN open
+ #define NZLIBREAD read
+ #define ZLIBREAD ck_read
+ #define ZLIBWRITE ck_write
+ #define ZLIBCLOSE close
+#endif
#ifdef __APPLE__
#include <sys/qos.h>
@@ -181,7 +242,7 @@ static void usage(u8 *argv0, int more_help) {
"it.\n"
" if using QEMU/FRIDA or the fuzzing target is "
"compiled\n"
- " for CmpLog then use '-c 0'. To disable Cmplog use '-c "
+ " for CmpLog then use '-c 0'. To disable CMPLOG use '-c "
"-'.\n"
" -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
" 1=small files, 2=larger files (default), 3=all "
@@ -335,6 +396,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
"AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
" suported formats: dogstatsd, librato, signalfx, influxdb\n"
+ "AFL_NO_FASTRESUME: do not read or write a fast resume file\n"
"AFL_NO_SYNC: disables all syncing\n"
"AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
"AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n"
@@ -960,7 +1022,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); }
+ if (afl->fsrv.mem_limit && afl->fsrv.mem_limit < 5) {
+
+ FATAL("Dangerously low value of -m");
+
+ }
if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) {
@@ -1868,6 +1934,15 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Using Frida Address Sanitizer Mode");
+ if (afl->fsrv.mem_limit) {
+
+ WARNF(
+ "in the Frida Address Sanitizer Mode we disable all memory "
+ "limits");
+ afl->fsrv.mem_limit = 0;
+
+ }
+
fasan_check_afl_preload(afl_preload);
setenv("ASAN_OPTIONS", "detect_leaks=false", 1);
@@ -2067,6 +2142,31 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->custom_mutators_count && afl->afl_env.afl_custom_mutator_late_send) {
+
+ u32 count_send = 0;
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz_send) {
+
+ if (count_send) {
+
+ FATAL(
+ "You can only have one custom send() function if you are using "
+ "AFL_CUSTOM_MUTATOR_LATE_SEND!");
+
+ }
+
+ afl->fsrv.late_send = el->afl_custom_fuzz_send;
+ afl->fsrv.custom_data_ptr = el->data;
+ count_send = 1;
+
+ }
+
+ });
+
+ }
+
if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
if (afl->custom_only) {
@@ -2101,13 +2201,92 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ setup_cmdline_file(afl, argv + optind);
+ check_binary(afl, argv[optind]);
+
+ u64 prev_target_hash = 0;
+ s32 fast_resume = 0;
+ #ifdef HAVE_ZLIB
+ gzFile fr_fd = NULL;
+ #else
+ s32 fr_fd = -1;
+ #endif
+
+ if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) {
+
+ u8 fn[PATH_MAX], buf[32];
+ snprintf(fn, PATH_MAX, "%s/target_hash", afl->out_dir);
+ s32 fd = open(fn, O_RDONLY);
+ if (fd >= 0) {
+
+ if (read(fd, buf, 32) >= 16) {
+
+ sscanf(buf, "%p", (void **)&prev_target_hash);
+
+ }
+
+ close(fd);
+
+ }
+
+ }
+
write_setup_file(afl, argc, argv);
- setup_cmdline_file(afl, argv + optind);
+ if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) {
+
+ u64 target_hash = get_binary_hash(afl->fsrv.target_path);
+
+ if (!target_hash || prev_target_hash != target_hash) {
+
+ ACTF("Target binary is different, cannot perform FAST RESUME!");
+
+ } else {
+
+ u8 fn[PATH_MAX];
+ snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir);
+ #ifdef HAVE_ZLIB
+ if ((fr_fd = ZLIBOPEN(fn, "rb")) != NULL) {
+
+ #else
+ if ((fr_fd = open(fn, O_RDONLY)) >= 0) {
+
+ #endif
+
+ u8 ver_string[8];
+ u64 *ver = (u64 *)ver_string;
+ u64 expect_ver =
+ afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
+
+ if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) !=
+ sizeof(ver_string))
+ WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME");
+ else if (expect_ver != *ver)
+ WARNF(
+ "Different AFL++ version or feature usage, cannot perform FAST "
+ "RESUME");
+ else {
+
+ OKF("Will perform FAST RESUME");
+ fast_resume = 1;
+
+ }
+
+ } else {
+
+ ACTF("fastresume.bin not found, cannot perform FAST RESUME!");
+
+ }
+
+ // If the fast resume file is not valid we will be unable to start, so
+ // we remove the file but keep the file descriptor open.
+ unlink(fn);
+
+ }
+
+ }
read_testcases(afl, NULL);
- // read_foreign_testcases(afl, 1); for the moment dont do this
- OKF("Loaded a total of %u seeds.", afl->queued_items);
pivot_inputs(afl);
@@ -2140,6 +2319,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ // read_foreign_testcases(afl, 1); for the moment dont do this
+ OKF("Loaded a total of %u seeds.", afl->queued_items);
+
/* If we don't have a file name chosen yet, use a safe default. */
if (!afl->fsrv.out_file) {
@@ -2196,8 +2378,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
- check_binary(afl, argv[optind]);
-
#ifdef AFL_PERSISTENT_RECORD
if (unlikely(afl->fsrv.persistent_record)) {
@@ -2416,7 +2596,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- OKF("Cmplog forkserver successfully started");
+ OKF("CMPLOG forkserver successfully started");
}
@@ -2454,29 +2634,102 @@ int main(int argc, char **argv_orig, char **envp) {
dedup_extras(afl);
if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
- // after we have the correct bitmap size we can read the bitmap -B option
- // and set the virgin maps
- if (afl->in_bitmap) {
+ if (unlikely(fast_resume)) {
- read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
+ u64 resume_start = get_cur_time_us();
+ // if we get here then we should abort on errors
+ ZLIBREAD(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
+ ZLIBREAD(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout");
+ ZLIBREAD(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash");
+ ZLIBREAD(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes");
- } else {
+ u8 res[1] = {0};
+ u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
+ u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
+ u32 r = 8 + afl->fsrv.map_size * 4;
+ u32 q_len = o_end - o_start;
+ u32 m_len = (afl->fsrv.map_size >> 3);
+ struct queue_entry *q;
- memset(afl->virgin_bits, 255, map_size);
+ for (u32 i = 0; i < afl->queued_items; i++) {
- }
+ q = afl->queue_buf[i];
+ ZLIBREAD(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
+ ZLIBREAD(fr_fd, res, 1, "check map");
+ if (res[0]) {
+
+ q->trace_mini = ck_alloc(m_len);
+ ZLIBREAD(fr_fd, q->trace_mini, m_len, "trace_mini");
+ r += q_len + m_len + 1;
+
+ } else {
+
+ r += q_len + 1;
+
+ }
+
+ afl->total_bitmap_size += q->bitmap_size;
+ ++afl->total_bitmap_entries;
+ update_bitmap_score(afl, q);
+
+ if (q->was_fuzzed) { --afl->pending_not_fuzzed; }
- memset(afl->virgin_tmout, 255, map_size);
- memset(afl->virgin_crash, 255, map_size);
+ if (q->disabled) {
+
+ if (!q->was_fuzzed) { --afl->pending_not_fuzzed; }
+ --afl->active_items;
+
+ }
+
+ if (q->var_behavior) { ++afl->queued_variable; }
+ if (q->favored) {
+
+ ++afl->queued_favored;
+ if (!q->was_fuzzed) { ++afl->pending_favored; }
+
+ }
+
+ }
- if (likely(!afl->afl_env.afl_no_startup_calibration)) {
+ u8 buf[4];
+ if (NZLIBREAD(fr_fd, buf, 3) > 0) {
- perform_dry_run(afl);
+ FATAL("invalid trailing data in fastresume.bin");
+
+ }
+
+ OKF("Successfully loaded fastresume.bin (%u bytes)!", r);
+ ZLIBCLOSE(fr_fd);
+ afl->reinit_table = 1;
+ update_calibration_time(afl, &resume_start);
} else {
- ACTF("skipping initial seed calibration due option override!");
- usleep(1000);
+ // after we have the correct bitmap size we can read the bitmap -B option
+ // and set the virgin maps
+ if (afl->in_bitmap) {
+
+ read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
+
+ } else {
+
+ memset(afl->virgin_bits, 255, map_size);
+
+ }
+
+ memset(afl->virgin_tmout, 255, map_size);
+ memset(afl->virgin_crash, 255, map_size);
+
+ if (likely(!afl->afl_env.afl_no_startup_calibration)) {
+
+ perform_dry_run(afl);
+
+ } else {
+
+ ACTF("Skipping initial seed calibration due option override!");
+ usleep(1000);
+
+ }
}
@@ -2984,6 +3237,28 @@ stop_fuzzing:
write_bitmap(afl);
save_auto(afl);
+ #ifdef __AFL_CODE_COVERAGE
+ if (afl->fsrv.persistent_trace_bits) {
+
+ char cfn[4096];
+ snprintf(cfn, sizeof(cfn), "%s/covmap.dump", afl->out_dir);
+
+ FILE *cov_fd;
+ if ((cov_fd = fopen(cfn, "w")) == NULL) {
+
+ PFATAL("could not create '%s'", cfn);
+
+ }
+
+ // Write the real map size, as the map size must exactly match the pointer
+ // map in length.
+ fwrite(afl->fsrv.persistent_trace_bits, 1, afl->fsrv.real_map_size, cov_fd);
+ fclose(cov_fd);
+
+ }
+
+ #endif
+
if (afl->pizza_is_served) {
SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST,
@@ -3067,6 +3342,72 @@ stop_fuzzing:
fclose(afl->fsrv.det_plot_file);
#endif
+ if (!afl->afl_env.afl_no_fastresume) {
+
+ /* create fastresume.bin */
+ u8 fr[PATH_MAX];
+ snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir);
+ ACTF("Writing %s ...", fr);
+ #ifdef HAVE_ZLIB
+ if ((fr_fd = ZLIBOPEN(fr, "wb9")) != NULL) {
+
+ #else
+ if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >=
+ #endif
+
+ u8 ver_string[8];
+ u32 w = 0;
+ u64 *ver = (u64 *)ver_string;
+ *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
+
+ ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string");
+ ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
+ ZLIBWRITE(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout");
+ ZLIBWRITE(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash");
+ ZLIBWRITE(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes");
+ w += sizeof(ver_string) + afl->fsrv.map_size * 4;
+
+ u8 on[1] = {1}, off[1] = {0};
+ u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
+ u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
+ u32 q_len = o_end - o_start;
+ u32 m_len = (afl->fsrv.map_size >> 3);
+ struct queue_entry *q;
+
+ afl->pending_not_fuzzed = afl->queued_items;
+ afl->active_items = afl->queued_items;
+
+ for (u32 i = 0; i < afl->queued_items; i++) {
+
+ q = afl->queue_buf[i];
+ ZLIBWRITE(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
+ if (!q->trace_mini) {
+
+ ZLIBWRITE(fr_fd, off, 1, "no_mini");
+ w += q_len + 1;
+
+ } else {
+
+ ZLIBWRITE(fr_fd, on, 1, "yes_mini");
+ ZLIBWRITE(fr_fd, q->trace_mini, m_len, "trace_mini");
+ w += q_len + m_len + 1;
+
+ }
+
+ }
+
+ ZLIBCLOSE(fr_fd);
+ afl->var_byte_count = count_bytes(afl, afl->var_bytes);
+ OKF("Written fastresume.bin with %u bytes!", w);
+
+ } else {
+
+ WARNF("Could not create fastresume.bin");
+
+ }
+
+ }
+
destroy_queue(afl);
destroy_extras(afl);
destroy_custom_mutators(afl);
diff --git a/src/afl-performance.c b/src/afl-performance.c
index e8ece6b5..b824fd35 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -99,11 +99,13 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
u64 get_binary_hash(u8 *fn) {
+ if (!fn) { return 0; }
int fd = open(fn, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
struct stat st;
if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
u32 f_len = st.st_size;
+ if (!f_len) { return 0; }
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
close(fd);