clang-tidy readability-braces (#323)

This commit is contained in:
Dominik Maier
2020-04-19 16:42:40 +02:00
committed by GitHub
parent baec99079f
commit 8197e9b2e4
35 changed files with 2925 additions and 1281 deletions

View File

@ -10,7 +10,7 @@ AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false

View File

@ -16,7 +16,8 @@ int target_func(unsigned char *buf, int size) {
} }
break; break;
default: break; default:
break;
} }

View File

@ -956,7 +956,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
static inline u32 get_rand_seed(afl_state_t *afl) { static inline u32 get_rand_seed(afl_state_t *afl) {
if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed; if (unlikely(afl->fixed_seed)) { return (u32)afl->init_seed; }
return afl->rand_seed[0]; return afl->rand_seed[0];
} }
@ -967,8 +967,12 @@ static inline u32 get_rand_seed(afl_state_t *afl) {
static inline u64 next_p2(u64 val) { static inline u64 next_p2(u64 val) {
u64 ret = 1; u64 ret = 1;
while (val > ret) while (val > ret) {
ret <<= 1; ret <<= 1;
}
return ret; return ret;
} }

View File

@ -87,7 +87,7 @@ static inline void *DFL_ck_alloc_nozero(u32 size) {
void *ret; void *ret;
if (!size) return NULL; if (!size) { return NULL; }
ALLOC_CHECK_SIZE(size); ALLOC_CHECK_SIZE(size);
ret = malloc(size); ret = malloc(size);
@ -103,7 +103,7 @@ static inline void *DFL_ck_alloc(u32 size) {
void *mem; void *mem;
if (!size) return NULL; if (!size) { return NULL; }
mem = DFL_ck_alloc_nozero(size); mem = DFL_ck_alloc_nozero(size);
return memset(mem, 0, size); return memset(mem, 0, size);
@ -115,7 +115,7 @@ static inline void *DFL_ck_alloc(u32 size) {
static inline void DFL_ck_free(void *mem) { static inline void DFL_ck_free(void *mem) {
if (!mem) return; if (!mem) { return; }
free(mem); free(mem);
@ -165,7 +165,7 @@ static inline u8 *DFL_ck_strdup(u8 *str) {
u8 *ret; u8 *ret;
u32 size; u32 size;
if (!str) return NULL; if (!str) { return NULL; }
size = strlen((char *)str) + 1; size = strlen((char *)str) + 1;
@ -184,7 +184,7 @@ static inline void *DFL_ck_memdup(void *mem, u32 size) {
void *ret; void *ret;
if (!mem || !size) return NULL; if (!mem || !size) { return NULL; }
ALLOC_CHECK_SIZE(size); ALLOC_CHECK_SIZE(size);
ret = malloc(size); ret = malloc(size);
@ -201,7 +201,7 @@ static inline u8 *DFL_ck_memdup_str(u8 *mem, u32 size) {
u8 *ret; u8 *ret;
if (!mem || !size) return NULL; if (!mem || !size) { return NULL; }
ALLOC_CHECK_SIZE(size); ALLOC_CHECK_SIZE(size);
ret = malloc(size + 1); ret = malloc(size + 1);
@ -772,8 +772,12 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func,
*/ */
static inline size_t next_pow2(size_t in) { static inline size_t next_pow2(size_t in) {
if (in == 0 || in > (size_t)-1) if (in == 0 || in > (size_t)-1) {
return 0; /* avoid undefined behaviour under-/overflow */ return 0; /* avoid undefined behaviour under-/overflow */
}
size_t out = in - 1; size_t out = in - 1;
out |= out >> 1; out |= out >> 1;
out |= out >> 2; out |= out >> 2;
@ -794,10 +798,10 @@ static inline size_t next_pow2(size_t in) {
static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
/* No need to realloc */ /* No need to realloc */
if (likely(size_needed && *size >= size_needed)) return *buf; if (likely(size_needed && *size >= size_needed)) { return *buf; }
/* No initial size was set */ /* No initial size was set */
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; if (size_needed < INITIAL_GROWTH_SIZE) { size_needed = INITIAL_GROWTH_SIZE; }
/* grow exponentially */ /* grow exponentially */
size_t next_size = next_pow2(size_needed); size_t next_size = next_pow2(size_needed);
@ -824,13 +828,13 @@ static inline void *ck_maybe_grow(void **buf, size_t *size,
size_t size_needed) { size_t size_needed) {
/* Oops. found a bug? */ /* Oops. found a bug? */
if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size"); if (unlikely(size_needed < 1)) { FATAL("cannot grow to non-positive size"); }
/* No need to realloc */ /* No need to realloc */
if (likely(*size >= size_needed)) return *buf; if (likely(*size >= size_needed)) { return *buf; }
/* No initial size was set */ /* No initial size was set */
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; if (size_needed < INITIAL_GROWTH_SIZE) { size_needed = INITIAL_GROWTH_SIZE; }
/* grow exponentially */ /* grow exponentially */
size_t next_size = next_pow2(size_needed); size_t next_size = next_pow2(size_needed);

View File

@ -109,3 +109,5 @@ static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
#endif #endif
#endif

View File

@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include "types.h"
#include "types.h" #include "types.h"
typedef struct afl_forkserver { typedef struct afl_forkserver {

View File

@ -83,7 +83,7 @@ static inline void list_append(list_t *list, void *el) {
element_t *el_box = NULL; element_t *el_box = NULL;
PRE_ALLOC(el_box, list->element_prealloc_buf, LIST_PREALLOC_SIZE, PRE_ALLOC(el_box, list->element_prealloc_buf, LIST_PREALLOC_SIZE,
list->element_prealloc_count); list->element_prealloc_count);
if (!el_box) FATAL("failed to allocate list element"); if (!el_box) { FATAL("failed to allocate list element"); }
el_box->data = el; el_box->data = el;
el_box->next = head; el_box->next = head;
el_box->prev = head->prev; el_box->prev = head->prev;

View File

@ -274,7 +274,8 @@ static void __tokencap_dump(const u8 *ptr, size_t len, u8 is_text) {
pos += 4; pos += 4;
break; break;
default: buf[pos++] = ptr[i]; default:
buf[pos++] = ptr[i];
} }

View File

@ -360,11 +360,20 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
switch (max_size) { switch (max_size) {
case 8: IRB.CreateCall(cmplogHookIns1, args, "tmp"); break; case 8:
case 16: IRB.CreateCall(cmplogHookIns2, args, "tmp"); break; IRB.CreateCall(cmplogHookIns1, args, "tmp");
case 32: IRB.CreateCall(cmplogHookIns4, args, "tmp"); break; break;
case 64: IRB.CreateCall(cmplogHookIns8, args, "tmp"); break; case 16:
default: break; IRB.CreateCall(cmplogHookIns2, args, "tmp");
break;
case 32:
IRB.CreateCall(cmplogHookIns4, args, "tmp");
break;
case 64:
IRB.CreateCall(cmplogHookIns8, args, "tmp");
break;
default:
break;
} }

View File

@ -318,10 +318,18 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
CmpInst::Predicate new_pred; CmpInst::Predicate new_pred;
switch (pred) { switch (pred) {
case CmpInst::ICMP_UGE: new_pred = CmpInst::ICMP_UGT; break; case CmpInst::ICMP_UGE:
case CmpInst::ICMP_SGE: new_pred = CmpInst::ICMP_SGT; break; new_pred = CmpInst::ICMP_UGT;
case CmpInst::ICMP_ULE: new_pred = CmpInst::ICMP_ULT; break; break;
case CmpInst::ICMP_SLE: new_pred = CmpInst::ICMP_SLT; break; case CmpInst::ICMP_SGE:
new_pred = CmpInst::ICMP_SGT;
break;
case CmpInst::ICMP_ULE:
new_pred = CmpInst::ICMP_ULT;
break;
case CmpInst::ICMP_SLE:
new_pred = CmpInst::ICMP_SLT;
break;
default: // keep the compiler happy default: // keep the compiler happy
continue; continue;
@ -384,10 +392,18 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
CmpInst::Predicate new_pred; CmpInst::Predicate new_pred;
switch (pred) { switch (pred) {
case CmpInst::FCMP_UGE: new_pred = CmpInst::FCMP_UGT; break; case CmpInst::FCMP_UGE:
case CmpInst::FCMP_OGE: new_pred = CmpInst::FCMP_OGT; break; new_pred = CmpInst::FCMP_UGT;
case CmpInst::FCMP_ULE: new_pred = CmpInst::FCMP_ULT; break; break;
case CmpInst::FCMP_OLE: new_pred = CmpInst::FCMP_OLT; break; case CmpInst::FCMP_OGE:
new_pred = CmpInst::FCMP_OGT;
break;
case CmpInst::FCMP_ULE:
new_pred = CmpInst::FCMP_ULT;
break;
case CmpInst::FCMP_OLE:
new_pred = CmpInst::FCMP_OLT;
break;
default: // keep the compiler happy default: // keep the compiler happy
continue; continue;
@ -855,7 +871,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
icmp_exponent_result = icmp_exponent_result =
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0); BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
break; break;
default: continue; default:
continue;
} }
@ -958,7 +975,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
icmp_fraction_result = icmp_fraction_result =
BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0); BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
break; break;
default: continue; default:
continue;
} }
@ -1004,7 +1022,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
PN->addIncoming(icmp_exponent_result, signequal_bb); PN->addIncoming(icmp_exponent_result, signequal_bb);
PN->addIncoming(icmp_fraction_result, middle_bb); PN->addIncoming(icmp_fraction_result, middle_bb);
break; break;
default: continue; default:
continue;
} }

View File

@ -29,7 +29,9 @@ int target_func(char *buf, int size) {
} }
break; break;
default: puts("default action"); break; default:
puts("default action");
break;
} }

View File

@ -51,9 +51,11 @@ int main() {
switch (z) { switch (z) {
case 0xBEEF: break; case 0xBEEF:
break;
default: return 4; default:
return 4;
} }

View File

@ -55,11 +55,20 @@ static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2,
switch (ot & MO_SIZE) { switch (ot & MO_SIZE) {
case MO_64: gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2); break; case MO_64:
case MO_32: gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2); break; gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2);
case MO_16: gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2); break; break;
case MO_8: gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2); break; case MO_32:
default: break; gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2);
break;
case MO_16:
gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2);
break;
case MO_8:
gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2);
break;
default:
break;
} }
@ -78,10 +87,17 @@ static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2,
switch (ot & MO_SIZE) { switch (ot & MO_SIZE) {
case MO_64: gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2); break; case MO_64:
case MO_32: gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2); break; gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2);
case MO_16: gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2); break; break;
default: break; case MO_32:
gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2);
break;
case MO_16:
gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2);
break;
default:
break;
} }

View File

@ -122,7 +122,7 @@ static void classify_counts(u8 *mem) {
while (i--) { while (i--) {
if (*mem) *mem = 1; if (*mem) { *mem = 1; }
mem++; mem++;
} }
@ -147,8 +147,11 @@ static inline u8 anything_set(void) {
u32 *ptr = (u32 *)trace_bits; u32 *ptr = (u32 *)trace_bits;
u32 i = (map_size >> 2); u32 i = (map_size >> 2);
while (i--) while (i--) {
if (*(ptr++)) return 1;
if (*(ptr++)) { return 1; }
}
return 0; return 0;
@ -169,13 +172,16 @@ static void read_initial_file(void) {
struct stat st; struct stat st;
s32 fd = open(in_file, O_RDONLY); s32 fd = open(in_file, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", in_file); if (fd < 0) { PFATAL("Unable to open '%s'", in_file); }
if (fstat(fd, &st) || !st.st_size) FATAL("Zero-sized input file."); if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); }
if (st.st_size >= TMIN_MAX_FILE) {
if (st.st_size >= TMIN_MAX_FILE)
FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024); FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
}
in_len = st.st_size; in_len = st.st_size;
in_data = ck_alloc_nozero(in_len); in_data = ck_alloc_nozero(in_len);
@ -197,7 +203,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
if (ret < 0) PFATAL("Unable to create '%s'", path); if (ret < 0) { PFATAL("Unable to create '%s'", path); }
ck_write(ret, mem, len, path); ck_write(ret, mem, len, path);
@ -225,7 +231,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
child_pid = fork(); child_pid = fork();
if (child_pid < 0) PFATAL("fork() failed"); if (child_pid < 0) { PFATAL("fork() failed"); }
if (!child_pid) { if (!child_pid) {
@ -278,7 +284,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
setitimer(ITIMER_REAL, &it, NULL); setitimer(ITIMER_REAL, &it, NULL);
if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); if (waitpid(child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
child_pid = 0; child_pid = 0;
it.it_value.tv_sec = 0; it.it_value.tv_sec = 0;
@ -290,9 +296,12 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
/* Clean up bitmap, analyze exit condition, etc. */ /* Clean up bitmap, analyze exit condition, etc. */
if (*(u32 *)trace_bits == EXEC_FAIL_SIG) if (*(u32 *)trace_bits == EXEC_FAIL_SIG) {
FATAL("Unable to execute '%s'", argv[0]); FATAL("Unable to execute '%s'", argv[0]);
}
classify_counts(trace_bits); classify_counts(trace_bits);
total_execs++; total_execs++;
@ -325,7 +334,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) {
} }
if (first_run) orig_cksum = cksum; if (first_run) { orig_cksum = cksum; }
return cksum; return cksum;
@ -340,9 +349,12 @@ static void show_char(u8 val) {
switch (val) { switch (val) {
case 0 ... 32: case 0 ... 32:
case 127 ... 255: SAYF("#%02x", val); break; case 127 ... 255:
SAYF("#%02x", val);
break;
default: SAYF(" %c ", val); default:
SAYF(" %c ", val);
} }
@ -387,7 +399,12 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) { while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) {
if (rtype < (b_data[i + rlen] & 0x0f)) rtype = b_data[i + rlen] & 0x0f; if (rtype < (b_data[i + rlen] & 0x0f)) {
rtype = b_data[i + rlen] & 0x0f;
}
rlen++; rlen++;
} }
@ -454,9 +471,11 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
case 1: case 1:
case 3: case 3:
case 5 ... MAX_AUTO_EXTRA - 1: break; case 5 ... MAX_AUTO_EXTRA - 1:
break;
default: rtype = RESP_SUSPECT; default:
rtype = RESP_SUSPECT;
} }
@ -472,34 +491,58 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
if (!((i + off) % 16)) { if (!((i + off) % 16)) {
if (off) SAYF(cRST cLCY ">"); if (off) { SAYF(cRST cLCY ">"); }
if (use_hex_offsets) {
if (use_hex_offsets)
SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off); SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off);
else
} else {
SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off); SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off);
}
} }
switch (rtype) { switch (rtype) {
case RESP_NONE: SAYF(cLGR bgGRA); break; case RESP_NONE:
case RESP_MINOR: SAYF(cBRI bgGRA); break; SAYF(cLGR bgGRA);
case RESP_VARIABLE: SAYF(cBLK bgCYA); break; break;
case RESP_FIXED: SAYF(cBLK bgMGN); break; case RESP_MINOR:
case RESP_LEN: SAYF(cBLK bgLGN); break; SAYF(cBRI bgGRA);
case RESP_CKSUM: SAYF(cBLK bgYEL); break; break;
case RESP_SUSPECT: SAYF(cBLK bgLRD); break; case RESP_VARIABLE:
SAYF(cBLK bgCYA);
break;
case RESP_FIXED:
SAYF(cBLK bgMGN);
break;
case RESP_LEN:
SAYF(cBLK bgLGN);
break;
case RESP_CKSUM:
SAYF(cBLK bgYEL);
break;
case RESP_SUSPECT:
SAYF(cBLK bgLRD);
break;
} }
show_char(in_data[i + off]); show_char(in_data[i + off]);
if (off != rlen - 1 && (i + off + 1) % 16) if (off != rlen - 1 && (i + off + 1) % 16) {
SAYF(" "); SAYF(" ");
else
} else {
SAYF(cRST " "); SAYF(cRST " ");
}
} }
#else #else
@ -511,13 +554,27 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) {
switch (rtype) { switch (rtype) {
case RESP_NONE: SAYF("no-op block\n"); break; case RESP_NONE:
case RESP_MINOR: SAYF("superficial content\n"); break; SAYF("no-op block\n");
case RESP_VARIABLE: SAYF("critical stream\n"); break; break;
case RESP_FIXED: SAYF("\"magic value\" section\n"); break; case RESP_MINOR:
case RESP_LEN: SAYF("suspected length field\n"); break; SAYF("superficial content\n");
case RESP_CKSUM: SAYF("suspected cksum or magic int\n"); break; break;
case RESP_SUSPECT: SAYF("suspected checksummed block\n"); break; case RESP_VARIABLE:
SAYF("critical stream\n");
break;
case RESP_FIXED:
SAYF("\"magic value\" section\n");
break;
case RESP_LEN:
SAYF("suspected length field\n");
break;
case RESP_CKSUM:
SAYF("suspected cksum or magic int\n");
break;
case RESP_SUSPECT:
SAYF("suspected checksummed block\n");
break;
} }
@ -594,16 +651,21 @@ static void analyze(char **argv) {
b_data[i] = RESP_FIXED; b_data[i] = RESP_FIXED;
} else } else {
b_data[i] = RESP_VARIABLE; b_data[i] = RESP_VARIABLE;
}
/* When all checksums change, flip most significant bit of b_data. */ /* When all checksums change, flip most significant bit of b_data. */
if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 && if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 &&
prev_a10 != add_10) prev_a10 != add_10) {
seq_byte ^= 0x80; seq_byte ^= 0x80;
}
b_data[i] |= seq_byte; b_data[i] |= seq_byte;
prev_xff = xor_ff; prev_xff = xor_ff;
@ -620,10 +682,13 @@ static void analyze(char **argv) {
OKF("Analysis complete. Interesting bits: %0.02f%% of the input file.", OKF("Analysis complete. Interesting bits: %0.02f%% of the input file.",
100.0 - ((double)boring_len * 100) / in_len); 100.0 - ((double)boring_len * 100) / in_len);
if (exec_hangs) if (exec_hangs) {
WARNF(cLRD "Encountered %u timeouts - results may be skewed." cRST, WARNF(cLRD "Encountered %u timeouts - results may be skewed." cRST,
exec_hangs); exec_hangs);
}
ck_free(b_data); ck_free(b_data);
} }
@ -634,7 +699,7 @@ static void handle_stop_sig(int sig) {
stop_soon = 1; stop_soon = 1;
if (child_pid > 0) kill(child_pid, SIGKILL); if (child_pid > 0) { kill(child_pid, SIGKILL); }
} }
@ -645,7 +710,7 @@ static void set_up_environment(void) {
u8 *x; u8 *x;
dev_null_fd = open("/dev/null", O_RDWR); dev_null_fd = open("/dev/null", O_RDWR);
if (dev_null_fd < 0) PFATAL("Unable to open /dev/null"); if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
if (!prog_in) { if (!prog_in) {
@ -654,7 +719,7 @@ static void set_up_environment(void) {
if (access(use_dir, R_OK | W_OK | X_OK)) { if (access(use_dir, R_OK | W_OK | X_OK)) {
use_dir = get_afl_env("TMPDIR"); use_dir = get_afl_env("TMPDIR");
if (!use_dir) use_dir = "/tmp"; if (!use_dir) { use_dir = "/tmp"; }
} }
@ -668,25 +733,37 @@ static void set_up_environment(void) {
if (x) { if (x) {
if (!strstr(x, "abort_on_error=1")) if (!strstr(x, "abort_on_error=1")) {
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
if (!strstr(x, "symbolize=0")) }
if (!strstr(x, "symbolize=0")) {
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
}
} }
x = get_afl_env("MSAN_OPTIONS"); x = get_afl_env("MSAN_OPTIONS");
if (x) { if (x) {
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) {
FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY( FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY(
MSAN_ERROR) " - please fix!"); MSAN_ERROR) " - please fix!");
if (!strstr(x, "symbolize=0")) }
if (!strstr(x, "symbolize=0")) {
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
}
} }
setenv("ASAN_OPTIONS", setenv("ASAN_OPTIONS",
@ -713,20 +790,28 @@ static void set_up_environment(void) {
s32 i, afl_preload_size = strlen(afl_preload); s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) { for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') if (afl_preload[i] == ',') {
PFATAL( PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is " "Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!"); "specified!");
}
} }
if (qemu_preload) if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload); qemu_preload, afl_preload, afl_preload);
else
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload); afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1); setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf); ck_free(buf);
@ -820,26 +905,26 @@ int main(int argc, char **argv, char **envp) {
SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n"); SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n");
while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) {
switch (opt) { switch (opt) {
case 'i': case 'i':
if (in_file) FATAL("Multiple -i options not supported"); if (in_file) { FATAL("Multiple -i options not supported"); }
in_file = optarg; in_file = optarg;
break; break;
case 'f': case 'f':
if (prog_in) FATAL("Multiple -f options not supported"); if (prog_in) { FATAL("Multiple -f options not supported"); }
use_stdin = 0; use_stdin = 0;
prog_in = optarg; prog_in = optarg;
break; break;
case 'e': case 'e':
if (edges_only) FATAL("Multiple -e options not supported"); if (edges_only) { FATAL("Multiple -e options not supported"); }
edges_only = 1; edges_only = 1;
break; break;
@ -847,7 +932,7 @@ int main(int argc, char **argv, char **envp) {
u8 suffix = 'M'; u8 suffix = 'M';
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) { FATAL("Wrong usage of -m"); } if (!optarg) { FATAL("Wrong usage of -m"); }
@ -860,66 +945,83 @@ int main(int argc, char **argv, char **envp) {
} }
if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
optarg[0] == '-') optarg[0] == '-') {
FATAL("Bad syntax used for -m"); FATAL("Bad syntax used for -m");
switch (suffix) {
case 'T': mem_limit *= 1024 * 1024; break;
case 'G': mem_limit *= 1024; break;
case 'k': mem_limit /= 1024; break;
case 'M': break;
default: FATAL("Unsupported suffix or bad syntax for -m");
} }
if (mem_limit < 5) FATAL("Dangerously low value of -m"); switch (suffix) {
case 'T':
mem_limit *= 1024 * 1024;
break;
case 'G':
mem_limit *= 1024;
break;
case 'k':
mem_limit /= 1024;
break;
case 'M':
break;
default:
FATAL("Unsupported suffix or bad syntax for -m");
}
if (mem_limit < 5) { FATAL("Dangerously low value of -m"); }
if (sizeof(rlim_t) == 4 && mem_limit > 2000) {
if (sizeof(rlim_t) == 4 && mem_limit > 2000)
FATAL("Value of -m out of range on 32-bit systems"); FATAL("Value of -m out of range on 32-bit systems");
}
} }
break; break;
case 't': case 't':
if (timeout_given) FATAL("Multiple -t options not supported"); if (timeout_given) { FATAL("Multiple -t options not supported"); }
timeout_given = 1; timeout_given = 1;
if (!optarg) FATAL("Wrong usage of -t"); if (!optarg) { FATAL("Wrong usage of -t"); }
exec_tmout = atoi(optarg); exec_tmout = atoi(optarg);
if (exec_tmout < 10 || optarg[0] == '-') if (exec_tmout < 10 || optarg[0] == '-') {
FATAL("Dangerously low value of -t"); FATAL("Dangerously low value of -t");
}
break; break;
case 'Q': case 'Q':
if (qemu_mode) FATAL("Multiple -Q options not supported"); if (qemu_mode) { FATAL("Multiple -Q options not supported"); }
if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; if (!mem_limit_given) { mem_limit = MEM_LIMIT_QEMU; }
qemu_mode = 1; qemu_mode = 1;
break; break;
case 'U': case 'U':
if (unicorn_mode) FATAL("Multiple -U options not supported"); if (unicorn_mode) { FATAL("Multiple -U options not supported"); }
if (!mem_limit_given) mem_limit = MEM_LIMIT_UNICORN; if (!mem_limit_given) { mem_limit = MEM_LIMIT_UNICORN; }
unicorn_mode = 1; unicorn_mode = 1;
break; break;
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
if (use_wine) FATAL("Multiple -W options not supported"); if (use_wine) { FATAL("Multiple -W options not supported"); }
qemu_mode = 1; qemu_mode = 1;
use_wine = 1; use_wine = 1;
if (!mem_limit_given) mem_limit = 0; if (!mem_limit_given) { mem_limit = 0; }
break; break;
@ -928,11 +1030,14 @@ int main(int argc, char **argv, char **envp) {
return -1; return -1;
break; break;
default: usage(argv[0]); default:
usage(argv[0]);
} }
if (optind == argc || !in_file) usage(argv[0]); }
if (optind == argc || !in_file) { usage(argv[0]); }
map_size = get_map_size(); map_size = get_map_size();
@ -952,17 +1057,24 @@ int main(int argc, char **argv, char **envp) {
if (qemu_mode) { if (qemu_mode) {
if (use_wine) if (use_wine) {
use_argv = use_argv =
get_wine_argv(argv[0], &target_path, argc - optind, argv + optind); get_wine_argv(argv[0], &target_path, argc - optind, argv + optind);
else
} else {
use_argv = use_argv =
get_qemu_argv(argv[0], &target_path, argc - optind, argv + optind); get_qemu_argv(argv[0], &target_path, argc - optind, argv + optind);
} else }
} else {
use_argv = argv + optind; use_argv = argv + optind;
}
SAYF("\n"); SAYF("\n");
read_initial_file(); read_initial_file();
@ -972,17 +1084,23 @@ int main(int argc, char **argv, char **envp) {
analyze_run_target(use_argv, in_data, in_len, 1); analyze_run_target(use_argv, in_data, in_len, 1);
if (child_timed_out) if (child_timed_out) {
FATAL("Target binary times out (adjusting -t may help)."); FATAL("Target binary times out (adjusting -t may help).");
if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) }
if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) {
FATAL("No instrumentation detected."); FATAL("No instrumentation detected.");
}
analyze(use_argv); analyze(use_argv);
OKF("We're done here. Have a nice day!\n"); OKF("We're done here. Have a nice day!\n");
if (target_path) ck_free(target_path); if (target_path) { ck_free(target_path); }
afl_shm_deinit(&shm); afl_shm_deinit(&shm);

View File

