diff options
Diffstat (limited to 'src/afl-fuzz-bitmap.c')
-rw-r--r-- | src/afl-fuzz-bitmap.c | 169 |
1 files changed, 95 insertions, 74 deletions
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 7e2d3212..b6a494db 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -24,6 +24,7 @@ */ #include "afl-fuzz.h" +#include <limits.h> /* Write bitmap to file. The bitmap is useful mostly for the secret -B option, to focus a separate fuzzing session on a particular @@ -31,13 +32,13 @@ void write_bitmap(afl_state_t *afl) { - u8 *fname; + u8 fname[PATH_MAX]; s32 fd; if (!afl->bitmap_changed) return; afl->bitmap_changed = 0; - fname = alloc_printf("%s/fuzz_bitmap", afl->out_dir); + snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) PFATAL("Unable to open '%s'", fname); @@ -45,7 +46,6 @@ void write_bitmap(afl_state_t *afl) { ck_write(fd, afl->virgin_bits, MAP_SIZE, fname); close(fd); - ck_free(fname); } @@ -78,16 +78,17 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { u64 *current = (u64 *)afl->fsrv.trace_bits; u64 *virgin = (u64 *)virgin_map; - u32 i = (MAP_SIZE >> 3); + u32 i = (afl->fsrv.map_size >> 3); #else u32 *current = (u32 *)afl->fsrv.trace_bits; u32 *virgin = (u32 *)virgin_map; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); #endif /* ^WORD_SIZE_64 */ + if (i == 0) i = 1; u8 ret = 0; @@ -138,7 +139,8 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { } - if (ret && virgin_map == afl->virgin_bits) afl->bitmap_changed = 1; + if (unlikely(ret) && unlikely(virgin_map == afl->virgin_bits)) + afl->bitmap_changed = 1; return ret; @@ -147,12 +149,14 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { /* Count the number of bits set in the provided bitmap. Used for the status screen several times every second, does not have to be fast. */ -u32 count_bits(u8 *mem) { +u32 count_bits(afl_state_t *afl, u8 *mem) { u32 *ptr = (u32 *)mem; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; + if (i == 0) i = 1; + while (i--) { u32 v = *(ptr++); @@ -177,27 +181,27 @@ u32 count_bits(u8 *mem) { } -#define FF(_b) (0xff << ((_b) << 3)) - /* Count the number of bytes set in the bitmap. Called fairly sporadically, mostly to update the status screen or calibrate and examine confirmed new paths. */ -u32 count_bytes(u8 *mem) { +u32 count_bytes(afl_state_t *afl, u8 *mem) { u32 *ptr = (u32 *)mem; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; + if (i == 0) i = 1; + while (i--) { u32 v = *(ptr++); if (!v) continue; - if (v & FF(0)) ++ret; - if (v & FF(1)) ++ret; - if (v & FF(2)) ++ret; - if (v & FF(3)) ++ret; + if (v & 0x000000ff) ++ret; + if (v & 0x0000ff00) ++ret; + if (v & 0x00ff0000) ++ret; + if (v & 0xff000000) ++ret; } @@ -208,12 +212,14 @@ u32 count_bytes(u8 *mem) { /* Count the number of non-255 bytes set in the bitmap. Used strictly for the status screen, several calls per second or so. */ -u32 count_non_255_bytes(u8 *mem) { +u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) { u32 *ptr = (u32 *)mem; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; + if (i == 0) i = 1; + while (i--) { u32 v = *(ptr++); @@ -222,10 +228,10 @@ u32 count_non_255_bytes(u8 *mem) { case. */ if (v == 0xffffffff) continue; - if ((v & FF(0)) != FF(0)) ++ret; - if ((v & FF(1)) != FF(1)) ++ret; - if ((v & FF(2)) != FF(2)) ++ret; - if ((v & FF(3)) != FF(3)) ++ret; + if ((v & 0x000000ff) != 0x000000ff) ++ret; + if ((v & 0x0000ff00) != 0x0000ff00) ++ret; + if ((v & 0x00ff0000) != 0x00ff0000) ++ret; + if ((v & 0xff000000) != 0xff000000) ++ret; } @@ -246,9 +252,11 @@ const u8 simplify_lookup[256] = { #ifdef WORD_SIZE_64 -void simplify_trace(u64 *mem) { +void simplify_trace(afl_state_t *afl, u64 *mem) { - u32 i = MAP_SIZE >> 3; + u32 i = (afl->fsrv.map_size >> 3); + + if (i == 0) i = 1; while (i--) { @@ -279,9 +287,11 @@ void simplify_trace(u64 *mem) { #else -void simplify_trace(u32 *mem) { +void simplify_trace(afl_state_t *afl, u32 *mem) { + + u32 i = (afl->fsrv.map_size >> 2); - u32 i = MAP_SIZE >> 2; + if (i == 0) i = 1; while (i--) { @@ -341,9 +351,11 @@ void init_count_class16(void) { #ifdef WORD_SIZE_64 -void classify_counts(u64 *mem) { +void classify_counts(afl_state_t *afl, u64 *mem) { + + u32 i = (afl->fsrv.map_size >> 3); - u32 i = MAP_SIZE >> 3; + if (i == 0) i = 1; while (i--) { @@ -368,9 +380,11 @@ void classify_counts(u64 *mem) { #else -void classify_counts(u32 *mem) { +void classify_counts(afl_state_t *afl, u32 *mem) { - u32 i = MAP_SIZE >> 2; + u32 i = (afl->fsrv.map_size >> 2); + + if (i == 0) i = 1; while (i--) { @@ -397,11 +411,11 @@ void classify_counts(u32 *mem) { count information here. This is called only sporadically, for some new paths. */ -void minimize_bits(u8 *dst, u8 *src) { +void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) { u32 i = 0; - while (i < MAP_SIZE) { + while (i < afl->fsrv.map_size) { if (*(src++)) dst[i >> 3] |= 1 << (i & 7); ++i; @@ -413,13 +427,13 @@ void minimize_bits(u8 *dst, u8 *src) { #ifndef SIMPLE_FILES /* Construct a file name for a new test case, capturing the operation - that led to its discovery. Uses a static buffer. */ + that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */ u8 *describe_op(afl_state_t *afl, u8 hnb) { u8 *ret = afl->describe_op_buf_256; - if (afl->syncing_party) { + if (unlikely(afl->syncing_party)) { sprintf(ret, "sync:%s,src:%06u", afl->syncing_party, afl->syncing_case); @@ -461,20 +475,23 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) { static void write_crash_readme(afl_state_t *afl) { - u8 * fn = alloc_printf("%s/crashes/README.txt", afl->out_dir); + u8 fn[PATH_MAX]; s32 fd; FILE *f; + u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; + + sprintf(fn, "%s/crashes/README.txt", afl->out_dir); + fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - ck_free(fn); /* Do not die on errors here - that would be impolite. */ - if (fd < 0) return; + if (unlikely(fd < 0)) return; f = fdopen(fd, "w"); - if (!f) { + if (unlikely(!f)) { close(fd); return; @@ -501,7 +518,9 @@ static void write_crash_readme(afl_state_t *afl) { " https://github.com/AFLplusplus/AFLplusplus\n\n", - afl->orig_cmdline, DMS(afl->fsrv.mem_limit << 20)); /* ignore errors */ + afl->orig_cmdline, + stringify_mem_size(val_buf, sizeof(val_buf), + afl->fsrv.mem_limit << 20)); /* ignore errors */ fclose(f); @@ -513,15 +532,17 @@ static void write_crash_readme(afl_state_t *afl) { u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { - if (len == 0) return 0; + if (unlikely(len == 0)) return 0; - u8 *fn = ""; + u8 *queue_fn = ""; u8 hnb; s32 fd; u8 keeping = 0, res; + u8 fn[PATH_MAX]; + /* Update path frequency. */ - u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + u32 cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); struct queue_entry *q = afl->queue; while (q) { @@ -537,30 +558,31 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } - if (fault == afl->crash_mode) { + if (unlikely(fault == afl->crash_mode)) { /* Keep only if there are new bits in the map, add to queue for future fuzzing, etc. */ if (!(hnb = has_new_bits(afl, afl->virgin_bits))) { - if (afl->crash_mode) ++afl->total_crashes; + if (unlikely(afl->crash_mode)) ++afl->total_crashes; return 0; } #ifndef SIMPLE_FILES - fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths, - describe_op(afl, hnb)); + queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, + afl->queued_paths, describe_op(afl, hnb)); #else - fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); + queue_fn = + alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths); #endif /* ^!SIMPLE_FILES */ - add_to_queue(afl, fn, len, 0); + add_to_queue(afl, queue_fn, len, 0); if (hnb == 2) { @@ -576,11 +598,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0); - if (res == FAULT_ERROR) FATAL("Unable to execute target application"); + if (unlikely(res == FAULT_ERROR)) + FATAL("Unable to execute target application"); - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); - ck_write(fd, mem, len, fn); + fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn); + ck_write(fd, mem, len, queue_fn); close(fd); keeping = 1; @@ -600,12 +623,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (afl->unique_hangs >= KEEP_UNIQUE_HANG) return keeping; - if (!afl->dumb_mode) { + if (likely(!afl->dumb_mode)) { #ifdef WORD_SIZE_64 - simplify_trace((u64 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u64 *)afl->fsrv.trace_bits); #else - simplify_trace((u32 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ if (!has_new_bits(afl, afl->virgin_tmout)) return keeping; @@ -622,7 +645,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 new_fault; write_to_testcase(afl, mem, len); - new_fault = run_target(afl, afl->hang_tmout); + new_fault = run_target(afl, &afl->fsrv, afl->hang_tmout); /* A corner case that one user reported bumping into: increasing the timeout actually uncovers a crash. Make sure we don't discard it if @@ -636,12 +659,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - fn = alloc_printf("%s/hangs/id:%06llu,%s", afl->out_dir, - afl->unique_hangs, describe_op(afl, 0)); + snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir, + afl->unique_hangs, describe_op(afl, 0)); #else - fn = alloc_printf("%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs); + snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, + afl->unique_hangs); #endif /* ^!SIMPLE_FILES */ @@ -663,38 +687,37 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; - if (!afl->dumb_mode) { + if (likely(!afl->dumb_mode)) { #ifdef WORD_SIZE_64 - simplify_trace((u64 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u64 *)afl->fsrv.trace_bits); #else - simplify_trace((u32 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ if (!has_new_bits(afl, afl->virgin_crash)) return keeping; } - if (!afl->unique_crashes) write_crash_readme(afl); + if (unlikely(!afl->unique_crashes)) write_crash_readme(afl); #ifndef SIMPLE_FILES - fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, - afl->unique_crashes, afl->kill_signal, - describe_op(afl, 0)); + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, + afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); #else - fn = alloc_printf("%s/crashes/id_%06llu_%02u", afl->out_dir, - afl->unique_crashes, afl->kill_signal); + snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, + afl->unique_crashes, afl->kill_signal); #endif /* ^!SIMPLE_FILES */ ++afl->unique_crashes; - if (afl->infoexec) { // if the user wants to be informed on new crashes - - // do + if (unlikely(afl->infoexec)) { + + // if the user wants to be informed on new crashes - do that #if !TARGET_OS_IPHONE - // that if (system(afl->infoexec) == -1) hnb += 0; // we dont care if system errors, but we dont want a // compiler warning either @@ -719,12 +742,10 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { test case, too. */ fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); + if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn); ck_write(fd, mem, len, fn); close(fd); - ck_free(fn); - return keeping; } |