aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-02-26 09:45:43 +0100
committerGitHub <noreply@github.com>2021-02-26 09:45:43 +0100
commit78d96c4dc86ac20e2a6e244017407ccc037ff13b (patch)
treee277f092c27714f75e0c19f9ac8ab18dbfd1745a /src
parent7ae7b0f3732cfd9d82cf9403818012d00faa07c3 (diff)
parentee0ca07f3c9f7c5971440f5dca70a2ee6f37584d (diff)
downloadafl++-78d96c4dc86ac20e2a6e244017407ccc037ff13b.tar.gz
Merge pull request #759 from AFLplusplus/dev
push to stable
Diffstat (limited to 'src')
-rw-r--r--src/afl-cc.c17
-rw-r--r--src/afl-common.c137
-rw-r--r--src/afl-fuzz-init.c48
-rw-r--r--src/afl-fuzz-redqueen.c114
-rw-r--r--src/afl-fuzz-run.c2
-rw-r--r--src/afl-fuzz-state.c2
-rw-r--r--src/afl-fuzz-stats.c36
-rw-r--r--src/afl-fuzz.c113
8 files changed, 355 insertions, 114 deletions
diff --git a/src/afl-cc.c b/src/afl-cc.c
index d41f79a2..c3910e6d 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -1421,6 +1421,14 @@ int main(int argc, char **argv, char **envp) {
}
+ if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT &&
+ (compiler_mode == LLVM || compiler_mode == UNSET)) {
+
+ instrument_mode = INSTRUMENT_CLASSIC;
+ compiler_mode = LLVM;
+
+ }
+
if (!compiler_mode) {
// lto is not a default because outside of afl-cc RANLIB and AR have to
@@ -1699,7 +1707,10 @@ int main(int argc, char **argv, char **envp) {
"Do not be overwhelmed :) afl-cc uses good defaults if no options are "
"selected.\n"
"Read the documentation for FEATURES though, all are good but few are "
- "defaults.\n\n");
+ "defaults.\n"
+ "Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast "
+ "with\n"
+ "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n");
exit(1);
@@ -1791,8 +1802,8 @@ int main(int argc, char **argv, char **envp) {
if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC &&
instrument_mode != INSTRUMENT_CFG)
FATAL(
- "CTX and NGRAM instrumentation options can only be used with CFG "
- "(recommended) and CLASSIC instrumentation modes!");
+ "CTX and NGRAM instrumentation options can only be used with LLVM and "
+ "CFG or CLASSIC instrumentation modes!");
if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO"))
FATAL(
diff --git a/src/afl-common.c b/src/afl-common.c
index 589aac71..078ffb9d 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -518,6 +518,141 @@ int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) {
}
+static inline unsigned int helper_min3(unsigned int a, unsigned int b,
+ unsigned int c) {
+
+ return a < b ? (a < c ? a : c) : (b < c ? b : c);
+
+}
+
+// from
+// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C
+static int string_distance_levenshtein(char *s1, char *s2) {
+
+ unsigned int s1len, s2len, x, y, lastdiag, olddiag;
+ s1len = strlen(s1);
+ s2len = strlen(s2);
+ unsigned int column[s1len + 1];
+ column[s1len] = 1;
+
+ for (y = 1; y <= s1len; y++)
+ column[y] = y;
+ for (x = 1; x <= s2len; x++) {
+
+ column[0] = x;
+ for (y = 1, lastdiag = x - 1; y <= s1len; y++) {
+
+ olddiag = column[y];
+ column[y] = helper_min3(column[y] + 1, column[y - 1] + 1,
+ lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1));
+ lastdiag = olddiag;
+
+ }
+
+ }
+
+ return column[s1len];
+
+}
+
+#define ENV_SIMILARITY_TRESHOLD 3
+
+void print_suggested_envs(char *mispelled_env) {
+
+ size_t env_name_len =
+ strcspn(mispelled_env, "=") - 4; // remove the AFL_prefix
+ char *env_name = ck_alloc(env_name_len + 1);
+ memcpy(env_name, mispelled_env + 4, env_name_len);
+
+ char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *));
+ int found = 0;
+
+ int j;
+ for (j = 0; afl_environment_variables[j] != NULL; ++j) {
+
+ char *afl_env = afl_environment_variables[j] + 4;
+ int distance = string_distance_levenshtein(afl_env, env_name);
+ if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
+
+ SAYF("Did you mean %s?\n", afl_environment_variables[j]);
+ seen[j] = 1;
+ found = 1;
+
+ }
+
+ }
+
+ if (found) goto cleanup;
+
+ for (j = 0; afl_environment_variables[j] != NULL; ++j) {
+
+ char * afl_env = afl_environment_variables[j] + 4;
+ size_t afl_env_len = strlen(afl_env);
+ char * reduced = ck_alloc(afl_env_len + 1);
+
+ size_t start = 0;
+ while (start < afl_env_len) {
+
+ size_t end = start + strcspn(afl_env + start, "_") + 1;
+ memcpy(reduced, afl_env, start);
+ if (end < afl_env_len)
+ memcpy(reduced + start, afl_env + end, afl_env_len - end);
+ reduced[afl_env_len - end + start] = 0;
+
+ int distance = string_distance_levenshtein(reduced, env_name);
+ if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
+
+ SAYF("Did you mean %s?\n", afl_environment_variables[j]);
+ seen[j] = 1;
+ found = 1;
+
+ }
+
+ start = end;
+
+ };
+
+ ck_free(reduced);
+
+ }
+
+ if (found) goto cleanup;
+
+ char * reduced = ck_alloc(env_name_len + 1);
+ size_t start = 0;
+ while (start < env_name_len) {
+
+ size_t end = start + strcspn(env_name + start, "_") + 1;
+ memcpy(reduced, env_name, start);
+ if (end < env_name_len)
+ memcpy(reduced + start, env_name + end, env_name_len - end);
+ reduced[env_name_len - end + start] = 0;
+
+ for (j = 0; afl_environment_variables[j] != NULL; ++j) {
+
+ int distance = string_distance_levenshtein(
+ afl_environment_variables[j] + 4, reduced);
+ if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
+
+ SAYF("Did you mean %s?\n", afl_environment_variables[j]);
+ seen[j] = 1;
+
+ }
+
+ }
+
+ start = end;
+
+ };
+
+ ck_free(reduced);
+
+cleanup:
+ ck_free(env_name);
+ ck_free(seen);
+
+}
+
void check_environment_vars(char **envp) {
if (be_quiet) { return; }
@@ -587,6 +722,8 @@ void check_environment_vars(char **envp) {
WARNF("Mistyped AFL environment variable: %s", env);
issue_detected = 1;
+ print_suggested_envs(env);
+
}
}
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 702e732d..3dbc4c65 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -882,32 +882,23 @@ void perform_dry_run(afl_state_t *afl) {
if (afl->timeout_given) {
- /* The -t nn+ syntax in the command line sets afl->timeout_given to
- '2' and instructs afl-fuzz to tolerate but skip queue entries that
- time out. */
+ /* if we have a timeout but a timeout value was given then always
+ skip. The '+' meaning has been changed! */
+ WARNF("Test case results in a timeout (skipping)");
+ ++cal_failures;
+ q->cal_failed = CAL_CHANCES;
+ q->disabled = 1;
+ q->perf_score = 0;
- if (afl->timeout_given > 1) {
+ if (!q->was_fuzzed) {
- WARNF("Test case results in a timeout (skipping)");
- q->cal_failed = CAL_CHANCES;
- ++cal_failures;
- break;
+ q->was_fuzzed = 1;
+ --afl->pending_not_fuzzed;
+ --afl->active_paths;
}
- SAYF("\n" cLRD "[-] " cRST
- "The program took more than %u ms to process one of the initial "
- "test cases.\n"
- " Usually, the right thing to do is to relax the -t option - "
- "or to delete it\n"
- " altogether and allow the fuzzer to auto-calibrate. That "
- "said, if you know\n"
- " what you are doing and want to simply skip the unruly test "
- "cases, append\n"
- " '+' at the end of the value passed to -t ('-t %u+').\n",
- afl->fsrv.exec_tmout, afl->fsrv.exec_tmout);
-
- FATAL("Test case '%s' results in a timeout", fn);
+ break;
} else {
@@ -1060,13 +1051,22 @@ void perform_dry_run(afl_state_t *afl) {
p->perf_score = 0;
u32 i = 0;
- while (unlikely(afl->queue_buf[i]->disabled)) {
+ while (unlikely(i < afl->queued_paths && afl->queue_buf[i] &&
+ afl->queue_buf[i]->disabled)) {
++i;
}
- afl->queue = afl->queue_buf[i];
+ if (i < afl->queued_paths && afl->queue_buf[i]) {
+
+ afl->queue = afl->queue_buf[i];
+
+ } else {
+
+ afl->queue = afl->queue_buf[0];
+
+ }
afl->max_depth = 0;
for (i = 0; i < afl->queued_paths; i++) {
@@ -2017,7 +2017,7 @@ void setup_dirs_fds(afl_state_t *afl) {
fprintf(afl->fsrv.plot_file,
"# unix_time, cycles_done, cur_path, paths_total, "
"pending_total, pending_favs, map_size, unique_crashes, "
- "unique_hangs, max_depth, execs_per_sec\n");
+ "unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
fflush(afl->fsrv.plot_file);
/* ignore errors */
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 3ac7ba11..1ab5f996 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -30,7 +30,6 @@
//#define _DEBUG
//#define CMPLOG_INTROSPECTION
-#define CMPLOG_COMBINE
// CMP attribute enum
enum {
@@ -205,14 +204,31 @@ static void type_replace(afl_state_t *afl, u8 *buf, u32 len) {
case '\t':
c = ' ';
break;
- /*
- case '\r':
- case '\n':
- // nothing ...
- break;
- */
+ case '\r':
+ c = '\n';
+ break;
+ case '\n':
+ c = '\r';
+ break;
+ case 0:
+ c = 1;
+ break;
+ case 1:
+ c = 0;
+ break;
+ case 0xff:
+ c = 0;
+ break;
default:
- c = (buf[i] ^ 0xff);
+ if (buf[i] < 32) {
+
+ c = (buf[i] ^ 0x1f);
+
+ } else {
+
+ c = (buf[i] ^ 0x7f); // we keep the highest bit
+
+ }
}
@@ -506,7 +522,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
}
-#ifdef CMPLOG_SOLVE_TRANSFORM
+//#ifdef CMPLOG_SOLVE_TRANSFORM
static int strntoll(const char *str, size_t sz, char **end, int base,
long long *out) {
@@ -591,7 +607,7 @@ static int is_hex(const char *str) {
}
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
// tests 4 bytes at location
static int is_base64(const char *str) {
@@ -704,10 +720,10 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
}
- #endif
-
#endif
+//#endif
+
static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 pattern, u64 repl, u64 o_pattern,
u64 changed_val, u8 attr, u32 idx, u32 taint_len,
@@ -731,9 +747,9 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// o_pattern, pattern, repl, changed_val, idx, taint_len,
// h->shape + 1, attr);
-#ifdef CMPLOG_SOLVE_TRANSFORM
+ //#ifdef CMPLOG_SOLVE_TRANSFORM
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
- if (lvl & LVL3) {
+ if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u8 * endptr;
u8 use_num = 0, use_unum = 0;
@@ -754,11 +770,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- #ifdef _DEBUG
+#ifdef _DEBUG
if (idx == 0)
fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n",
afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern);
- #endif
+#endif
// num is likely not pattern as atoi("AAA") will be zero...
if (use_num && ((u64)num == pattern || !num)) {
@@ -1043,7 +1059,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
-#endif
+ //#endif
// we only allow this for ascii2integer (above) so leave if this is the case
if (unlikely(pattern == o_pattern)) { return 0; }
@@ -1198,8 +1214,12 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// 16 = modified float, 32 = modified integer (modified = wont match
// in original buffer)
-#ifdef CMPLOG_SOLVE_ARITHMETIC
- if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; }
+ //#ifdef CMPLOG_SOLVE_ARITHMETIC
+ if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
+
+ return 0;
+
+ }
if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) {
@@ -1304,11 +1324,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
double *f = (double *)&repl;
float g = (float)*f;
repl_new = 0;
- #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
memcpy((char *)&repl_new, (char *)&g, 4);
- #else
+#else
memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
- #endif
+#endif
changed_val = repl_new;
h->shape = 3; // modify shape
@@ -1363,7 +1383,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
-#endif /* CMPLOG_SOLVE_ARITHMETIC */
+ //#endif /* CMPLOG_SOLVE_ARITHMETIC
return 0;
@@ -1522,7 +1542,7 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
for (k = 0; k < size; ++k) {
#else
- u32 off = 16 - size;
+ u32 off = 16 - size;
for (k = 16 - size; k < 16; ++k) {
#endif
@@ -1840,9 +1860,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
#ifndef CMPLOG_COMBINE
(void)(cbuf);
#endif
-#ifndef CMPLOG_SOLVE_TRANSFORM
- (void)(changed_val);
-#endif
+ //#ifndef CMPLOG_SOLVE_TRANSFORM
+ // (void)(changed_val);
+ //#endif
u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
@@ -1922,16 +1942,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
-#ifdef CMPLOG_SOLVE_TRANSFORM
+ //#ifdef CMPLOG_SOLVE_TRANSFORM
if (*status == 1) return 0;
- if (lvl & LVL3) {
+ if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
u32 tob64 = 0, fromb64 = 0;
- #endif
+#endif
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
u8 xor_val[32], arith_val[32], tmp[48];
@@ -2027,7 +2047,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
if (i % 3 == 2 && i < 24) {
if (is_base64(repl + ((i / 3) << 2))) tob64 += 3;
@@ -2040,7 +2060,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #endif
+#endif
if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) {
@@ -2068,20 +2088,20 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #ifdef _DEBUG
+#ifdef _DEBUG
fprintf(stderr,
"RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u "
"tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u "
"from_0=%u from_slash=%u from_x=%u\n",
idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0,
to_slash, to_x, from_0, from_slash, from_x);
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+ #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64,
fromb64);
- #endif
#endif
+#endif
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
// input is base64 and converted to binary? convert repl to base64!
if ((i % 4) == 3 && i < 24 && fromb64 > i) {
@@ -2104,7 +2124,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #endif
+#endif
// input is converted to hex? convert repl to binary!
if (i < 16 && tohex > i) {
@@ -2233,16 +2253,16 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
- #ifdef CMPLOG_COMBINE
+#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i + 1); }
- #endif
+#endif
if ((i >= 7 &&
(i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i >
(fromhex + from_0 + from_x + from_slash + 1)
- #ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
+#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
&& i > tob64 + 3 && i > fromb64 + 4
- #endif
+#endif
)) ||
repl[i] != changed_val[i] || *status == 1) {
@@ -2256,7 +2276,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
}
-#endif
+ //#endif
return 0;
@@ -2589,9 +2609,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
} else if ((lvl & LVL1)
-#ifdef CMPLOG_SOLVE_TRANSFORM
- || (lvl & LVL3)
-#endif
+ //#ifdef CMPLOG_SOLVE_TRANSFORM
+ || ((lvl & LVL3) && afl->cmplog_enable_transform)
+ //#endif
) {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
@@ -2672,7 +2692,7 @@ exit_its:
#else
u32 *v = (u32 *)afl->virgin_bits;
u32 *s = (u32 *)virgin_save;
- u32 i;
+ u32 i;
for (i = 0; i < (afl->shm.map_size >> 2); i++) {
v[i] &= s[i];
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 97cb7415..0b84a542 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -707,6 +707,8 @@ void sync_fuzzers(afl_state_t *afl) {
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
+ afl->last_sync_time = get_cur_time();
+
}
/* Trim all new test cases to save cycles when doing deterministic checks. The
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 5040e3ef..3d36e712 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -486,6 +486,8 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
WARNF("Mistyped AFL environment variable: %s", env);
issue_detected = 1;
+ print_suggested_envs(env);
+
}
}
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 66efeb20..bd856088 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -185,15 +185,14 @@ void load_stats_file(afl_state_t *afl) {
/* Update stats file for unattended monitoring. */
-void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
- double eps) {
+void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
+ double stability, double eps) {
#ifndef __HAIKU__
struct rusage rus;
#endif
u64 cur_time = get_cur_time();
- u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
u8 fn[PATH_MAX];
FILE *f;
@@ -353,9 +352,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
/* Update the plot file if there is a reason to. */
-void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
+void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
+ double eps) {
- if (unlikely(afl->plot_prev_qp == afl->queued_paths &&
+ if (unlikely(afl->stop_soon) ||
+ unlikely(afl->plot_prev_qp == afl->queued_paths &&
afl->plot_prev_pf == afl->pending_favored &&
afl->plot_prev_pnf == afl->pending_not_fuzzed &&
afl->plot_prev_ce == afl->current_entry &&
@@ -384,16 +385,16 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) {
/* Fields in the file:
unix_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed,
- favored_not_fuzzed, afl->unique_crashes, afl->unique_hangs, afl->max_depth,
- execs_per_sec */
+ favored_not_fuzzed, unique_crashes, unique_hangs, max_depth,
+ execs_per_sec, edges_found */
- fprintf(
- afl->fsrv.plot_file,
- "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu\n",
- get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry,
- afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored,
- bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps,
- afl->plot_prev_ed); /* ignore errors */
+ fprintf(afl->fsrv.plot_file,
+ "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
+ "%u\n",
+ get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry,
+ afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored,
+ bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth,
+ eps, afl->plot_prev_ed, t_bytes); /* ignore errors */
fflush(afl->fsrv.plot_file);
@@ -532,7 +533,8 @@ void show_stats(afl_state_t *afl) {
if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) {
afl->stats_last_stats_ms = cur_ms;
- write_stats_file(afl, t_byte_ratio, stab_ratio, afl->stats_avg_exec);
+ write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
+ afl->stats_avg_exec);
save_auto(afl);
write_bitmap(afl);
@@ -555,7 +557,7 @@ void show_stats(afl_state_t *afl) {
if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) {
afl->stats_last_plot_ms = cur_ms;
- maybe_update_plot_file(afl, t_byte_ratio, afl->stats_avg_exec);
+ maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec);
}
@@ -1217,7 +1219,7 @@ void show_init_stats(afl_state_t *afl) {
stringify_int(IB(0), min_us), stringify_int(IB(1), max_us),
stringify_int(IB(2), avg_us));
- if (!afl->timeout_given) {
+ if (afl->timeout_given != 1) {
/* Figure out the appropriate timeout. The basic idea is: 5x average or
1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second.
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 8eb3625b..a02eadb2 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -103,7 +103,10 @@ static void usage(u8 *argv0, int more_help) {
" quad -- see docs/power_schedules.md\n"
" -f file - location read by the fuzzed program (default: stdin "
"or @@)\n"
- " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n"
+ " -t msec - timeout for each run (auto-scaled, default %u ms). "
+ "Add a '+'\n"
+ " to auto-calculate the timeout, the value being the "
+ "maximum.\n"
" -m megs - memory limit for child process (%u MB, 0 = no limit "
"[default])\n"
" -Q - use binary-only instrumentation (QEMU mode)\n"
@@ -122,10 +125,10 @@ static void usage(u8 *argv0, int more_help) {
" -c program - enable CmpLog by specifying a binary compiled for "
"it.\n"
" if using QEMU, just use -c 0.\n"
- " -l cmplog_level - set the complexity/intensivity of CmpLog.\n"
- " Values: 1 (basic), 2 (larger files) and 3 "
- "(transform)\n\n"
-
+ " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
+ " 1=small files (default), 2=larger files, 3=all "
+ "files,\n"
+ " A=arithmetic solving, T=transformational solving.\n\n"
"Fuzzing behavior settings:\n"
" -Z - sequential queue selection instead of weighted "
"random\n"
@@ -137,8 +140,8 @@ static void usage(u8 *argv0, int more_help) {
"Testing settings:\n"
" -s seed - use a fixed seed for the RNG\n"
- " -V seconds - fuzz for a specific time then terminate\n"
- " -E execs - fuzz for a approx. no of total executions then "
+ " -V seconds - fuzz for a specified time then terminate\n"
+ " -E execs - fuzz for an approx. no. of total executions then "
"terminate\n"
" Note: not precise and can have several more "
"executions.\n\n"
@@ -812,13 +815,36 @@ int main(int argc, char **argv_orig, char **envp) {
case 'l': {
- if (optarg) { afl->cmplog_lvl = atoi(optarg); }
- if (afl->cmplog_lvl < 1 || afl->cmplog_lvl > CMPLOG_LVL_MAX) {
+ if (!optarg) { FATAL("missing parameter for 'l'"); }
+ char *c = optarg;
+ while (*c) {
- FATAL(
- "Bad complog level value, accepted values are 1 (default), 2 and "
- "%u.",
- CMPLOG_LVL_MAX);
+ switch (*c) {
+
+ case '0':
+ case '1':
+ afl->cmplog_lvl = 1;
+ break;
+ case '2':
+ afl->cmplog_lvl = 2;
+ break;
+ case '3':
+ afl->cmplog_lvl = 3;
+ break;
+ case 'a':
+ case 'A':
+ afl->cmplog_enable_arith = 1;
+ break;
+ case 't':
+ case 'T':
+ afl->cmplog_enable_transform = 1;
+ break;
+ default:
+ FATAL("Unknown option value '%c' in -l %s", *c, optarg);
+
+ }
+
+ ++c;
}
@@ -1428,7 +1454,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!afl->timeout_given) { find_timeout(afl); }
+ if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
!afl->in_place_resume) {
@@ -1682,20 +1708,49 @@ int main(int argc, char **argv_orig, char **envp) {
cull_queue(afl);
- if (!afl->pending_not_fuzzed) {
+ // ensure we have at least one seed that is not disabled.
+ u32 entry, valid_seeds = 0;
+ for (entry = 0; entry < afl->queued_paths; ++entry)
+ if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
+
+ if (!afl->pending_not_fuzzed || !valid_seeds) {
FATAL("We need at least one valid input seed that does not crash!");
}
+ if (afl->timeout_given == 2) { // -t ...+ option
+
+ if (valid_seeds == 1) {
+
+ WARNF(
+ "Only one valid seed is present, auto-calculating the timeout is "
+ "disabled!");
+ afl->timeout_given = 1;
+
+ } else {
+
+ u64 max_ms = 0;
+
+ for (entry = 0; entry < afl->queued_paths; ++entry)
+ if (!afl->queue_buf[entry]->disabled)
+ if (afl->queue_buf[entry]->exec_us > max_ms)
+ max_ms = afl->queue_buf[entry]->exec_us;
+
+ afl->fsrv.exec_tmout = max_ms;
+
+ }
+
+ }
+
show_init_stats(afl);
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
afl->start_time = get_cur_time();
if (afl->in_place_resume || afl->afl_env.afl_autoresume) load_stats_file(afl);
- write_stats_file(afl, 0, 0, 0);
- maybe_update_plot_file(afl, 0, 0);
+ write_stats_file(afl, 0, 0, 0, 0);
+ maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
if (afl->stop_soon) { goto stop_fuzzing; }
@@ -1745,12 +1800,15 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->old_seed_selection)) {
afl->current_entry = 0;
- while (unlikely(afl->queue_buf[afl->current_entry]->disabled)) {
+ while (unlikely(afl->current_entry < afl->queued_paths &&
+ afl->queue_buf[afl->current_entry]->disabled)) {
++afl->current_entry;
}
+ if (afl->current_entry >= afl->queued_paths) { afl->current_entry = 0; }
+
afl->queue_cur = afl->queue_buf[afl->current_entry];
if (unlikely(seek_to)) {
@@ -1953,15 +2011,24 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->is_main_node)) {
- if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
+ if (unlikely(get_cur_time() >
+ (SYNC_TIME >> 1) + afl->last_sync_time)) {
+
+ if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
- sync_fuzzers(afl);
+ sync_fuzzers(afl);
+
+ }
}
} else {
- if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
+ if (unlikely(get_cur_time() > SYNC_TIME + afl->last_sync_time)) {
+
+ if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
+
+ }
}
@@ -1976,12 +2043,12 @@ int main(int argc, char **argv_orig, char **envp) {
}
write_bitmap(afl);
- maybe_update_plot_file(afl, 0, 0);
+ maybe_update_plot_file(afl, 0, 0, 0);
save_auto(afl);
stop_fuzzing:
- write_stats_file(afl, 0, 0, 0);
+ write_stats_file(afl, 0, 0, 0, 0);
afl->force_ui_update = 1; // ensure the screen is reprinted
show_stats(afl); // print the screen one last time