fix token usage in normal and MOpt mode
MODIFY
docs/Changelog.md
docs/Changelog.md
@@ -12,6 +12,9 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix */build_...sh scripts to work outside of git
- new custom_mutator: libafl with token fuzzing :)
- afl-fuzz:
+ - AFL never implemented auto token inserts (but user token inserts,
+ user token overwrite and auto token overwrite), added now!
+ - Mopt fix to always select the correct algorithm
- when you just want to compile once and set CMPLOG, then just
set -c 0 to tell afl-fuzz that the fuzzing binary is also for
CMPLOG.

MODIFY
include/afl-fuzz.h
include/afl-fuzz.h
@@ -230,12 +230,13 @@ enum {
/* 12 */ STAGE_EXTRAS_UO,
/* 13 */ STAGE_EXTRAS_UI,
/* 14 */ STAGE_EXTRAS_AO,
- /* 15 */ STAGE_HAVOC,
- /* 16 */ STAGE_SPLICE,
- /* 17 */ STAGE_PYTHON,
- /* 18 */ STAGE_CUSTOM_MUTATOR,
- /* 19 */ STAGE_COLORIZATION,
- /* 20 */ STAGE_ITS,
+ /* 15 */ STAGE_EXTRAS_AI,
+ /* 16 */ STAGE_HAVOC,
+ /* 17 */ STAGE_SPLICE,
+ /* 18 */ STAGE_PYTHON,
+ /* 19 */ STAGE_CUSTOM_MUTATOR,
+ /* 20 */ STAGE_COLORIZATION,
+ /* 21 */ STAGE_ITS,
STAGE_NUM_MAX

MODIFY
src/afl-fuzz-one.c
src/afl-fuzz-one.c
@@ -1779,6 +1779,62 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max;
+ /* Insertion of auto extras. */
+
+ afl->stage_name = "auto extras (insert)";
+ afl->stage_short = "ext_AI";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->a_extras_cnt * (len + 1);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ ex_tmp = afl_realloc(AFL_BUF_PARAM(ex), len + MAX_DICT_FILE);
+ if (unlikely(!ex_tmp)) { PFATAL("alloc"); }
+
+ for (i = 0; i <= (u32)len; ++i) {
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < afl->a_extras_cnt; ++j) {
+
+ if (len + afl->a_extras[j].len > MAX_FILE) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ /* Insert token */
+ memcpy(ex_tmp + i, afl->a_extras[j].data, afl->a_extras[j].len);
+
+ /* Copy tail */
+ memcpy(ex_tmp + i + afl->a_extras[j].len, out_buf + i, len - i);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s AUTO_EXTRAS_insert-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, ex_tmp, len + afl->a_extras[j].len)) {
+
+ goto abandon_entry;
+
+ }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Copy head */
+ ex_tmp[i] = out_buf[i];
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max;
+
skip_extras:
/* If we made this to here without jumping to havoc_stage or abandon_entry,
@@ -4367,6 +4423,62 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max;
+ /* Insertion of auto extras. */
+
+ afl->stage_name = "auto extras (insert)";
+ afl->stage_short = "ext_AI";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->a_extras_cnt * (len + 1);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ ex_tmp = afl_realloc(AFL_BUF_PARAM(ex), len + MAX_DICT_FILE);
+ if (unlikely(!ex_tmp)) { PFATAL("alloc"); }
+
+ for (i = 0; i <= (u32)len; ++i) {
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < afl->a_extras_cnt; ++j) {
+
+ if (len + afl->a_extras[j].len > MAX_FILE) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ /* Insert token */
+ memcpy(ex_tmp + i, afl->a_extras[j].data, afl->a_extras[j].len);
+
+ /* Copy tail */
+ memcpy(ex_tmp + i + afl->a_extras[j].len, out_buf + i, len - i);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_AUTO_EXTRAS_insert-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, ex_tmp, len + afl->a_extras[j].len)) {
+
+ goto abandon_entry;
+
+ }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Copy head */
+ ex_tmp[i] = out_buf[i];
+
+ } /* for i = 0; i <= len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max;
+
skip_extras:
/* If we made this to here without jumping to havoc_stage or abandon_entry,
@@ -4464,14 +4576,14 @@ pacemaker_fuzzing:
havoc_queued = afl->queued_items;
- u32 r_max;
+ u32 r_max, r;
r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
/* add expensive havoc cases here, they are activated after a full
- cycle without finds happened */
+ cycle without any finds happened */
++r_max;
@@ -4497,7 +4609,7 @@ pacemaker_fuzzing:
for (i = 0; i < use_stacking; ++i) {
- switch (select_algorithm(afl, r_max)) {
+ switch (r = (select_algorithm(afl, r_max))) {
case 0:
/* Flip a single bit somewhere. Spooky! */
@@ -4914,10 +5026,16 @@ pacemaker_fuzzing:
} /* case 15 */
+ default: {
+
+ }
+
/* Values 16 and 17 can be selected only if there are any extras
present in the dictionaries. */
- case 16: {
+ r -= 16;
+
+ if (r == 0 && (afl->extras_cnt || afl->a_extras_cnt)) {
/* Overwrite bytes with an extra. */
@@ -4969,7 +5087,7 @@ pacemaker_fuzzing:
/* Insert an extra. */
- case 17: {
+ else if (r == 1 && (afl->extras_cnt || afl->a_extras_cnt)) {
u32 use_extra, extra_len,
insert_at = rand_below(afl, temp_len + 1);
@@ -4996,8 +5114,8 @@ pacemaker_fuzzing:
extra_len = afl->extras[use_extra].len;
ptr = afl->extras[use_extra].data;
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
- insert_at, extra_len);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " EXTRA_INSERT-%u-%u", insert_at, extra_len);
strcat(afl->mutation, afl->m_tmp);
#endif
@@ -5019,9 +5137,7 @@ pacemaker_fuzzing:
MOpt_globals.cycles_v2[STAGE_InsertExtra]++;
break;
- }
-
- default: {
+ } else {
if (unlikely(afl->ready_for_splicing_count < 2)) break;

MODIFY
src/afl-fuzz-stats.c
src/afl-fuzz-stats.c
@@ -1021,13 +1021,15 @@ void show_stats_normal(afl_state_t *afl) {
if (unlikely(!afl->skip_deterministic)) {
- sprintf(tmp, "%s/%s, %s/%s, %s/%s",
+ sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
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(2), afl->stage_finds[STAGE_EXTRAS_UI]),
u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
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]),
+ u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]),
+ u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI]));
} else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
@@ -1839,13 +1841,15 @@ void show_stats_pizza(afl_state_t *afl) {
if (unlikely(!afl->skip_deterministic)) {
- sprintf(tmp, "%s/%s, %s/%s, %s/%s",
+ sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
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(2), afl->stage_finds[STAGE_EXTRAS_UI]),
u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
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]),
+ u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]),
+ u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI]));
} else if (unlikely(!afl->extras_cnt || afl->custom_only)) {

fix token usage in normal and MOpt mode