@ -126,9 +126,9 @@ static void edit_params(int argc, char **argv) {
is not set. We need to check these non-standard variables to properly is not set. We need to check these non-standard variables to properly
handle the pass_thru logic later on. */ handle the pass_thru logic later on. */
if (!tmp_dir) tmp_dir = getenv("TEMP"); if (!tmp_dir) { tmp_dir = getenv("TEMP"); }
if (!tmp_dir) tmp_dir = getenv("TMP"); if (!tmp_dir) { tmp_dir = getenv("TMP"); }
if (!tmp_dir) tmp_dir = "/tmp"; if (!tmp_dir) { tmp_dir = "/tmp"; }
as_params = ck_alloc((argc + 32) * sizeof(u8 *)); as_params = ck_alloc((argc + 32) * sizeof(u8 *));
@ -138,11 +138,16 @@ static void edit_params(int argc, char **argv) {
for (i = 1; i < argc - 1; i++) { for (i = 1; i < argc - 1; i++) {
if (!strcmp(argv[i], "--64")) if (!strcmp(argv[i], "--64")) {
use_64bit = 1; use_64bit = 1;
else if (!strcmp(argv[i], "--32"))
} else if (!strcmp(argv[i], "--32")) {
use_64bit = 0; use_64bit = 0;
}
#ifdef __APPLE__ #ifdef __APPLE__
/* The Apple case is a bit different... */ /* The Apple case is a bit different... */
@ -195,11 +200,16 @@ static void edit_params(int argc, char **argv) {
} }
if (input_file[1]) if (input_file[1]) {
FATAL("Incorrect use (not called through afl-gcc?)"); FATAL("Incorrect use (not called through afl-gcc?)");
else
} else {
input_file = NULL; input_file = NULL;
}
} else { } else {
/* Check if this looks like a standard invocation as a part of an attempt /* Check if this looks like a standard invocation as a part of an attempt
@ -210,11 +220,16 @@ static void edit_params(int argc, char **argv) {
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/var/tmp/", 9) &&
strncmp(input_file, "/tmp/", 5) && strncmp(input_file, "/tmp/", 5) &&
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) {
pass_thru = 1; pass_thru = 1;
else if (getenv("AFL_AS_FORCE_INSTRUMENT"))
} else if (getenv("AFL_AS_FORCE_INSTRUMENT")) {
unsetenv("AFL_AS_FORCE_INSTRUMENT"); unsetenv("AFL_AS_FORCE_INSTRUMENT");
}
} }
modified_file = modified_file =
@ -251,19 +266,21 @@ static void add_instrumentation(void) {
if (input_file) { if (input_file) {
inf = fopen(input_file, "r"); inf = fopen(input_file, "r");
if (!inf) PFATAL("Unable to read '%s'", input_file); if (!inf) { PFATAL("Unable to read '%s'", input_file); }
} else } else {
inf = stdin; inf = stdin;
}
outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);
if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file); if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); }
outf = fdopen(outfd, "w"); outf = fdopen(outfd, "w");
if (!outf) PFATAL("fdopen() failed"); if (!outf) { PFATAL("fdopen() failed"); }
while (fgets(line, MAX_LINE, inf)) { while (fgets(line, MAX_LINE, inf)) {
@ -287,7 +304,7 @@ static void add_instrumentation(void) {
fputs(line, outf); fputs(line, outf);
if (pass_thru) continue; if (pass_thru) { continue; }
/* All right, this is where the actual fun begins. For one, we only want to /* All right, this is where the actual fun begins. For one, we only want to
instrument the .text section. So, let's keep track of that in processed instrument the .text section. So, let's keep track of that in processed
@ -300,9 +317,12 @@ static void add_instrumentation(void) {
around them, so we use that as a signal. */ around them, so we use that as a signal. */
if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) && if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) &&
isdigit(line[10]) && line[11] == '\n') isdigit(line[10]) && line[11] == '\n') {
skip_next_label = 1; skip_next_label = 1;
}
if (!strncmp(line + 2, "text\n", 5) || if (!strncmp(line + 2, "text\n", 5) ||
!strncmp(line + 2, "section\t.text", 13) || !strncmp(line + 2, "section\t.text", 13) ||
!strncmp(line + 2, "section\t__TEXT,__text", 21) || !strncmp(line + 2, "section\t__TEXT,__text", 21) ||
@ -330,23 +350,23 @@ static void add_instrumentation(void) {
if (strstr(line, ".code")) { if (strstr(line, ".code")) {
if (strstr(line, ".code32")) skip_csect = use_64bit; if (strstr(line, ".code32")) { skip_csect = use_64bit; }
if (strstr(line, ".code64")) skip_csect = !use_64bit; if (strstr(line, ".code64")) { skip_csect = !use_64bit; }
} }
/* Detect syntax changes, as could happen with hand-written assembly. /* Detect syntax changes, as could happen with hand-written assembly.
Skip Intel blocks, resume instrumentation when back to AT&T. */ Skip Intel blocks, resume instrumentation when back to AT&T. */
if (strstr(line, ".intel_syntax")) skip_intel = 1; if (strstr(line, ".intel_syntax")) { skip_intel = 1; }
if (strstr(line, ".att_syntax")) skip_intel = 0; if (strstr(line, ".att_syntax")) { skip_intel = 0; }
/* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */ /* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */
if (line[0] == '#' || line[1] == '#') { if (line[0] == '#' || line[1] == '#') {
if (strstr(line, "#APP")) skip_app = 1; if (strstr(line, "#APP")) { skip_app = 1; }
if (strstr(line, "#NO_APP")) skip_app = 0; if (strstr(line, "#NO_APP")) { skip_app = 0; }
} }
@ -375,9 +395,12 @@ static void add_instrumentation(void) {
*/ */
if (skip_intel || skip_app || skip_csect || !instr_ok || line[0] == '#' || if (skip_intel || skip_app || skip_csect || !instr_ok || line[0] == '#' ||
line[0] == ' ') line[0] == ' ') {
continue; continue;
}
/* Conditional branch instruction (jnz, etc). We append the instrumentation /* Conditional branch instruction (jnz, etc). We append the instrumentation
right after the branch (to instrument the not-taken path) and at the right after the branch (to instrument the not-taken path) and at the
branch destination label (handled later on). */ branch destination label (handled later on). */
@ -449,11 +472,16 @@ static void add_instrumentation(void) {
.Lfunc_begin0-style exception handling calculations (a problem on .Lfunc_begin0-style exception handling calculations (a problem on
MacOS X). */ MacOS X). */
if (!skip_next_label) if (!skip_next_label) {
instrument_next = 1; instrument_next = 1;
else
} else {
skip_next_label = 0; skip_next_label = 0;
}
} }
} else { } else {
@ -468,17 +496,19 @@ static void add_instrumentation(void) {
} }
if (ins_lines) fputs(use_64bit ? main_payload_64 : main_payload_32, outf); if (ins_lines) { fputs(use_64bit ? main_payload_64 : main_payload_32, outf); }
if (input_file) fclose(inf); if (input_file) { fclose(inf); }
fclose(outf); fclose(outf);
if (!be_quiet) { if (!be_quiet) {
if (!ins_lines) if (!ins_lines) {
WARNF("No instrumentation targets found%s.", WARNF("No instrumentation targets found%s.",
pass_thru ? " (pass-thru mode)" : ""); pass_thru ? " (pass-thru mode)" : "");
else {
} else {
char modeline[100]; char modeline[100];
snprintf(modeline, sizeof(modeline), "%s%s%s%s", snprintf(modeline, sizeof(modeline), "%s%s%s%s",
@ -514,10 +544,12 @@ int main(int argc, char **argv) {
SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n"); SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n");
} else } else {
be_quiet = 1; be_quiet = 1;
}
if (argc < 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) { if (argc < 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) {
fprintf( fprintf(
@ -565,14 +597,20 @@ int main(int argc, char **argv) {
if (inst_ratio_str) { if (inst_ratio_str) {
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) {
FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)"); FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)");
}
} }
if (getenv(AS_LOOP_ENV_VAR)) if (getenv(AS_LOOP_ENV_VAR)) {
FATAL("Endless loop when calling 'as' (remove '.' from your PATH)"); FATAL("Endless loop when calling 'as' (remove '.' from your PATH)");
}
setenv(AS_LOOP_ENV_VAR, "1", 1); setenv(AS_LOOP_ENV_VAR, "1", 1);
/* When compiling with ASAN, we don't have a particularly elegant way to skip /* When compiling with ASAN, we don't have a particularly elegant way to skip
@ -582,11 +620,11 @@ int main(int argc, char **argv) {
if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) { if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) {
sanitizer = 1; sanitizer = 1;
if (!getenv("AFL_INST_RATIO")) inst_ratio /= 3; if (!getenv("AFL_INST_RATIO")) { inst_ratio /= 3; }
} }
if (!just_version) add_instrumentation(); if (!just_version) { add_instrumentation(); }
if (!(pid = fork())) { if (!(pid = fork())) {
@ -595,11 +633,11 @@ int main(int argc, char **argv) {
} }
if (pid < 0) PFATAL("fork() failed"); if (pid < 0) { PFATAL("fork() failed"); }
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); if (waitpid(pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); }
if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file); if (!getenv("AFL_KEEP_ASSEMBLY")) { unlink(modified_file); }
exit(WEXITSTATUS(status)); exit(WEXITSTATUS(status));

View File

@ -101,7 +101,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
if (aa_loc) { if (aa_loc) {
if (!prog_in) FATAL("@@ syntax is not supported by this tool."); if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
*use_stdin = 0; *use_stdin = 0;
@ -198,7 +198,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
cp = alloc_printf("%s/afl-qemu-trace", tmp); cp = alloc_printf("%s/afl-qemu-trace", tmp);
if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
*target_path_p = new_argv[0] = cp; *target_path_p = new_argv[0] = cp;
return new_argv; return new_argv;
@ -230,7 +230,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
if (cp) ck_free(cp); if (cp) { ck_free(cp); }
*target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); *target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace");
return new_argv; return new_argv;
@ -277,13 +277,13 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
cp = alloc_printf("%s/afl-qemu-trace", tmp); cp = alloc_printf("%s/afl-qemu-trace", tmp);
if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
ck_free(cp); ck_free(cp);
cp = alloc_printf("%s/afl-wine-trace", tmp); cp = alloc_printf("%s/afl-wine-trace", tmp);
if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
*target_path_p = new_argv[0] = cp; *target_path_p = new_argv[0] = cp;
return new_argv; return new_argv;
@ -416,15 +416,22 @@ u8 *find_binary(u8 *fname) {
ck_free(cur_elem); ck_free(cur_elem);
if (!stat(target_path, &st) && S_ISREG(st.st_mode) && if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
(st.st_mode & 0111) && st.st_size >= 4) (st.st_mode & 0111) && st.st_size >= 4) {
break; break;
}
ck_free(target_path); ck_free(target_path);
target_path = NULL; target_path = NULL;
} }
if (!target_path) FATAL("Program '%s' not found or not executable", fname); if (!target_path) {
FATAL("Program '%s' not found or not executable", fname);
}
} }
@ -434,7 +441,7 @@ u8 *find_binary(u8 *fname) {
void check_environment_vars(char **envp) { void check_environment_vars(char **envp) {
if (be_quiet) return; if (be_quiet) { return; }
int index = 0, found = 0; int index = 0, found = 0;
char *env, *val; char *env, *val;
@ -448,24 +455,30 @@ void check_environment_vars(char **envp) {
} else if (strncmp(env, "AFL_", 4) == 0) { } else if (strncmp(env, "AFL_", 4) == 0) {
int i = 0, match = 0; int i = 0, match = 0;
while (match == 0 && afl_environment_variables[i] != NULL) while (match == 0 && afl_environment_variables[i] != NULL) {
if (strncmp(env, afl_environment_variables[i], if (strncmp(env, afl_environment_variables[i],
strlen(afl_environment_variables[i])) == 0 && strlen(afl_environment_variables[i])) == 0 &&
env[strlen(afl_environment_variables[i])] == '=') { env[strlen(afl_environment_variables[i])] == '=') {
match = 1; match = 1;
if ((val = getenv(afl_environment_variables[i])) && !*val) if ((val = getenv(afl_environment_variables[i])) && !*val) {
WARNF( WARNF(
"AFL environment variable %s defined but is empty, this can " "AFL environment variable %s defined but is empty, this can "
"lead to unexpected consequences", "lead to unexpected consequences",
afl_environment_variables[i]); afl_environment_variables[i]);
}
} else { } else {
i++; i++;
} }
}
if (match == 0) { if (match == 0) {
WARNF("Mistyped AFL environment variable: %s", env); WARNF("Mistyped AFL environment variable: %s", env);
@ -477,7 +490,7 @@ void check_environment_vars(char **envp) {
} }
if (found) sleep(2); if (found) { sleep(2); }
} }
@ -485,10 +498,16 @@ char *get_afl_env(char *env) {
char *val; char *val;
if ((val = getenv(env)) != NULL) if ((val = getenv(env)) != NULL) {
if (!be_quiet)
if (!be_quiet) {
OKF("Loaded environment variable %s with value %s", env, val); OKF("Loaded environment variable %s with value %s", env, val);
}
}
return val; return val;
} }
@ -499,7 +518,7 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
s32 fd = open(fname, O_RDONLY); s32 fd = open(fname, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", fname); if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
ck_read(fd, map, len, fname); ck_read(fd, map, len, fname);
@ -906,9 +925,13 @@ u32 get_map_size() {
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
map_size = atoi(ptr); map_size = atoi(ptr);
if (map_size < 8 || map_size > (1 << 29)) if (map_size < 8 || map_size > (1 << 29)) {
FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size); FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size);
if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3);
}
if (map_size % 8) { map_size = (((map_size >> 3) + 1) << 3); }
} }

View File

@ -128,12 +128,16 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
unsigned char tmp[4] = {0, 0, 0, 0}; unsigned char tmp[4] = {0, 0, 0, 0};
pid_t child_pid = -1; pid_t child_pid = -1;
if (!be_quiet) ACTF("Using Fauxserver:"); if (!be_quiet) { ACTF("Using Fauxserver:"); }
/* Phone home and tell the parent that we're OK. If parent isn't there, /* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */ assume we're not running in forkserver mode and just execute program. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) abort(); // TODO: Abort? if (write(FORKSRV_FD + 1, tmp, 4) != 4) {
abort(); // TODO: Abort?
}
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
@ -144,13 +148,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
/* Wait for parent by reading from the pipe. Exit if read fails. */ /* Wait for parent by reading from the pipe. Exit if read fails. */
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(0); if (read(FORKSRV_FD, &was_killed, 4) != 4) { exit(0); }
/* Create a clone of our process. */ /* Create a clone of our process. */
child_pid = fork(); child_pid = fork();
if (child_pid < 0) PFATAL("Fork failed"); if (child_pid < 0) { PFATAL("Fork failed"); }
/* In child process: close fds, resume execution. */ /* In child process: close fds, resume execution. */
@ -177,7 +181,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
/* In parent process: write PID to AFL. */ /* In parent process: write PID to AFL. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(0); if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { exit(0); }
/* after child exited, get and relay exit status to parent through waitpid. /* after child exited, get and relay exit status to parent through waitpid.
*/ */
@ -191,7 +195,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
/* Relay wait status to AFL pipe, then loop back. */ /* Relay wait status to AFL pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(0); if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
} }
@ -212,25 +216,28 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
int status; int status;
s32 rlen; s32 rlen;
if (!be_quiet) ACTF("Spinning up the fork server..."); if (!be_quiet) { ACTF("Spinning up the fork server..."); }
if (fsrv->use_fauxsrv) { if (fsrv->use_fauxsrv) {
/* TODO: Come up with sone nice way to initalize this all */ /* TODO: Come up with sone nice way to initalize this all */
if (fsrv->init_child_func != fsrv_exec_child) if (fsrv->init_child_func != fsrv_exec_child) {
FATAL("Different forkserver not compatible with fauxserver"); FATAL("Different forkserver not compatible with fauxserver");
}
fsrv->init_child_func = afl_fauxsrv_execv; fsrv->init_child_func = afl_fauxsrv_execv;
} }
if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); if (pipe(st_pipe) || pipe(ctl_pipe)) { PFATAL("pipe() failed"); }
fsrv->last_run_timed_out = 0; fsrv->last_run_timed_out = 0;
fsrv->fsrv_pid = fork(); fsrv->fsrv_pid = fork();
if (fsrv->fsrv_pid < 0) PFATAL("fork() failed"); if (fsrv->fsrv_pid < 0) { PFATAL("fork() failed"); }
if (!fsrv->fsrv_pid) { if (!fsrv->fsrv_pid) {
@ -295,8 +302,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* Set up control and status pipes, close the unneeded original fds. */ /* Set up control and status pipes, close the unneeded original fds. */
if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) { PFATAL("dup2() failed"); }
if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed"); if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) { PFATAL("dup2() failed"); }
close(ctl_pipe[0]); close(ctl_pipe[0]);
close(ctl_pipe[1]); close(ctl_pipe[1]);
@ -308,12 +315,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
#ifndef HAVE_ARC4RANDOM #ifndef HAVE_ARC4RANDOM
close(fsrv->dev_urandom_fd); close(fsrv->dev_urandom_fd);
#endif #endif
if (fsrv->plot_file != NULL) fclose(fsrv->plot_file); if (fsrv->plot_file != NULL) { fclose(fsrv->plot_file); }
/* This should improve performance a bit, since it stops the linker from /* This should improve performance a bit, since it stops the linker from
doing extra work post-fork(). */ doing extra work post-fork(). */
if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); }
/* Set sane defaults for ASAN if nothing else specified. */ /* Set sane defaults for ASAN if nothing else specified. */
@ -391,17 +398,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (rlen == 4) { if (rlen == 4) {
if (!be_quiet) OKF("All right - fork server is up."); if (!be_quiet) { OKF("All right - fork server is up."); }
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
if (!be_quiet && getenv("AFL_DEBUG")) if (!be_quiet && getenv("AFL_DEBUG")) {
ACTF("Extended forkserver functions received (%08x).", status); ACTF("Extended forkserver functions received (%08x).", status);
}
if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) {
fsrv->snapshot = 1; fsrv->snapshot = 1;
if (!be_quiet) ACTF("Using SNAPSHOT feature."); if (!be_quiet) { ACTF("Using SNAPSHOT feature."); }
} }
@ -409,7 +419,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status);
if (!fsrv->map_size) fsrv->map_size = MAP_SIZE; if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
if (unlikely(tmp_map_size % 8)) { if (unlikely(tmp_map_size % 8)) {
@ -419,13 +429,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} }
if (!be_quiet) ACTF("Target map size: %u", tmp_map_size); if (!be_quiet) { ACTF("Target map size: %u", tmp_map_size); }
if (tmp_map_size > fsrv->map_size) if (tmp_map_size > fsrv->map_size) {
FATAL( FATAL(
"Target's coverage map size of %u is larger than the one this " "Target's coverage map size of %u is larger than the one this "
"afl++ is set with (%u) (change MAP_SIZE_POW2 in config.h and " "afl++ is set with (%u) (change MAP_SIZE_POW2 in config.h and "
"recompile or set AFL_MAP_SIZE)\n", "recompile or set AFL_MAP_SIZE)\n",
tmp_map_size, fsrv->map_size); tmp_map_size, fsrv->map_size);
}
fsrv->map_size = tmp_map_size; fsrv->map_size = tmp_map_size;
} }
@ -436,27 +450,44 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
// this is not afl-fuzz - we deny and return // this is not afl-fuzz - we deny and return
status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT)); status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT));
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed."); FATAL("Writing to forkserver failed.");
}
return; return;
} }
if (!be_quiet) ACTF("Using AUTODICT feature."); if (!be_quiet) { ACTF("Using AUTODICT feature."); }
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed."); FATAL("Writing to forkserver failed.");
if (read(fsrv->fsrv_st_fd, &status, 4) != 4)
}
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
FATAL("Reading from forkserver failed."); FATAL("Reading from forkserver failed.");
if (status < 2 || (u32)status > 0xffffff) }
if (status < 2 || (u32)status > 0xffffff) {
FATAL("Dictionary has an illegal size: %d", status); FATAL("Dictionary has an illegal size: %d", status);
}
u32 len = status, offset = 0, count = 0; u32 len = status, offset = 0, count = 0;
u8 *dict = ck_alloc(len); u8 *dict = ck_alloc(len);
if (dict == NULL) if (dict == NULL) {
FATAL("Could not allocate %u bytes of autodictionary memory", len); FATAL("Could not allocate %u bytes of autodictionary memory", len);
}
while (len != 0) { while (len != 0) {
rlen = read(fsrv->fsrv_st_fd, dict + offset, len); rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
@ -486,7 +517,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} }
if (!be_quiet) ACTF("Loaded %u autodictionary entries", count); if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
ck_free(dict); ck_free(dict);
} }
@ -497,10 +528,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} }
if (fsrv->last_run_timed_out) if (fsrv->last_run_timed_out) {
FATAL("Timeout while initializing fork server (adjusting -t may help)"); FATAL("Timeout while initializing fork server (adjusting -t may help)");
if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed"); }
if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); }
if (WIFSIGNALED(status)) { if (WIFSIGNALED(status)) {
@ -580,9 +614,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} }
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) {
FATAL("Unable to execute target application ('%s')", argv[0]); FATAL("Unable to execute target application ('%s')", argv[0]);
}
if (fsrv->mem_limit && fsrv->mem_limit < 500 && fsrv->uses_asan) { if (fsrv->mem_limit && fsrv->mem_limit < 500 && fsrv->uses_asan) {
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
@ -651,7 +688,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
static void afl_fsrv_kill(afl_forkserver_t *fsrv) { static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
if (fsrv->child_pid > 0) kill(fsrv->child_pid, SIGKILL); if (fsrv->child_pid > 0) { kill(fsrv->child_pid, SIGKILL); }
if (fsrv->fsrv_pid > 0) { if (fsrv->fsrv_pid > 0) {
kill(fsrv->fsrv_pid, SIGKILL); kill(fsrv->fsrv_pid, SIGKILL);
@ -680,7 +717,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
} }
if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); }
} else { } else {
@ -692,7 +729,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
if (!fsrv->out_file) { if (!fsrv->out_file) {
if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); }
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
} else { } else {
@ -727,7 +764,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) { if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) {
if (*stop_soon_p) return 0; if (*stop_soon_p) { return 0; }
RPFATAL(res, "Unable to request new process from fork server (OOM?)"); RPFATAL(res, "Unable to request new process from fork server (OOM?)");
} }
@ -736,12 +773,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
if (*stop_soon_p) return 0; if (*stop_soon_p) { return 0; }
RPFATAL(res, "Unable to request new process from fork server (OOM?)"); RPFATAL(res, "Unable to request new process from fork server (OOM?)");
} }
if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); }
exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p); exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p);
@ -752,13 +789,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
kill(fsrv->child_pid, SIGKILL); kill(fsrv->child_pid, SIGKILL);
fsrv->last_run_timed_out = 1; fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0; if (read(fsrv->fsrv_st_fd, &status, 4) < 4) { exec_ms = 0; }
} }
if (!exec_ms) { if (!exec_ms) {
if (*stop_soon_p) return 0; if (*stop_soon_p) { return 0; }
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
"Unable to communicate with fork server. Some possible reasons:\n\n" "Unable to communicate with fork server. Some possible reasons:\n\n"
" - You've run out of memory. Use -m to increase the the memory " " - You've run out of memory. Use -m to increase the the memory "
@ -784,7 +821,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
} }
if (!WIFSTOPPED(status)) fsrv->child_pid = 0; if (!WIFSTOPPED(status)) { fsrv->child_pid = 0; }
fsrv->total_execs++; fsrv->total_execs++;
@ -800,9 +837,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
fsrv->last_kill_signal = WTERMSIG(status); fsrv->last_kill_signal = WTERMSIG(status);
if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) {
return FSRV_RUN_TMOUT; return FSRV_RUN_TMOUT;
}
return FSRV_RUN_CRASH; return FSRV_RUN_CRASH;
} }

View File

@ -35,13 +35,13 @@ void write_bitmap(afl_state_t *afl) {
u8 fname[PATH_MAX]; u8 fname[PATH_MAX];
s32 fd; s32 fd;
if (!afl->bitmap_changed) return; if (!afl->bitmap_changed) { return; }
afl->bitmap_changed = 0; afl->bitmap_changed = 0;
snprintf(fname, PATH_MAX, "%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); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) PFATAL("Unable to open '%s'", fname); if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname); ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname);
@ -102,11 +102,16 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
(cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) || (cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) ||
(cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) || (cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) ||
(cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) || (cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) ||
(cur[7] && vir[7] == 0xff)) (cur[7] && vir[7] == 0xff)) {
ret = 2; ret = 2;
else
} else {
ret = 1; ret = 1;
}
#else #else
if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) || if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) ||
@ -129,9 +134,12 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) {
} }
if (unlikely(ret) && likely(virgin_map == afl->virgin_bits)) if (unlikely(ret) && likely(virgin_map == afl->virgin_bits)) {
afl->bitmap_changed = 1; afl->bitmap_changed = 1;
}
return ret; return ret;
} }
@ -183,11 +191,11 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) {
u32 v = *(ptr++); u32 v = *(ptr++);
if (!v) continue; if (!v) { continue; }
if (v & 0x000000ff) ++ret; if (v & 0x000000ff) { ++ret; }
if (v & 0x0000ff00) ++ret; if (v & 0x0000ff00) { ++ret; }
if (v & 0x00ff0000) ++ret; if (v & 0x00ff0000) { ++ret; }
if (v & 0xff000000) ++ret; if (v & 0xff000000) { ++ret; }
} }
@ -211,11 +219,11 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
/* This is called on the virgin bitmap, so optimize for the most likely /* This is called on the virgin bitmap, so optimize for the most likely
case. */ case. */
if (v == 0xffffffff) continue; if (v == 0xffffffff) { continue; }
if ((v & 0x000000ff) != 0x000000ff) ++ret; if ((v & 0x000000ff) != 0x000000ff) { ++ret; }
if ((v & 0x0000ff00) != 0x0000ff00) ++ret; if ((v & 0x0000ff00) != 0x0000ff00) { ++ret; }
if ((v & 0x00ff0000) != 0x00ff0000) ++ret; if ((v & 0x00ff0000) != 0x00ff0000) { ++ret; }
if ((v & 0xff000000) != 0xff000000) ++ret; if ((v & 0xff000000) != 0xff000000) { ++ret; }
} }
@ -257,10 +265,12 @@ void simplify_trace(afl_state_t *afl, u64 *mem) {
mem8[6] = simplify_lookup[mem8[6]]; mem8[6] = simplify_lookup[mem8[6]];
mem8[7] = simplify_lookup[mem8[7]]; mem8[7] = simplify_lookup[mem8[7]];
} else } else {
*mem = 0x0101010101010101ULL; *mem = 0x0101010101010101ULL;
}
++mem; ++mem;
} }
@ -322,11 +332,17 @@ void init_count_class16(void) {
u32 b1, b2; u32 b1, b2;
for (b1 = 0; b1 < 256; b1++) for (b1 = 0; b1 < 256; b1++) {
for (b2 = 0; b2 < 256; b2++)
for (b2 = 0; b2 < 256; b2++) {
count_class_lookup16[(b1 << 8) + b2] = count_class_lookup16[(b1 << 8) + b2] =
(count_class_lookup8[b1] << 8) | count_class_lookup8[b2]; (count_class_lookup8[b1] << 8) | count_class_lookup8[b2];
}
}
} }
#ifdef WORD_SIZE_64 #ifdef WORD_SIZE_64
@ -397,7 +413,7 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
while (i < afl->fsrv.map_size) { while (i < afl->fsrv.map_size) {
if (*(src++)) dst[i >> 3] |= 1 << (i & 7); if (*(src++)) { dst[i >> 3] |= 1 << (i & 7); }
++i; ++i;
} }
@ -423,27 +439,35 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time); sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
if (afl->splicing_with >= 0) if (afl->splicing_with >= 0) {
sprintf(ret + strlen(ret), "+%06d", afl->splicing_with); sprintf(ret + strlen(ret), "+%06d", afl->splicing_with);
}
sprintf(ret + strlen(ret), ",op:%s", afl->stage_short); sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
if (afl->stage_cur_byte >= 0) { if (afl->stage_cur_byte >= 0) {
sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte); sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
if (afl->stage_val_type != STAGE_VAL_NONE) if (afl->stage_val_type != STAGE_VAL_NONE) {
sprintf(ret + strlen(ret), ",val:%s%+d", sprintf(ret + strlen(ret), ",val:%s%+d",
(afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "", (afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
afl->stage_cur_val); afl->stage_cur_val);
} else }
} else {
sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val); sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
}
} }
if (hnb == 2) strcat(ret, ",+cov"); if (hnb == 2) { strcat(ret, ",+cov"); }
return ret; return ret;
@ -467,7 +491,7 @@ static void write_crash_readme(afl_state_t *afl) {
/* Do not die on errors here - that would be impolite. */ /* Do not die on errors here - that would be impolite. */
if (unlikely(fd < 0)) return; if (unlikely(fd < 0)) { return; }
f = fdopen(fd, "w"); f = fdopen(fd, "w");
@ -512,7 +536,7 @@ static void write_crash_readme(afl_state_t *afl) {
u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(len == 0)) return 0; if (unlikely(len == 0)) { return 0; }
u8 *queue_fn = ""; u8 *queue_fn = "";
u8 hnb = '\0'; u8 hnb = '\0';
@ -545,7 +569,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (!(hnb = has_new_bits(afl, afl->virgin_bits))) { if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
if (unlikely(afl->crash_mode)) ++afl->total_crashes; if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
return 0; return 0;
} }
@ -578,11 +602,14 @@ 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); res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0);
if (unlikely(res == FSRV_RUN_ERROR)) if (unlikely(res == FSRV_RUN_ERROR)) {
FATAL("Unable to execute target application"); FATAL("Unable to execute target application");
}
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn); if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
ck_write(fd, mem, len, queue_fn); ck_write(fd, mem, len, queue_fn);
close(fd); close(fd);
@ -601,7 +628,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
++afl->total_tmouts; ++afl->total_tmouts;
if (afl->unique_hangs >= KEEP_UNIQUE_HANG) return keeping; if (afl->unique_hangs >= KEEP_UNIQUE_HANG) { return keeping; }
if (likely(!afl->dumb_mode)) { if (likely(!afl->dumb_mode)) {
@ -611,7 +638,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); simplify_trace(afl, (u32 *)afl->fsrv.trace_bits);
#endif /* ^WORD_SIZE_64 */ #endif /* ^WORD_SIZE_64 */
if (!has_new_bits(afl, afl->virgin_tmout)) return keeping; if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; }
} }
@ -631,9 +658,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
timeout actually uncovers a crash. Make sure we don't discard it if timeout actually uncovers a crash. Make sure we don't discard it if
so. */ so. */
if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) goto keep_as_crash; if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) {
if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) return keeping; goto keep_as_crash;
}
if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) { return keeping; }
} }
@ -665,7 +696,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
++afl->total_crashes; ++afl->total_crashes;
if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) { return keeping; }
if (likely(!afl->dumb_mode)) { if (likely(!afl->dumb_mode)) {
@ -675,11 +706,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); simplify_trace(afl, (u32 *)afl->fsrv.trace_bits);
#endif /* ^WORD_SIZE_64 */ #endif /* ^WORD_SIZE_64 */
if (!has_new_bits(afl, afl->virgin_crash)) return keeping; if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; }
} }
if (unlikely(!afl->unique_crashes)) write_crash_readme(afl); if (unlikely(!afl->unique_crashes)) { write_crash_readme(afl); }
#ifndef SIMPLE_FILES #ifndef SIMPLE_FILES
@ -715,9 +746,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
break; break;
case FSRV_RUN_ERROR: FATAL("Unable to execute target application"); case FSRV_RUN_ERROR:
FATAL("Unable to execute target application");
default: return keeping; default:
return keeping;
} }
@ -725,7 +758,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
test case, too. */ test case, too. */
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn); if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
ck_write(fd, mem, len, fn); ck_write(fd, mem, len, fn);
close(fd); close(fd);

