aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-fuzz-one.c783
-rw-r--r--src/afl-fuzz-queue.c111
-rw-r--r--src/afl-fuzz-redqueen.c102
-rw-r--r--src/afl-fuzz-state.c15
-rw-r--r--src/afl-fuzz-stats.c133
-rw-r--r--src/afl-fuzz.c81
6 files changed, 1091 insertions, 134 deletions
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 72383727..f8680100 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -24,6 +24,12 @@
*/
#include "afl-fuzz.h"
+#include <string.h>
+#include <limits.h>
+
+/* static u8 *strnstr(const u8 *s, const u8 *find, size_t slen);
+static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from,
+ u8 *to); */
/* MOpt */
@@ -362,6 +368,526 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) {
#endif /* !IGNORE_FINDS */
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
+#if 0
+/* search a string */
+
+static u8 *strnstr(const u8 *s, const u8 *find, size_t slen) {
+
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != '\0') {
+
+ len = strlen(find);
+ do {
+
+ do {
+
+ if (slen-- < 1 || (sc = *s++) == '\0') return (NULL);
+
+ } while (sc != c);
+
+ if (len > slen) return (NULL);
+
+ } while (strncmp(s, find, len) != 0);
+
+ s--;
+
+ }
+
+ return ((u8 *)s);
+
+}
+
+/* replace between deliminators, if rep == NULL, then we will duplicate the
+ * target */
+
+static u32 delim_replace(u8 **out_buf, s32 *temp_len, size_t pos,
+ const u8 *ldelim, const u8 *rdelim, u8 *rep) {
+
+ u8 *end_buf = *out_buf + *temp_len;
+ u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, *temp_len - pos);
+
+ if (ldelim_start != NULL) {
+
+ u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN
+ ? AFL_TXT_STRING_MAX_LEN
+ : end_buf - ldelim_start - 1);
+
+ if (max > 0) {
+
+ u8 *rdelim_end = strnstr(ldelim_start + 1, rdelim, max);
+
+ if (rdelim_end != NULL) {
+
+ u32 rep_len, delim_space_len = rdelim_end - ldelim_start - 1, xtra = 0;
+
+ if (rep != NULL) {
+
+ rep_len = (u32)strlen(rep);
+
+ } else { // NULL? then we copy the value in between the delimiters
+
+ rep_len = delim_space_len;
+ delim_space_len = 0;
+ rep = ldelim_start + 1;
+ xtra = rep_len;
+
+ }
+
+ if (rep_len != delim_space_len) {
+
+ memmove(ldelim_start + rep_len + xtra + 1, rdelim_end,
+ *temp_len - (rdelim_end - *out_buf));
+
+ }
+
+ memcpy(ldelim_start + 1, rep, rep_len);
+ *temp_len = (*temp_len - delim_space_len + rep_len);
+
+ return 1;
+
+ }
+
+ }
+
+ }
+
+ return 0;
+
+}
+
+static u32 delim_swap(u8 **out_buf, s32 *temp_len, size_t pos, const u8 *ldelim,
+ const u8 *mdelim, const u8 *rdelim) {
+
+ u8 *out_buf_end = *out_buf + *temp_len;
+ u32 max = (*temp_len - pos > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN
+ : *temp_len - pos);
+ u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, max);
+
+ if (ldelim_start != NULL) {
+
+ max = (out_buf_end - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN
+ ? AFL_TXT_STRING_MAX_LEN
+ : out_buf_end - ldelim_start - 1);
+ if (max > 1) {
+
+ u8 *mdelim_pos = strnstr(ldelim_start + 1, mdelim, max);
+
+ if (mdelim_pos != NULL) {
+
+ max = (out_buf_end - mdelim_pos - 1 > AFL_TXT_STRING_MAX_LEN
+ ? AFL_TXT_STRING_MAX_LEN
+ : out_buf_end - mdelim_pos - 1);
+ if (max > 0) {
+
+ u8 *rdelim_end = strnstr(mdelim + 1, rdelim, max);
+
+ if (rdelim_end != NULL) {
+
+ u32 first_len = mdelim_pos - ldelim_start - 1;
+ u32 second_len = rdelim_end - mdelim_pos - 1;
+ u8 scratch[AFL_TXT_STRING_MAX_LEN];
+
+ memcpy(scratch, ldelim_start + 1, first_len);
+
+ if (first_len != second_len) {
+
+ memmove(ldelim_start + second_len + 1, mdelim_pos,
+ out_buf_end - mdelim_pos);
+
+ }
+
+ memcpy(ldelim_start + 1, mdelim_pos + 1, second_len);
+
+ if (first_len != second_len) {
+
+ memmove(mdelim_pos + first_len + 1, rdelim_end,
+ out_buf_end - rdelim_end);
+
+ }
+
+ memcpy(mdelim_pos + 1, scratch, first_len);
+
+ return 1;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return 0;
+
+}
+
+/* replace a string */
+
+static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from,
+ u8 *to) {
+
+ u8 *start = strnstr(*out_buf + pos, from, *temp_len - pos);
+
+ if (start) {
+
+ u32 from_len = strlen(from);
+ u32 to_len = strlen(to);
+
+ if (from_len != to_len) {
+
+ memmove(start + to_len, start + from_len,
+ *temp_len - from_len - (start - *out_buf));
+
+ }
+
+ memcpy(start, to, to_len);
+ *temp_len = (*temp_len - from_len + to_len);
+
+ return 1;
+
+ }
+
+ return 0;
+
+}
+
+/* Returns 1 if a mutant was generated and placed in out_buf, 0 if none
+ * generated. */
+
+static const uint8_t text_mutation_special_chars[] = {
+
+ '\t', '\n', '\r', ' ', '!', '"', '$', '%', '&', '\'', '(', ')', '*',
+ '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[',
+ '\\', ']', '^', '_', '`', '{', '|', '}', '~', ' ' // space is here twice
+
+};
+
+static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) {
+
+ if (*orig_temp_len < AFL_TXT_MIN_LEN) { return 0; }
+
+ s32 temp_len;
+ u32 pos, yes = 0,
+ mutations = rand_below(afl, AFL_TXT_STRING_MAX_MUTATIONS) + 16;
+ u8 *new_buf =
+ ck_maybe_grow(BUF_PARAMS(out_scratch),
+ *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS + 16);
+ u8 fromc[2] = {0, 0}, toc[2] = {0, 0};
+ temp_len = *orig_temp_len;
+ memcpy(new_buf, *out_buf, temp_len);
+ new_buf[temp_len] = 0;
+
+ for (u32 i = 0; i < mutations; i++) {
+
+ if (temp_len < AFL_TXT_MIN_LEN) { return 0; }
+
+ pos = rand_below(afl, temp_len - 1);
+ int choice = rand_below(afl, 100);
+
+ switch (choice) {
+
+ /* 50% -> fixed replacements */
+
+ case 0: /* Semantic statement deletion */
+ yes += string_replace(&new_buf, &temp_len, pos, "\n", "#");
+ break;
+ case 1:
+ yes += string_replace(&new_buf, &temp_len, pos, "(", "(!");
+ break;
+ case 2:
+ yes += string_replace(&new_buf, &temp_len, pos, "==", "!=");
+ break;
+ case 3:
+ yes += string_replace(&new_buf, &temp_len, pos, "!=", "==");
+ break;
+ case 4:
+ yes += string_replace(&new_buf, &temp_len, pos, "==", "<");
+ break;
+ case 5:
+ yes += string_replace(&new_buf, &temp_len, pos, "<", "==");
+ break;
+ case 6:
+ yes += string_replace(&new_buf, &temp_len, pos, "==", ">");
+ break;
+ case 7:
+ yes += string_replace(&new_buf, &temp_len, pos, ">", "==");
+ break;
+ case 8:
+ yes += string_replace(&new_buf, &temp_len, pos, "=", "<");
+ break;
+ case 9:
+ yes += string_replace(&new_buf, &temp_len, pos, "=", ">");
+ break;
+ case 10:
+ yes += string_replace(&new_buf, &temp_len, pos, "<", ">");
+ break;
+ case 11:
+ yes += string_replace(&new_buf, &temp_len, pos, ">", "<");
+ break;
+ case 12:
+ yes += string_replace(&new_buf, &temp_len, pos, "++", "--");
+ break;
+ case 13:
+ yes += string_replace(&new_buf, &temp_len, pos, "--", "++");
+ break;
+ case 14:
+ yes += string_replace(&new_buf, &temp_len, pos, "+", "-");
+ break;
+ case 15:
+ yes += string_replace(&new_buf, &temp_len, pos, "-", "+");
+ break;
+ case 16:
+ yes += string_replace(&new_buf, &temp_len, pos, "0", "1");
+ break;
+ case 17:
+ yes += string_replace(&new_buf, &temp_len, pos, "1", "0");
+ break;
+ case 18:
+ yes += string_replace(&new_buf, &temp_len, pos, "&&", "||");
+ break;
+ case 19:
+ yes += string_replace(&new_buf, &temp_len, pos, "||", "&&");
+ break;
+ case 20:
+ yes += string_replace(&new_buf, &temp_len, pos, "!", "");
+ break;
+ case 21:
+ yes += string_replace(&new_buf, &temp_len, pos, "==", "=");
+ break;
+ case 22:
+ yes += string_replace(&new_buf, &temp_len, pos, "=", "==");
+ break;
+ case 23:
+ yes += string_replace(&new_buf, &temp_len, pos, "--", "");
+ break;
+ case 24:
+ yes += string_replace(&new_buf, &temp_len, pos, "<<", "<");
+ break;
+ case 25:
+ yes += string_replace(&new_buf, &temp_len, pos, ">>", ">");
+ break;
+ case 26:
+ yes += string_replace(&new_buf, &temp_len, pos, "<", "<<");
+ break;
+ case 27:
+ yes += string_replace(&new_buf, &temp_len, pos, ">", ">>");
+ break;
+ case 28:
+ yes += string_replace(&new_buf, &temp_len, pos, "'", "\"");
+ break;
+ case 29:
+ yes += string_replace(&new_buf, &temp_len, pos, "\"", "'");
+ break;
+ case 30: /* Remove a semicolon delimited statement after a semicolon */
+ yes += delim_replace(&new_buf, &temp_len, pos, ";", ";", ";");
+ break;
+ case 31: /* Remove a semicolon delimited statement after a left curly
+ brace */
+ yes += delim_replace(&new_buf, &temp_len, pos, "}", ";", "}");
+ break;
+ case 32: /* Remove a curly brace construct */
+ yes += delim_replace(&new_buf, &temp_len, pos, "{", "}", "");
+ break;
+ case 33: /* Replace a curly brace construct with an empty one */
+ yes += delim_replace(&new_buf, &temp_len, pos, "{", "}", "{}");
+ break;
+ case 34:
+ yes += delim_swap(&new_buf, &temp_len, pos, ";", ";", ";");
+ break;
+ case 35:
+ yes += delim_swap(&new_buf, &temp_len, pos, "}", ";", ";");
+ break;
+ case 36: /* Swap comma delimited things case 1 */
+ yes += delim_swap(&new_buf, &temp_len, pos, "(", ",", ")");
+ break;
+ case 37: /* Swap comma delimited things case 2 */
+ yes += delim_swap(&new_buf, &temp_len, pos, "(", ",", ",");
+ break;
+ case 38: /* Swap comma delimited things case 3 */
+ yes += delim_swap(&new_buf, &temp_len, pos, ",", ",", ",");
+ break;
+ case 39: /* Swap comma delimited things case 4 */
+ yes += delim_swap(&new_buf, &temp_len, pos, ",", ",", ")");
+ break;
+ case 40: /* Just delete a line */
+ yes += delim_replace(&new_buf, &temp_len, pos, "\n", "\n", "");
+ break;
+ case 41: /* Delete something like "const" case 1 */
+ yes += delim_replace(&new_buf, &temp_len, pos, " ", " ", "");
+ break;
+ case 42: /* Delete something like "const" case 2 */
+ yes += delim_replace(&new_buf, &temp_len, pos, "\n", " ", "");
+ break;
+ case 43: /* Delete something like "const" case 3 */
+ yes += delim_replace(&new_buf, &temp_len, pos, "(", " ", "");
+ break;
+ case 44: /* Swap space delimited things case 1 */
+ yes += delim_swap(&new_buf, &temp_len, pos, " ", " ", " ");
+ break;
+ case 45: /* Swap space delimited things case 2 */
+ yes += delim_swap(&new_buf, &temp_len, pos, " ", " ", ")");
+ break;
+ case 46: /* Swap space delimited things case 3 */
+ yes += delim_swap(&new_buf, &temp_len, pos, "(", " ", " ");
+ break;
+ case 47: /* Swap space delimited things case 4 */
+ yes += delim_swap(&new_buf, &temp_len, pos, "(", " ", ")");
+ break;
+ case 48: /* Duplicate a single line of code */
+ yes += delim_replace(&new_buf, &temp_len, pos, "\n", "\n", NULL);
+ break;
+ case 49: /* Duplicate a construct (most often, a non-nested for loop */
+ yes += delim_replace(&new_buf, &temp_len, pos, "\n", "}", NULL);
+ break;
+ default: {
+
+ /* 5% is transforming ascii numbers */
+
+ if (choice < 55) {
+
+ for (u32 j = pos; j < temp_len; ++j) {
+
+ if (isdigit(new_buf[j])) {
+
+ new_buf[temp_len] =
+ 0; // should be safe thanks to the initial grow
+
+ u8 * endptr;
+ unsigned long long num =
+ strtoull(new_buf + j, (char **)&endptr, 0);
+
+ switch (rand_below(afl, 8)) {
+
+ case 0:
+ num = rand_below(afl, INT_MAX);
+ break;
+ case 1:
+ num = rand_next(afl);
+ break;
+ case 2:
+ num += 1 + rand_below(afl, 255);
+ break;
+ case 3:
+ num -= 1 + rand_below(afl, 255);
+ break;
+ case 4:
+ num *= 1 + rand_below(afl, 255);
+ break;
+ case 5:
+ num /= 1 + rand_below(afl, 255);
+ break;
+ case 6:
+ num /= 1 + rand_below(afl, 255);
+ break;
+ case 7:
+ num = ~num;
+ break;
+
+ }
+
+ const char *fmt = "%llu";
+ if (rand_below(afl, 5) == 0) // add - sign with 1/5 probability
+ fmt = "-%llu";
+
+ size_t num_len = snprintf(NULL, 0, fmt, num);
+ size_t old_len = endptr - (new_buf + j);
+ if (num_len < old_len) {
+
+ memmove(new_buf + j + num_len, new_buf + j + old_len,
+ temp_len - (j + old_len));
+ snprintf(new_buf + j, num_len, fmt, num);
+ temp_len -= old_len - num_len;
+
+ } else if (num_len == old_len) {
+
+ snprintf(new_buf + j, num_len, fmt, num);
+
+ } else {
+
+ new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
+ temp_len + (num_len - old_len) +
+ AFL_TXT_STRING_MAX_MUTATIONS + 1);
+ memmove(new_buf + j + num_len, new_buf + j + old_len,
+ temp_len - (j + old_len));
+ snprintf(new_buf + j, num_len, fmt, num);
+ temp_len += num_len - old_len;
+
+ }
+
+ yes += 1;
+ break;
+
+ }
+
+ }
+
+ } else if (choice < 85) {
+
+ /* 30% is special character transform */
+
+ fromc[0] = text_mutation_special_chars[rand_below(
+ afl, sizeof(text_mutation_special_chars))];
+
+ do {
+
+ toc[0] = text_mutation_special_chars[rand_below(
+ afl, sizeof(text_mutation_special_chars))];
+
+ } while (toc[0] == fromc[0]);
+
+ yes += string_replace(&new_buf, &temp_len, pos, fromc, toc);
+ break;
+
+ } else {
+
+ /* 15% is random text character transform */
+
+ u32 iter, cnt, loc, prev_loc = temp_len;
+ if (temp_len > 32) {
+
+ cnt = 1 + rand_below(afl, 5);
+
+ } else {
+
+ cnt = rand_below(afl, 2);
+
+ }
+
+ for (iter = 0; iter <= cnt; iter++) {
+
+ while ((loc = rand_below(afl, temp_len)) == prev_loc)
+ ;
+ new_buf[loc] = 32 + rand_below(afl, 'z' - ' ' + 1);
+ prev_loc = loc;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ if (yes == 0 || temp_len <= 0) { return 0; }
+
+ swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
+ *out_buf = new_buf;
+ *orig_temp_len = temp_len;
+
+ return 1;
+
+}
+
+#endif /* if 0 */
+
/* Take the current entry from the queue, fuzz it for a while. This
function is a tad too long... returns 0 if fuzzed successfully, 1 if
skipped or bailed out. */
@@ -1854,6 +2380,22 @@ havoc_stage:
/* We essentially just do several thousand runs (depending on perf_score)
where we take the input file and make random stacked tweaks. */
+ u32 r_max, r;
+
+ if (unlikely(afl->expand_havoc)) {
+
+ /* add expensive havoc cases here, they are activated after a full
+ cycle without finds happened */
+
+ r_max = 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
+ /* + (afl->queue_cur->is_ascii ? AFL_TXT_BIAS : 0); */
+
+ } else {
+
+ r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
+
+ }
+
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
@@ -1896,8 +2438,9 @@ havoc_stage:
}
- switch (rand_below(
- afl, 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) {
+ // retry_havoc:
+
+ switch ((r = rand_below(afl, r_max))) {
case 0:
@@ -2192,85 +2735,206 @@ havoc_stage:
}
- /* Values 15 and 16 can be selected only if there are any extras
- present in the dictionaries. */
+ default:
- case 15: {
+ if (likely(r <= 16 && (afl->extras_cnt || afl->a_extras_cnt))) {
- /* Overwrite bytes with an extra. */
+ /* Values 15 and 16 can be selected only if there are any extras
+ present in the dictionaries. */
- if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
+ if (r == 15) {
- /* No user-specified extras or odds in our favor. Let's use an
- auto-detected one. */
+ /* Overwrite bytes with an extra. */
- u32 use_extra = rand_below(afl, afl->a_extras_cnt);
- u32 extra_len = afl->a_extras[use_extra].len;
- u32 insert_at;
+ if (!afl->extras_cnt ||
+ (afl->a_extras_cnt && rand_below(afl, 2))) {
- if (extra_len > temp_len) { break; }
+ /* No user-specified extras or odds in our favor. Let's use an
+ auto-detected one. */
- insert_at = rand_below(afl, temp_len - extra_len + 1);
- memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
- extra_len);
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
+ u32 insert_at;
- } else {
+ if (extra_len > temp_len) { break; }
- /* No auto extras or odds in our favor. Use the dictionary. */
+ insert_at = rand_below(afl, temp_len - extra_len + 1);
+ memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+ extra_len);
- u32 use_extra = rand_below(afl, afl->extras_cnt);
- u32 extra_len = afl->extras[use_extra].len;
- u32 insert_at;
+ } else {
- if (extra_len > temp_len) { break; }
+ /* No auto extras or odds in our favor. Use the dictionary. */
- insert_at = rand_below(afl, temp_len - extra_len + 1);
- memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len);
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
+ u32 insert_at;
- }
+ if (extra_len > temp_len) { break; }
- break;
+ insert_at = rand_below(afl, temp_len - extra_len + 1);
+ memcpy(out_buf + insert_at, afl->extras[use_extra].data,
+ extra_len);
- }
+ }
+
+ break;
+
+ } else { // case 16
+
+ u32 use_extra, extra_len,
+ insert_at = rand_below(afl, temp_len + 1);
+ u8 *ptr;
+
+ /* Insert an extra. Do the same dice-rolling stuff as for the
+ previous case. */
+
+ if (!afl->extras_cnt ||
+ (afl->a_extras_cnt && rand_below(afl, 2))) {
+
+ use_extra = rand_below(afl, afl->a_extras_cnt);
+ extra_len = afl->a_extras[use_extra].len;
+ ptr = afl->a_extras[use_extra].data;
+
+ } else {
+
+ use_extra = rand_below(afl, afl->extras_cnt);
+ extra_len = afl->extras[use_extra].len;
+ ptr = afl->extras[use_extra].data;
+
+ }
+
+ if (temp_len + extra_len >= MAX_FILE) { break; }
- case 16: {
+ out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len);
+
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
- u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1);
- u8 *ptr;
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
- /* Insert an extra. Do the same dice-rolling stuff as for the
- previous case. */
+ temp_len += extra_len;
- if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
+ break;
- use_extra = rand_below(afl, afl->a_extras_cnt);
- extra_len = afl->a_extras[use_extra].len;
- ptr = afl->a_extras[use_extra].data;
+ }
} else {
- use_extra = rand_below(afl, afl->extras_cnt);
- extra_len = afl->extras[use_extra].len;
- ptr = afl->extras[use_extra].data;
+ /*
+ switch (r) {
- }
+ case 15: // fall through
+ case 16:
+ case 17: {*/
- if (temp_len + extra_len >= MAX_FILE) { break; }
+ /* Overwrite bytes with a randomly selected chunk from another
+ testcase or insert that chunk. */
- out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len);
+ if (afl->queued_paths < 4) break;
- /* Tail */
- memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
- temp_len - insert_at);
+ /* Pick a random queue entry and seek to it. */
- /* Inserted part */
- memcpy(out_buf + insert_at, ptr, extra_len);
+ u32 tid;
+ do
+ tid = rand_below(afl, afl->queued_paths);
+ while (tid == afl->current_entry);
- temp_len += extra_len;
+ struct queue_entry *target = afl->queue_buf[tid];
- break;
+ /* Make sure that the target has a reasonable length. */
- }
+ while (target && (target->len < 2 || target == afl->queue_cur))
+ target = target->next;
+
+ if (!target) break;
+
+ /* Read the testcase into a new buffer. */
+
+ fd = open(target->fname, O_RDONLY);
+
+ if (unlikely(fd < 0)) {
+
+ PFATAL("Unable to open '%s'", target->fname);
+
+ }
+
+ u32 new_len = target->len;
+ u8 *new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len);
+
+ ck_read(fd, new_buf, new_len, target->fname);
+
+ close(fd);
+
+ u8 overwrite = 0;
+ if (temp_len >= 2 && rand_below(afl, 2))
+ overwrite = 1;
+ else if (temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+
+ if (temp_len >= 2)
+ overwrite = 1;
+ else
+ break;
+
+ }
+
+ if (overwrite) {
+
+ u32 copy_from, copy_to, copy_len;
+
+ copy_len = choose_block_len(afl, new_len - 1);
+ if (copy_len > temp_len) copy_len = temp_len;
+
+ copy_from = rand_below(afl, new_len - copy_len + 1);
+ copy_to = rand_below(afl, temp_len - copy_len + 1);
+
+ memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+
+ } else {
+
+ u32 clone_from, clone_to, clone_len;
+
+ clone_len = choose_block_len(afl, new_len);
+ clone_from = rand_below(afl, new_len - clone_len + 1);
+
+ clone_to = rand_below(afl, temp_len);
+
+ u8 *temp_buf =
+ ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
+
+ /* Head */
+
+ memcpy(temp_buf, out_buf, clone_to);
+
+ /* Inserted part */
+
+ memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
+
+ /* Tail */
+ memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
+
+ swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
+ out_buf = temp_buf;
+ temp_len += clone_len;
+
+ }
+
+ break;
+
+ }
+
+ /* default:
+
+ // perform ascii mutations
+ if (text_mutation(afl, &out_buf, &temp_len) == 0)
+ goto retry_havoc;
+
+ } // end default: switch(r)
+
+ */
}
@@ -2357,20 +3021,7 @@ retry_splicing:
} while (tid == afl->current_entry);
afl->splicing_with = tid;
- target = afl->queue;
-
- while (tid >= 100) {
-
- target = target->next_100;
- tid -= 100;
-
- }
-
- while (tid--) {
-
- target = target->next;
-
- }
+ target = afl->queue_buf[tid];
/* Make sure that the target has a reasonable length. */
@@ -4750,7 +5401,7 @@ u8 fuzz_one(afl_state_t *afl) {
return (key_val_lv_1 | key_val_lv_2);
-#undef BUF_PARAMS
-
}
+#undef BUF_PARAMS
+
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index 7afdd9f1..56073b0a 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -24,6 +24,9 @@
#include "afl-fuzz.h"
#include <limits.h>
+#include <ctype.h>
+
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
/* Mark deterministic checks as done for a particular queue entry. We use the
.state file to avoid repeating deterministic fuzzing when resuming aborted
@@ -100,6 +103,108 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
}
+/* check if ascii or UTF-8 */
+
+static u8 check_if_text(struct queue_entry *q) {
+
+ if (q->len < AFL_TXT_MIN_LEN) return 0;
+
+ u8 buf[MAX_FILE];
+ s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp;
+
+ if ((fd = open(q->fname, O_RDONLY)) < 0) return 0;
+ if ((comp = read(fd, buf, len)) != len) return 0;
+ close(fd);
+
+ while (offset < len) {
+
+ // ASCII: <= 0x7F to allow ASCII control characters
+ if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A ||
+ buf[offset + 0] == 0x0D ||
+ (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) {
+
+ offset++;
+ utf8++;
+ ascii++;
+ continue;
+
+ }
+
+ if (isascii((int)buf[offset]) || isprint((int)buf[offset])) {
+
+ ascii++;
+ // we continue though as it can also be a valid utf8
+
+ }
+
+ // non-overlong 2-byte
+ if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) {
+
+ offset += 2;
+ utf8++;
+ comp--;
+ continue;
+
+ }
+
+ // excluding overlongs
+ if ((buf[offset + 0] == 0xE0 &&
+ (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] &&
+ buf[offset + 2] <= 0xBF)) || // straight 3-byte
+ (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) ||
+ buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] &&
+ buf[offset + 2] <= 0xBF)) || // excluding surrogates
+ (buf[offset + 0] == 0xED &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF))) {
+
+ offset += 3;
+ utf8++;
+ comp -= 2;
+ continue;
+
+ }
+
+ // planes 1-3
+ if ((buf[offset + 0] == 0xF0 &&
+ (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+ (0x80 <= buf[offset + 3] &&
+ buf[offset + 3] <= 0xBF)) || // planes 4-15
+ ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+ (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16
+ (buf[offset + 0] == 0xF4 &&
+ (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) &&
+ (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
+ (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF))) {
+
+ offset += 4;
+ utf8++;
+ comp -= 3;
+ continue;
+
+ }
+
+ offset++;
+
+ }
+
+ u32 percent_utf8 = (utf8 * 100) / comp;
+ u32 percent_ascii = (ascii * 100) / len;
+
+ if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT)
+ return 2;
+ if (percent_ascii >= AFL_TXT_MIN_PERCENT) return 1;
+ return 0;
+
+}
+
/* Append new test case to the queue. */
void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
@@ -138,6 +243,10 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
}
+ struct queue_entry **queue_buf = ck_maybe_grow(
+ BUF_PARAMS(queue), afl->queued_paths * sizeof(struct queue_entry *));
+ queue_buf[afl->queued_paths - 1] = q;
+
afl->last_path_time = get_cur_time();
if (afl->custom_mutators_count) {
@@ -159,6 +268,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
}
+ q->is_ascii = check_if_text(q);
+
}
/* Destroy the entire queue. */
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index c53e0e06..57e60c3d 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -24,6 +24,7 @@
*/
+#include <limits.h>
#include "afl-fuzz.h"
#include "cmplog.h"
@@ -262,6 +263,58 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
}
+static long long strntoll(const char *str, size_t sz, char **end, int base) {
+
+ char buf[64];
+ long long ret;
+ const char *beg = str;
+
+ for (; beg && sz && *beg == ' '; beg++, sz--)
+ ;
+
+ if (!sz || sz >= sizeof(buf)) {
+
+ if (end) *end = (char *)str;
+ return 0;
+
+ }
+
+ memcpy(buf, beg, sz);
+ buf[sz] = '\0';
+ ret = strtoll(buf, end, base);
+ if (ret == LLONG_MIN || ret == LLONG_MAX) return ret;
+ if (end) *end = (char *)beg + (*end - buf);
+ return ret;
+
+}
+
+static unsigned long long strntoull(const char *str, size_t sz, char **end,
+ int base) {
+
+ char buf[64];
+ unsigned long long ret;
+ const char * beg = str;
+
+ for (; beg && sz && *beg == ' '; beg++, sz--)
+ ;
+
+ if (!sz || sz >= sizeof(buf)) {
+
+ if (end) *end = (char *)str;
+ return 0;
+
+ }
+
+ memcpy(buf, beg, sz);
+ buf[sz] = '\0';
+ ret = strtoull(buf, end, base);
+ if (end) *end = (char *)beg + (*end - buf);
+ return ret;
+
+}
+
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 pattern, u64 repl, u64 o_pattern, u32 idx,
u8 *orig_buf, u8 *buf, u32 len, u8 do_reverse,
@@ -279,7 +332,54 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u32 its_len = len - idx;
// *status = 0;
- if (SHAPE_BYTES(h->shape) >= 8) {
+ u8 * endptr;
+ u8 use_num = 0, use_unum = 0;
+ unsigned long long unum;
+ long long num;
+ if (afl->queue_cur->is_ascii) {
+
+ endptr = buf_8;
+ num = strntoll(buf_8, len - idx, (char **)&endptr, 0);
+ if (endptr == buf_8) {
+
+ unum = strntoull(buf_8, len - idx, (char **)&endptr, 0);
+ if (endptr == buf_8) use_unum = 1;
+
+ } else
+
+ use_num = 1;
+
+ }
+
+ if (use_num && num == pattern) {
+
+ size_t old_len = endptr - buf_8;
+ size_t num_len = snprintf(NULL, 0, "%lld", num);
+
+ u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), len + num_len);
+ memcpy(new_buf, buf, idx);
+
+ snprintf(new_buf + idx, num_len, "%lld", num);
+ memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
+
+ if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
+
+ } else if (use_unum && unum == pattern) {
+
+ size_t old_len = endptr - buf_8;
+ size_t num_len = snprintf(NULL, 0, "%llu", unum);
+
+ u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), len + num_len);
+ memcpy(new_buf, buf, idx);
+
+ snprintf(new_buf + idx, num_len, "%llu", unum);
+ memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
+
+ if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
+
+ }
+
+ if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) {
if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) {
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index e0e43f54..66280ed1 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -293,6 +293,20 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_autoresume =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_CYCLE_SCHEDULES",
+
+ afl_environment_variable_len)) {
+
+ afl->cycle_schedules = afl->afl_env.afl_cycle_schedules =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
+ } else if (!strncmp(env, "AFL_EXPAND_HAVOC_NOW",
+
+ afl_environment_variable_len)) {
+
+ afl->expand_havoc = afl->afl_env.afl_expand_havoc =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_CAL_FAST",
afl_environment_variable_len)) {
@@ -405,6 +419,7 @@ void afl_state_deinit(afl_state_t *afl) {
if (afl->pass_stats) { ck_free(afl->pass_stats); }
if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
+ if (afl->queue_buf) { free(afl->queue_buf); }
if (afl->out_buf) { free(afl->out_buf); }
if (afl->out_scratch_buf) { free(afl->out_scratch_buf); }
if (afl->eff_buf) { free(afl->eff_buf); }
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 2546a57a..9b16c226 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -82,58 +82,60 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
#endif
- fprintf(f,
- "start_time : %llu\n"
- "last_update : %llu\n"
- "run_time : %llu\n"
- "fuzzer_pid : %u\n"
- "cycles_done : %llu\n"
- "cycles_wo_finds : %llu\n"
- "execs_done : %llu\n"
- "execs_per_sec : %0.02f\n"
- "execs_ps_last_min : %0.02f\n"
- "paths_total : %u\n"
- "paths_favored : %u\n"
- "paths_found : %u\n"
- "paths_imported : %u\n"
- "max_depth : %u\n"
- "cur_path : %u\n" /* Must match find_start_position() */
- "pending_favs : %u\n"
- "pending_total : %u\n"
- "variable_paths : %u\n"
- "stability : %0.02f%%\n"
- "bitmap_cvg : %0.02f%%\n"
- "unique_crashes : %llu\n"
- "unique_hangs : %llu\n"
- "last_path : %llu\n"
- "last_crash : %llu\n"
- "last_hang : %llu\n"
- "execs_since_crash : %llu\n"
- "exec_timeout : %u\n"
- "slowest_exec_ms : %u\n"
- "peak_rss_mb : %lu\n"
- "cpu_affinity : %d\n"
- "edges_found : %u\n"
- "var_byte_count : %u\n"
- "afl_banner : %s\n"
- "afl_version : " VERSION
- "\n"
- "target_mode : %s%s%s%s%s%s%s%s%s\n"
- "command_line : %s\n",
- afl->start_time / 1000, cur_time / 1000,
- (cur_time - afl->start_time) / 1000, (u32)getpid(),
- afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
- afl->fsrv.total_execs,
- afl->fsrv.total_execs /
- ((double)(get_cur_time() - afl->start_time) / 1000),
- afl->last_avg_execs_saved, afl->queued_paths, afl->queued_favored,
- afl->queued_discovered, afl->queued_imported, afl->max_depth,
- afl->current_entry, afl->pending_favored, afl->pending_not_fuzzed,
- afl->queued_variable, stability, bitmap_cvg, afl->unique_crashes,
- afl->unique_hangs, afl->last_path_time / 1000,
- afl->last_crash_time / 1000, afl->last_hang_time / 1000,
- afl->fsrv.total_execs - afl->last_crash_execs, afl->fsrv.exec_tmout,
- afl->slowest_exec_ms,
+ fprintf(
+ f,
+ "start_time : %llu\n"
+ "last_update : %llu\n"
+ "run_time : %llu\n"
+ "fuzzer_pid : %u\n"
+ "cycles_done : %llu\n"
+ "cycles_wo_finds : %llu\n"
+ "execs_done : %llu\n"
+ "execs_per_sec : %0.02f\n"
+ "execs_ps_last_min : %0.02f\n"
+ "paths_total : %u\n"
+ "paths_favored : %u\n"
+ "paths_found : %u\n"
+ "paths_imported : %u\n"
+ "max_depth : %u\n"
+ "cur_path : %u\n" /* Must match find_start_position() */
+ "pending_favs : %u\n"
+ "pending_total : %u\n"
+ "variable_paths : %u\n"
+ "stability : %0.02f%%\n"
+ "bitmap_cvg : %0.02f%%\n"
+ "unique_crashes : %llu\n"
+ "unique_hangs : %llu\n"
+ "last_path : %llu\n"
+ "last_crash : %llu\n"
+ "last_hang : %llu\n"
+ "execs_since_crash : %llu\n"
+ "exec_timeout : %u\n"
+ "slowest_exec_ms : %u\n"
+ "peak_rss_mb : %lu\n"
+ "cpu_affinity : %d\n"
+ "edges_found : %u\n"
+ "var_byte_count : %u\n"
+ "havoc_expansion : %u\n"
+ "afl_banner : %s\n"
+ "afl_version : " VERSION
+ "\n"
+ "target_mode : %s%s%s%s%s%s%s%s%s\n"
+ "command_line : %s\n",
+ afl->start_time / 1000, cur_time / 1000,
+ (cur_time - afl->start_time) / 1000, (u32)getpid(),
+ afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
+ afl->fsrv.total_execs,
+ afl->fsrv.total_execs /
+ ((double)(get_cur_time() - afl->start_time) / 1000),
+ afl->last_avg_execs_saved,
+ afl->queued_paths, afl->queued_favored, afl->queued_discovered,
+ afl->queued_imported, afl->max_depth, afl->current_entry,
+ afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable,
+ stability, bitmap_cvg, afl->unique_crashes, afl->unique_hangs,
+ afl->last_path_time / 1000, afl->last_crash_time / 1000,
+ afl->last_hang_time / 1000, afl->fsrv.total_execs - afl->last_crash_execs,
+ afl->fsrv.exec_tmout, afl->slowest_exec_ms,
#ifndef __HAIKU__
#ifdef __APPLE__
(unsigned long int)(rus.ru_maxrss >> 20),
@@ -148,20 +150,19 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
#else
-1,
#endif
- t_bytes, afl->var_byte_count, afl->use_banner,
- afl->unicorn_mode ? "unicorn" : "",
- afl->fsrv.qemu_mode ? "qemu " : "",
- afl->non_instrumented_mode ? " non_instrumented " : "",
- afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
- afl->persistent_mode ? "persistent " : "",
- afl->shmem_testcase_mode ? "shmem_testcase " : "",
- afl->deferred_mode ? "deferred " : "",
- (afl->unicorn_mode || afl->fsrv.qemu_mode ||
- afl->non_instrumented_mode || afl->no_forkserver ||
- afl->crash_mode || afl->persistent_mode || afl->deferred_mode)
- ? ""
- : "default",
- afl->orig_cmdline);
+ t_bytes, afl->var_byte_count, afl->expand_havoc, afl->use_banner,
+ afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "",
+ afl->non_instrumented_mode ? " non_instrumented " : "",
+ afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
+ afl->persistent_mode ? "persistent " : "",
+ afl->shmem_testcase_mode ? "shmem_testcase " : "",
+ afl->deferred_mode ? "deferred " : "",
+ (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->non_instrumented_mode ||
+ afl->no_forkserver || afl->crash_mode || afl->persistent_mode ||
+ afl->deferred_mode)
+ ? ""
+ : "default",
+ afl->orig_cmdline);
/* ignore errors */
if (afl->debug) {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index eb4b6a87..5bedf6e1 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -916,6 +916,7 @@ int main(int argc, char **argv_orig, char **envp) {
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_FAST_CAL")) { afl->fast_cal = 1; }
+ if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
if (afl->afl_env.afl_autoresume) {
@@ -1271,11 +1272,42 @@ int main(int argc, char **argv_orig, char **envp) {
/* If we had a full queue cycle with no new finds, try
recombination strategies next. */
- if (afl->queued_paths == prev_queued) {
+ if (afl->queued_paths == prev_queued &&
+ (get_cur_time() - afl->start_time) >= 3600) {
if (afl->use_splicing) {
++afl->cycles_wo_finds;
+ switch (afl->expand_havoc) {
+
+ case 0:
+ afl->expand_havoc = 1;
+ break;
+ case 1:
+ if (afl->limit_time_sig == 0) {
+
+ afl->limit_time_sig = -1;
+ afl->limit_time_puppet = 0;
+
+ }
+
+ afl->expand_havoc = 2;
+ break;
+ case 2:
+ // afl->cycle_schedules = 1;
+ afl->expand_havoc = 3;
+ break;
+ case 3:
+ // nothing else currently
+ break;
+
+ }
+
+ if (afl->expand_havoc) {
+
+ } else
+
+ afl->expand_havoc = 1;
} else {
@@ -1289,6 +1321,53 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->cycle_schedules) {
+
+ /* we cannot mix non-AFLfast schedules with others */
+
+ switch (afl->schedule) {
+
+ case EXPLORE:
+ afl->schedule = EXPLOIT;
+ break;
+ case EXPLOIT:
+ afl->schedule = MMOPT;
+ break;
+ case MMOPT:
+ afl->schedule = SEEK;
+ break;
+ case SEEK:
+ afl->schedule = EXPLORE;
+ break;
+ case FAST:
+ afl->schedule = COE;
+ break;
+ case COE:
+ afl->schedule = LIN;
+ break;
+ case LIN:
+ afl->schedule = QUAD;
+ break;
+ case QUAD:
+ afl->schedule = RARE;
+ break;
+ case RARE:
+ afl->schedule = FAST;
+ break;
+
+ }
+
+ struct queue_entry *q = afl->queue;
+ // we must recalculate the scores of all queue entries
+ while (q) {
+
+ update_bitmap_score(afl, q);
+ q = q->next;
+
+ }
+
+ }
+
prev_queued = afl->queued_paths;
if (afl->sync_id && afl->queue_cycle == 1 &&