aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-forkserver.c39
-rw-r--r--src/afl-fuzz-bitmap.c9
-rw-r--r--src/afl-fuzz-extras.c58
-rw-r--r--src/afl-fuzz-one.c35
-rw-r--r--src/afl-fuzz-redqueen.c15
-rw-r--r--src/afl-fuzz-run.c10
-rw-r--r--src/afl-fuzz-state.c5
-rw-r--r--src/afl-showmap.c104
8 files changed, 181 insertions, 94 deletions
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 6819fc8a..25983f26 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -58,6 +58,8 @@ static list_t fsrv_list = {.element_prealloc_count = 0};
static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) {
+ if (fsrv->qemu_mode) setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0);
+
execv(fsrv->target_path, argv);
}
@@ -122,8 +124,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
Returns the time passed to read.
If the wait times out, returns timeout_ms + 1;
Returns 0 if an error occurred (fd closed, signal, ...); */
-static u32 __attribute__ ((hot)) read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms,
- volatile u8 *stop_soon_p) {
+static u32 __attribute__((hot))
+read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, volatile u8 *stop_soon_p) {
fd_set readfds;
FD_ZERO(&readfds);
@@ -322,7 +324,7 @@ static void report_error_and_exit(int error) {
cloning a stopped child. So, we just execute once, and then send commands
through a pipe. The other part of this logic is in afl-as.h / llvm_mode */
-void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
+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];
@@ -628,13 +630,19 @@ void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
- if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) {
+ if (fsrv->autodict_func == NULL || fsrv->afl_ptr == NULL) {
// this is not afl-fuzz - we deny and return
- if (fsrv->use_shmem_fuzz)
+ if (fsrv->use_shmem_fuzz) {
+
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
- else
+
+ } else {
+
status = (FS_OPT_ENABLED);
+
+ }
+
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed.");
@@ -647,11 +655,16 @@ void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
- if (fsrv->use_shmem_fuzz)
+ if (fsrv->use_shmem_fuzz) {
+
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
- else
+
+ } else {
+
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
+ }
+
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed.");
@@ -670,7 +683,8 @@ void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
- u32 len = status, offset = 0, count = 0;
+ u32 offset = 0, count = 0;
+ u32 len = status;
u8 *dict = ck_alloc(len);
if (dict == NULL) {
@@ -701,8 +715,8 @@ void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
while (offset < (u32)status &&
(u8)dict[offset] + offset < (u32)status) {
- fsrv->function_ptr(fsrv->function_opt, dict + offset + 1,
- (u8)dict[offset]);
+ fsrv->autodict_func(fsrv->afl_ptr, dict + offset + 1,
+ (u8)dict[offset]);
offset += (1 + dict[offset]);
count++;
@@ -861,7 +875,8 @@ void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - the target was compiled with afl-clang-lto and a constructor "
"was\n"
" instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
- "your problem\n\n"
+ "your \n"
+ " problem\n\n"
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index f6389c06..1b9df624 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -57,7 +57,7 @@ void write_bitmap(afl_state_t *afl) {
This function is called after every exec() on a fairly large buffer, so
it needs to be fast. We do this in 32-bit and 64-bit flavors. */
-u8 __attribute__ ((hot)) has_new_bits(afl_state_t *afl, u8 *virgin_map) {
+u8 __attribute__((hot)) has_new_bits(afl_state_t *afl, u8 *virgin_map) {
#ifdef WORD_SIZE_64
@@ -347,7 +347,7 @@ void init_count_class16(void) {
#ifdef WORD_SIZE_64
-void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) {
+void __attribute__((hot)) classify_counts(afl_forkserver_t *fsrv) {
u64 *mem = (u64 *)fsrv->trace_bits;
@@ -376,7 +376,7 @@ void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) {
#else
-void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) {
+void __attribute__((hot)) classify_counts(afl_forkserver_t *fsrv) {
u32 *mem = (u32 *)fsrv->trace_bits;
@@ -534,7 +534,8 @@ static void write_crash_readme(afl_state_t *afl) {
save or queue the input test case for further analysis if so. Returns 1 if
entry is saved, 0 otherwise. */
-u8 __attribute__ ((hot)) save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
+u8 __attribute__((hot))
+save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(len == 0)) { return 0; }
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 097871c8..17f02984 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -25,23 +25,28 @@
#include "afl-fuzz.h"
-/* Helper function for load_extras. */
+/* helper function for auto_extras qsort */
+static int compare_auto_extras_len(const void *ae1, const void *ae2) {
+
+ return ((struct auto_extra_data *)ae1)->len -
+ ((struct auto_extra_data *)ae2)->len;
+
+}
-static int compare_extras_len(const void *p1, const void *p2) {
+/* descending order */
- struct extra_data *e1 = (struct extra_data *)p1,
- *e2 = (struct extra_data *)p2;
+static int compare_auto_extras_use_d(const void *ae1, const void *ae2) {
- return e1->len - e2->len;
+ return ((struct auto_extra_data *)ae2)->hit_cnt -
+ ((struct auto_extra_data *)ae1)->hit_cnt;
}
-static int compare_extras_use_d(const void *p1, const void *p2) {
+/* Helper function for load_extras. */
- struct extra_data *e1 = (struct extra_data *)p1,
- *e2 = (struct extra_data *)p2;
+static int compare_extras_len(const void *e1, const void *e2) {
- return e2->hit_cnt - e1->hit_cnt;
+ return ((struct extra_data *)e1)->len - ((struct extra_data *)e2)->len;
}
@@ -354,14 +359,10 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
}
/* Maybe add automatic extra. */
-/* Ugly hack: afl state is transfered as u8* because we import data via
- afl-forkserver.c - which is shared with other afl tools that do not
- have the afl state struct */
-void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
+void maybe_add_auto(afl_state_t *afl, u8 *mem, u32 len) {
- afl_state_t *afl = (afl_state_t *)afl_tmp;
- u32 i;
+ u32 i;
/* Allow users to specify that they don't want auto dictionaries. */
@@ -375,7 +376,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
}
- if (i == len) { return; }
+ if (i == len || unlikely(len > MAX_AUTO_EXTRA)) { return; }
/* Reject builtin interesting values. */
@@ -452,10 +453,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
if (afl->a_extras_cnt < MAX_AUTO_EXTRAS) {
- afl->a_extras = ck_realloc_block(
- afl->a_extras, (afl->a_extras_cnt + 1) * sizeof(struct extra_data));
-
- afl->a_extras[afl->a_extras_cnt].data = ck_memdup(mem, len);
+ memcpy(afl->a_extras[afl->a_extras_cnt].data, mem, len);
afl->a_extras[afl->a_extras_cnt].len = len;
++afl->a_extras_cnt;
@@ -463,9 +461,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
i = MAX_AUTO_EXTRAS / 2 + rand_below(afl, (MAX_AUTO_EXTRAS + 1) / 2);
- ck_free(afl->a_extras[i].data);
-
- afl->a_extras[i].data = ck_memdup(mem, len);
+ memcpy(afl->a_extras[i].data, mem, len);
afl->a_extras[i].len = len;
afl->a_extras[i].hit_cnt = 0;
@@ -475,13 +471,13 @@ sort_a_extras:
/* First, sort all auto extras by use count, descending order. */
- qsort(afl->a_extras, afl->a_extras_cnt, sizeof(struct extra_data),
- compare_extras_use_d);
+ qsort(afl->a_extras, afl->a_extras_cnt, sizeof(struct auto_extra_data),
+ compare_auto_extras_use_d);
/* Then, sort the top USE_AUTO_EXTRAS entries by size. */
qsort(afl->a_extras, MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt),
- sizeof(struct extra_data), compare_extras_len);
+ sizeof(struct auto_extra_data), compare_auto_extras_len);
}
@@ -544,7 +540,7 @@ void load_auto(afl_state_t *afl) {
if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) {
- maybe_add_auto((u8 *)afl, tmp, len);
+ maybe_add_auto(afl, tmp, len);
}
@@ -579,13 +575,5 @@ void destroy_extras(afl_state_t *afl) {
ck_free(afl->extras);
- for (i = 0; i < afl->a_extras_cnt; ++i) {
-
- ck_free(afl->a_extras[i].data);
-
- }
-
- ck_free(afl->a_extras);
-
}
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 452c5298..0a4be320 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -95,7 +95,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
default:
- if (rand_below(afl, 10)) {
+ if (likely(rand_below(afl, 10))) {
min_value = HAVOC_BLK_MEDIUM;
max_value = HAVOC_BLK_LARGE;
@@ -421,7 +421,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (((afl->queue_cur->was_fuzzed > 0 || afl->queue_cur->fuzz_level > 0) ||
!afl->queue_cur->favored) &&
- rand_below(afl, 100) < SKIP_TO_NEW_PROB) {
+ likely(rand_below(afl, 100) < SKIP_TO_NEW_PROB)) {
return 1;
@@ -438,11 +438,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (afl->queue_cycle > 1 &&
(afl->queue_cur->fuzz_level == 0 || afl->queue_cur->was_fuzzed)) {
- if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) { return 1; }
+ if (likely(rand_below(afl, 100) < SKIP_NFAV_NEW_PROB)) { return 1; }
} else {
- if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) { return 1; }
+ if (likely(rand_below(afl, 100) < SKIP_NFAV_OLD_PROB)) { return 1; }
}
@@ -526,8 +526,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
* TRIMMING *
************/
- if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
- !afl->disable_trim) {
+ if (unlikely(!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
+ !afl->disable_trim)) {
u8 res = trim_case(afl, afl->queue_cur, in_buf);
@@ -562,7 +562,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (unlikely(perf_score == 0)) { goto abandon_entry; }
- if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) {
+ if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
if (input_to_state_stage(afl, in_buf, out_buf, len,
afl->queue_cur->exec_cksum)) {
@@ -591,8 +591,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
/* Skip deterministic fuzzing if exec path checksum puts this out of scope
for this main instance. */
- if (afl->main_node_max && (afl->queue_cur->exec_cksum % afl->main_node_max) !=
- afl->main_node_id - 1) {
+ if (unlikely(afl->main_node_max &&
+ (afl->queue_cur->exec_cksum % afl->main_node_max) !=
+ afl->main_node_id - 1)) {
goto custom_mutator_stage;
@@ -681,7 +682,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
- maybe_add_auto((u8 *)afl, a_collect, a_len);
+ maybe_add_auto(afl, a_collect, a_len);
}
@@ -692,7 +693,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
- maybe_add_auto((u8 *)afl, a_collect, a_len);
+ maybe_add_auto(afl, a_collect, a_len);
}
@@ -2131,7 +2132,7 @@ havoc_stage:
u32 clone_from, clone_to, clone_len;
u8 *new_buf;
- if (actually_clone) {
+ if (likely(actually_clone)) {
clone_len = choose_block_len(afl, temp_len);
clone_from = rand_below(afl, temp_len - clone_len + 1);
@@ -2154,7 +2155,7 @@ havoc_stage:
/* Inserted part */
- if (actually_clone) {
+ if (likely(actually_clone)) {
memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
@@ -2194,7 +2195,7 @@ havoc_stage:
copy_from = rand_below(afl, temp_len - copy_len + 1);
copy_to = rand_below(afl, temp_len - copy_len + 1);
- if (rand_below(afl, 4)) {
+ if (likely(rand_below(afl, 4))) {
if (copy_from != copy_to) {
@@ -2753,7 +2754,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
- if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) {
+ if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
if (input_to_state_stage(afl, in_buf, out_buf, len,
afl->queue_cur->exec_cksum)) {
@@ -2882,7 +2883,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
- maybe_add_auto((u8 *)afl, a_collect, a_len);
+ maybe_add_auto(afl, a_collect, a_len);
}
@@ -2893,7 +2894,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
- maybe_add_auto((u8 *)afl, a_collect, a_len);
+ maybe_add_auto(afl, a_collect, a_len);
}
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 9716be95..f21dd0b0 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -151,7 +151,8 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
/* Discard if the mutations change the paths or if it is too decremental
in speed */
if (cksum != exec_cksum ||
- (stop_us - start_us > 2 * afl->queue_cur->exec_us)) {
+ ((stop_us - start_us > 2 * afl->queue_cur->exec_us) &&
+ likely(!afl->fixed_seed))) {
ranges = add_range(ranges, rng->start, rng->start + s / 2);
ranges = add_range(ranges, rng->start + s / 2 + 1, rng->end);
@@ -499,7 +500,7 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
}
- maybe_add_auto((u8 *)afl, (u8 *)&v, shape);
+ maybe_add_auto(afl, (u8 *)&v, shape);
u64 rev;
switch (shape) {
@@ -508,15 +509,15 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
break;
case 2:
rev = SWAP16((u16)v);
- maybe_add_auto((u8 *)afl, (u8 *)&rev, shape);
+ maybe_add_auto(afl, (u8 *)&rev, shape);
break;
case 4:
rev = SWAP32((u32)v);
- maybe_add_auto((u8 *)afl, (u8 *)&rev, shape);
+ maybe_add_auto(afl, (u8 *)&rev, shape);
break;
case 8:
rev = SWAP64(v);
- maybe_add_auto((u8 *)afl, (u8 *)&rev, shape);
+ maybe_add_auto(afl, (u8 *)&rev, shape);
break;
}
@@ -771,8 +772,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
if (afl->pass_stats[key].total == 0) {
- maybe_add_auto((u8 *)afl, o->v0, SHAPE_BYTES(h->shape));
- maybe_add_auto((u8 *)afl, o->v1, SHAPE_BYTES(h->shape));
+ maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape));
+ maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape));
}
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 97fcb3c8..d3f823c9 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -38,8 +38,8 @@ u64 time_spent_working = 0;
/* Execute target application, monitoring for timeouts. Return status
information. The called program will update afl->fsrv->trace_bits. */
-fsrv_run_result_t __attribute__ ((hot)) fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
- u32 timeout) {
+fsrv_run_result_t __attribute__((hot))
+fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
#ifdef PROFILING
static u64 time_spent_start = 0;
@@ -72,7 +72,8 @@ fsrv_run_result_t __attribute__ ((hot)) fuzz_run_target(afl_state_t *afl, afl_fo
old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is
rewound and truncated. */
-void __attribute__ ((hot)) write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
+void __attribute__((hot))
+write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
#ifdef _AFL_DOCUMENT_MUTATIONS
s32 doc_fd;
@@ -858,7 +859,8 @@ abort_trimming:
error conditions, returning 1 if it's time to bail out. This is
a helper function for fuzz_one(). */
-u8 __attribute__ ((hot)) common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
+u8 __attribute__((hot))
+common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index e2d62bc6..d4de91a4 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -112,8 +112,9 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->fsrv.use_stdin = 1;
afl->fsrv.map_size = map_size;
- afl->fsrv.function_opt = (u8 *)afl;
- afl->fsrv.function_ptr = &maybe_add_auto;
+ // afl_state_t is not available in forkserver.c
+ afl->fsrv.afl_ptr = (void *)afl;
+ afl->fsrv.autodict_func = (void (*)(void *, u8 *, u32)) & maybe_add_auto;
afl->cal_cycles = CAL_CYCLES;
afl->cal_cycles_long = CAL_CYCLES_LONG;
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 0aa116e5..47c615d8 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -68,9 +68,11 @@ static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
*out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
-static u8 *in_data; /* Input data */
+static u8 *in_data, /* Input data */
+ *coverage_map; /* Coverage map */
-static u32 total, highest; /* tuple content information */
+static u64 total; /* tuple content information */
+static u32 tcnt, highest; /* tuple content information */
static u32 in_len, /* Input data length */
arg_offset; /* Total number of execs */
@@ -83,7 +85,8 @@ static u8 quiet_mode, /* Hide non-essential messages? */
cmin_mode, /* Generate output in afl-cmin mode? */
binary_mode, /* Write output as a binary map */
keep_cores, /* Allow coredumps? */
- remove_shm = 1; /* remove shmem? */
+ remove_shm = 1, /* remove shmem? */
+ collect_coverage; /* collect coverage */
static volatile u8 stop_soon, /* Ctrl-C pressed? */
child_crashed; /* Child crashed? */
@@ -175,6 +178,25 @@ static void at_exit_handler(void) {
}
+/* Analyze results. */
+
+static void analyze_results(afl_forkserver_t *fsrv) {
+
+ u32 i;
+ for (i = 0; i < map_size; i++) {
+
+ if (fsrv->trace_bits[i]) {
+
+ total += fsrv->trace_bits[i];
+ if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
+ if (!coverage_map[i]) { coverage_map[i] = 1; }
+
+ }
+
+ }
+
+}
+
/* Write results. */
static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
@@ -588,9 +610,14 @@ 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, -o must be a "
+ " -i dir - process all files in this directory, must be combined "
+ "with -o.\n"
+ " 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 "
+ "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"
@@ -624,7 +651,6 @@ int main(int argc, char **argv_orig, char **envp) {
s32 opt, i;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
- u32 tcnt = 0;
char **use_argv;
char **argv = argv_cpy_dup(argc, argv_orig);
@@ -639,10 +665,14 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrh")) > 0) {
switch (opt) {
+ case 'C':
+ collect_coverage = 1;
+ break;
+
case 'i':
if (in_dir) { FATAL("Multiple -i options not supported"); }
in_dir = optarg;
@@ -820,6 +850,13 @@ int main(int argc, char **argv_orig, char **envp) {
if (optind == argc || !out_file) { usage(argv[0]); }
+ if (in_dir) {
+
+ if (!out_file && !collect_coverage)
+ FATAL("for -i you need to specify either -C and/or -o");
+
+ }
+
if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
@@ -910,7 +947,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (in_dir) {
- DIR * dir_in, *dir_out;
+ DIR * dir_in, *dir_out = NULL;
struct dirent *dir_ent;
int done = 0;
u8 infile[PATH_MAX], outfile[PATH_MAX];
@@ -924,20 +961,43 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
+ // if a queue subdirectory exists switch to that
+ u8 *dn = alloc_printf("%s/queue", in_dir);
+ if ((dir_in = opendir(dn)) != NULL) {
+
+ closedir(dir_in);
+ in_dir = dn;
+
+ } else
+
+ ck_free(dn);
+ if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
+
if (!(dir_in = opendir(in_dir))) {
PFATAL("cannot open directory %s", in_dir);
}
- if (!(dir_out = opendir(out_file))) {
+ if (!collect_coverage) {
+
+ if (!(dir_out = opendir(out_file))) {
+
+ if (mkdir(out_file, 0700)) {
- if (mkdir(out_file, 0700)) {
+ PFATAL("cannot create output directory %s", out_file);
- PFATAL("cannot create output directory %s", out_file);
+ }
}
+ } else {
+
+ if ((coverage_map = (u8 *)malloc(map_size)) == NULL)
+ FATAL("coult not grab memory");
+ edges_only = 0;
+ raw_instr_output = 1;
+
}
u8 *use_dir = ".";
@@ -978,6 +1038,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_start(fsrv, use_argv, &stop_soon,
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+ map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
@@ -1005,7 +1066,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue;
#endif
- snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
+ if (!collect_coverage)
+ snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name);
if (read_file(infile)) {
@@ -1019,7 +1081,10 @@ int main(int argc, char **argv_orig, char **envp) {
showmap_run_target_forkserver(fsrv, in_data, in_len);
ck_free(in_data);
- tcnt = write_results_to_file(fsrv, outfile);
+ if (collect_coverage)
+ analyze_results(fsrv);
+ else
+ tcnt = write_results_to_file(fsrv, outfile);
}
@@ -1030,6 +1095,13 @@ int main(int argc, char **argv_orig, char **envp) {
closedir(dir_in);
if (dir_out) { closedir(dir_out); }
+ if (collect_coverage) {
+
+ memcpy(fsrv->trace_bits, coverage_map, map_size);
+ tcnt = write_results_to_file(fsrv, out_file);
+
+ }
+
} else {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
@@ -1043,8 +1115,14 @@ int main(int argc, char **argv_orig, char **envp) {
if (!quiet_mode) {
if (!tcnt) { FATAL("No instrumentation detected" cRST); }
- OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST,
+ OKF("Captured %u tuples (highest value %u, total values %llu) in "
+ "'%s'." cRST,
tcnt, highest, total, out_file);
+ if (collect_coverage)
+ OKF("A coverage of %u edges were achieved out of %u existing (%.02f%%) "
+ "with %llu input files.",
+ tcnt, map_size, ((float)tcnt * 100) / (float)map_size,
+ fsrv->total_execs);
}