View File

@ -37,9 +37,12 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);
if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) {
argv[0] = fsrv->cmplog_binary; argv[0] = fsrv->cmplog_binary;
}
execv(argv[0], argv); execv(argv[0], argv);
} }
@ -54,7 +57,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
size_t post_len = size_t post_len =
afl->post_handler(afl->post_data, out_buf, len, &post_buf); afl->post_handler(afl->post_data, out_buf, len, &post_buf);
if (!post_buf || !post_len) return 0; if (!post_buf || !post_len) { return 0; }
out_buf = post_buf; out_buf = post_buf;
len = post_len; len = post_len;
@ -64,7 +67,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) return 1; if (afl->stop_soon) { return 1; }
if (fault == FSRV_RUN_TMOUT) { if (fault == FSRV_RUN_TMOUT) {
@ -75,10 +78,12 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
} }
} else } else {
afl->subseq_tmouts = 0; afl->subseq_tmouts = 0;
}
/* Users can hit us with SIGUSR1 to request the current input /* Users can hit us with SIGUSR1 to request the current input
to be abandoned. */ to be abandoned. */

View File

@ -59,7 +59,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
f = fopen(fname, "r"); f = fopen(fname, "r");
if (!f) PFATAL("Unable to open '%s'", fname); if (!f) { PFATAL("Unable to open '%s'", fname); }
while ((lptr = fgets(buf, MAX_LINE, f))) { while ((lptr = fgets(buf, MAX_LINE, f))) {
@ -70,57 +70,79 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
/* Trim on left and right. */ /* Trim on left and right. */
while (isspace(*lptr)) while (isspace(*lptr)) {
++lptr; ++lptr;
}
rptr = lptr + strlen(lptr) - 1; rptr = lptr + strlen(lptr) - 1;
while (rptr >= lptr && isspace(*rptr)) while (rptr >= lptr && isspace(*rptr)) {
--rptr; --rptr;
}
++rptr; ++rptr;
*rptr = 0; *rptr = 0;
/* Skip empty lines and comments. */ /* Skip empty lines and comments. */
if (!*lptr || *lptr == '#') continue; if (!*lptr || *lptr == '#') { continue; }
/* All other lines must end with '"', which we can consume. */ /* All other lines must end with '"', which we can consume. */
--rptr; --rptr;
if (rptr < lptr || *rptr != '"') if (rptr < lptr || *rptr != '"') {
FATAL("Malformed name=\"value\" pair in line %u.", cur_line); FATAL("Malformed name=\"value\" pair in line %u.", cur_line);
}
*rptr = 0; *rptr = 0;
/* Skip alphanumerics and dashes (label). */ /* Skip alphanumerics and dashes (label). */
while (isalnum(*lptr) || *lptr == '_') while (isalnum(*lptr) || *lptr == '_') {
++lptr; ++lptr;
}
/* If @number follows, parse that. */ /* If @number follows, parse that. */
if (*lptr == '@') { if (*lptr == '@') {
++lptr; ++lptr;
if (atoi(lptr) > dict_level) continue; if (atoi(lptr) > dict_level) { continue; }
while (isdigit(*lptr)) while (isdigit(*lptr)) {
++lptr; ++lptr;
}
} }
/* Skip whitespace and = signs. */ /* Skip whitespace and = signs. */
while (isspace(*lptr) || *lptr == '=') while (isspace(*lptr) || *lptr == '=') {
++lptr; ++lptr;
}
/* Consume opening '"'. */ /* Consume opening '"'. */
if (*lptr != '"') if (*lptr != '"') {
FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line);
}
++lptr; ++lptr;
if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); if (!*lptr) { FATAL("Empty keyword in line %u.", cur_line); }
/* Okay, let's allocate memory and copy data between "...", handling /* Okay, let's allocate memory and copy data between "...", handling
\xNN escaping, \\, and \". */ \xNN escaping, \\, and \". */
@ -130,7 +152,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr); wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr);
if (!wptr) PFATAL("no mem for data"); if (!wptr) { PFATAL("no mem for data"); }
while (*lptr) { while (*lptr) {
@ -154,9 +176,12 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
} }
if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) {
FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line);
}
*(wptr++) = ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) | *(wptr++) = ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) |
(strchr(hexdigits, tolower(lptr[2])) - hexdigits); (strchr(hexdigits, tolower(lptr[2])) - hexdigits);
@ -165,7 +190,9 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
break; break;
default: *(wptr++) = *(lptr++); ++klen; default:
*(wptr++) = *(lptr++);
++klen;
} }
@ -173,14 +200,17 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
afl->extras[afl->extras_cnt].len = klen; afl->extras[afl->extras_cnt].len = klen;
if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE) if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE) {
FATAL( FATAL(
"Keyword too big in line %u (%s, limit is %s)", cur_line, "Keyword too big in line %u (%s, limit is %s)", cur_line,
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen), stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
if (*min_len > klen) *min_len = klen; }
if (*max_len < klen) *max_len = klen;
if (*min_len > klen) { *min_len = klen; }
if (*max_len < klen) { *max_len = klen; }
++afl->extras_cnt; ++afl->extras_cnt;
@ -227,7 +257,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
} }
if (x) FATAL("Dictionary levels not supported for directories."); if (x) { FATAL("Dictionary levels not supported for directories."); }
while ((de = readdir(d))) { while ((de = readdir(d))) {
@ -235,7 +265,11 @@ void load_extras(afl_state_t *afl, u8 *dir) {
u8 * fn = alloc_printf("%s/%s", dir, de->d_name); u8 * fn = alloc_printf("%s/%s", dir, de->d_name);
s32 fd; s32 fd;
if (lstat(fn, &st) || access(fn, R_OK)) PFATAL("Unable to access '%s'", fn); if (lstat(fn, &st) || access(fn, R_OK)) {
PFATAL("Unable to access '%s'", fn);
}
/* This also takes care of . and .. */ /* This also takes care of . and .. */
if (!S_ISREG(st.st_mode) || !st.st_size) { if (!S_ISREG(st.st_mode) || !st.st_size) {
@ -245,14 +279,17 @@ void load_extras(afl_state_t *afl, u8 *dir) {
} }
if (st.st_size > MAX_DICT_FILE) if (st.st_size > MAX_DICT_FILE) {
FATAL( FATAL(
"Extra '%s' is too big (%s, limit is %s)", fn, "Extra '%s' is too big (%s, limit is %s)", fn,
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size), stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
if (min_len > st.st_size) min_len = st.st_size; }
if (max_len < st.st_size) max_len = st.st_size;
if (min_len > st.st_size) { min_len = st.st_size; }
if (max_len < st.st_size) { max_len = st.st_size; }
afl->extras = ck_realloc_block( afl->extras = ck_realloc_block(
afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data)); afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data));
@ -262,7 +299,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
fd = open(fn, O_RDONLY); fd = open(fn, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", fn); if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
ck_read(fd, afl->extras[afl->extras_cnt].data, st.st_size, fn); ck_read(fd, afl->extras[afl->extras_cnt].data, st.st_size, fn);
@ -277,7 +314,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
check_and_sort: check_and_sort:
if (!afl->extras_cnt) FATAL("No usable files in '%s'", dir); if (!afl->extras_cnt) { FATAL("No usable files in '%s'", dir); }
qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data), qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data),
compare_extras_len); compare_extras_len);
@ -286,22 +323,32 @@ check_and_sort:
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len), stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len)); stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
if (max_len > 32) if (max_len > 32) {
WARNF("Some tokens are relatively large (%s) - consider trimming.", WARNF("Some tokens are relatively large (%s) - consider trimming.",
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len)); stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len));
if (afl->extras_cnt > MAX_DET_EXTRAS) }
if (afl->extras_cnt > MAX_DET_EXTRAS) {
WARNF("More than %d tokens - will use them probabilistically.", WARNF("More than %d tokens - will use them probabilistically.",
MAX_DET_EXTRAS); MAX_DET_EXTRAS);
}
} }
/* Helper function for maybe_add_auto(afl, ) */ /* Helper function for maybe_add_auto(afl, ) */
static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) { static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
while (len--) while (len--) {
if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1;
if (tolower(*(m1++)) ^ tolower(*(m2++))) { return 1; }
}
return 0; return 0;
} }
@ -318,14 +365,17 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
/* Allow users to specify that they don't want auto dictionaries. */ /* Allow users to specify that they don't want auto dictionaries. */
if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return; if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) { return; }
/* Skip runs of identical bytes. */ /* Skip runs of identical bytes. */
for (i = 1; i < len; ++i) for (i = 1; i < len; ++i) {
if (mem[0] ^ mem[i]) break;
if (i == len) return; if (mem[0] ^ mem[i]) { break; }
}
if (i == len) { return; }
/* Reject builtin interesting values. */ /* Reject builtin interesting values. */
@ -333,33 +383,51 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
i = sizeof(interesting_16) >> 1; i = sizeof(interesting_16) >> 1;
while (i--) while (i--) {
if (*((u16 *)mem) == interesting_16[i] || if (*((u16 *)mem) == interesting_16[i] ||
*((u16 *)mem) == SWAP16(interesting_16[i])) *((u16 *)mem) == SWAP16(interesting_16[i])) {
return; return;
}
}
} }
if (len == 4) { if (len == 4) {
i = sizeof(interesting_32) >> 2; i = sizeof(interesting_32) >> 2;
while (i--) while (i--) {
if (*((u32 *)mem) == interesting_32[i] || if (*((u32 *)mem) == interesting_32[i] ||
*((u32 *)mem) == SWAP32(interesting_32[i])) *((u32 *)mem) == SWAP32(interesting_32[i])) {
return; return;
}
}
} }
/* Reject anything that matches existing extras. Do a case-insensitive /* Reject anything that matches existing extras. Do a case-insensitive
match. We optimize by exploiting the fact that extras[] are sorted match. We optimize by exploiting the fact that extras[] are sorted
by size. */ by size. */
for (i = 0; i < afl->extras_cnt; ++i) for (i = 0; i < afl->extras_cnt; ++i) {
if (afl->extras[i].len >= len) break;
for (; i < afl->extras_cnt && afl->extras[i].len == len; ++i) if (afl->extras[i].len >= len) { break; }
if (!memcmp_nocase(afl->extras[i].data, mem, len)) return;
}
for (; i < afl->extras_cnt && afl->extras[i].len == len; ++i) {
if (!memcmp_nocase(afl->extras[i].data, mem, len)) { return; }
}
/* Last but not least, check afl->a_extras[] for matches. There are no /* Last but not least, check afl->a_extras[] for matches. There are no
guarantees of a particular sort order. */ guarantees of a particular sort order. */
@ -423,7 +491,7 @@ void save_auto(afl_state_t *afl) {
u32 i; u32 i;
if (!afl->auto_changed) return; if (!afl->auto_changed) { return; }
afl->auto_changed = 0; afl->auto_changed = 0;
for (i = 0; i < MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) { for (i = 0; i < MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
@ -434,7 +502,7 @@ void save_auto(afl_state_t *afl) {
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", fn); if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
ck_write(fd, afl->a_extras[i].data, afl->a_extras[i].len, fn); ck_write(fd, afl->a_extras[i].data, afl->a_extras[i].len, fn);
@ -461,7 +529,7 @@ void load_auto(afl_state_t *afl) {
if (fd < 0) { if (fd < 0) {
if (errno != ENOENT) PFATAL("Unable to open '%s'", fn); if (errno != ENOENT) { PFATAL("Unable to open '%s'", fn); }
ck_free(fn); ck_free(fn);
break; break;
@ -472,21 +540,29 @@ void load_auto(afl_state_t *afl) {
len = read(fd, tmp, MAX_AUTO_EXTRA + 1); len = read(fd, tmp, MAX_AUTO_EXTRA + 1);
if (len < 0) PFATAL("Unable to read from '%s'", fn); if (len < 0) { PFATAL("Unable to read from '%s'", fn); }
if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) {
if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA)
maybe_add_auto((u8 *)afl, tmp, len); maybe_add_auto((u8 *)afl, tmp, len);
}
close(fd); close(fd);
ck_free(fn); ck_free(fn);
} }
if (i) if (i) {
OKF("Loaded %u auto-discovered dictionary tokens.", i); OKF("Loaded %u auto-discovered dictionary tokens.", i);
else
} else {
OKF("No auto-generated dictionary tokens to reuse."); OKF("No auto-generated dictionary tokens to reuse.");
}
} }
/* Destroy extras. */ /* Destroy extras. */
@ -495,14 +571,20 @@ void destroy_extras(afl_state_t *afl) {
u32 i; u32 i;
for (i = 0; i < afl->extras_cnt; ++i) for (i = 0; i < afl->extras_cnt; ++i) {
ck_free(afl->extras[i].data); ck_free(afl->extras[i].data);
}
ck_free(afl->extras); ck_free(afl->extras);
for (i = 0; i < afl->a_extras_cnt; ++i) for (i = 0; i < afl->a_extras_cnt; ++i) {
ck_free(afl->a_extras[i].data); ck_free(afl->a_extras[i].data);
}
ck_free(afl->a_extras); ck_free(afl->a_extras);
} }

File diff suppressed because it is too large Load Diff

View File

@ -35,12 +35,15 @@ void setup_custom_mutator(afl_state_t *afl) {
if (fn) { if (fn) {
if (afl->limit_time_sig) if (afl->limit_time_sig) {
FATAL( FATAL(
"MOpt and custom mutator are mutually exclusive. We accept pull " "MOpt and custom mutator are mutually exclusive. We accept pull "
"requests that integrates MOpt with the optional mutators " "requests that integrates MOpt with the optional mutators "
"(custom/radamsa/redquenn/...)."); "(custom/radamsa/redquenn/...).");
}
load_custom_mutator(afl, fn); load_custom_mutator(afl, fn);
return; return;
@ -53,12 +56,15 @@ void setup_custom_mutator(afl_state_t *afl) {
if (module_name) { if (module_name) {
if (afl->limit_time_sig) if (afl->limit_time_sig) {
FATAL( FATAL(
"MOpt and Python mutator are mutually exclusive. We accept pull " "MOpt and Python mutator are mutually exclusive. We accept pull "
"requests that integrates MOpt with the optional mutators " "requests that integrates MOpt with the optional mutators "
"(custom/radamsa/redqueen/...)."); "(custom/radamsa/redqueen/...).");
}
load_custom_mutator_py(afl, module_name); load_custom_mutator_py(afl, module_name);
} }
@ -76,7 +82,7 @@ void destroy_custom_mutator(afl_state_t *afl) {
afl->mutator->afl_custom_deinit(afl->mutator->data); afl->mutator->afl_custom_deinit(afl->mutator->data);
if (afl->mutator->dh) dlclose(afl->mutator->dh); if (afl->mutator->dh) { dlclose(afl->mutator->dh); }
if (afl->mutator->pre_save_buf) { if (afl->mutator->pre_save_buf) {
@ -104,20 +110,26 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("Loading custom mutator library from '%s'...", fn); ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW); dh = dlopen(fn, RTLD_NOW);
if (!dh) FATAL("%s", dlerror()); if (!dh) { FATAL("%s", dlerror()); }
afl->mutator->dh = dh; afl->mutator->dh = dh;
/* Mutator */ /* Mutator */
/* "afl_custom_init", required */ /* "afl_custom_init", required */
afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init"); afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
if (!afl->mutator->afl_custom_init) if (!afl->mutator->afl_custom_init) {
FATAL("Symbol 'afl_custom_init' not found."); FATAL("Symbol 'afl_custom_init' not found.");
}
/* "afl_custom_deinit", required */ /* "afl_custom_deinit", required */
afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit"); afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
if (!afl->mutator->afl_custom_deinit) if (!afl->mutator->afl_custom_deinit) {
FATAL("Symbol 'afl_custom_deinit' not found."); FATAL("Symbol 'afl_custom_deinit' not found.");
}
/* "afl_custom_fuzz" or "afl_custom_mutator", required */ /* "afl_custom_fuzz" or "afl_custom_mutator", required */
afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz"); afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
if (!afl->mutator->afl_custom_fuzz) { if (!afl->mutator->afl_custom_fuzz) {
@ -126,32 +138,47 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'."); WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator"); afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
if (!afl->mutator->afl_custom_fuzz) if (!afl->mutator->afl_custom_fuzz) {
FATAL("Symbol 'afl_custom_mutator' not found."); FATAL("Symbol 'afl_custom_mutator' not found.");
}
} }
/* "afl_custom_pre_save", optional */ /* "afl_custom_pre_save", optional */
afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save"); afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save");
if (!afl->mutator->afl_custom_pre_save) if (!afl->mutator->afl_custom_pre_save) {
WARNF("Symbol 'afl_custom_pre_save' not found."); WARNF("Symbol 'afl_custom_pre_save' not found.");
}
u8 notrim = 0; u8 notrim = 0;
/* "afl_custom_init_trim", optional */ /* "afl_custom_init_trim", optional */
afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim"); afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
if (!afl->mutator->afl_custom_init_trim) if (!afl->mutator->afl_custom_init_trim) {
WARNF("Symbol 'afl_custom_init_trim' not found."); WARNF("Symbol 'afl_custom_init_trim' not found.");
}
/* "afl_custom_trim", optional */ /* "afl_custom_trim", optional */
afl->mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim"); afl->mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
if (!afl->mutator->afl_custom_trim) if (!afl->mutator->afl_custom_trim) {
WARNF("Symbol 'afl_custom_trim' not found."); WARNF("Symbol 'afl_custom_trim' not found.");
}
/* "afl_custom_post_trim", optional */ /* "afl_custom_post_trim", optional */
afl->mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim"); afl->mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
if (!afl->mutator->afl_custom_post_trim) if (!afl->mutator->afl_custom_post_trim) {
WARNF("Symbol 'afl_custom_post_trim' not found."); WARNF("Symbol 'afl_custom_post_trim' not found.");
}
if (notrim) { if (notrim) {
afl->mutator->afl_custom_init_trim = NULL; afl->mutator->afl_custom_init_trim = NULL;
@ -166,33 +193,48 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
/* "afl_custom_havoc_mutation", optional */ /* "afl_custom_havoc_mutation", optional */
afl->mutator->afl_custom_havoc_mutation = afl->mutator->afl_custom_havoc_mutation =
dlsym(dh, "afl_custom_havoc_mutation"); dlsym(dh, "afl_custom_havoc_mutation");
if (!afl->mutator->afl_custom_havoc_mutation) if (!afl->mutator->afl_custom_havoc_mutation) {
WARNF("Symbol 'afl_custom_havoc_mutation' not found."); WARNF("Symbol 'afl_custom_havoc_mutation' not found.");
}
/* "afl_custom_havoc_mutation", optional */ /* "afl_custom_havoc_mutation", optional */
afl->mutator->afl_custom_havoc_mutation_probability = afl->mutator->afl_custom_havoc_mutation_probability =
dlsym(dh, "afl_custom_havoc_mutation_probability"); dlsym(dh, "afl_custom_havoc_mutation_probability");
if (!afl->mutator->afl_custom_havoc_mutation_probability) if (!afl->mutator->afl_custom_havoc_mutation_probability) {
WARNF("Symbol 'afl_custom_havoc_mutation_probability' not found."); WARNF("Symbol 'afl_custom_havoc_mutation_probability' not found.");
}
/* "afl_custom_queue_get", optional */ /* "afl_custom_queue_get", optional */
afl->mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get"); afl->mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
if (!afl->mutator->afl_custom_queue_get) if (!afl->mutator->afl_custom_queue_get) {
WARNF("Symbol 'afl_custom_queue_get' not found."); WARNF("Symbol 'afl_custom_queue_get' not found.");
}
/* "afl_custom_queue_new_entry", optional */ /* "afl_custom_queue_new_entry", optional */
afl->mutator->afl_custom_queue_new_entry = afl->mutator->afl_custom_queue_new_entry =
dlsym(dh, "afl_custom_queue_new_entry"); dlsym(dh, "afl_custom_queue_new_entry");
if (!afl->mutator->afl_custom_queue_new_entry) if (!afl->mutator->afl_custom_queue_new_entry) {
WARNF("Symbol 'afl_custom_queue_new_entry' not found"); WARNF("Symbol 'afl_custom_queue_new_entry' not found");
}
OKF("Custom mutator '%s' installed successfully.", fn); OKF("Custom mutator '%s' installed successfully.", fn);
/* Initialize the custom mutator */ /* Initialize the custom mutator */
if (afl->mutator->afl_custom_init) if (afl->mutator->afl_custom_init) {
afl->mutator->data = afl->mutator->data =
afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
}
} }
u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
@ -210,12 +252,19 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
afl->stage_cur = 0; afl->stage_cur = 0;
afl->stage_max = afl->stage_max =
afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len); afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
if (unlikely(afl->stage_max) < 0) if (unlikely(afl->stage_max) < 0) {
FATAL("custom_init_trim error ret: %d", afl->stage_max); FATAL("custom_init_trim error ret: %d", afl->stage_max);
if (afl->not_on_tty && afl->debug)
}
if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
q->len); q->len);
}
while (afl->stage_cur < afl->stage_max) { while (afl->stage_cur < afl->stage_max) {
u8 *retbuf = NULL; u8 *retbuf = NULL;
@ -227,13 +276,18 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf); size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf);
if (unlikely(!retbuf)) if (unlikely(!retbuf)) {
FATAL("custom_trim failed (ret %zd)", retlen); FATAL("custom_trim failed (ret %zd)", retlen);
else if (unlikely(retlen > orig_len))
} else if (unlikely(retlen > orig_len)) {
FATAL( FATAL(
"Trimmed data returned by custom mutator is larger than original " "Trimmed data returned by custom mutator is larger than original "
"data"); "data");
}
write_to_testcase(afl, retbuf, retlen); write_to_testcase(afl, retbuf, retlen);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
@ -263,32 +317,45 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
afl->stage_cur = afl->stage_cur =
afl->mutator->afl_custom_post_trim(afl->mutator->data, 1); afl->mutator->afl_custom_post_trim(afl->mutator->data, 1);
if (afl->not_on_tty && afl->debug) if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)", SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)",
afl->stage_cur, afl->stage_max, q->len); afl->stage_cur, afl->stage_max, q->len);
}
} else { } else {
/* Tell the custom mutator that the trimming was unsuccessful */ /* Tell the custom mutator that the trimming was unsuccessful */
afl->stage_cur = afl->stage_cur =
afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); afl->mutator->afl_custom_post_trim(afl->mutator->data, 0);
if (unlikely(afl->stage_cur < 0)) if (unlikely(afl->stage_cur < 0)) {
FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
if (afl->not_on_tty && afl->debug)
}
if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur,
afl->stage_max); afl->stage_max);
}
} }
/* Since this can be slow, update the screen every now and then. */ /* Since this can be slow, update the screen every now and then. */
if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl); if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
} }
if (afl->not_on_tty && afl->debug) if (afl->not_on_tty && afl->debug) {
SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len); SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len);
}
/* If we have made changes to in_buf, we also need to update the on-disk /* If we have made changes to in_buf, we also need to update the on-disk
version of the test case. */ version of the test case. */
@ -300,7 +367,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", q->fname); if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
ck_write(fd, in_buf, q->len, q->fname); ck_write(fd, in_buf, q->len, q->fname);
close(fd); close(fd);

File diff suppressed because it is too large Load Diff

View File

@ -111,10 +111,10 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (!module_name) return NULL; if (!module_name) { return NULL; }
py_mutator_t *py = calloc(1, sizeof(py_mutator_t)); py_mutator_t *py = calloc(1, sizeof(py_mutator_t));
if (!py) PFATAL("Could not allocate memory for python mutator!"); if (!py) { PFATAL("Could not allocate memory for python mutator!"); }
Py_Initialize(); Py_Initialize();
@ -160,12 +160,12 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (py_idx == PY_FUNC_PRE_SAVE) { if (py_idx == PY_FUNC_PRE_SAVE) {
// Implenting the pre_save API is optional for now // Implenting the pre_save API is optional for now
if (PyErr_Occurred()) PyErr_Print(); if (PyErr_Occurred()) { PyErr_Print(); }
} else if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) { } else if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
// Implementing the trim API is optional for now // Implementing the trim API is optional for now
if (PyErr_Occurred()) PyErr_Print(); if (PyErr_Occurred()) { PyErr_Print(); }
py_notrim = 1; py_notrim = 1;
} else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) && } else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) &&
@ -173,11 +173,11 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
(py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) { (py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) {
// Implenting the havoc and queue API is optional for now // Implenting the havoc and queue API is optional for now
if (PyErr_Occurred()) PyErr_Print(); if (PyErr_Occurred()) { PyErr_Print(); }
} else { } else {
if (PyErr_Occurred()) PyErr_Print(); if (PyErr_Occurred()) { PyErr_Print(); }
fprintf(stderr, fprintf(stderr,
"Cannot find/call function with index %d in external " "Cannot find/call function with index %d in external "
"Python module.\n", "Python module.\n",
@ -222,9 +222,12 @@ void finalize_py_module(void *py_mutator) {
deinit_py(py_mutator); deinit_py(py_mutator);
u32 i; u32 i;
for (i = 0; i < PY_FUNC_COUNT; ++i) for (i = 0; i < PY_FUNC_COUNT; ++i) {
Py_XDECREF(py->py_functions[i]); Py_XDECREF(py->py_functions[i]);
}
Py_DECREF(py->py_module); Py_DECREF(py->py_module);
} }
@ -308,38 +311,67 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
PyObject **py_functions = py_mutator->py_functions; PyObject **py_functions = py_mutator->py_functions;
if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = unsupported; if (py_functions[PY_FUNC_INIT]) {
if (py_functions[PY_FUNC_DEINIT]) afl->mutator->afl_custom_deinit = deinit_py; afl->mutator->afl_custom_init = unsupported;
}
if (py_functions[PY_FUNC_DEINIT]) {
afl->mutator->afl_custom_deinit = deinit_py;
}
/* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
is quite different from the custom mutator. */ is quite different from the custom mutator. */
afl->mutator->afl_custom_fuzz = fuzz_py; afl->mutator->afl_custom_fuzz = fuzz_py;
if (py_functions[PY_FUNC_PRE_SAVE]) if (py_functions[PY_FUNC_PRE_SAVE]) {
afl->mutator->afl_custom_pre_save = pre_save_py; afl->mutator->afl_custom_pre_save = pre_save_py;
if (py_functions[PY_FUNC_INIT_TRIM]) }
if (py_functions[PY_FUNC_INIT_TRIM]) {
afl->mutator->afl_custom_init_trim = init_trim_py; afl->mutator->afl_custom_init_trim = init_trim_py;
if (py_functions[PY_FUNC_POST_TRIM]) }
if (py_functions[PY_FUNC_POST_TRIM]) {
afl->mutator->afl_custom_post_trim = post_trim_py; afl->mutator->afl_custom_post_trim = post_trim_py;
if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py; }
if (py_functions[PY_FUNC_TRIM]) { afl->mutator->afl_custom_trim = trim_py; }
if (py_functions[PY_FUNC_HAVOC_MUTATION]) {
if (py_functions[PY_FUNC_HAVOC_MUTATION])
afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py; afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py;
if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) }
if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) {
afl->mutator->afl_custom_havoc_mutation_probability = afl->mutator->afl_custom_havoc_mutation_probability =
havoc_mutation_probability_py; havoc_mutation_probability_py;
if (py_functions[PY_FUNC_QUEUE_GET]) }
if (py_functions[PY_FUNC_QUEUE_GET]) {
afl->mutator->afl_custom_queue_get = queue_get_py; afl->mutator->afl_custom_queue_get = queue_get_py;
if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) }
if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) {
afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py; afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py;
}
OKF("Python mutator '%s' installed successfully.", module_name); OKF("Python mutator '%s' installed successfully.", module_name);
/* Initialize the custom mutator */ /* Initialize the custom mutator */

View File

@ -38,7 +38,7 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
strrchr(q->fname, '/') + 1); strrchr(q->fname, '/') + 1);
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", fn); if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd); close(fd);
q->passed_det = 1; q->passed_det = 1;
@ -61,7 +61,7 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
if (symlink(ldest, fn)) { if (symlink(ldest, fn)) {
s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", fn); if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd); close(fd);
} }
@ -77,7 +77,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
u8 fn[PATH_MAX]; u8 fn[PATH_MAX];
if (state == q->fs_redundant) return; if (state == q->fs_redundant) { return; }
q->fs_redundant = state; q->fs_redundant = state;
@ -89,12 +89,12 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
s32 fd; s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", fn); if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd); close(fd);
} else { } else {
if (unlink(fn)) PFATAL("Unable to remove '%s'", fn); if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); }
} }
@ -113,17 +113,19 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
q->n_fuzz = 1; q->n_fuzz = 1;
q->trace_mini = NULL; q->trace_mini = NULL;
if (q->depth > afl->max_depth) afl->max_depth = q->depth; if (q->depth > afl->max_depth) { afl->max_depth = q->depth; }
if (afl->queue_top) { if (afl->queue_top) {
afl->queue_top->next = q; afl->queue_top->next = q;
afl->queue_top = q; afl->queue_top = q;
} else } else {
afl->q_prev100 = afl->queue = afl->queue_top = q; afl->q_prev100 = afl->queue = afl->queue_top = q;
}
++afl->queued_paths; ++afl->queued_paths;
++afl->pending_not_fuzzed; ++afl->pending_not_fuzzed;
@ -143,7 +145,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
u8 *fname_orig = NULL; u8 *fname_orig = NULL;
/* At the initialization stage, queue_cur is NULL */ /* At the initialization stage, queue_cur is NULL */
if (afl->queue_cur) fname_orig = afl->queue_cur->fname; if (afl->queue_cur) { fname_orig = afl->queue_cur->fname; }
afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname, afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname,
fname_orig); fname_orig);
@ -188,14 +190,19 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
u64 fuzz_p2 = next_pow2(q->n_fuzz); u64 fuzz_p2 = next_pow2(q->n_fuzz);
if (afl->schedule == MMOPT || afl->schedule == RARE || if (afl->schedule == MMOPT || afl->schedule == RARE ||
unlikely(afl->fixed_seed)) unlikely(afl->fixed_seed)) {
fav_factor = q->len << 2; fav_factor = q->len << 2;
else
} else {
fav_factor = q->exec_us * q->len; fav_factor = q->exec_us * q->len;
}
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
winner, and how it compares to us. */ winner, and how it compares to us. */
for (i = 0; i < afl->fsrv.map_size; ++i) for (i = 0; i < afl->fsrv.map_size; ++i) {
if (afl->fsrv.trace_bits[i]) { if (afl->fsrv.trace_bits[i]) {
@ -206,27 +213,41 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz); u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz);
if (afl->schedule == MMOPT || afl->schedule == RARE || if (afl->schedule == MMOPT || afl->schedule == RARE ||
unlikely(afl->fixed_seed)) unlikely(afl->fixed_seed)) {
top_rated_fav_factor = afl->top_rated[i]->len << 2; top_rated_fav_factor = afl->top_rated[i]->len << 2;
else
} else {
top_rated_fav_factor = top_rated_fav_factor =
afl->top_rated[i]->exec_us * afl->top_rated[i]->len; afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
if (fuzz_p2 > top_rated_fuzz_p2) }
if (fuzz_p2 > top_rated_fuzz_p2) {
continue; continue;
else if (fuzz_p2 == top_rated_fuzz_p2)
if (fav_factor > top_rated_fav_factor) continue; } else if (fuzz_p2 == top_rated_fuzz_p2) {
if (fav_factor > top_rated_fav_factor) { continue; }
}
if (afl->schedule == MMOPT || afl->schedule == RARE || if (afl->schedule == MMOPT || afl->schedule == RARE ||
unlikely(afl->fixed_seed)) { unlikely(afl->fixed_seed)) {
if (fav_factor > afl->top_rated[i]->len << 2) continue; if (fav_factor > afl->top_rated[i]->len << 2) { continue; }
} else { } else {
if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len) if (fav_factor >
afl->top_rated[i]->exec_us * afl->top_rated[i]->len) {
continue; continue;
}
} }
/* Looks like we're going to win. Decrease ref count for the /* Looks like we're going to win. Decrease ref count for the
@ -258,6 +279,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
} }
}
} }
/* The second part of the mechanism discussed above is a routine that /* The second part of the mechanism discussed above is a routine that
@ -273,7 +296,7 @@ void cull_queue(afl_state_t *afl) {
u32 i; u32 i;
u8 * temp_v = afl->map_tmp_buf; u8 * temp_v = afl->map_tmp_buf;
if (afl->dumb_mode || !afl->score_changed) return; if (afl->dumb_mode || !afl->score_changed) { return; }
afl->score_changed = 0; afl->score_changed = 0;
@ -294,25 +317,38 @@ void cull_queue(afl_state_t *afl) {
/* Let's see if anything in the bitmap isn't captured in temp_v. /* Let's see if anything in the bitmap isn't captured in temp_v.
If yes, and if it has a afl->top_rated[] contender, let's use it. */ If yes, and if it has a afl->top_rated[] contender, let's use it. */
for (i = 0; i < afl->fsrv.map_size; ++i) for (i = 0; i < afl->fsrv.map_size; ++i) {
if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) {
u32 j = len; u32 j = len;
/* Remove all bits belonging to the current entry from temp_v. */ /* Remove all bits belonging to the current entry from temp_v. */
while (j--) while (j--) {
if (afl->top_rated[i]->trace_mini[j])
if (afl->top_rated[i]->trace_mini[j]) {
temp_v[j] &= ~afl->top_rated[i]->trace_mini[j]; temp_v[j] &= ~afl->top_rated[i]->trace_mini[j];
}
}
afl->top_rated[i]->favored = 1; afl->top_rated[i]->favored = 1;
++afl->queued_favored; ++afl->queued_favored;
if (afl->top_rated[i]->fuzz_level == 0 || !afl->top_rated[i]->was_fuzzed) if (afl->top_rated[i]->fuzz_level == 0 ||
!afl->top_rated[i]->was_fuzzed) {
++afl->pending_favored; ++afl->pending_favored;
}
} }
}
q = afl->queue; q = afl->queue;
while (q) { while (q) {
@ -347,39 +383,67 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
if (afl->schedule != MMOPT && afl->schedule != RARE && if (afl->schedule != MMOPT && afl->schedule != RARE &&
likely(!afl->fixed_seed)) { likely(!afl->fixed_seed)) {
if (q->exec_us * 0.1 > avg_exec_us) if (q->exec_us * 0.1 > avg_exec_us) {
perf_score = 10; perf_score = 10;
else if (q->exec_us * 0.25 > avg_exec_us)
} else if (q->exec_us * 0.25 > avg_exec_us) {
perf_score = 25; perf_score = 25;
else if (q->exec_us * 0.5 > avg_exec_us)
} else if (q->exec_us * 0.5 > avg_exec_us) {
perf_score = 50; perf_score = 50;
else if (q->exec_us * 0.75 > avg_exec_us)
} else if (q->exec_us * 0.75 > avg_exec_us) {
perf_score = 75; perf_score = 75;
else if (q->exec_us * 4 < avg_exec_us)
} else if (q->exec_us * 4 < avg_exec_us) {
perf_score = 300; perf_score = 300;
else if (q->exec_us * 3 < avg_exec_us)
} else if (q->exec_us * 3 < avg_exec_us) {
perf_score = 200; perf_score = 200;
else if (q->exec_us * 2 < avg_exec_us)
} else if (q->exec_us * 2 < avg_exec_us) {
perf_score = 150; perf_score = 150;
}
} }
/* Adjust score based on bitmap size. The working theory is that better /* Adjust score based on bitmap size. The working theory is that better
coverage translates to better targets. Multiplier from 0.25x to 3x. */ coverage translates to better targets. Multiplier from 0.25x to 3x. */
if (q->bitmap_size * 0.3 > avg_bitmap_size) if (q->bitmap_size * 0.3 > avg_bitmap_size) {
perf_score *= 3; perf_score *= 3;
else if (q->bitmap_size * 0.5 > avg_bitmap_size)
} else if (q->bitmap_size * 0.5 > avg_bitmap_size) {
perf_score *= 2; perf_score *= 2;
else if (q->bitmap_size * 0.75 > avg_bitmap_size)
} else if (q->bitmap_size * 0.75 > avg_bitmap_size) {
perf_score *= 1.5; perf_score *= 1.5;
else if (q->bitmap_size * 3 < avg_bitmap_size)
} else if (q->bitmap_size * 3 < avg_bitmap_size) {
perf_score *= 0.25; perf_score *= 0.25;
else if (q->bitmap_size * 2 < avg_bitmap_size)
} else if (q->bitmap_size * 2 < avg_bitmap_size) {
perf_score *= 0.5; perf_score *= 0.5;
else if (q->bitmap_size * 1.5 < avg_bitmap_size)
} else if (q->bitmap_size * 1.5 < avg_bitmap_size) {
perf_score *= 0.75; perf_score *= 0.75;
}
/* Adjust score based on handicap. Handicap is proportional to how late /* Adjust score based on handicap. Handicap is proportional to how late
in the game we learned about this path. Latecomers are allowed to run in the game we learned about this path. Latecomers are allowed to run
for a bit longer until they catch up with the rest. */ for a bit longer until they catch up with the rest. */
@ -402,11 +466,19 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
switch (q->depth) { switch (q->depth) {
case 0 ... 3: break; case 0 ... 3:
case 4 ... 7: perf_score *= 2; break; break;
case 8 ... 13: perf_score *= 3; break; case 4 ... 7:
case 14 ... 25: perf_score *= 4; break; perf_score *= 2;
default: perf_score *= 5; break;
case 8 ... 13:
perf_score *= 3;
break;
case 14 ... 25:
perf_score *= 4;
break;
default:
perf_score *= 5;
} }
@ -418,9 +490,12 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
switch (afl->schedule) { switch (afl->schedule) {
case EXPLORE: break; case EXPLORE:
break;
case EXPLOIT: factor = MAX_FACTOR; break; case EXPLOIT:
factor = MAX_FACTOR;
break;
case COE: case COE:
fuzz_total = 0; fuzz_total = 0;
@ -435,16 +510,21 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
} }
if (unlikely(!n_paths)) FATAL("Queue state corrupt"); if (unlikely(!n_paths)) { FATAL("Queue state corrupt"); }
fuzz_mu = fuzz_total / n_paths; fuzz_mu = fuzz_total / n_paths;
if (fuzz <= fuzz_mu) { if (fuzz <= fuzz_mu) {
if (q->fuzz_level < 16) if (q->fuzz_level < 16) {
factor = ((u32)(1 << q->fuzz_level)); factor = ((u32)(1 << q->fuzz_level));
else
} else {
factor = MAX_FACTOR; factor = MAX_FACTOR;
}
} else { } else {
factor = 0; factor = 0;
@ -454,13 +534,21 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
break; break;
case FAST: case FAST:
if (q->fuzz_level < 16) if (q->fuzz_level < 16) {
factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz); factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz);
else
} else {
factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz)); factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz));
}
break; break;
case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break; case LIN:
factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz);
break;
case QUAD: case QUAD:
factor = q->fuzz_level * q->fuzz_level / (fuzz == 0 ? 1 : fuzz); factor = q->fuzz_level * q->fuzz_level / (fuzz == 0 ? 1 : fuzz);
@ -477,7 +565,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
(afl->max_depth - q->depth)) / 5)); (afl->max_depth - q->depth)) / 5));
*/ */
// put focus on the last 5 entries // put focus on the last 5 entries
if (afl->max_depth - q->depth < 5) perf_score *= 2; if (afl->max_depth - q->depth < 5) { perf_score *= 2; }
break; break;
@ -493,26 +581,35 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
break; break;
default: PFATAL("Unknown Power Schedule"); default:
PFATAL("Unknown Power Schedule");
} }
if (factor > MAX_FACTOR) factor = MAX_FACTOR; if (factor > MAX_FACTOR) { factor = MAX_FACTOR; }
perf_score *= factor / POWER_BETA; perf_score *= factor / POWER_BETA;
// MOpt mode // MOpt mode
if (afl->limit_time_sig != 0 && afl->max_depth - q->depth < 3) if (afl->limit_time_sig != 0 && afl->max_depth - q->depth < 3) {
perf_score *= 2; perf_score *= 2;
else if (perf_score < 1)
} else if (perf_score < 1) {
// Add a lower bound to AFLFast's energy assignment strategies // Add a lower bound to AFLFast's energy assignment strategies
perf_score = 1; perf_score = 1;
}
/* Make sure that we don't go over limit. */ /* Make sure that we don't go over limit. */
if (perf_score > afl->havoc_max_mult * 100) if (perf_score > afl->havoc_max_mult * 100) {
perf_score = afl->havoc_max_mult * 100; perf_score = afl->havoc_max_mult * 100;
}
return perf_score; return perf_score;
} }

View File

@ -73,11 +73,16 @@ static struct range *pop_biggest_range(struct range **ranges) {
if (rmax) { if (rmax) {
if (prev_rmax) if (prev_rmax) {
prev_rmax->next = rmax->next; prev_rmax->next = rmax->next;
else
} else {
*ranges = rmax->next; *ranges = rmax->next;
}
} }
return rmax; return rmax;
@ -86,7 +91,7 @@ static struct range *pop_biggest_range(struct range **ranges) {
static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) { static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) {
if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1; if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
*cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); *cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
return 0; return 0;
@ -96,9 +101,12 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) {
static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) { static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) {
u32 i; u32 i;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i) {
buf[i] = rand_below(afl, 256); buf[i] = rand_below(afl, 256);
}
} }
static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
@ -131,9 +139,12 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
u32 cksum; u32 cksum;
u64 start_us = get_cur_time_us(); u64 start_us = get_cur_time_us();
if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) {
goto checksum_fail; goto checksum_fail;
}
u64 stop_us = get_cur_time_us(); u64 stop_us = get_cur_time_us();
/* Discard if the mutations change the paths or if it is too decremental /* Discard if the mutations change the paths or if it is too decremental
@ -159,7 +170,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
} }
if (afl->stage_cur < afl->stage_max) afl->queue_cur->fully_colorized = 1; if (afl->stage_cur < afl->stage_max) { afl->queue_cur->fully_colorized = 1; }
new_hit_cnt = afl->queued_paths + afl->unique_crashes; new_hit_cnt = afl->queued_paths + afl->unique_crashes;
afl->stage_finds[STAGE_COLORIZATION] += new_hit_cnt - orig_hit_cnt; afl->stage_finds[STAGE_COLORIZATION] += new_hit_cnt - orig_hit_cnt;
@ -192,7 +203,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
} }
if (fd < 0) PFATAL("Unable to create '%s'", afl->queue_cur->fname); if (fd < 0) { PFATAL("Unable to create '%s'", afl->queue_cur->fname); }
ck_write(fd, buf, len, afl->queue_cur->fname); ck_write(fd, buf, len, afl->queue_cur->fname);
afl->queue_cur->len = len; // no-op, just to be 100% safe afl->queue_cur->len = len; // no-op, just to be 100% safe
@ -204,7 +215,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) {
return 0; return 0;
checksum_fail: checksum_fail:
if (rng) ck_free(rng); if (rng) { ck_free(rng); }
ck_free(backup); ck_free(backup);
while (ranges) { while (ranges) {
@ -230,15 +241,20 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
orig_hit_cnt = afl->queued_paths + afl->unique_crashes; orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1; if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
new_hit_cnt = afl->queued_paths + afl->unique_crashes; new_hit_cnt = afl->queued_paths + afl->unique_crashes;
if (unlikely(new_hit_cnt != orig_hit_cnt)) if (unlikely(new_hit_cnt != orig_hit_cnt)) {
*status = 1; *status = 1;
else
} else {
*status = 2; *status = 2;
}
return 0; return 0;
} }
@ -265,18 +281,24 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) { if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) {
*buf_64 = repl; *buf_64 = repl;
if (unlikely(its_fuzz(afl, buf, len, status))) return 1; if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
*buf_64 = pattern; *buf_64 = pattern;
} }
// reverse encoding // reverse encoding
if (do_reverse) if (do_reverse) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl), if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl),
SWAP64(o_pattern), idx, orig_buf, buf, SWAP64(o_pattern), idx, orig_buf, buf,
len, 0, status))) len, 0, status))) {
return 1; return 1;
}
}
} }
if (SHAPE_BYTES(h->shape) == 4 || *status == 2) { if (SHAPE_BYTES(h->shape) == 4 || *status == 2) {
@ -285,18 +307,24 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
*o_buf_32 == (u32)o_pattern) { *o_buf_32 == (u32)o_pattern) {
*buf_32 = (u32)repl; *buf_32 = (u32)repl;
if (unlikely(its_fuzz(afl, buf, len, status))) return 1; if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
*buf_32 = pattern; *buf_32 = pattern;
} }
// reverse encoding // reverse encoding
if (do_reverse) if (do_reverse) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl), if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl),
SWAP32(o_pattern), idx, orig_buf, buf, SWAP32(o_pattern), idx, orig_buf, buf,
len, 0, status))) len, 0, status))) {
return 1; return 1;
}
}
} }
if (SHAPE_BYTES(h->shape) == 2 || *status == 2) { if (SHAPE_BYTES(h->shape) == 2 || *status == 2) {
@ -305,18 +333,24 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
*o_buf_16 == (u16)o_pattern) { *o_buf_16 == (u16)o_pattern) {
*buf_16 = (u16)repl; *buf_16 = (u16)repl;
if (unlikely(its_fuzz(afl, buf, len, status))) return 1; if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
*buf_16 = (u16)pattern; *buf_16 = (u16)pattern;
} }
// reverse encoding // reverse encoding
if (do_reverse) if (do_reverse) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl), if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl),
SWAP16(o_pattern), idx, orig_buf, buf, SWAP16(o_pattern), idx, orig_buf, buf,
len, 0, status))) len, 0, status))) {
return 1; return 1;
}
}
} }
if (SHAPE_BYTES(h->shape) == 1 || *status == 2) { if (SHAPE_BYTES(h->shape) == 1 || *status == 2) {
@ -324,7 +358,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) { if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) {
*buf_8 = (u8)repl; *buf_8 = (u8)repl;
if (unlikely(its_fuzz(afl, buf, len, status))) return 1; if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
*buf_8 = (u8)pattern; *buf_8 = (u8)pattern;
} }
@ -343,14 +377,21 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
u8 cons_ff = 0, cons_0 = 0; u8 cons_ff = 0, cons_0 = 0;
for (k = 0; k < shape; ++k) { for (k = 0; k < shape; ++k) {
if (b[k] == 0) if (b[k] == 0) {
++cons_0; ++cons_0;
else if (b[k] == 0xff)
} else if (b[k] == 0xff) {
++cons_0; ++cons_0;
else
} else {
cons_0 = cons_ff = 0; cons_0 = cons_ff = 0;
if (cons_0 > 1 || cons_ff > 1) return; }
if (cons_0 > 1 || cons_ff > 1) { return; }
} }
@ -359,7 +400,8 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
u64 rev; u64 rev;
switch (shape) { switch (shape) {
case 1: break; case 1:
break;
case 2: case 2:
rev = SWAP16((u16)v); rev = SWAP16((u16)v);
maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); maybe_add_auto((u8 *)afl, (u8 *)&rev, shape);
@ -383,7 +425,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
u32 i, j, idx; u32 i, j, idx;
u32 loggeds = h->hits; u32 loggeds = h->hits;
if (h->hits > CMP_MAP_H) loggeds = CMP_MAP_H; if (h->hits > CMP_MAP_H) { loggeds = CMP_MAP_H; }
u8 status = 0; u8 status = 0;
// opt not in the paper // opt not in the paper
@ -410,12 +452,12 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
} else { } else {
if (s_v0 != o->v0) s_v0_fixed = 0; if (s_v0 != o->v0) { s_v0_fixed = 0; }
if (s_v1 != o->v1) s_v1_fixed = 0; if (s_v1 != o->v1) { s_v1_fixed = 0; }
if (s_v0 + 1 != o->v0) s_v0_inc = 0; if (s_v0 + 1 != o->v0) { s_v0_inc = 0; }
if (s_v1 + 1 != o->v1) s_v1_inc = 0; if (s_v1 + 1 != o->v1) { s_v1_inc = 0; }
if (s_v0 - 1 != o->v0) s_v0_dec = 0; if (s_v0 - 1 != o->v0) { s_v0_dec = 0; }
if (s_v1 - 1 != o->v1) s_v1_dec = 0; if (s_v1 - 1 != o->v1) { s_v1_dec = 0; }
s_v0 = o->v0; s_v0 = o->v0;
s_v1 = o->v1; s_v1 = o->v1;
@ -424,32 +466,56 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
struct cmp_operands *orig_o = &afl->orig_cmp_map->log[key][i]; struct cmp_operands *orig_o = &afl->orig_cmp_map->log[key][i];
// opt not in the paper // opt not in the paper
for (j = 0; j < i; ++j) for (j = 0; j < i; ++j) {
if (afl->shm.cmp_map->log[key][j].v0 == o->v0 && if (afl->shm.cmp_map->log[key][j].v0 == o->v0 &&
afl->shm.cmp_map->log[key][i].v1 == o->v1) afl->shm.cmp_map->log[key][i].v1 == o->v1) {
goto cmp_fuzz_next_iter; goto cmp_fuzz_next_iter;
}
}
for (idx = 0; idx < len && fails < 8; ++idx) { for (idx = 0; idx < len && fails < 8; ++idx) {
if (unlikely(cmp_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx, if (unlikely(cmp_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
orig_buf, buf, len, 1, &status))) orig_buf, buf, len, 1, &status))) {
return 1; return 1;
if (status == 2)
}
if (status == 2) {
++fails; ++fails;
else if (status == 1)
} else if (status == 1) {
break; break;
}
if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx, if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
orig_buf, buf, len, 1, &status))) orig_buf, buf, len, 1, &status))) {
return 1; return 1;
if (status == 2)
}
if (status == 2) {
++fails; ++fails;
else if (status == 1)
} else if (status == 1) {
break; break;
}
} }
if (status == 1) found_one = 1; if (status == 1) { found_one = 1; }
// If failed, add to dictionary // If failed, add to dictionary
if (fails == 8) { if (fails == 8) {
@ -481,7 +547,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
} }
if (afl->pass_stats[key].total < 0xff) afl->pass_stats[key].total++; if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
return 0; return 0;
@ -502,11 +568,14 @@ static u8 rtn_extend_encoding(afl_state_t *afl, struct cmp_header *h,
for (i = 0; i < its_len; ++i) { for (i = 0; i < its_len; ++i) {
if (pattern[idx + i] != buf[idx + i] || if (pattern[idx + i] != buf[idx + i] ||
o_pattern[idx + i] != orig_buf[idx + i] || *status == 1) o_pattern[idx + i] != orig_buf[idx + i] || *status == 1) {
break; break;
}
buf[idx + i] = repl[idx + i]; buf[idx + i] = repl[idx + i];
if (unlikely(its_fuzz(afl, buf, len, status))) return 1; if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
} }
@ -521,7 +590,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
u32 i, j, idx; u32 i, j, idx;
u32 loggeds = h->hits; u32 loggeds = h->hits;
if (h->hits > CMP_MAP_RTN_H) loggeds = CMP_MAP_RTN_H; if (h->hits > CMP_MAP_RTN_H) { loggeds = CMP_MAP_RTN_H; }
u8 status = 0; u8 status = 0;
// opt not in the paper // opt not in the paper
@ -539,32 +608,56 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
&((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i]; &((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i];
// opt not in the paper // opt not in the paper
for (j = 0; j < i; ++j) for (j = 0; j < i; ++j) {
if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o, if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o,
sizeof(struct cmpfn_operands))) sizeof(struct cmpfn_operands))) {
goto rtn_fuzz_next_iter; goto rtn_fuzz_next_iter;
}
}
for (idx = 0; idx < len && fails < 8; ++idx) { for (idx = 0; idx < len && fails < 8; ++idx) {
if (unlikely(rtn_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx, if (unlikely(rtn_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
orig_buf, buf, len, &status))) orig_buf, buf, len, &status))) {
return 1; return 1;
if (status == 2)
}
if (status == 2) {
++fails; ++fails;
else if (status == 1)
} else if (status == 1) {
break; break;
}
if (unlikely(rtn_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx, if (unlikely(rtn_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
orig_buf, buf, len, &status))) orig_buf, buf, len, &status))) {
return 1; return 1;
if (status == 2)
}
if (status == 2) {
++fails; ++fails;
else if (status == 1)
} else if (status == 1) {
break; break;
}
} }
if (status == 1) found_one = 1; if (status == 1) { found_one = 1; }
// If failed, add to dictionary // If failed, add to dictionary
if (fails == 8) { if (fails == 8) {
@ -589,7 +682,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
} }
if (afl->pass_stats[key].total < 0xff) afl->pass_stats[key].total++; if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
return 0; return 0;
@ -602,25 +695,31 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
u32 exec_cksum) { u32 exec_cksum) {
u8 r = 1; u8 r = 1;
if (afl->orig_cmp_map == NULL) if (afl->orig_cmp_map == NULL) {
afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map)); afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map));
if (afl->pass_stats == NULL) }
if (afl->pass_stats == NULL) {
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W); afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
}
// do it manually, forkserver clear only afl->fsrv.trace_bits // do it manually, forkserver clear only afl->fsrv.trace_bits
memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers)); memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers));
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1; if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map)); memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map));
if (unlikely(colorization(afl, buf, len, exec_cksum))) return 1; if (unlikely(colorization(afl, buf, len, exec_cksum))) { return 1; }
// do it manually, forkserver clear only afl->fsrv.trace_bits // do it manually, forkserver clear only afl->fsrv.trace_bits
memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers)); memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers));
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1; if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; }
u64 orig_hit_cnt, new_hit_cnt; u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs; u64 orig_execs = afl->fsrv.total_execs;
@ -634,33 +733,41 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
u32 k; u32 k;
for (k = 0; k < CMP_MAP_W; ++k) { for (k = 0; k < CMP_MAP_W; ++k) {
if (!afl->shm.cmp_map->headers[k].hits) continue; if (!afl->shm.cmp_map->headers[k].hits) { continue; }
if (afl->pass_stats[k].total && if (afl->pass_stats[k].total &&
(rand_below(afl, afl->pass_stats[k].total) >= (rand_below(afl, afl->pass_stats[k].total) >=
afl->pass_stats[k].faileds || afl->pass_stats[k].faileds ||
afl->pass_stats[k].total == 0xff)) afl->pass_stats[k].total == 0xff)) {
afl->shm.cmp_map->headers[k].hits = 0; // blacklist this cmp afl->shm.cmp_map->headers[k].hits = 0; // blacklist this cmp
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) }
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H); afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
else
} else {
afl->stage_max += afl->stage_max +=
MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H); MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
}
} }
for (k = 0; k < CMP_MAP_W; ++k) { for (k = 0; k < CMP_MAP_W; ++k) {
if (!afl->shm.cmp_map->headers[k].hits) continue; if (!afl->shm.cmp_map->headers[k].hits) { continue; }
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) { if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, len))) goto exit_its; if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, len))) { goto exit_its; }
} else { } else {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, len))) goto exit_its; if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, len))) { goto exit_its; }
} }

View File

@ -72,9 +72,12 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem, size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
len, &new_buf); len, &new_buf);
if (unlikely(!new_buf)) if (unlikely(!new_buf)) {
FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size); FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
}
/* everything as planned. use the new data. */ /* everything as planned. use the new data. */
afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size); afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size);
@ -108,27 +111,34 @@ static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at,
} }
if (fd < 0) PFATAL("Unable to create '%s'", afl->fsrv.out_file); if (fd < 0) { PFATAL("Unable to create '%s'", afl->fsrv.out_file); }
} else } else {
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
if (skip_at) ck_write(fd, mem, skip_at, afl->fsrv.out_file); }
if (skip_at) { ck_write(fd, mem, skip_at, afl->fsrv.out_file); }
u8 *memu8 = mem; u8 *memu8 = mem;
if (tail_len) if (tail_len) {
ck_write(fd, memu8 + skip_at + skip_len, tail_len, afl->fsrv.out_file); ck_write(fd, memu8 + skip_at + skip_len, tail_len, afl->fsrv.out_file);
}
if (!afl->fsrv.out_file) { if (!afl->fsrv.out_file) {
if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed"); if (ftruncate(fd, len - skip_len)) { PFATAL("ftruncate() failed"); }
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
} else } else {
close(fd); close(fd);
}
} }
/* Calibrate a new test case. This is done when processing the input directory /* Calibrate a new test case. This is done when processing the input directory
@ -151,10 +161,13 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
trying to calibrate already-added finds. This helps avoid trouble due trying to calibrate already-added finds. This helps avoid trouble due
to intermittent latency. */ to intermittent latency. */
if (!from_queue || afl->resuming_fuzz) if (!from_queue || afl->resuming_fuzz) {
use_tmout = MAX(afl->fsrv.exec_tmout + CAL_TMOUT_ADD, use_tmout = MAX(afl->fsrv.exec_tmout + CAL_TMOUT_ADD,
afl->fsrv.exec_tmout * CAL_TMOUT_PERC / 100); afl->fsrv.exec_tmout * CAL_TMOUT_PERC / 100);
}
++q->cal_failed; ++q->cal_failed;
afl->stage_name = "calibration"; afl->stage_name = "calibration";
@ -177,18 +190,24 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
} }
if (q->exec_cksum) if (q->exec_cksum) {
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
}
start_us = get_cur_time_us(); start_us = get_cur_time_us();
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
u32 cksum; u32 cksum;
if (!first_run && !(afl->stage_cur % afl->stats_update_freq)) if (!first_run && !(afl->stage_cur % afl->stats_update_freq)) {
show_stats(afl); show_stats(afl);
}
write_to_testcase(afl, use_mem, q->len); write_to_testcase(afl, use_mem, q->len);
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
@ -196,7 +215,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */ we want to bail out quickly. */
if (afl->stop_soon || fault != afl->crash_mode) goto abort_calibration; if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
if (!afl->dumb_mode && !afl->stage_cur && if (!afl->dumb_mode && !afl->stage_cur &&
!count_bytes(afl, afl->fsrv.trace_bits)) { !count_bytes(afl, afl->fsrv.trace_bits)) {
@ -211,7 +230,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
if (q->exec_cksum != cksum) { if (q->exec_cksum != cksum) {
u8 hnb = has_new_bits(afl, afl->virgin_bits); u8 hnb = has_new_bits(afl, afl->virgin_bits);
if (hnb > new_bits) new_bits = hnb; if (hnb > new_bits) { new_bits = hnb; }
if (q->exec_cksum) { if (q->exec_cksum) {
@ -220,9 +239,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
for (i = 0; i < afl->fsrv.map_size; ++i) { for (i = 0; i < afl->fsrv.map_size; ++i) {
if (unlikely(!afl->var_bytes[i]) && if (unlikely(!afl->var_bytes[i]) &&
unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i])) unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i])) {
afl->var_bytes[i] = 1; afl->var_bytes[i] = 1;
}
} }
var_detected = 1; var_detected = 1;
@ -261,9 +283,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
parent. This is a non-critical problem, but something to warn the user parent. This is a non-critical problem, but something to warn the user
about. */ about. */
if (!afl->dumb_mode && first_run && !fault && !new_bits) if (!afl->dumb_mode && first_run && !fault && !new_bits) {
fault = FSRV_RUN_NOBITS; fault = FSRV_RUN_NOBITS;
}
abort_calibration: abort_calibration:
if (new_bits == 2 && !q->has_new_cov) { if (new_bits == 2 && !q->has_new_cov) {
@ -292,7 +317,7 @@ abort_calibration:
afl->stage_cur = old_sc; afl->stage_cur = old_sc;
afl->stage_max = old_sm; afl->stage_max = old_sm;
if (!first_run) show_stats(afl); if (!first_run) { show_stats(afl); }
return fault; return fault;
@ -307,7 +332,7 @@ void sync_fuzzers(afl_state_t *afl) {
u32 sync_cnt = 0; u32 sync_cnt = 0;
sd = opendir(afl->sync_dir); sd = opendir(afl->sync_dir);
if (!sd) PFATAL("Unable to open '%s'", afl->sync_dir); if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
afl->stage_max = afl->stage_cur = 0; afl->stage_max = afl->stage_cur = 0;
afl->cur_depth = 0; afl->cur_depth = 0;
@ -326,9 +351,12 @@ void sync_fuzzers(afl_state_t *afl) {
/* Skip dot files and our own output directory. */ /* Skip dot files and our own output directory. */
if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) {
continue; continue;
}
/* Skip anything that doesn't have a queue/ subdirectory. */ /* Skip anything that doesn't have a queue/ subdirectory. */
qd_path = alloc_printf("%s/%s/queue", afl->sync_dir, sd_ent->d_name); qd_path = alloc_printf("%s/%s/queue", afl->sync_dir, sd_ent->d_name);
@ -347,9 +375,13 @@ void sync_fuzzers(afl_state_t *afl) {
id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600);
if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path); if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); }
if (read(id_fd, &min_accept, sizeof(u32)) > 0) lseek(id_fd, 0, SEEK_SET); if (read(id_fd, &min_accept, sizeof(u32)) > 0) {
lseek(id_fd, 0, SEEK_SET);
}
next_min_accept = min_accept; next_min_accept = min_accept;
@ -372,14 +404,20 @@ void sync_fuzzers(afl_state_t *afl) {
if (qd_ent->d_name[0] == '.' || if (qd_ent->d_name[0] == '.' ||
sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &afl->syncing_case) != 1 || sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &afl->syncing_case) != 1 ||
afl->syncing_case < min_accept) afl->syncing_case < min_accept) {
continue; continue;
}
/* OK, sounds like a new one. Let's give it a try. */ /* OK, sounds like a new one. Let's give it a try. */
if (afl->syncing_case >= next_min_accept) if (afl->syncing_case >= next_min_accept) {
next_min_accept = afl->syncing_case + 1; next_min_accept = afl->syncing_case + 1;
}
path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); path = alloc_printf("%s/%s", qd_path, qd_ent->d_name);
/* Allow this to fail in case the other fuzzer is resuming or so... */ /* Allow this to fail in case the other fuzzer is resuming or so... */
@ -393,7 +431,7 @@ void sync_fuzzers(afl_state_t *afl) {
} }
if (fstat(fd, &st)) PFATAL("fstat() failed"); if (fstat(fd, &st)) { PFATAL("fstat() failed"); }
/* Ignore zero-sized or oversized files. */ /* Ignore zero-sized or oversized files. */
@ -402,7 +440,7 @@ void sync_fuzzers(afl_state_t *afl) {
u8 fault; u8 fault;
u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path); if (mem == MAP_FAILED) { PFATAL("Unable to mmap '%s'", path); }
/* See what happens. We rely on save_if_interesting() to catch major /* See what happens. We rely on save_if_interesting() to catch major
errors and save the test case. */ errors and save the test case. */
@ -411,7 +449,7 @@ void sync_fuzzers(afl_state_t *afl) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) goto close_sync; if (afl->stop_soon) { goto close_sync; }
afl->syncing_party = sd_ent->d_name; afl->syncing_party = sd_ent->d_name;
afl->queued_imported += afl->queued_imported +=
@ -420,7 +458,7 @@ void sync_fuzzers(afl_state_t *afl) {
munmap(mem, st.st_size); munmap(mem, st.st_size);
if (!(afl->stage_cur++ % afl->stats_update_freq)) show_stats(afl); if (!(afl->stage_cur++ % afl->stats_update_freq)) { show_stats(afl); }
} }
@ -450,9 +488,12 @@ void sync_fuzzers(afl_state_t *afl) {
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
/* Custom mutator trimmer */ /* Custom mutator trimmer */
if (afl->mutator && afl->mutator->afl_custom_trim) if (afl->mutator && afl->mutator->afl_custom_trim) {
return trim_case_custom(afl, q, in_buf); return trim_case_custom(afl, q, in_buf);
}
u8 needs_write = 0, fault = 0; u8 needs_write = 0, fault = 0;
u32 trim_exec = 0; u32 trim_exec = 0;
u32 remove_len; u32 remove_len;
@ -464,7 +505,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
detected, it will still work to some extent, so we don't check for detected, it will still work to some extent, so we don't check for
this. */ this. */
if (q->len < 5) return 0; if (q->len < 5) { return 0; }
afl->stage_name = afl->stage_name_buf; afl->stage_name = afl->stage_name_buf;
afl->bytes_trim_in += q->len; afl->bytes_trim_in += q->len;
@ -499,7 +540,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs; ++afl->trim_execs;
if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming; if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
/* Note that we don't keep track of crashes or hangs here; maybe TODO? /* Note that we don't keep track of crashes or hangs here; maybe TODO?
*/ */
@ -531,13 +572,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
} }
} else } else {
remove_pos += remove_len; remove_pos += remove_len;
}
/* Since this can be slow, update the screen every now and then. */ /* Since this can be slow, update the screen every now and then. */
if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl); if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
++afl->stage_cur; ++afl->stage_cur;
} }
@ -564,7 +607,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
} }
if (fd < 0) PFATAL("Unable to create '%s'", q->fname); if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
ck_write(fd, in_buf, q->len, q->fname); ck_write(fd, in_buf, q->len, q->fname);
close(fd); close(fd);
@ -595,7 +638,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
size_t post_len = size_t post_len =
afl->post_handler(afl->post_data, out_buf, len, &post_buf); afl->post_handler(afl->post_data, out_buf, len, &post_buf);
if (!post_buf || !post_len) return 0; if (!post_buf || !post_len) { return 0; }
out_buf = post_buf; out_buf = post_buf;
len = post_len; len = post_len;
@ -605,7 +648,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) return 1; if (afl->stop_soon) { return 1; }
if (fault == FSRV_RUN_TMOUT) { if (fault == FSRV_RUN_TMOUT) {
@ -616,10 +659,12 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
} }
} else } else {
afl->subseq_tmouts = 0; afl->subseq_tmouts = 0;
}
/* Users can hit us with SIGUSR1 to request the current input /* Users can hit us with SIGUSR1 to request the current input
to be abandoned. */ to be abandoned. */
@ -636,9 +681,12 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
afl->queued_discovered += save_if_interesting(afl, out_buf, len, fault); afl->queued_discovered += save_if_interesting(afl, out_buf, len, fault);
if (!(afl->stage_cur % afl->stats_update_freq) || if (!(afl->stage_cur % afl->stats_update_freq) ||
afl->stage_cur + 1 == afl->stage_max) afl->stage_cur + 1 == afl->stage_max) {
show_stats(afl); show_stats(afl);
}
return 0; return 0;
} }

View File

@ -81,7 +81,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
and out_size are NULL/0 by default. */ and out_size are NULL/0 by default. */
memset(afl, 0, sizeof(afl_state_t)); memset(afl, 0, sizeof(afl_state_t));
if (!map_size) afl->shm.map_size = MAP_SIZE; if (!map_size) { afl->shm.map_size = MAP_SIZE; }
afl->w_init = 0.9; afl->w_init = 0.9;
afl->w_end = 0.3; afl->w_end = 0.3;
@ -344,10 +344,12 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
} }
} else } else {
i++; i++;
}
} }
if (match == 0) { if (match == 0) {
@ -361,7 +363,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
} }
if (found) sleep(2); if (found) { sleep(2); }
} }
@ -369,18 +371,18 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
void afl_state_deinit(afl_state_t *afl) { void afl_state_deinit(afl_state_t *afl) {
if (afl->post_deinit) afl->post_deinit(afl->post_data); if (afl->post_deinit) { afl->post_deinit(afl->post_data); }
if (afl->in_place_resume) ck_free(afl->in_dir); if (afl->in_place_resume) { ck_free(afl->in_dir); }
if (afl->sync_id) ck_free(afl->out_dir); if (afl->sync_id) { ck_free(afl->out_dir); }
if (afl->pass_stats) ck_free(afl->pass_stats); if (afl->pass_stats) { ck_free(afl->pass_stats); }
if (afl->orig_cmp_map) ck_free(afl->orig_cmp_map); if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
if (afl->out_buf) free(afl->out_buf); if (afl->out_buf) { free(afl->out_buf); }
if (afl->out_scratch_buf) free(afl->out_scratch_buf); if (afl->out_scratch_buf) { free(afl->out_scratch_buf); }
if (afl->eff_buf) free(afl->eff_buf); if (afl->eff_buf) { free(afl->eff_buf); }
if (afl->in_buf) free(afl->in_buf); if (afl->in_buf) { free(afl->in_buf); }
if (afl->in_scratch_buf) free(afl->in_scratch_buf); if (afl->in_scratch_buf) { free(afl->in_scratch_buf); }
if (afl->ex_buf) free(afl->ex_buf); if (afl->ex_buf) { free(afl->ex_buf); }
ck_free(afl->virgin_bits); ck_free(afl->virgin_bits);
ck_free(afl->virgin_tmout); ck_free(afl->virgin_tmout);

View File

@ -43,11 +43,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", fn); if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
f = fdopen(fd, "w"); f = fdopen(fd, "w");
if (!f) PFATAL("fdopen() failed"); if (!f) { PFATAL("fdopen() failed"); }
/* Keep last values in case we're called from another context /* Keep last values in case we're called from another context
where exec/sec stats and such are not readily available. */ where exec/sec stats and such are not readily available. */
@ -65,7 +65,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
} }
if (getrusage(RUSAGE_CHILDREN, &rus)) rus.ru_maxrss = 0; if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
fprintf( fprintf(
f, f,
@ -153,9 +153,12 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
afl->plot_prev_uc == afl->unique_crashes && afl->plot_prev_uc == afl->unique_crashes &&
afl->plot_prev_uh == afl->unique_hangs && afl->plot_prev_uh == afl->unique_hangs &&
afl->plot_prev_md == afl->max_depth) || afl->plot_prev_md == afl->max_depth) ||
unlikely(!afl->queue_cycle)) unlikely(!afl->queue_cycle)) {
return; return;
}
afl->plot_prev_qp = afl->queued_paths; afl->plot_prev_qp = afl->queued_paths;
afl->plot_prev_pf = afl->pending_favored; afl->plot_prev_pf = afl->pending_favored;
afl->plot_prev_pnf = afl->pending_not_fuzzed; afl->plot_prev_pnf = afl->pending_not_fuzzed;
@ -190,10 +193,10 @@ static void check_term_size(afl_state_t *afl) {
afl->term_too_small = 0; afl->term_too_small = 0;
if (ioctl(1, TIOCGWINSZ, &ws)) return; if (ioctl(1, TIOCGWINSZ, &ws)) { return; }
if (ws.ws_row == 0 || ws.ws_col == 0) return; if (ws.ws_row == 0 || ws.ws_col == 0) { return; }
if (ws.ws_row < 24 || ws.ws_col < 79) afl->term_too_small = 1; if (ws.ws_row < 24 || ws.ws_col < 79) { afl->term_too_small = 1; }
} }
@ -241,12 +244,15 @@ void show_stats(afl_state_t *afl) {
/* If not enough time has passed since last UI update, bail out. */ /* If not enough time has passed since last UI update, bail out. */
if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ && if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ &&
!afl->force_ui_update) !afl->force_ui_update) {
return; return;
}
/* Check if we're past the 10 minute mark. */ /* Check if we're past the 10 minute mark. */
if (cur_ms - afl->start_time > 10 * 60 * 1000) afl->run_over10m = 1; if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; }
/* Calculate smoothed exec speed stats. */ /* Calculate smoothed exec speed stats. */
@ -263,9 +269,13 @@ void show_stats(afl_state_t *afl) {
/* If there is a dramatic (5x+) jump in speed, reset the indicator /* If there is a dramatic (5x+) jump in speed, reset the indicator
more quickly. */ more quickly. */
if (cur_avg * 5 < afl->stats_avg_exec || cur_avg / 5 > afl->stats_avg_exec) if (cur_avg * 5 < afl->stats_avg_exec ||
cur_avg / 5 > afl->stats_avg_exec) {
afl->stats_avg_exec = cur_avg; afl->stats_avg_exec = cur_avg;
}
afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
cur_avg * (1.0 / AVG_SMOOTHING); cur_avg * (1.0 / AVG_SMOOTHING);
@ -277,18 +287,23 @@ void show_stats(afl_state_t *afl) {
/* Tell the callers when to contact us (as measured in execs). */ /* Tell the callers when to contact us (as measured in execs). */
afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10); afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10);
if (!afl->stats_update_freq) afl->stats_update_freq = 1; if (!afl->stats_update_freq) { afl->stats_update_freq = 1; }
/* Do some bitmap stats. */ /* Do some bitmap stats. */
t_bytes = count_non_255_bytes(afl, afl->virgin_bits); 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.map_size;
if (likely(t_bytes) && unlikely(afl->var_byte_count)) if (likely(t_bytes) && unlikely(afl->var_byte_count)) {
stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes); stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes);
else
} else {
stab_ratio = 100; stab_ratio = 100;
}
/* Roughly every minute, update fuzzer stats and save auto tokens. */ /* Roughly every minute, update fuzzer stats and save auto tokens. */
if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) { if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
@ -312,19 +327,25 @@ void show_stats(afl_state_t *afl) {
/* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
if (!afl->dumb_mode && afl->cycles_wo_finds > 100 && if (!afl->dumb_mode && afl->cycles_wo_finds > 100 &&
!afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) {
afl->stop_soon = 2; afl->stop_soon = 2;
if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) }
if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) {
afl->stop_soon = 2; afl->stop_soon = 2;
}
/* If we're not on TTY, bail out. */ /* If we're not on TTY, bail out. */
if (afl->not_on_tty) return; if (afl->not_on_tty) { return; }
/* If we haven't started doing things, bail out. */ /* If we haven't started doing things, bail out. */
if (!afl->queue_cur) return; if (!afl->queue_cur) { return; }
/* Compute some mildly useful bitmap stats. */ /* Compute some mildly useful bitmap stats. */
@ -389,9 +410,9 @@ void show_stats(afl_state_t *afl) {
/* Lord, forgive me this. */ /* Lord, forgive me this. */
SAYF(SET_G1 bSTG bLT bH bSTOP cCYA SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
" process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA
" overall results " bSTG bH2 bH2 bRT "\n"); " overall results " bSTG bH2 bH2 bRT "\n");
if (afl->dumb_mode) { if (afl->dumb_mode) {
@ -402,24 +423,33 @@ void show_stats(afl_state_t *afl) {
u64 min_wo_finds = (cur_ms - afl->last_path_time) / 1000 / 60; u64 min_wo_finds = (cur_ms - afl->last_path_time) / 1000 / 60;
/* First queue cycle: don't stop now! */ /* First queue cycle: don't stop now! */
if (afl->queue_cycle == 1 || min_wo_finds < 15) if (afl->queue_cycle == 1 || min_wo_finds < 15) {
strcpy(tmp, cMGN); strcpy(tmp, cMGN);
else
} else
/* Subsequent cycles, but we're still making finds. */ /* Subsequent cycles, but we're still making finds. */
if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) {
strcpy(tmp, cYEL); strcpy(tmp, cYEL);
else
} else
/* No finds for a long time and no test cases to try. */ /* No finds for a long time and no test cases to try. */
if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed &&
min_wo_finds > 120) min_wo_finds > 120) {
strcpy(tmp, cLGN); strcpy(tmp, cLGN);
/* Default: cautiously OK to stop? */ /* Default: cautiously OK to stop? */
else
} else {
strcpy(tmp, cLBL); strcpy(tmp, cLBL);
}
} }
u_stringify_time_diff(time_tmp, cur_ms, afl->start_time); u_stringify_time_diff(time_tmp, cur_ms, afl->start_time);
@ -439,16 +469,18 @@ void show_stats(afl_state_t *afl) {
} else { } else {
if (afl->dumb_mode) if (afl->dumb_mode) {
SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST
" (non-instrumented mode) "); " (non-instrumented mode) ");
else } else {
SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD
"(odd, check syntax!) "); "(odd, check syntax!) ");
}
} }
SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n", SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n",
@ -473,9 +505,9 @@ void show_stats(afl_state_t *afl) {
" uniq hangs : " cRST "%-6s" bSTG bV "\n", " uniq hangs : " cRST "%-6s" bSTG bV "\n",
time_tmp, tmp); time_tmp, tmp);
SAYF(bVR bH bSTOP cCYA SAYF(bVR bH bSTOP cCYA
" cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
" map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); " map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
/* This gets funny because we want to print several variable-length variables /* 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 together, but then cram them into a fixed-width field - so we need to
@ -505,9 +537,9 @@ void show_stats(afl_state_t *afl) {
SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp);
SAYF(bVR bH bSTOP cCYA SAYF(bVR bH bSTOP cCYA
" stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
" findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
((double)afl->queued_favored) * 100 / afl->queued_paths); ((double)afl->queued_favored) * 100 / afl->queued_paths);
@ -581,7 +613,7 @@ void show_stats(afl_state_t *afl) {
/* Aaaalmost there... hold on! */ /* Aaaalmost there... hold on! */
SAYF(bVR bH cCYA bSTOP SAYF(bVR bH cCYA bSTOP
" fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
" path geometry " bSTG bH5 bH2 bVL "\n"); " path geometry " bSTG bH5 bH2 bVL "\n");
@ -605,7 +637,8 @@ void show_stats(afl_state_t *afl) {
" levels : " cRST "%-10s" bSTG bV "\n", " levels : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->max_depth)); tmp, u_stringify_int(IB(0), afl->max_depth));
if (!afl->skip_deterministic) if (!afl->skip_deterministic) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s", sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]), u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
@ -614,11 +647,14 @@ void show_stats(afl_state_t *afl) {
u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]), u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32])); u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
}
SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP
" pending : " cRST "%-10s" bSTG bV "\n", " pending : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
if (!afl->skip_deterministic) if (!afl->skip_deterministic) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s", sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]), u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
@ -627,11 +663,14 @@ void show_stats(afl_state_t *afl) {
u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]), u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32])); u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
}
SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
" pend fav : " cRST "%-10s" bSTG bV "\n", " pend fav : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->pending_favored)); tmp, u_stringify_int(IB(0), afl->pending_favored));
if (!afl->skip_deterministic) if (!afl->skip_deterministic) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s", sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]), u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]),
@ -640,11 +679,14 @@ void show_stats(afl_state_t *afl) {
u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]), u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]),
u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32])); u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32]));
}
SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP
" own finds : " cRST "%-10s" bSTG bV "\n", " own finds : " cRST "%-10s" bSTG bV "\n",
tmp, u_stringify_int(IB(0), afl->queued_discovered)); tmp, u_stringify_int(IB(0), afl->queued_discovered));
if (!afl->skip_deterministic) if (!afl->skip_deterministic) {
sprintf(tmp, "%s/%s, %s/%s, %s/%s", sprintf(tmp, "%s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]), u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
@ -653,6 +695,8 @@ void show_stats(afl_state_t *afl) {
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]), u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO])); u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
}
SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP
" imported : " cRST "%-10s" bSTG bV "\n", " imported : " cRST "%-10s" bSTG bV "\n",
tmp, tmp,
@ -669,11 +713,16 @@ void show_stats(afl_state_t *afl) {
SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp); SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
if (t_bytes) if (t_bytes) {
sprintf(tmp, "%0.02f%%", stab_ratio); sprintf(tmp, "%0.02f%%", stab_ratio);
else
} else {
strcpy(tmp, "n/a"); strcpy(tmp, "n/a");
}
SAYF(" stability : %s%-10s" bSTG bV "\n", SAYF(" stability : %s%-10s" bSTG bV "\n",
(stab_ratio < 85 && afl->var_byte_count > 40) (stab_ratio < 85 && afl->var_byte_count > 40)
? cLRD ? cLRD
@ -769,14 +818,17 @@ void show_stats(afl_state_t *afl) {
/* If we could still run one or more processes, use green. */ /* If we could still run one or more processes, use green. */
if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) {
cpu_color = cLGN; cpu_color = cLGN;
}
/* If we're clearly oversubscribed, use red. */ /* If we're clearly oversubscribed, use red. */
if (!afl->no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD; if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; }
if (afl->fsrv.snapshot) spacing = snap; if (afl->fsrv.snapshot) { spacing = snap; }
#ifdef HAVE_AFFINITY #ifdef HAVE_AFFINITY
@ -799,10 +851,12 @@ void show_stats(afl_state_t *afl) {
#endif /* ^HAVE_AFFINITY */ #endif /* ^HAVE_AFFINITY */
} else } else {
SAYF("\r"); SAYF("\r");
}
/* Last line */ /* Last line */
SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1); SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
@ -829,17 +883,21 @@ void show_init_stats(afl_state_t *afl) {
u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX]; u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX];
#define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)]) #define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)])
if (afl->total_cal_cycles) avg_us = afl->total_cal_us / afl->total_cal_cycles; if (afl->total_cal_cycles) {
avg_us = afl->total_cal_us / afl->total_cal_cycles;
}
while (q) { while (q) {
if (!min_us || q->exec_us < min_us) min_us = q->exec_us; if (!min_us || q->exec_us < min_us) { min_us = q->exec_us; }
if (q->exec_us > max_us) max_us = q->exec_us; if (q->exec_us > max_us) { max_us = q->exec_us; }
if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size; if (!min_bits || q->bitmap_size < min_bits) { min_bits = q->bitmap_size; }
if (q->bitmap_size > max_bits) max_bits = q->bitmap_size; if (q->bitmap_size > max_bits) { max_bits = q->bitmap_size; }
if (q->len > max_len) max_len = q->len; if (q->len > max_len) { max_len = q->len; }
q = q->next; q = q->next;
@ -847,38 +905,61 @@ void show_init_stats(afl_state_t *afl) {
SAYF("\n"); SAYF("\n");
if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) {
WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.", WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
doc_path); doc_path);
}
/* Let's keep things moving with slow binaries. */ /* Let's keep things moving with slow binaries. */
if (avg_us > 50000) if (avg_us > 50000) {
afl->havoc_div = 10; /* 0-19 execs/sec */ afl->havoc_div = 10; /* 0-19 execs/sec */
else if (avg_us > 20000)
} else if (avg_us > 20000) {
afl->havoc_div = 5; /* 20-49 execs/sec */ afl->havoc_div = 5; /* 20-49 execs/sec */
else if (avg_us > 10000)
} else if (avg_us > 10000) {
afl->havoc_div = 2; /* 50-100 execs/sec */ afl->havoc_div = 2; /* 50-100 execs/sec */
}
if (!afl->resuming_fuzz) { if (!afl->resuming_fuzz) {
if (max_len > 50 * 1024) if (max_len > 50 * 1024) {
WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!", WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!",
stringify_mem_size(IB(0), max_len), doc_path); stringify_mem_size(IB(0), max_len), doc_path);
else if (max_len > 10 * 1024)
} else if (max_len > 10 * 1024) {
WARNF("Some test cases are big (%s) - see %s/perf_tips.md.", WARNF("Some test cases are big (%s) - see %s/perf_tips.md.",
stringify_mem_size(IB(0), max_len), doc_path); stringify_mem_size(IB(0), max_len), doc_path);
if (afl->useless_at_start && !afl->in_bitmap) }
if (afl->useless_at_start && !afl->in_bitmap) {
WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); WARNF(cLRD "Some test cases look useless. Consider using a smaller set.");
if (afl->queued_paths > 100) }
if (afl->queued_paths > 100) {
WARNF(cLRD WARNF(cLRD
"You probably have far too many input files! Consider trimming " "You probably have far too many input files! Consider trimming "
"down."); "down.");
else if (afl->queued_paths > 20)
} else if (afl->queued_paths > 20) {
WARNF("You have lots of input files; try starting small."); WARNF("You have lots of input files; try starting small.");
}
} }
OKF("Here are some useful stats:\n\n" OKF("Here are some useful stats:\n\n"
@ -903,20 +984,30 @@ void show_init_stats(afl_state_t *afl) {
random scheduler jitter is less likely to have any impact, and because random scheduler jitter is less likely to have any impact, and because
our patience is wearing thin =) */ our patience is wearing thin =) */
if (avg_us > 50000) if (avg_us > 50000) {
afl->fsrv.exec_tmout = avg_us * 2 / 1000; afl->fsrv.exec_tmout = avg_us * 2 / 1000;
else if (avg_us > 10000)
} else if (avg_us > 10000) {
afl->fsrv.exec_tmout = avg_us * 3 / 1000; afl->fsrv.exec_tmout = avg_us * 3 / 1000;
else
} else {
afl->fsrv.exec_tmout = avg_us * 5 / 1000; afl->fsrv.exec_tmout = avg_us * 5 / 1000;
}
afl->fsrv.exec_tmout = MAX(afl->fsrv.exec_tmout, max_us / 1000); afl->fsrv.exec_tmout = MAX(afl->fsrv.exec_tmout, max_us / 1000);
afl->fsrv.exec_tmout = afl->fsrv.exec_tmout =
(afl->fsrv.exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; (afl->fsrv.exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND;
if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) {
afl->fsrv.exec_tmout = EXEC_TIMEOUT; afl->fsrv.exec_tmout = EXEC_TIMEOUT;
}
ACTF("No -t option specified, so I'll use exec timeout of %u ms.", ACTF("No -t option specified, so I'll use exec timeout of %u ms.",
afl->fsrv.exec_tmout); afl->fsrv.exec_tmout);
@ -932,9 +1023,12 @@ void show_init_stats(afl_state_t *afl) {
/* In dumb mode, re-running every timing out test case with a generous time /* In dumb mode, re-running every timing out test case with a generous time
limit is very expensive, so let's select a more conservative default. */ limit is very expensive, so let's select a more conservative default. */
if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout)) if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout)) {
afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100); afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
}
OKF("All set and ready to roll!"); OKF("All set and ready to roll!");
#undef IB #undef IB

View File

@ -37,7 +37,7 @@ static u8 *get_libradamsa_path(u8 *own_loc) {
cp = alloc_printf("%s/libradamsa.so", tmp); cp = alloc_printf("%s/libradamsa.so", tmp);
if (access(cp, X_OK)) FATAL("Unable to find '%s'", cp); if (access(cp, X_OK)) { FATAL("Unable to find '%s'", cp); }
return cp; return cp;
@ -53,12 +53,14 @@ static u8 *get_libradamsa_path(u8 *own_loc) {
cp = alloc_printf("%s/libradamsa.so", own_copy); cp = alloc_printf("%s/libradamsa.so", own_copy);
ck_free(own_copy); ck_free(own_copy);
if (!access(cp, X_OK)) return cp; if (!access(cp, X_OK)) { return cp; }
} else } else {
ck_free(own_copy); ck_free(own_copy);
}
if (!access(AFL_PATH "/libradamsa.so", X_OK)) { if (!access(AFL_PATH "/libradamsa.so", X_OK)) {
return ck_strdup(AFL_PATH "/libradamsa.so"); return ck_strdup(AFL_PATH "/libradamsa.so");
@ -148,7 +150,8 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
"case\n\n", "case\n\n",
argv0, EXEC_TIMEOUT, MEM_LIMIT); argv0, EXEC_TIMEOUT, MEM_LIMIT);
if (more_help > 1) if (more_help > 1) {
SAYF( SAYF(
"Environment variables used:\n" "Environment variables used:\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
@ -193,11 +196,15 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
//"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n" //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n"
"\n" "\n"
); );
else
} else {
SAYF( SAYF(
"To view also the supported environment variables of afl-fuzz please " "To view also the supported environment variables of afl-fuzz please "
"use \"-hh\".\n\n"); "use \"-hh\".\n\n");
}
#ifdef USE_PYTHON #ifdef USE_PYTHON
SAYF("Compiled with %s module support, see docs/custom_mutator.md\n", SAYF("Compiled with %s module support, see docs/custom_mutator.md\n",
(char *)PYTHON_VERSION); (char *)PYTHON_VERSION);
@ -216,13 +223,13 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) {
static int stricmp(char const *a, char const *b) { static int stricmp(char const *a, char const *b) {
if (!a || !b) FATAL("Null reference"); if (!a || !b) { FATAL("Null reference"); }
for (;; ++a, ++b) { for (;; ++a, ++b) {
int d; int d;
d = tolower(*a) - tolower(*b); d = tolower(*a) - tolower(*b);
if (d != 0 || !*a) return d; if (d != 0 || !*a) { return d; }
} }
@ -247,14 +254,14 @@ int main(int argc, char **argv_orig, char **envp) {
afl_state_t *afl = calloc(1, sizeof(afl_state_t)); afl_state_t *afl = calloc(1, sizeof(afl_state_t));
if (!afl) { FATAL("Could not create afl state"); } if (!afl) { FATAL("Could not create afl state"); }
if (get_afl_env("AFL_DEBUG")) afl->debug = 1; if (get_afl_env("AFL_DEBUG")) { afl->debug = 1; }
map_size = get_map_size(); map_size = get_map_size();
afl_state_init(afl, map_size); afl_state_init(afl, map_size);
afl_fsrv_init(&afl->fsrv); afl_fsrv_init(&afl->fsrv);
read_afl_environment(afl, envp); read_afl_environment(afl, envp);
if (afl->shm.map_size) afl->fsrv.map_size = afl->shm.map_size; if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
exit_1 = !!afl->afl_env.afl_bench_just_one; exit_1 = !!afl->afl_env.afl_bench_just_one;
SAYF(cCYA "afl-fuzz" VERSION cRST SAYF(cCYA "afl-fuzz" VERSION cRST
@ -266,11 +273,14 @@ int main(int argc, char **argv_orig, char **envp) {
afl->init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); afl->init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
while ((opt = getopt(argc, argv, while ((opt = getopt(argc, argv,
"+c:i:I:o:f:m:t:T:dnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > 0) "+c:i:I:o:f:m:t:T:dnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) >
0) {
switch (opt) { switch (opt) {
case 'I': afl->infoexec = optarg; break; case 'I':
afl->infoexec = optarg;
break;
case 'c': { case 'c': {
@ -334,7 +344,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'e': case 'e':
if (afl->file_extension) FATAL("Multiple -e options not supported"); if (afl->file_extension) { FATAL("Multiple -e options not supported"); }
afl->file_extension = optarg; afl->file_extension = optarg;
@ -342,16 +352,16 @@ int main(int argc, char **argv_orig, char **envp) {
case 'i': /* input dir */ case 'i': /* input dir */
if (afl->in_dir) FATAL("Multiple -i options not supported"); if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
afl->in_dir = optarg; afl->in_dir = optarg;
if (!strcmp(afl->in_dir, "-")) afl->in_place_resume = 1; if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
break; break;
case 'o': /* output dir */ case 'o': /* output dir */
if (afl->out_dir) FATAL("Multiple -o options not supported"); if (afl->out_dir) { FATAL("Multiple -o options not supported"); }
afl->out_dir = optarg; afl->out_dir = optarg;
break; break;
@ -359,7 +369,7 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *c; u8 *c;
if (afl->sync_id) FATAL("Multiple -S or -M options not supported"); if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
afl->sync_id = ck_strdup(optarg); afl->sync_id = ck_strdup(optarg);
if ((c = strchr(afl->sync_id, ':'))) { if ((c = strchr(afl->sync_id, ':'))) {
@ -368,9 +378,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (sscanf(c + 1, "%u/%u", &afl->master_id, &afl->master_max) != 2 || if (sscanf(c + 1, "%u/%u", &afl->master_id, &afl->master_max) != 2 ||
!afl->master_id || !afl->master_max || !afl->master_id || !afl->master_max ||
afl->master_id > afl->master_max || afl->master_max > 1000000) afl->master_id > afl->master_max || afl->master_max > 1000000) {
FATAL("Bogus master ID passed to -M"); FATAL("Bogus master ID passed to -M");
}
} }
afl->force_deterministic = 1; afl->force_deterministic = 1;
@ -381,20 +394,20 @@ int main(int argc, char **argv_orig, char **envp) {
case 'S': case 'S':
if (afl->sync_id) FATAL("Multiple -S or -M options not supported"); if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
afl->sync_id = ck_strdup(optarg); afl->sync_id = ck_strdup(optarg);
break; break;
case 'f': /* target file */ case 'f': /* target file */
if (afl->fsrv.out_file) FATAL("Multiple -f options not supported"); if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); }
afl->fsrv.out_file = ck_strdup(optarg); afl->fsrv.out_file = ck_strdup(optarg);
afl->fsrv.use_stdin = 0; afl->fsrv.use_stdin = 0;
break; break;
case 'x': /* dictionary */ case 'x': /* dictionary */
if (extras_dir) FATAL("Multiple -x options not supported"); if (extras_dir) { FATAL("Multiple -x options not supported"); }
extras_dir = optarg; extras_dir = optarg;
break; break;
@ -402,19 +415,27 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 0; u8 suffix = 0;
if (afl->timeout_given) FATAL("Multiple -t options not supported"); if (afl->timeout_given) { FATAL("Multiple -t options not supported"); }
if (sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 || if (sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 ||
optarg[0] == '-') optarg[0] == '-') {
FATAL("Bad syntax used for -t"); FATAL("Bad syntax used for -t");
if (afl->fsrv.exec_tmout < 5) FATAL("Dangerously low value of -t"); }
if (afl->fsrv.exec_tmout < 5) { FATAL("Dangerously low value of -t"); }
if (suffix == '+') {
if (suffix == '+')
afl->timeout_given = 2; afl->timeout_given = 2;
else
} else {
afl->timeout_given = 1; afl->timeout_given = 1;
}
break; break;
} }
@ -423,10 +444,10 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 'M'; u8 suffix = 'M';
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) FATAL("Wrong usage of -m"); if (!optarg) { FATAL("Wrong usage of -m"); }
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
@ -436,32 +457,51 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 || if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 ||
optarg[0] == '-') optarg[0] == '-') {
FATAL("Bad syntax used for -m"); FATAL("Bad syntax used for -m");
switch (suffix) {
case 'T': afl->fsrv.mem_limit *= 1024 * 1024; break;
case 'G': afl->fsrv.mem_limit *= 1024; break;
case 'k': afl->fsrv.mem_limit /= 1024; break;
case 'M': break;
default: FATAL("Unsupported suffix or bad syntax for -m");
} }
if (afl->fsrv.mem_limit < 5) FATAL("Dangerously low value of -m"); switch (suffix) {
case 'T':
afl->fsrv.mem_limit *= 1024 * 1024;
break;
case 'G':
afl->fsrv.mem_limit *= 1024;
break;
case 'k':
afl->fsrv.mem_limit /= 1024;
break;
case 'M':
break;
default:
FATAL("Unsupported suffix or bad syntax for -m");
}
if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); }
if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) {
if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000)
FATAL("Value of -m out of range on 32-bit systems"); FATAL("Value of -m out of range on 32-bit systems");
}
} }
break; break;
case 'd': /* skip deterministic */ case 'd': /* skip deterministic */
if (afl->skip_deterministic) FATAL("Multiple -d options not supported"); if (afl->skip_deterministic) {
FATAL("Multiple -d options not supported");
}
afl->skip_deterministic = 1; afl->skip_deterministic = 1;
afl->use_splicing = 1; afl->use_splicing = 1;
break; break;
@ -479,7 +519,7 @@ int main(int argc, char **argv_orig, char **envp) {
I only used this once or twice to get variants of a particular I only used this once or twice to get variants of a particular
file, so I'm not making this an official setting. */ file, so I'm not making this an official setting. */
if (afl->in_bitmap) FATAL("Multiple -B options not supported"); if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); }
afl->in_bitmap = optarg; afl->in_bitmap = optarg;
read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
@ -487,85 +527,99 @@ int main(int argc, char **argv_orig, char **envp) {
case 'C': /* crash mode */ case 'C': /* crash mode */
if (afl->crash_mode) FATAL("Multiple -C options not supported"); if (afl->crash_mode) { FATAL("Multiple -C options not supported"); }
afl->crash_mode = FSRV_RUN_CRASH; afl->crash_mode = FSRV_RUN_CRASH;
break; break;
case 'n': /* dumb mode */ case 'n': /* dumb mode */
if (afl->dumb_mode) FATAL("Multiple -n options not supported"); if (afl->dumb_mode) { FATAL("Multiple -n options not supported"); }
if (afl->afl_env.afl_dumb_forksrv) if (afl->afl_env.afl_dumb_forksrv) {
afl->dumb_mode = 2; afl->dumb_mode = 2;
else
} else {
afl->dumb_mode = 1; afl->dumb_mode = 1;
}
break; break;
case 'T': /* banner */ case 'T': /* banner */
if (afl->use_banner) FATAL("Multiple -T options not supported"); if (afl->use_banner) { FATAL("Multiple -T options not supported"); }
afl->use_banner = optarg; afl->use_banner = optarg;
break; break;
case 'Q': /* QEMU mode */ case 'Q': /* QEMU mode */
if (afl->fsrv.qemu_mode) FATAL("Multiple -Q options not supported"); if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
afl->fsrv.qemu_mode = 1; afl->fsrv.qemu_mode = 1;
if (!mem_limit_given) afl->fsrv.mem_limit = MEM_LIMIT_QEMU; if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
break; break;
case 'N': /* Unicorn mode */ case 'N': /* Unicorn mode */
if (afl->no_unlink) FATAL("Multiple -N options not supported"); if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
afl->no_unlink = 1; afl->no_unlink = 1;
break; break;
case 'U': /* Unicorn mode */ case 'U': /* Unicorn mode */
if (afl->unicorn_mode) FATAL("Multiple -U options not supported"); if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); }
afl->unicorn_mode = 1; afl->unicorn_mode = 1;
if (!mem_limit_given) afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; }
break; break;
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
if (afl->use_wine) FATAL("Multiple -W options not supported"); if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
afl->fsrv.qemu_mode = 1; afl->fsrv.qemu_mode = 1;
afl->use_wine = 1; afl->use_wine = 1;
if (!mem_limit_given) afl->fsrv.mem_limit = 0; if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
break; break;
case 'V': { case 'V': {
afl->most_time_key = 1; afl->most_time_key = 1;
if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') {
FATAL("Bad syntax used for -V"); FATAL("Bad syntax used for -V");
}
} break; } break;
case 'E': { case 'E': {
afl->most_execs_key = 1; afl->most_execs_key = 1;
if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') {
FATAL("Bad syntax used for -E"); FATAL("Bad syntax used for -E");
}
} break; } break;
case 'L': { /* MOpt mode */ case 'L': { /* MOpt mode */
if (afl->limit_time_sig) FATAL("Multiple -L options not supported"); if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); }
afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT; afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT;
if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) {
FATAL("Bad syntax used for -L"); FATAL("Bad syntax used for -L");
}
if (afl->limit_time_puppet == -1) { if (afl->limit_time_puppet == -1) {
afl->limit_time_sig = -1; afl->limit_time_sig = -1;
@ -583,19 +637,23 @@ int main(int argc, char **argv_orig, char **envp) {
u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000; u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
if (limit_time_puppet2 < afl->limit_time_puppet) if (limit_time_puppet2 < afl->limit_time_puppet) {
FATAL("limit_time overflow"); FATAL("limit_time overflow");
}
afl->limit_time_puppet = limit_time_puppet2; afl->limit_time_puppet = limit_time_puppet2;
SAYF("limit_time_puppet %d\n", afl->limit_time_puppet); SAYF("limit_time_puppet %d\n", afl->limit_time_puppet);
afl->swarm_now = 0; afl->swarm_now = 0;
if (afl->limit_time_puppet == 0) afl->key_puppet = 1; if (afl->limit_time_puppet == 0) { afl->key_puppet = 1; }
int i; int i;
int tmp_swarm = 0; int tmp_swarm = 0;
if (afl->g_now > afl->g_max) afl->g_now = 0; if (afl->g_now > afl->g_max) { afl->g_now = 0; }
afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) / afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) /
(afl->g_max) + (afl->g_max) +
afl->w_end; afl->w_end;
@ -643,11 +701,16 @@ int main(int argc, char **argv_orig, char **envp) {
afl->x_now[tmp_swarm][i] += afl->v_now[tmp_swarm][i]; afl->x_now[tmp_swarm][i] += afl->v_now[tmp_swarm][i];
if (afl->x_now[tmp_swarm][i] > v_max) if (afl->x_now[tmp_swarm][i] > v_max) {
afl->x_now[tmp_swarm][i] = v_max; afl->x_now[tmp_swarm][i] = v_max;
else if (afl->x_now[tmp_swarm][i] < v_min)
} else if (afl->x_now[tmp_swarm][i] < v_min) {
afl->x_now[tmp_swarm][i] = v_min; afl->x_now[tmp_swarm][i] = v_min;
}
x_temp += afl->x_now[tmp_swarm][i]; x_temp += afl->x_now[tmp_swarm][i];
} }
@ -655,19 +718,27 @@ int main(int argc, char **argv_orig, char **envp) {
for (i = 0; i < operator_num; ++i) { for (i = 0; i < operator_num; ++i) {
afl->x_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i] / x_temp; afl->x_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i] / x_temp;
if (likely(i != 0)) if (likely(i != 0)) {
afl->probability_now[tmp_swarm][i] = afl->probability_now[tmp_swarm][i] =
afl->probability_now[tmp_swarm][i - 1] + afl->probability_now[tmp_swarm][i - 1] +
afl->x_now[tmp_swarm][i]; afl->x_now[tmp_swarm][i];
else
} else {
afl->probability_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i]; afl->probability_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i];
}
} }
if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 || if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 ||
afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) {
FATAL("ERROR probability"); FATAL("ERROR probability");
}
} }
for (i = 0; i < operator_num; ++i) { for (i = 0; i < operator_num; ++i) {
@ -682,25 +753,37 @@ int main(int argc, char **argv_orig, char **envp) {
} break; } break;
case 'h': show_help++; break; // not needed case 'h':
show_help++;
break; // not needed
case 'R': case 'R':
if (afl->use_radamsa) if (afl->use_radamsa) {
afl->use_radamsa = 2; afl->use_radamsa = 2;
else
} else {
afl->use_radamsa = 1; afl->use_radamsa = 1;
}
break; break;
default: default:
if (!show_help) show_help = 1; if (!show_help) { show_help = 1; }
} }
if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) }
if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
usage(afl, argv[0], show_help); usage(afl, argv[0], show_help);
}
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
"Eißfeldt, Andrea Fioraldi and Dominik Maier"); "Eißfeldt, Andrea Fioraldi and Dominik Maier");
OKF("afl++ is open source, get it at " OKF("afl++ is open source, get it at "
@ -711,40 +794,57 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL");
if (afl->sync_id && afl->force_deterministic && if (afl->sync_id && afl->force_deterministic &&
afl->afl_env.afl_custom_mutator_only) afl->afl_env.afl_custom_mutator_only) {
WARNF( WARNF(
"Using -M master with the AFL_CUSTOM_MUTATOR_ONLY mutator options will " "Using -M master with the AFL_CUSTOM_MUTATOR_ONLY mutator options will "
"result in no deterministic mutations being done!"); "result in no deterministic mutations being done!");
if (afl->fixed_seed) OKF("Running with fixed seed: %u", (u32)afl->init_seed); }
if (afl->fixed_seed) {
OKF("Running with fixed seed: %u", (u32)afl->init_seed);
}
srandom((u32)afl->init_seed); srandom((u32)afl->init_seed);
srand((u32)afl->init_seed); // in case it is a different implementation srand((u32)afl->init_seed); // in case it is a different implementation
if (afl->use_radamsa) { if (afl->use_radamsa) {
if (afl->limit_time_sig > 0) if (afl->limit_time_sig > 0) {
FATAL( FATAL(
"MOpt and Radamsa are mutually exclusive unless you specify -L -1. " "MOpt and Radamsa are mutually exclusive unless you specify -L -1. "
"We accept pull requests that integrates MOpt with the optional " "We accept pull requests that integrates MOpt with the optional "
"mutators (custom/radamsa/redqueen/...)."); "mutators (custom/radamsa/redqueen/...).");
if (afl->limit_time_sig && afl->use_radamsa > 1) }
if (afl->limit_time_sig && afl->use_radamsa > 1) {
FATAL("Radamsa in radamsa-only mode can not run together with -L"); FATAL("Radamsa in radamsa-only mode can not run together with -L");
}
OKF("Using Radamsa add-on"); OKF("Using Radamsa add-on");
u8 * libradamsa_path = get_libradamsa_path(argv[0]); u8 * libradamsa_path = get_libradamsa_path(argv[0]);
void *handle = dlopen(libradamsa_path, RTLD_NOW); void *handle = dlopen(libradamsa_path, RTLD_NOW);
ck_free(libradamsa_path); ck_free(libradamsa_path);
if (!handle) FATAL("Failed to dlopen() libradamsa"); if (!handle) { FATAL("Failed to dlopen() libradamsa"); }
void (*radamsa_init_ptr)(void) = dlsym(handle, "radamsa_init"); void (*radamsa_init_ptr)(void) = dlsym(handle, "radamsa_init");
afl->radamsa_mutate_ptr = dlsym(handle, "radamsa"); afl->radamsa_mutate_ptr = dlsym(handle, "radamsa");
if (!radamsa_init_ptr || !afl->radamsa_mutate_ptr) if (!radamsa_init_ptr || !afl->radamsa_mutate_ptr) {
FATAL("Failed to dlsym() libradamsa"); FATAL("Failed to dlsym() libradamsa");
}
/* randamsa_init installs some signal hadlers, call it before /* randamsa_init installs some signal hadlers, call it before
setup_signal_handlers so that AFL++ can then replace those signal setup_signal_handlers so that AFL++ can then replace those signal
handlers */ handlers */
@ -767,80 +867,113 @@ int main(int argc, char **argv_orig, char **envp) {
afl->power_name = power_names[afl->schedule]; afl->power_name = power_names[afl->schedule];
if (afl->sync_id) fix_up_sync(afl); if (afl->sync_id) { fix_up_sync(afl); }
if (!strcmp(afl->in_dir, afl->out_dir)) {
if (!strcmp(afl->in_dir, afl->out_dir))
FATAL("Input and output directories can't be the same"); FATAL("Input and output directories can't be the same");
if (afl->dumb_mode) {
if (afl->crash_mode) FATAL("-C and -n are mutually exclusive");
if (afl->fsrv.qemu_mode) FATAL("-Q and -n are mutually exclusive");
if (afl->unicorn_mode) FATAL("-U and -n are mutually exclusive");
} }
if (get_afl_env("AFL_DISABLE_TRIM")) afl->disable_trim = 1; if (afl->dumb_mode) {
if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
}
if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI"))
FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive"); FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive");
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) }
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
WARNF(cLRD WARNF(cLRD
"Target binary called without a prefixed path, make sure you are " "Target binary called without a prefixed path, make sure you are "
"fuzzing the right binary: " cRST "%s", "fuzzing the right binary: " cRST "%s",
argv[optind]); argv[optind]);
}
ACTF("Getting to work..."); ACTF("Getting to work...");
switch (afl->schedule) { switch (afl->schedule) {
case FAST: OKF("Using exponential power schedule (FAST)"); break; case FAST:
case COE: OKF("Using cut-off exponential power schedule (COE)"); break; OKF("Using exponential power schedule (FAST)");
break;
case COE:
OKF("Using cut-off exponential power schedule (COE)");
break;
case EXPLOIT: case EXPLOIT:
OKF("Using exploitation-based constant power schedule (EXPLOIT)"); OKF("Using exploitation-based constant power schedule (EXPLOIT)");
break; break;
case LIN: OKF("Using linear power schedule (LIN)"); break; case LIN:
case QUAD: OKF("Using quadratic power schedule (QUAD)"); break; OKF("Using linear power schedule (LIN)");
case MMOPT: OKF("Using modified MOpt power schedule (MMOPT)"); break; break;
case RARE: OKF("Using rare edge focus power schedule (RARE)"); break; case QUAD:
OKF("Using quadratic power schedule (QUAD)");
break;
case MMOPT:
OKF("Using modified MOpt power schedule (MMOPT)");
break;
case RARE:
OKF("Using rare edge focus power schedule (RARE)");
break;
case EXPLORE: case EXPLORE:
OKF("Using exploration-based constant power schedule (EXPLORE, default)"); OKF("Using exploration-based constant power schedule (EXPLORE, default)");
break; break;
default: FATAL("Unknown power schedule"); break; default:
FATAL("Unknown power schedule");
break;
} }
if (get_afl_env("AFL_NO_FORKSRV")) afl->no_forkserver = 1; if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
if (get_afl_env("AFL_NO_CPU_RED")) afl->no_cpu_meter_red = 1; 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_NO_ARITH")) { afl->no_arith = 1; }
if (get_afl_env("AFL_SHUFFLE_QUEUE")) afl->shuffle_queue = 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_FAST_CAL")) { afl->fast_cal = 1; }
if (afl->afl_env.afl_autoresume) { if (afl->afl_env.afl_autoresume) {
afl->autoresume = 1; afl->autoresume = 1;
if (afl->in_place_resume) SAYF("AFL_AUTORESUME has no effect for '-i -'"); if (afl->in_place_resume) {
SAYF("AFL_AUTORESUME has no effect for '-i -'");
}
} }
if (afl->afl_env.afl_hang_tmout) { if (afl->afl_env.afl_hang_tmout) {
afl->hang_tmout = atoi(afl->afl_env.afl_hang_tmout); afl->hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
if (!afl->hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); if (!afl->hang_tmout) { FATAL("Invalid value of AFL_HANG_TMOUT"); }
} }
if (afl->dumb_mode == 2 && afl->no_forkserver) if (afl->dumb_mode == 2 && afl->no_forkserver) {
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
}
afl->fsrv.use_fauxsrv = afl->dumb_mode == 1 || afl->no_forkserver; afl->fsrv.use_fauxsrv = afl->dumb_mode == 1 || afl->no_forkserver;
if (getenv("LD_PRELOAD")) if (getenv("LD_PRELOAD")) {
WARNF( WARNF(
"LD_PRELOAD is set, are you sure that is what to you want to do " "LD_PRELOAD is set, are you sure that is what to you want to do "
"instead of using AFL_PRELOAD?"); "instead of using AFL_PRELOAD?");
}
if (afl->afl_env.afl_preload) { if (afl->afl_env.afl_preload) {
if (afl->fsrv.qemu_mode) { if (afl->fsrv.qemu_mode) {
@ -852,20 +985,28 @@ int main(int argc, char **argv_orig, char **envp) {
s32 i, afl_preload_size = strlen(afl_preload); s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) { for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') if (afl_preload[i] == ',') {
PFATAL( PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is " "Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!"); "specified!");
}
} }
if (qemu_preload) if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload); qemu_preload, afl_preload, afl_preload);
else
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload); afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1); setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf); ck_free(buf);
@ -879,15 +1020,18 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (getenv("AFL_LD_PRELOAD")) if (getenv("AFL_LD_PRELOAD")) {
FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
}
save_cmdline(afl, argc, argv); save_cmdline(afl, argc, argv);
fix_up_banner(afl, argv[optind]); fix_up_banner(afl, argv[optind]);
check_if_tty(afl); check_if_tty(afl);
if (afl->afl_env.afl_force_ui) afl->not_on_tty = 0; if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
if (afl->afl_env.afl_cal_fast) { if (afl->afl_env.afl_cal_fast) {
@ -921,7 +1065,7 @@ int main(int argc, char **argv_orig, char **envp) {
setup_post(afl); setup_post(afl);
if (!afl->in_bitmap) memset(afl->virgin_bits, 255, afl->fsrv.map_size); if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); }
memset(afl->virgin_tmout, 255, afl->fsrv.map_size); memset(afl->virgin_tmout, 255, afl->fsrv.map_size);
memset(afl->virgin_crash, 255, afl->fsrv.map_size); memset(afl->virgin_crash, 255, afl->fsrv.map_size);
@ -938,9 +1082,9 @@ int main(int argc, char **argv_orig, char **envp) {
pivot_inputs(afl); pivot_inputs(afl);
if (extras_dir) load_extras(afl, extras_dir); if (extras_dir) { load_extras(afl, extras_dir); }
if (!afl->timeout_given) find_timeout(afl); if (!afl->timeout_given) { find_timeout(afl); }
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL && if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
!afl->in_place_resume) { !afl->in_place_resume) {
@ -959,16 +1103,21 @@ int main(int argc, char **argv_orig, char **envp) {
} }
/* there is still a race condition here, but well ... */ /* there is still a race condition here, but well ... */
if (access(tmpfile, F_OK) != -1) if (access(tmpfile, F_OK) != -1) {
FATAL( FATAL(
"AFL_TMPDIR already has an existing temporary input file: %s - if " "AFL_TMPDIR already has an existing temporary input file: %s - if "
"this is not from another instance, then just remove the file.", "this is not from another instance, then just remove the file.",
tmpfile); tmpfile);
} else }
} else {
afl->tmp_dir = afl->out_dir; afl->tmp_dir = afl->out_dir;
}
/* If we don't have a file name chosen yet, use a safe default. */ /* If we don't have a file name chosen yet, use a safe default. */
if (!afl->fsrv.out_file) { if (!afl->fsrv.out_file) {
@ -1005,13 +1154,17 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (!afl->fsrv.out_file) setup_stdio_file(afl); if (!afl->fsrv.out_file) { setup_stdio_file(afl); }
if (afl->cmplog_binary) { if (afl->cmplog_binary) {
if (afl->unicorn_mode) if (afl->unicorn_mode) {
FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry"); FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry");
if (!afl->fsrv.qemu_mode) check_binary(afl, afl->cmplog_binary);
}
if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); }
} }
@ -1021,13 +1174,18 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.qemu_mode) { if (afl->fsrv.qemu_mode) {
if (afl->use_wine) if (afl->use_wine) {
use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind, use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind,
argv + optind); argv + optind);
else
} else {
use_argv = get_qemu_argv(argv[0], &afl->fsrv.target_path, argc - optind, use_argv = get_qemu_argv(argv[0], &afl->fsrv.target_path, argc - optind,
argv + optind); argv + optind);
}
} else { } else {
use_argv = argv + optind; use_argv = argv + optind;
@ -1062,7 +1220,7 @@ int main(int argc, char **argv_orig, char **envp) {
maybe_update_plot_file(afl, 0, 0); maybe_update_plot_file(afl, 0, 0);
save_auto(afl); save_auto(afl);
if (afl->stop_soon) goto stop_fuzzing; if (afl->stop_soon) { goto stop_fuzzing; }
/* Woop woop woop */ /* Woop woop woop */
@ -1070,7 +1228,7 @@ int main(int argc, char **argv_orig, char **envp) {
sleep(4); sleep(4);
afl->start_time += 4000; afl->start_time += 4000;
if (afl->stop_soon) goto stop_fuzzing; if (afl->stop_soon) { goto stop_fuzzing; }
} }
@ -1112,34 +1270,44 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->queued_paths == prev_queued) { if (afl->queued_paths == prev_queued) {
if (afl->use_splicing) if (afl->use_splicing) {
++afl->cycles_wo_finds; ++afl->cycles_wo_finds;
else
} else {
afl->use_splicing = 1; afl->use_splicing = 1;
} else }
} else {
afl->cycles_wo_finds = 0; afl->cycles_wo_finds = 0;
}
prev_queued = afl->queued_paths; prev_queued = afl->queued_paths;
if (afl->sync_id && afl->queue_cycle == 1 && if (afl->sync_id && afl->queue_cycle == 1 &&
afl->afl_env.afl_import_first) afl->afl_env.afl_import_first) {
sync_fuzzers(afl); sync_fuzzers(afl);
}
} }
skipped_fuzz = fuzz_one(afl); skipped_fuzz = fuzz_one(afl);
if (!skipped_fuzz && !afl->stop_soon && afl->sync_id) { if (!skipped_fuzz && !afl->stop_soon && afl->sync_id) {
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) sync_fuzzers(afl); if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
} }
if (!afl->stop_soon && exit_1) afl->stop_soon = 2; if (!afl->stop_soon && exit_1) { afl->stop_soon = 2; }
if (afl->stop_soon) break; if (afl->stop_soon) { break; }
afl->queue_cur = afl->queue_cur->next; afl->queue_cur = afl->queue_cur->next;
++afl->current_entry; ++afl->current_entry;
@ -1159,11 +1327,18 @@ stop_fuzzing:
SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
afl->stop_soon == 2 ? "programmatically" : "by user"); afl->stop_soon == 2 ? "programmatically" : "by user");
if (afl->most_time_key == 2) if (afl->most_time_key == 2) {
SAYF(cYEL "[!] " cRST "Time limit was reached\n"); SAYF(cYEL "[!] " cRST "Time limit was reached\n");
if (afl->most_execs_key == 2)
}
if (afl->most_execs_key == 2) {
SAYF(cYEL "[!] " cRST "Execution limit was reached\n"); SAYF(cYEL "[!] " cRST "Execution limit was reached\n");
}
/* Running for more than 30 minutes but still doing first cycle? */ /* Running for more than 30 minutes but still doing first cycle? */
if (afl->queue_cycle == 1 && if (afl->queue_cycle == 1 &&
@ -1182,7 +1357,7 @@ stop_fuzzing:
destroy_custom_mutator(afl); destroy_custom_mutator(afl);
afl_shm_deinit(&afl->shm); afl_shm_deinit(&afl->shm);
afl_fsrv_deinit(&afl->fsrv); afl_fsrv_deinit(&afl->fsrv);
if (afl->orig_cmdline) ck_free(afl->orig_cmdline); if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.target_path);
ck_free(afl->fsrv.out_file); ck_free(afl->fsrv.out_file);
ck_free(afl->sync_id); ck_free(afl->sync_id);

View File

@ -128,11 +128,16 @@ static void edit_params(u32 argc, char **argv) {
cc_params = ck_alloc((argc + 128) * sizeof(u8 *)); cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
name = strrchr(argv[0], '/'); name = strrchr(argv[0], '/');
if (!name) if (!name) {
name = argv[0]; name = argv[0];
else
} else {
++name; ++name;
}
if (!strncmp(name, "afl-clang", 9)) { if (!strncmp(name, "afl-clang", 9)) {
clang_mode = 1; clang_mode = 1;
@ -211,7 +216,7 @@ static void edit_params(u32 argc, char **argv) {
if (!strncmp(cur, "-B", 2)) { if (!strncmp(cur, "-B", 2)) {
if (!be_quiet) WARNF("-B is already set, overriding"); if (!be_quiet) { WARNF("-B is already set, overriding"); }
if (!cur[2] && argc > 1) { if (!cur[2] && argc > 1) {
@ -224,18 +229,22 @@ static void edit_params(u32 argc, char **argv) {
} }
if (!strcmp(cur, "-integrated-as")) continue; if (!strcmp(cur, "-integrated-as")) { continue; }
if (!strcmp(cur, "-pipe")) continue; if (!strcmp(cur, "-pipe")) { continue; }
#if defined(__FreeBSD__) && defined(WORD_SIZE_64) #if defined(__FreeBSD__) && defined(WORD_SIZE_64)
if (!strcmp(cur, "-m32")) m32_set = 1; if (!strcmp(cur, "-m32")) m32_set = 1;
#endif #endif
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) if (!strcmp(cur, "-fsanitize=address") ||
!strcmp(cur, "-fsanitize=memory")) {
asan_set = 1; asan_set = 1;
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; }
if (strstr(cur, "FORTIFY_SOURCE")) { fortify_set = 1; }
cc_params[cc_par_cnt++] = cur; cc_params[cc_par_cnt++] = cur;
@ -244,13 +253,13 @@ static void edit_params(u32 argc, char **argv) {
cc_params[cc_par_cnt++] = "-B"; cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = as_path; cc_params[cc_par_cnt++] = as_path;
if (clang_mode) cc_params[cc_par_cnt++] = "-no-integrated-as"; if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
if (getenv("AFL_HARDEN")) { if (getenv("AFL_HARDEN")) {
cc_params[cc_par_cnt++] = "-fstack-protector-all"; cc_params[cc_par_cnt++] = "-fstack-protector-all";
if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; if (!fortify_set) { cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; }
} }
@ -262,21 +271,35 @@ static void edit_params(u32 argc, char **argv) {
} else if (getenv("AFL_USE_ASAN")) { } else if (getenv("AFL_USE_ASAN")) {
if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); if (getenv("AFL_USE_MSAN")) {
FATAL("ASAN and MSAN are mutually exclusive");
}
if (getenv("AFL_HARDEN")) {
if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive"); FATAL("ASAN and AFL_HARDEN are mutually exclusive");
}
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=address"; cc_params[cc_par_cnt++] = "-fsanitize=address";
} else if (getenv("AFL_USE_MSAN")) { } else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); if (getenv("AFL_USE_ASAN")) {
FATAL("ASAN and MSAN are mutually exclusive");
}
if (getenv("AFL_HARDEN")) {
if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive"); FATAL("MSAN and AFL_HARDEN are mutually exclusive");
}
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=memory"; cc_params[cc_par_cnt++] = "-fsanitize=memory";
@ -386,10 +409,12 @@ int main(int argc, char **argv) {
"afl-gcc is deprecated, llvm_mode is much faster and has more " "afl-gcc is deprecated, llvm_mode is much faster and has more "
"options\n"); "options\n");
} else } else {
be_quiet = 1; be_quiet = 1;
}
if (argc < 2) { if (argc < 2) {
SAYF( SAYF(
@ -416,7 +441,11 @@ int main(int argc, char **argv) {
((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) { ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) {
u32 map_size = atoi(ptr); u32 map_size = atoi(ptr);
if (map_size != MAP_SIZE) FATAL("AFL_MAP_SIZE is not supported by afl-gcc"); if (map_size != MAP_SIZE) {
FATAL("AFL_MAP_SIZE is not supported by afl-gcc");
}
} }

View File

@ -102,8 +102,12 @@ repeat_loop:
v1 = CTEST_BUSY_CYCLES; v1 = CTEST_BUSY_CYCLES;
while (v1--) while (v1--) {
v2++; v2++;
}
sched_yield(); sched_yield();
en_t = get_cur_time_us(); en_t = get_cur_time_us();
@ -154,7 +158,7 @@ int main(int argc, char **argv) {
s32 fr = fork(); s32 fr = fork();
if (fr < 0) PFATAL("fork failed"); if (fr < 0) { PFATAL("fork failed"); }
if (!fr) { if (!fr) {
@ -192,8 +196,12 @@ int main(int argc, char **argv) {
#endif #endif
#if defined(__linux__) #if defined(__linux__)
if (sched_setaffinity(0, sizeof(c), &c)) if (sched_setaffinity(0, sizeof(c), &c)) {
PFATAL("sched_setaffinity failed for cpu %d", i); PFATAL("sched_setaffinity failed for cpu %d", i);
}
#endif #endif
util_perc = measure_preemption(CTEST_CORE_TRG_MS); util_perc = measure_preemption(CTEST_CORE_TRG_MS);
@ -221,10 +229,10 @@ int main(int argc, char **argv) {
for (i = 0; i < cpu_cnt; i++) { for (i = 0; i < cpu_cnt; i++) {
int ret; int ret;
if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed"); if (waitpid(-1, &ret, 0) < 0) { PFATAL("waitpid failed"); }
if (WEXITSTATUS(ret) == 0) idle_cpus++; if (WEXITSTATUS(ret) == 0) { idle_cpus++; }
if (WEXITSTATUS(ret) <= 1) maybe_cpus++; if (WEXITSTATUS(ret) <= 1) { maybe_cpus++; }
} }

View File

@ -86,7 +86,7 @@ void afl_shm_deinit(sharedmem_t *shm) {
#else #else
shmctl(shm->shm_id, IPC_RMID, NULL); shmctl(shm->shm_id, IPC_RMID, NULL);
if (shm->cmplog_mode) shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); if (shm->cmplog_mode) { shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); }
#endif #endif
shm->map = NULL; shm->map = NULL;
@ -152,14 +152,14 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600); shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600);
if (shm->shm_id < 0) PFATAL("shmget() failed"); if (shm->shm_id < 0) { PFATAL("shmget() failed"); }
if (shm->cmplog_mode) { if (shm->cmplog_mode) {
shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map), shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map),
IPC_CREAT | IPC_EXCL | 0600); IPC_CREAT | IPC_EXCL | 0600);
if (shm->cmplog_shm_id < 0) PFATAL("shmget() failed"); if (shm->cmplog_shm_id < 0) { PFATAL("shmget() failed"); }
} }
@ -170,7 +170,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
fork server commands. This should be replaced with better auto-detection fork server commands. This should be replaced with better auto-detection
later on, perhaps? */ later on, perhaps? */
if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); if (!dumb_mode) { setenv(SHM_ENV_VAR, shm_str, 1); }
ck_free(shm_str); ck_free(shm_str);
@ -178,7 +178,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
shm_str = alloc_printf("%d", shm->cmplog_shm_id); shm_str = alloc_printf("%d", shm->cmplog_shm_id);
if (!dumb_mode) setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); if (!dumb_mode) { setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); }
ck_free(shm_str); ck_free(shm_str);
@ -186,13 +186,17 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) {
shm->map = shmat(shm->shm_id, NULL, 0); shm->map = shmat(shm->shm_id, NULL, 0);
if (shm->map == (void *)-1 || !shm->map) PFATAL("shmat() failed"); if (shm->map == (void *)-1 || !shm->map) { PFATAL("shmat() failed"); }
if (shm->cmplog_mode) { if (shm->cmplog_mode) {
shm->cmp_map = shmat(shm->cmplog_shm_id, NULL, 0); shm->cmp_map = shmat(shm->cmplog_shm_id, NULL, 0);
if (shm->cmp_map == (void *)-1 || !shm->cmp_map) PFATAL("shmat() failed"); if (shm->cmp_map == (void *)-1 || !shm->cmp_map) {
PFATAL("shmat() failed");
}
} }

View File

@ -121,7 +121,7 @@ static void classify_counts(afl_forkserver_t *fsrv) {
while (i--) { while (i--) {
if (*mem) *mem = 1; if (*mem) { *mem = 1; }
mem++; mem++;
} }
@ -143,7 +143,7 @@ static void classify_counts(afl_forkserver_t *fsrv) {
static void at_exit_handler(void) { static void at_exit_handler(void) {
if (stdin_file) unlink(stdin_file); if (stdin_file) { unlink(stdin_file); }
} }
@ -161,25 +161,28 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
fd = open(outfile, O_WRONLY); fd = open(outfile, O_WRONLY);
if (fd < 0) PFATAL("Unable to open '%s'", out_file); if (fd < 0) { PFATAL("Unable to open '%s'", out_file); }
} else if (!strcmp(outfile, "-")) { } else if (!strcmp(outfile, "-")) {
fd = dup(1); fd = dup(1);
if (fd < 0) PFATAL("Unable to open stdout"); if (fd < 0) { PFATAL("Unable to open stdout"); }
} else { } else {
unlink(outfile); /* Ignore errors */ unlink(outfile); /* Ignore errors */
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", outfile); if (fd < 0) { PFATAL("Unable to create '%s'", outfile); }
} }
if (binary_mode) { if (binary_mode) {
for (i = 0; i < map_size; i++) for (i = 0; i < map_size; i++) {
if (fsrv->trace_bits[i]) ret++;
if (fsrv->trace_bits[i]) { ret++; }
}
ck_write(fd, fsrv->trace_bits, map_size, outfile); ck_write(fd, fsrv->trace_bits, map_size, outfile);
close(fd); close(fd);
@ -188,27 +191,29 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
FILE *f = fdopen(fd, "w"); FILE *f = fdopen(fd, "w");
if (!f) PFATAL("fdopen() failed"); if (!f) { PFATAL("fdopen() failed"); }
for (i = 0; i < map_size; i++) { for (i = 0; i < map_size; i++) {
if (!fsrv->trace_bits[i]) continue; if (!fsrv->trace_bits[i]) { continue; }
ret++; ret++;
total += fsrv->trace_bits[i]; total += fsrv->trace_bits[i];
if (highest < fsrv->trace_bits[i]) highest = fsrv->trace_bits[i]; if (highest < fsrv->trace_bits[i]) { highest = fsrv->trace_bits[i]; }
if (cmin_mode) { if (cmin_mode) {
if (fsrv->last_run_timed_out) break; if (fsrv->last_run_timed_out) { break; }
if (!caa && child_crashed != cco) break; if (!caa && child_crashed != cco) { break; }
fprintf(f, "%u%u\n", fsrv->trace_bits[i], i); fprintf(f, "%u%u\n", fsrv->trace_bits[i], i);
} else } else {
fprintf(f, "%06u:%u\n", i, fsrv->trace_bits[i]); fprintf(f, "%06u:%u\n", i, fsrv->trace_bits[i]);
}
} }
fclose(f); fclose(f);
@ -251,11 +256,14 @@ static u32 read_file(u8 *in_file) {
struct stat st; struct stat st;
s32 fd = open(in_file, O_RDONLY); s32 fd = open(in_file, O_RDONLY);
if (fd < 0) WARNF("Unable to open '%s'", in_file); if (fd < 0) { WARNF("Unable to open '%s'", in_file); }
if (fstat(fd, &st) || !st.st_size) {
if (fstat(fd, &st) || !st.st_size)
WARNF("Zero-sized input file '%s'.", in_file); WARNF("Zero-sized input file '%s'.", in_file);
}
in_len = st.st_size; in_len = st.st_size;
in_data = ck_alloc_nozero(in_len); in_data = ck_alloc_nozero(in_len);
@ -276,13 +284,13 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
static struct itimerval it; static struct itimerval it;
int status = 0; int status = 0;
if (!quiet_mode) SAYF("-- Program output begins --\n" cRST); if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
MEM_BARRIER(); MEM_BARRIER();
fsrv->child_pid = fork(); fsrv->child_pid = fork();
if (fsrv->child_pid < 0) PFATAL("fork() failed"); if (fsrv->child_pid < 0) { PFATAL("fork() failed"); }
if (!fsrv->child_pid) { if (!fsrv->child_pid) {
@ -319,14 +327,19 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
} }
if (!keep_cores) if (!keep_cores) {
r.rlim_max = r.rlim_cur = 0; r.rlim_max = r.rlim_cur = 0;
else
} else {
r.rlim_max = r.rlim_cur = RLIM_INFINITY; r.rlim_max = r.rlim_cur = RLIM_INFINITY;
}
setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); }
setsid(); setsid();
@ -349,7 +362,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
setitimer(ITIMER_REAL, &it, NULL); setitimer(ITIMER_REAL, &it, NULL);
if (waitpid(fsrv->child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
fsrv->child_pid = 0; fsrv->child_pid = 0;
it.it_value.tv_sec = 0; it.it_value.tv_sec = 0;
@ -360,26 +373,39 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
/* Clean up bitmap, analyze exit condition, etc. */ /* Clean up bitmap, analyze exit condition, etc. */
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) {
FATAL("Unable to execute '%s'", argv[0]); FATAL("Unable to execute '%s'", argv[0]);
}
classify_counts(fsrv); classify_counts(fsrv);
if (!quiet_mode) SAYF(cRST "-- Program output ends --\n"); if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); }
if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) {
if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status))
child_crashed = 1; child_crashed = 1;
}
if (!quiet_mode) { if (!quiet_mode) {
if (fsrv->last_run_timed_out) if (fsrv->last_run_timed_out) {
SAYF(cLRD "\n+++ Program timed off +++\n" cRST); SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
else if (stop_soon)
} else if (stop_soon) {
SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST); SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
else if (child_crashed)
} else if (child_crashed) {
SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST,
WTERMSIG(status)); WTERMSIG(status));
}
} }
} }
@ -421,20 +447,28 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
s32 i, afl_preload_size = strlen(afl_preload); s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) { for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') if (afl_preload[i] == ',') {
PFATAL( PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is " "Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!"); "specified!");
}
} }
if (qemu_preload) if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload); qemu_preload, afl_preload, afl_preload);
else
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload); afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1); setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf); ck_free(buf);
@ -549,20 +583,20 @@ int main(int argc, char **argv_orig, char **envp) {
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
if (getenv("AFL_QUIET") != NULL) be_quiet = 1; 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:eqZQUWbcrh")) > 0) {
switch (opt) { switch (opt) {
case 'i': case 'i':
if (in_dir) FATAL("Multiple -i options not supported"); if (in_dir) { FATAL("Multiple -i options not supported"); }
in_dir = optarg; in_dir = optarg;
break; break;
case 'o': case 'o':
if (out_file) FATAL("Multiple -o options not supported"); if (out_file) { FATAL("Multiple -o options not supported"); }
out_file = optarg; out_file = optarg;
break; break;
@ -570,10 +604,10 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 'M'; u8 suffix = 'M';
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) FATAL("Wrong usage of -m"); if (!optarg) { FATAL("Wrong usage of -m"); }
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
@ -583,25 +617,39 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 ||
optarg[0] == '-') optarg[0] == '-') {
FATAL("Bad syntax used for -m"); FATAL("Bad syntax used for -m");
switch (suffix) {
case 'T': fsrv->mem_limit *= 1024 * 1024; break;
case 'G': fsrv->mem_limit *= 1024; break;
case 'k': fsrv->mem_limit /= 1024; break;
case 'M': break;
default: FATAL("Unsupported suffix or bad syntax for -m");
} }
if (fsrv->mem_limit < 5) FATAL("Dangerously low value of -m"); switch (suffix) {
case 'T':
fsrv->mem_limit *= 1024 * 1024;
break;
case 'G':
fsrv->mem_limit *= 1024;
break;
case 'k':
fsrv->mem_limit /= 1024;
break;
case 'M':
break;
default:
FATAL("Unsupported suffix or bad syntax for -m");
}
if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); }
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) {
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000)
FATAL("Value of -m out of range on 32-bit systems"); FATAL("Value of -m out of range on 32-bit systems");
}
} }
break; break;
@ -615,32 +663,35 @@ int main(int argc, char **argv_orig, char **envp) {
case 't': case 't':
if (timeout_given) FATAL("Multiple -t options not supported"); if (timeout_given) { FATAL("Multiple -t options not supported"); }
timeout_given = 1; timeout_given = 1;
if (!optarg) FATAL("Wrong usage of -t"); if (!optarg) { FATAL("Wrong usage of -t"); }
if (strcmp(optarg, "none")) { if (strcmp(optarg, "none")) {
fsrv->exec_tmout = atoi(optarg); fsrv->exec_tmout = atoi(optarg);
if (fsrv->exec_tmout < 20 || optarg[0] == '-') if (fsrv->exec_tmout < 20 || optarg[0] == '-') {
FATAL("Dangerously low value of -t"); FATAL("Dangerously low value of -t");
}
} }
break; break;
case 'e': case 'e':
if (edges_only) FATAL("Multiple -e options not supported"); if (edges_only) { FATAL("Multiple -e options not supported"); }
if (raw_instr_output) FATAL("-e and -r are mutually exclusive"); if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); }
edges_only = 1; edges_only = 1;
break; break;
case 'q': case 'q':
if (quiet_mode) FATAL("Multiple -q options not supported"); if (quiet_mode) { FATAL("Multiple -q options not supported"); }
quiet_mode = 1; quiet_mode = 1;
break; break;
@ -660,27 +711,27 @@ int main(int argc, char **argv_orig, char **envp) {
case 'Q': case 'Q':
if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported"); if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU; if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
fsrv->qemu_mode = 1; fsrv->qemu_mode = 1;
break; break;
case 'U': case 'U':
if (unicorn_mode) FATAL("Multiple -U options not supported"); if (unicorn_mode) { FATAL("Multiple -U options not supported"); }
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_UNICORN; if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
unicorn_mode = 1; unicorn_mode = 1;
break; break;
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
if (use_wine) FATAL("Multiple -W options not supported"); if (use_wine) { FATAL("Multiple -W options not supported"); }
fsrv->qemu_mode = 1; fsrv->qemu_mode = 1;
use_wine = 1; use_wine = 1;
if (!mem_limit_given) fsrv->mem_limit = 0; if (!mem_limit_given) { fsrv->mem_limit = 0; }
break; break;
@ -694,14 +745,14 @@ int main(int argc, char **argv_orig, char **envp) {
case 'c': case 'c':
if (keep_cores) FATAL("Multiple -c options not supported"); if (keep_cores) { FATAL("Multiple -c options not supported"); }
keep_cores = 1; keep_cores = 1;
break; break;
case 'r': case 'r':
if (raw_instr_output) FATAL("Multiple -r options not supported"); if (raw_instr_output) { FATAL("Multiple -r options not supported"); }
if (edges_only) FATAL("-e and -r are mutually exclusive"); if (edges_only) { FATAL("-e and -r are mutually exclusive"); }
raw_instr_output = 1; raw_instr_output = 1;
break; break;
@ -710,11 +761,14 @@ int main(int argc, char **argv_orig, char **envp) {
return -1; return -1;
break; break;
default: usage(argv[0]); default:
usage(argv[0]);
} }
if (optind == argc || !out_file) usage(argv[0]); }
if (optind == argc || !out_file) { usage(argv[0]); }
check_environment_vars(envp); check_environment_vars(envp);
@ -735,7 +789,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (in_dir) { if (in_dir) {
if (at_file) PFATAL("Options -A and -i are mutually exclusive"); if (at_file) { PFATAL("Options -A and -i are mutually exclusive"); }
detect_file_args(argv + optind, "", &fsrv->use_stdin); detect_file_args(argv + optind, "", &fsrv->use_stdin);
} else { } else {
@ -744,22 +798,32 @@ int main(int argc, char **argv_orig, char **envp) {
} }
for (i = optind; i < argc; i++) for (i = optind; i < argc; i++) {
if (strcmp(argv[i], "@@") == 0) arg_offset = i;
if (strcmp(argv[i], "@@") == 0) { arg_offset = i; }
}
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
if (use_wine) if (use_wine) {
use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind, use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind,
argv + optind); argv + optind);
else
} else {
use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind, use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind,
argv + optind); argv + optind);
} else }
} else {
use_argv = argv + optind; use_argv = argv + optind;
}
if (in_dir) { if (in_dir) {
DIR * dir_in, *dir_out; DIR * dir_in, *dir_out;
@ -771,20 +835,30 @@ int main(int argc, char **argv_orig, char **envp) {
#endif #endif
fsrv->dev_null_fd = open("/dev/null", O_RDWR); fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null"); if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
if (!(dir_in = opendir(in_dir))) PFATAL("cannot open directory %s", in_dir); if (!(dir_in = opendir(in_dir))) {
PFATAL("cannot open directory %s", in_dir);
}
if (!(dir_out = opendir(out_file))) {
if (mkdir(out_file, 0700)) {
if (!(dir_out = opendir(out_file)))
if (mkdir(out_file, 0700))
PFATAL("cannot create output directory %s", out_file); PFATAL("cannot create output directory %s", out_file);
}
}
u8 *use_dir = "."; u8 *use_dir = ".";
if (access(use_dir, R_OK | W_OK | X_OK)) { if (access(use_dir, R_OK | W_OK | X_OK)) {
use_dir = get_afl_env("TMPDIR"); use_dir = get_afl_env("TMPDIR");
if (!use_dir) use_dir = "/tmp"; if (!use_dir) { use_dir = "/tmp"; }
} }
@ -792,7 +866,7 @@ int main(int argc, char **argv_orig, char **envp) {
unlink(stdin_file); unlink(stdin_file);
atexit(at_exit_handler); atexit(at_exit_handler);
fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600); fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file); if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
if (arg_offset && argv[arg_offset] != stdin_file) { if (arg_offset && argv[arg_offset] != stdin_file) {
@ -805,8 +879,12 @@ int main(int argc, char **argv_orig, char **envp) {
int i = optind; int i = optind;
SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path); SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path);
while (argv[i] != NULL) while (argv[i] != NULL) {
SAYF(" \"%s\"", argv[i++]); SAYF(" \"%s\"", argv[i++]);
}
SAYF("\n"); SAYF("\n");
SAYF(cMGN "[D]" cRST " %d - %d = %d, %s\n", arg_offset, optind, SAYF(cMGN "[D]" cRST " %d - %d = %d, %s\n", arg_offset, optind,
arg_offset - optind, infile); arg_offset - optind, infile);
@ -818,11 +896,19 @@ int main(int argc, char **argv_orig, char **envp) {
while (done == 0 && (dir_ent = readdir(dir_in))) { while (done == 0 && (dir_ent = readdir(dir_in))) {
if (dir_ent->d_name[0] == '.') if (dir_ent->d_name[0] == '.') {
continue; // skip anything that starts with '.' continue; // skip anything that starts with '.'
}
#if defined(DT_REG) /* Posix and Solaris do not know d_type and DT_REG */ #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 if (dir_ent->d_type != DT_REG) {
continue; // only regular files
}
#endif #endif
snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name); snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name);
@ -843,10 +929,10 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (!quiet_mode) OKF("Processed %llu input files.", fsrv->total_execs); if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); }
closedir(dir_in); closedir(dir_in);
if (dir_out) closedir(dir_out); if (dir_out) { closedir(dir_out); }
} else { } else {
@ -857,7 +943,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!quiet_mode) { if (!quiet_mode) {
if (!tcnt) FATAL("No instrumentation detected" cRST); 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 %u) in '%s'." cRST,
tcnt, highest, total, out_file); tcnt, highest, total, out_file);
@ -875,13 +961,13 @@ int main(int argc, char **argv_orig, char **envp) {
u32 ret = child_crashed * 2 + fsrv->last_run_timed_out; u32 ret = child_crashed * 2 + fsrv->last_run_timed_out;
if (fsrv->target_path) ck_free(fsrv->target_path); if (fsrv->target_path) { ck_free(fsrv->target_path); }
afl_fsrv_deinit(fsrv); afl_fsrv_deinit(fsrv);
if (stdin_file) ck_free(stdin_file); if (stdin_file) { ck_free(stdin_file); }
argv_cpy_free(argv); argv_cpy_free(argv);
if (fsrv->qemu_mode) free(use_argv[2]); if (fsrv->qemu_mode) { free(use_argv[2]); }
exit(ret); exit(ret);

View File

@ -108,7 +108,7 @@ static void apply_mask(u32 *mem, u32 *mask) {
u32 i = (map_size >> 2); u32 i = (map_size >> 2);
if (!mask) return; if (!mask) { return; }
while (i--) { while (i--) {
@ -129,7 +129,7 @@ static void classify_counts(afl_forkserver_t *fsrv) {
while (i--) { while (i--) {
if (*mem) *mem = 1; if (*mem) { *mem = 1; }
mem++; mem++;
} }
@ -154,8 +154,11 @@ static inline u8 anything_set(afl_forkserver_t *fsrv) {
u32 *ptr = (u32 *)fsrv->trace_bits; u32 *ptr = (u32 *)fsrv->trace_bits;
u32 i = (map_size >> 2); u32 i = (map_size >> 2);
while (i--) while (i--) {
if (*(ptr++)) return 1;
if (*(ptr++)) { return 1; }
}
return 0; return 0;
@ -174,13 +177,16 @@ static void read_initial_file(void) {
struct stat st; struct stat st;
s32 fd = open(in_file, O_RDONLY); s32 fd = open(in_file, O_RDONLY);
if (fd < 0) PFATAL("Unable to open '%s'", in_file); if (fd < 0) { PFATAL("Unable to open '%s'", in_file); }
if (fstat(fd, &st) || !st.st_size) FATAL("Zero-sized input file."); if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); }
if (st.st_size >= TMIN_MAX_FILE) {
if (st.st_size >= TMIN_MAX_FILE)
FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024); FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
}
in_len = st.st_size; in_len = st.st_size;
in_data = ck_alloc_nozero(in_len); in_data = ck_alloc_nozero(in_len);
@ -202,7 +208,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
if (ret < 0) PFATAL("Unable to create '%s'", path); if (ret < 0) { PFATAL("Unable to create '%s'", path); }
ck_write(ret, mem, len, path); ck_write(ret, mem, len, path);
@ -223,7 +229,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
fsrv_run_result_t ret = fsrv_run_result_t ret =
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon); afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child"); if (ret == FSRV_RUN_ERROR) { FATAL("Couldn't run child"); }
if (stop_soon) { if (stop_soon) {
@ -239,9 +245,14 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
switch (ret) { switch (ret) {
case FSRV_RUN_TMOUT: return 1; case FSRV_RUN_TMOUT:
case FSRV_RUN_CRASH: missed_crashes++; return 0; return 1;
default: missed_hangs++; return 0; case FSRV_RUN_CRASH:
missed_crashes++;
return 0;
default:
missed_hangs++;
return 0;
} }
@ -261,11 +272,11 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
if (ret == FSRV_RUN_CRASH) { if (ret == FSRV_RUN_CRASH) {
if (first_run) crash_mode = 1; if (first_run) { crash_mode = 1; }
if (crash_mode) { if (crash_mode) {
if (!exact_mode) return 1; if (!exact_mode) { return 1; }
} else { } else {
@ -287,13 +298,13 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
} }
if (ret == FSRV_RUN_NOINST) FATAL("Binary not instrumented?"); if (ret == FSRV_RUN_NOINST) { FATAL("Binary not instrumented?"); }
u32 cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST); u32 cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST);
if (first_run) orig_cksum = cksum; if (first_run) { orig_cksum = cksum; }
if (orig_cksum == cksum) return 1; if (orig_cksum == cksum) { return 1; }
missed_paths++; missed_paths++;
return 0; return 0;
@ -320,7 +331,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
set_len = next_pow2(in_len / TMIN_SET_STEPS); set_len = next_pow2(in_len / TMIN_SET_STEPS);
set_pos = 0; set_pos = 0;
if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE; if (set_len < TMIN_SET_MIN_SIZE) { set_len = TMIN_SET_MIN_SIZE; }
ACTF(cBRI "Stage #0: " cRST "One-time block normalization..."); ACTF(cBRI "Stage #0: " cRST "One-time block normalization...");
@ -328,8 +339,11 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
u32 use_len = MIN(set_len, in_len - set_pos); u32 use_len = MIN(set_len, in_len - set_pos);
for (i = 0; i < use_len; i++) for (i = 0; i < use_len; i++) {
if (in_data[set_pos + i] != '0') break;
if (in_data[set_pos + i] != '0') { break; }
}
if (i != use_len) { if (i != use_len) {
@ -374,7 +388,7 @@ next_pass:
next_del_blksize: next_del_blksize:
if (!del_len) del_len = 1; if (!del_len) { del_len = 1; }
del_pos = 0; del_pos = 0;
prev_del = 1; prev_del = 1;
@ -387,7 +401,7 @@ next_del_blksize:
s32 tail_len; s32 tail_len;
tail_len = in_len - del_pos - del_len; tail_len = in_len - del_pos - del_len;
if (tail_len < 0) tail_len = 0; if (tail_len < 0) { tail_len = 0; }
/* If we have processed at least one full block (initially, prev_del == 1), /* If we have processed at least one full block (initially, prev_del == 1),
and we did so without deleting the previous one, and we aren't at the and we did so without deleting the previous one, and we aren't at the
@ -420,10 +434,12 @@ next_del_blksize:
changed_any = 1; changed_any = 1;
} else } else {
del_pos += del_len; del_pos += del_len;
}
} }
if (del_len > 1 && in_len >= 1) { if (del_len > 1 && in_len >= 1) {
@ -435,11 +451,14 @@ next_del_blksize:
OKF("Block removal complete, %u bytes deleted.", stage_o_len - in_len); OKF("Block removal complete, %u bytes deleted.", stage_o_len - in_len);
if (!in_len && changed_any) if (!in_len && changed_any) {
WARNF(cLRD WARNF(cLRD
"Down to zero bytes - check the command line and mem limit!" cRST); "Down to zero bytes - check the command line and mem limit!" cRST);
if (cur_pass > 1 && !changed_any) goto finalize_all; }
if (cur_pass > 1 && !changed_any) { goto finalize_all; }
/************************* /*************************
* ALPHABET MINIMIZATION * * ALPHABET MINIMIZATION *
@ -453,7 +472,7 @@ next_del_blksize:
for (i = 0; i < in_len; i++) { for (i = 0; i < in_len; i++) {
if (!alpha_map[in_data[i]]) alpha_size++; if (!alpha_map[in_data[i]]) { alpha_size++; }
alpha_map[in_data[i]]++; alpha_map[in_data[i]]++;
} }
@ -466,12 +485,15 @@ next_del_blksize:
u32 r; u32 r;
u8 res; u8 res;
if (i == '0' || !alpha_map[i]) continue; if (i == '0' || !alpha_map[i]) { continue; }
memcpy(tmp_buf, in_data, in_len); memcpy(tmp_buf, in_data, in_len);
for (r = 0; r < in_len; r++) for (r = 0; r < in_len; r++) {
if (tmp_buf[r] == i) tmp_buf[r] = '0';
if (tmp_buf[r] == i) { tmp_buf[r] = '0'; }
}
res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
@ -506,7 +528,7 @@ next_del_blksize:
u8 res, orig = tmp_buf[i]; u8 res, orig = tmp_buf[i];
if (orig == '0') continue; if (orig == '0') { continue; }
tmp_buf[i] = '0'; tmp_buf[i] = '0';
res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0);
@ -517,10 +539,12 @@ next_del_blksize:
alpha_del2++; alpha_del2++;
changed_any = 1; changed_any = 1;
} else } else {
tmp_buf[i] = orig; tmp_buf[i] = orig;
}
} }
alpha_d_total += alpha_del2; alpha_d_total += alpha_del2;
@ -528,11 +552,11 @@ next_del_blksize:
OKF("Character minimization done, %u byte%s replaced.", alpha_del2, OKF("Character minimization done, %u byte%s replaced.", alpha_del2,
alpha_del2 == 1 ? "" : "s"); alpha_del2 == 1 ? "" : "s");
if (changed_any) goto next_pass; if (changed_any) { goto next_pass; }
finalize_all: finalize_all:
if (tmp_buf) ck_free(tmp_buf); if (tmp_buf) { ck_free(tmp_buf); }
if (hang_mode) { if (hang_mode) {
@ -558,9 +582,12 @@ finalize_all:
missed_hangs ? cLRD : "", missed_hangs); missed_hangs ? cLRD : "", missed_hangs);
if (fsrv->total_execs > 50 && missed_hangs * 10 > fsrv->total_execs && if (fsrv->total_execs > 50 && missed_hangs * 10 > fsrv->total_execs &&
!hang_mode) !hang_mode) {
WARNF(cLRD "Frequent timeouts - results may be skewed." cRST); WARNF(cLRD "Frequent timeouts - results may be skewed." cRST);
}
} }
/* Handle Ctrl-C and the like. */ /* Handle Ctrl-C and the like. */
@ -579,7 +606,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
u8 *x; u8 *x;
fsrv->dev_null_fd = open("/dev/null", O_RDWR); fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null"); if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
if (!out_file) { if (!out_file) {
@ -588,7 +615,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (access(use_dir, R_OK | W_OK | X_OK)) { if (access(use_dir, R_OK | W_OK | X_OK)) {
use_dir = get_afl_env("TMPDIR"); use_dir = get_afl_env("TMPDIR");
if (!use_dir) use_dir = "/tmp"; if (!use_dir) { use_dir = "/tmp"; }
} }
@ -600,7 +627,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600); fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file); if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
/* Set sane defaults... */ /* Set sane defaults... */
@ -608,25 +635,37 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
if (x) { if (x) {
if (!strstr(x, "abort_on_error=1")) if (!strstr(x, "abort_on_error=1")) {
FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
if (!strstr(x, "symbolize=0")) }
if (!strstr(x, "symbolize=0")) {
FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
}
} }
x = get_afl_env("MSAN_OPTIONS"); x = get_afl_env("MSAN_OPTIONS");
if (x) { if (x) {
if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) {
FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY( FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY(
MSAN_ERROR) " - please fix!"); MSAN_ERROR) " - please fix!");
if (!strstr(x, "symbolize=0")) }
if (!strstr(x, "symbolize=0")) {
FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
}
} }
setenv("ASAN_OPTIONS", setenv("ASAN_OPTIONS",
@ -653,20 +692,28 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
s32 i, afl_preload_size = strlen(afl_preload); s32 i, afl_preload_size = strlen(afl_preload);
for (i = 0; i < afl_preload_size; ++i) { for (i = 0; i < afl_preload_size; ++i) {
if (afl_preload[i] == ',') if (afl_preload[i] == ',') {
PFATAL( PFATAL(
"Comma (',') is not allowed in AFL_PRELOAD when -Q is " "Comma (',') is not allowed in AFL_PRELOAD when -Q is "
"specified!"); "specified!");
}
} }
if (qemu_preload) if (qemu_preload) {
buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
qemu_preload, afl_preload, afl_preload); qemu_preload, afl_preload, afl_preload);
else
} else {
buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s",
afl_preload, afl_preload); afl_preload, afl_preload);
}
setenv("QEMU_SET_ENV", buf, 1); setenv("QEMU_SET_ENV", buf, 1);
ck_free(buf); ck_free(buf);
@ -772,40 +819,44 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) {
switch (opt) { switch (opt) {
case 'i': case 'i':
if (in_file) FATAL("Multiple -i options not supported"); if (in_file) { FATAL("Multiple -i options not supported"); }
in_file = optarg; in_file = optarg;
break; break;
case 'o': case 'o':
if (output_file) FATAL("Multiple -o options not supported"); if (output_file) { FATAL("Multiple -o options not supported"); }
output_file = optarg; output_file = optarg;
break; break;
case 'f': case 'f':
if (out_file) FATAL("Multiple -f options not supported"); if (out_file) { FATAL("Multiple -f options not supported"); }
fsrv->use_stdin = 0; fsrv->use_stdin = 0;
out_file = optarg; out_file = optarg;
break; break;
case 'e': case 'e':
if (edges_only) FATAL("Multiple -e options not supported"); if (edges_only) { FATAL("Multiple -e options not supported"); }
if (hang_mode) if (hang_mode) {
FATAL("Edges only and hang mode are mutually exclusive."); FATAL("Edges only and hang mode are mutually exclusive.");
}
edges_only = 1; edges_only = 1;
break; break;
case 'x': case 'x':
if (exit_crash) FATAL("Multiple -x options not supported"); if (exit_crash) { FATAL("Multiple -x options not supported"); }
exit_crash = 1; exit_crash = 1;
break; break;
@ -813,10 +864,10 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 'M'; u8 suffix = 'M';
if (mem_limit_given) FATAL("Multiple -m options not supported"); if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1; mem_limit_given = 1;
if (!optarg) FATAL("Wrong usage of -m"); if (!optarg) { FATAL("Wrong usage of -m"); }
if (!strcmp(optarg, "none")) { if (!strcmp(optarg, "none")) {
@ -826,66 +877,83 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 ||
optarg[0] == '-') optarg[0] == '-') {
FATAL("Bad syntax used for -m"); FATAL("Bad syntax used for -m");
switch (suffix) {
case 'T': fsrv->mem_limit *= 1024 * 1024; break;
case 'G': fsrv->mem_limit *= 1024; break;
case 'k': fsrv->mem_limit /= 1024; break;
case 'M': break;
default: FATAL("Unsupported suffix or bad syntax for -m");
} }
if (fsrv->mem_limit < 5) FATAL("Dangerously low value of -m"); switch (suffix) {
case 'T':
fsrv->mem_limit *= 1024 * 1024;
break;
case 'G':
fsrv->mem_limit *= 1024;
break;
case 'k':
fsrv->mem_limit /= 1024;
break;
case 'M':
break;
default:
FATAL("Unsupported suffix or bad syntax for -m");
}
if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); }
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) {
if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000)
FATAL("Value of -m out of range on 32-bit systems"); FATAL("Value of -m out of range on 32-bit systems");
}
} }
break; break;
case 't': case 't':
if (timeout_given) FATAL("Multiple -t options not supported"); if (timeout_given) { FATAL("Multiple -t options not supported"); }
timeout_given = 1; timeout_given = 1;
if (!optarg) FATAL("Wrong usage of -t"); if (!optarg) { FATAL("Wrong usage of -t"); }
fsrv->exec_tmout = atoi(optarg); fsrv->exec_tmout = atoi(optarg);
if (fsrv->exec_tmout < 10 || optarg[0] == '-') if (fsrv->exec_tmout < 10 || optarg[0] == '-') {
FATAL("Dangerously low value of -t"); FATAL("Dangerously low value of -t");
}
break; break;
case 'Q': case 'Q':
if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported"); if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU; if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
fsrv->qemu_mode = 1; fsrv->qemu_mode = 1;
break; break;
case 'U': case 'U':
if (unicorn_mode) FATAL("Multiple -Q options not supported"); if (unicorn_mode) { FATAL("Multiple -Q options not supported"); }
if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_UNICORN; if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
unicorn_mode = 1; unicorn_mode = 1;
break; break;
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
if (use_wine) FATAL("Multiple -W options not supported"); if (use_wine) { FATAL("Multiple -W options not supported"); }
fsrv->qemu_mode = 1; fsrv->qemu_mode = 1;
use_wine = 1; use_wine = 1;
if (!mem_limit_given) fsrv->mem_limit = 0; if (!mem_limit_given) { fsrv->mem_limit = 0; }
break; break;
@ -893,9 +961,13 @@ int main(int argc, char **argv_orig, char **envp) {
/* Minimizes a testcase to the minimum that still times out */ /* Minimizes a testcase to the minimum that still times out */
if (hang_mode) FATAL("Multipe -H options not supported"); if (hang_mode) { FATAL("Multipe -H options not supported"); }
if (edges_only) if (edges_only) {
FATAL("Edges only and hang mode are mutually exclusive."); FATAL("Edges only and hang mode are mutually exclusive.");
}
hang_mode = 1; hang_mode = 1;
break; break;
@ -914,7 +986,7 @@ int main(int argc, char **argv_orig, char **envp) {
The option may be extended and made more official if it proves The option may be extended and made more official if it proves
to be useful. */ to be useful. */
if (mask_bitmap) FATAL("Multiple -B options not supported"); if (mask_bitmap) { FATAL("Multiple -B options not supported"); }
mask_bitmap = ck_alloc(map_size); mask_bitmap = ck_alloc(map_size);
read_bitmap(optarg, mask_bitmap, map_size); read_bitmap(optarg, mask_bitmap, map_size);
break; break;
@ -924,11 +996,14 @@ int main(int argc, char **argv_orig, char **envp) {
return -1; return -1;
break; break;
default: usage(argv[0]); default:
usage(argv[0]);
} }
if (optind == argc || !in_file || !output_file) usage(argv[0]); }
if (optind == argc || !in_file || !output_file) { usage(argv[0]); }
check_environment_vars(envp); check_environment_vars(envp);
@ -945,17 +1020,24 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->qemu_mode) { if (fsrv->qemu_mode) {
if (use_wine) if (use_wine) {
use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind, use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind,
argv + optind); argv + optind);
else
} else {
use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind, use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind,
argv + optind); argv + optind);
} else }
} else {
use_argv = argv + optind; use_argv = argv + optind;
}
exact_mode = !!get_afl_env("AFL_TMIN_EXACT"); exact_mode = !!get_afl_env("AFL_TMIN_EXACT");
if (hang_mode && exact_mode) { if (hang_mode && exact_mode) {
@ -977,17 +1059,23 @@ int main(int argc, char **argv_orig, char **envp) {
tmin_run_target(fsrv, use_argv, in_data, in_len, 1); tmin_run_target(fsrv, use_argv, in_data, in_len, 1);
if (hang_mode && !fsrv->last_run_timed_out) if (hang_mode && !fsrv->last_run_timed_out) {
FATAL( FATAL(
"Target binary did not time out but hang minimization mode " "Target binary did not time out but hang minimization mode "
"(-H) was set (-t %u).", "(-H) was set (-t %u).",
fsrv->exec_tmout); fsrv->exec_tmout);
if (fsrv->last_run_timed_out && !hang_mode) }
if (fsrv->last_run_timed_out && !hang_mode) {
FATAL( FATAL(
"Target binary times out (adjusting -t may help). Use -H to minimize a " "Target binary times out (adjusting -t may help). Use -H to minimize a "
"hang."); "hang.");
}
if (hang_mode) { if (hang_mode) {
OKF("Program hangs as expected, minimizing in " cCYA "hang" cRST " mode."); OKF("Program hangs as expected, minimizing in " cCYA "hang" cRST " mode.");
@ -997,7 +1085,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Program terminates normally, minimizing in " cCYA "instrumented" cRST OKF("Program terminates normally, minimizing in " cCYA "instrumented" cRST
" mode."); " mode.");
if (!anything_set(fsrv)) FATAL("No instrumentation detected."); if (!anything_set(fsrv)) { FATAL("No instrumentation detected."); }
} else { } else {
@ -1012,7 +1100,7 @@ int main(int argc, char **argv_orig, char **envp) {
ACTF("Writing output to '%s'...", output_file); ACTF("Writing output to '%s'...", output_file);
unlink(out_file); unlink(out_file);
if (out_file) ck_free(out_file); if (out_file) { ck_free(out_file); }
out_file = NULL; out_file = NULL;
close(write_to_file(output_file, in_data, in_len)); close(write_to_file(output_file, in_data, in_len));
@ -1021,9 +1109,9 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_deinit(&shm); afl_shm_deinit(&shm);
afl_fsrv_deinit(fsrv); afl_fsrv_deinit(fsrv);
if (fsrv->target_path) ck_free(fsrv->target_path); if (fsrv->target_path) { ck_free(fsrv->target_path); }
if (mask_bitmap) ck_free(mask_bitmap); if (mask_bitmap) { ck_free(mask_bitmap); }
if (in_data) ck_free(in_data); if (in_data) { ck_free(in_data); }
argv_cpy_free(argv); argv_cpy_free(argv);