aboutsummaryrefslogtreecommitdiff
path: root/src/afl-fuzz-one.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-fuzz-one.c')
-rw-r--r--src/afl-fuzz-one.c5735
1 files changed, 5735 insertions, 0 deletions
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
new file mode 100644
index 00000000..19f41ebe
--- /dev/null
+++ b/src/afl-fuzz-one.c
@@ -0,0 +1,5735 @@
+/*
+ american fuzzy lop++ - fuzze_one routines in different flavours
+ ---------------------------------------------------------------
+
+ Originally written by Michal Zalewski
+
+ Now maintained by Marc Heuse <mh@mh-sec.de>,
+ Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
+ Andrea Fioraldi <andreafioraldi@gmail.com>
+
+ Copyright 2016, 2017 Google Inc. All rights reserved.
+ Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ This is the real deal: the program takes an instrumented binary and
+ attempts a variety of basic fuzzing tricks, paying close attention to
+ how they affect the execution path.
+
+ */
+
+#include "afl-fuzz.h"
+#include <string.h>
+#include <limits.h>
+#include "cmplog.h"
+
+/* MOpt */
+
+static int select_algorithm(afl_state_t *afl, u32 max_algorithm) {
+
+ int i_puppet, j_puppet = 0, operator_number = max_algorithm;
+
+ double range_sele =
+ (double)afl->probability_now[afl->swarm_now][operator_number - 1];
+ double sele = ((double)(rand_below(afl, 10000) * 0.0001 * range_sele));
+
+ for (i_puppet = 0; i_puppet < operator_num; ++i_puppet) {
+
+ if (unlikely(i_puppet == 0)) {
+
+ if (sele < afl->probability_now[afl->swarm_now][i_puppet]) { break; }
+
+ } else {
+
+ if (sele < afl->probability_now[afl->swarm_now][i_puppet]) {
+
+ j_puppet = 1;
+ break;
+
+ }
+
+ }
+
+ }
+
+ if ((j_puppet == 1 &&
+ sele < afl->probability_now[afl->swarm_now][i_puppet - 1]) ||
+ (i_puppet + 1 < operator_num &&
+ sele > afl->probability_now[afl->swarm_now][i_puppet + 1])) {
+
+ FATAL("error select_algorithm");
+
+ }
+
+ return i_puppet;
+
+}
+
+/* Helper to choose random block len for block operations in fuzz_one().
+ Doesn't return zero, provided that max_len is > 0. */
+
+static inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
+
+ u32 min_value, max_value;
+ u32 rlim = MIN(afl->queue_cycle, (u32)3);
+
+ if (unlikely(!afl->run_over10m)) { rlim = 1; }
+
+ switch (rand_below(afl, rlim)) {
+
+ case 0:
+ min_value = 1;
+ max_value = HAVOC_BLK_SMALL;
+ break;
+
+ case 1:
+ min_value = HAVOC_BLK_SMALL;
+ max_value = HAVOC_BLK_MEDIUM;
+ break;
+
+ default:
+
+ if (likely(rand_below(afl, 10))) {
+
+ min_value = HAVOC_BLK_MEDIUM;
+ max_value = HAVOC_BLK_LARGE;
+
+ } else {
+
+ min_value = HAVOC_BLK_LARGE;
+ max_value = HAVOC_BLK_XL;
+
+ }
+
+ }
+
+ if (min_value >= limit) { min_value = 1; }
+
+ return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
+
+}
+
+/* Helper function to see if a particular change (xor_val = old ^ new) could
+ be a product of deterministic bit flips with the lengths and stepovers
+ attempted by afl-fuzz. This is used to avoid dupes in some of the
+ deterministic fuzzing operations that follow bit flips. We also
+ return 1 if xor_val is zero, which implies that the old and attempted new
+ values are identical and the exec would be a waste of time. */
+
+static u8 could_be_bitflip(u32 xor_val) {
+
+ u32 sh = 0;
+
+ if (!xor_val) { return 1; }
+
+ /* Shift left until first bit set. */
+
+ while (!(xor_val & 1)) {
+
+ ++sh;
+ xor_val >>= 1;
+
+ }
+
+ /* 1-, 2-, and 4-bit patterns are OK anywhere. */
+
+ if (xor_val == 1 || xor_val == 3 || xor_val == 15) { return 1; }
+
+ /* 8-, 16-, and 32-bit patterns are OK only if shift factor is
+ divisible by 8, since that's the stepover for these ops. */
+
+ if (sh & 7) { return 0; }
+
+ if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) {
+
+ return 1;
+
+ }
+
+ return 0;
+
+}
+
+/* Helper function to see if a particular value is reachable through
+ arithmetic operations. Used for similar purposes. */
+
+static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) {
+
+ u32 i, ov = 0, nv = 0, diffs = 0;
+
+ if (old_val == new_val) { return 1; }
+
+ /* See if one-byte adjustments to any byte could produce this result. */
+
+ for (i = 0; (u8)i < blen; ++i) {
+
+ u8 a = old_val >> (8 * i), b = new_val >> (8 * i);
+
+ if (a != b) {
+
+ ++diffs;
+ ov = a;
+ nv = b;
+
+ }
+
+ }
+
+ /* If only one byte differs and the values are within range, return 1. */
+
+ if (diffs == 1) {
+
+ if ((u8)(ov - nv) <= ARITH_MAX || (u8)(nv - ov) <= ARITH_MAX) { return 1; }
+
+ }
+
+ if (blen == 1) { return 0; }
+
+ /* See if two-byte adjustments to any byte would produce this result. */
+
+ diffs = 0;
+
+ for (i = 0; (u8)i < blen / 2; ++i) {
+
+ u16 a = old_val >> (16 * i), b = new_val >> (16 * i);
+
+ if (a != b) {
+
+ ++diffs;
+ ov = a;
+ nv = b;
+
+ }
+
+ }
+
+ /* If only one word differs and the values are within range, return 1. */
+
+ if (diffs == 1) {
+
+ if ((u16)(ov - nv) <= ARITH_MAX || (u16)(nv - ov) <= ARITH_MAX) {
+
+ return 1;
+
+ }
+
+ ov = SWAP16(ov);
+ nv = SWAP16(nv);
+
+ if ((u16)(ov - nv) <= ARITH_MAX || (u16)(nv - ov) <= ARITH_MAX) {
+
+ return 1;
+
+ }
+
+ }
+
+ /* Finally, let's do the same thing for dwords. */
+
+ if (blen == 4) {
+
+ if ((u32)(old_val - new_val) <= ARITH_MAX ||
+ (u32)(new_val - old_val) <= ARITH_MAX) {
+
+ return 1;
+
+ }
+
+ new_val = SWAP32(new_val);
+ old_val = SWAP32(old_val);
+
+ if ((u32)(old_val - new_val) <= ARITH_MAX ||
+ (u32)(new_val - old_val) <= ARITH_MAX) {
+
+ return 1;
+
+ }
+
+ }
+
+ return 0;
+
+}
+
+/* Last but not least, a similar helper to see if insertion of an
+ interesting integer is redundant given the insertions done for
+ shorter blen. The last param (check_le) is set if the caller
+ already executed LE insertion for current blen and wants to see
+ if BE variant passed in new_val is unique. */
+
+static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) {
+
+ u32 i, j;
+
+ if (old_val == new_val) { return 1; }
+
+ /* See if one-byte insertions from interesting_8 over old_val could
+ produce new_val. */
+
+ for (i = 0; i < blen; ++i) {
+
+ for (j = 0; j < sizeof(interesting_8); ++j) {
+
+ u32 tval =
+ (old_val & ~(0xff << (i * 8))) | (((u8)interesting_8[j]) << (i * 8));
+
+ if (new_val == tval) { return 1; }
+
+ }
+
+ }
+
+ /* Bail out unless we're also asked to examine two-byte LE insertions
+ as a preparation for BE attempts. */
+
+ if (blen == 2 && !check_le) { return 0; }
+
+ /* See if two-byte insertions over old_val could give us new_val. */
+
+ for (i = 0; (u8)i < blen - 1; ++i) {
+
+ for (j = 0; j < sizeof(interesting_16) / 2; ++j) {
+
+ u32 tval = (old_val & ~(0xffff << (i * 8))) |
+ (((u16)interesting_16[j]) << (i * 8));
+
+ if (new_val == tval) { return 1; }
+
+ /* Continue here only if blen > 2. */
+
+ if (blen > 2) {
+
+ tval = (old_val & ~(0xffff << (i * 8))) |
+ (SWAP16(interesting_16[j]) << (i * 8));
+
+ if (new_val == tval) { return 1; }
+
+ }
+
+ }
+
+ }
+
+ if (blen == 4 && check_le) {
+
+ /* See if four-byte insertions could produce the same result
+ (LE only). */
+
+ for (j = 0; j < sizeof(interesting_32) / 4; ++j) {
+
+ if (new_val == (u32)interesting_32[j]) { return 1; }
+
+ }
+
+ }
+
+ return 0;
+
+}
+
+#ifndef IGNORE_FINDS
+
+/* Helper function to compare buffers; returns first and last differing offset.
+ We use this to find reasonable locations for splicing two files. */
+
+static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) {
+
+ s32 f_loc = -1;
+ s32 l_loc = -1;
+ u32 pos;
+
+ for (pos = 0; pos < len; ++pos) {
+
+ if (*(ptr1++) != *(ptr2++)) {
+
+ if (f_loc == -1) { f_loc = pos; }
+ l_loc = pos;
+
+ }
+
+ }
+
+ *first = f_loc;
+ *last = l_loc;
+
+ return;
+
+}
+
+#endif /* !IGNORE_FINDS */
+
+/* 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. */
+
+u8 fuzz_one_original(afl_state_t *afl) {
+
+ u32 len, temp_len;
+ u32 j;
+ u32 i;
+ u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
+ u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum, _prev_cksum;
+ u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1;
+
+ u8 ret_val = 1, doing_det = 0;
+
+ u8 a_collect[MAX_AUTO_EXTRA];
+ u32 a_len = 0;
+
+#ifdef IGNORE_FINDS
+
+ /* In IGNORE_FINDS mode, skip any entries that weren't in the
+ initial data set. */
+
+ if (afl->queue_cur->depth > 1) return 1;
+
+#else
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ /* The custom mutator will decide to skip this test case or not. */
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_queue_get &&
+ !el->afl_custom_queue_get(el->data, afl->queue_cur->fname)) {
+
+ return 1;
+
+ }
+
+ });
+
+ }
+
+ if (likely(afl->pending_favored)) {
+
+ /* If we have any favored, non-fuzzed new arrivals in the queue,
+ possibly skip to them at the expense of already-fuzzed or non-favored
+ cases. */
+
+ if ((afl->queue_cur->fuzz_level || !afl->queue_cur->favored) &&
+ likely(rand_below(afl, 100) < SKIP_TO_NEW_PROB)) {
+
+ return 1;
+
+ }
+
+ } else if (!afl->non_instrumented_mode && !afl->queue_cur->favored &&
+
+ afl->queued_items > 10) {
+
+ /* Otherwise, still possibly skip non-favored cases, albeit less often.
+ The odds of skipping stuff are higher for already-fuzzed inputs and
+ lower for never-fuzzed entries. */
+
+ if (afl->queue_cycle > 1 && !afl->queue_cur->fuzz_level) {
+
+ if (likely(rand_below(afl, 100) < SKIP_NFAV_NEW_PROB)) { return 1; }
+
+ } else {
+
+ if (likely(rand_below(afl, 100) < SKIP_NFAV_OLD_PROB)) { return 1; }
+
+ }
+
+ }
+
+#endif /* ^IGNORE_FINDS */
+
+ if (unlikely(afl->not_on_tty)) {
+
+ ACTF(
+ "Fuzzing test case #%u (%u total, %llu crashes saved, "
+ "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
+ afl->current_entry, afl->queued_items, afl->saved_crashes,
+ afl->queue_cur->perf_score, afl->queue_cur->exec_us,
+ likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
+ afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii);
+ fflush(stdout);
+
+ }
+
+ orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
+ len = afl->queue_cur->len;
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+ afl->subseq_tmouts = 0;
+
+ afl->cur_depth = afl->queue_cur->depth;
+
+ /*******************************************
+ * CALIBRATION (only if failed earlier on) *
+ *******************************************/
+
+ if (unlikely(afl->queue_cur->cal_failed)) {
+
+ u8 res = FSRV_RUN_TMOUT;
+
+ if (afl->queue_cur->cal_failed < CAL_CHANCES) {
+
+ afl->queue_cur->exec_cksum = 0;
+
+ res =
+ calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
+
+ if (unlikely(res == FSRV_RUN_ERROR)) {
+
+ FATAL("Unable to execute target application");
+
+ }
+
+ }
+
+ if (unlikely(afl->stop_soon) || res != afl->crash_mode) {
+
+ ++afl->cur_skipped_items;
+ goto abandon_entry;
+
+ }
+
+ }
+
+ /************
+ * TRIMMING *
+ ************/
+
+ if (unlikely(!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
+ !afl->disable_trim)) {
+
+ u32 old_len = afl->queue_cur->len;
+
+ u8 res = trim_case(afl, afl->queue_cur, in_buf);
+ orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
+
+ if (unlikely(res == FSRV_RUN_ERROR)) {
+
+ FATAL("Unable to execute target application");
+
+ }
+
+ if (unlikely(afl->stop_soon)) {
+
+ ++afl->cur_skipped_items;
+ goto abandon_entry;
+
+ }
+
+ /* Don't retry trimming, even if it failed. */
+
+ afl->queue_cur->trim_done = 1;
+
+ len = afl->queue_cur->len;
+
+ /* maybe current entry is not ready for splicing anymore */
+ if (unlikely(len <= 4 && old_len > 4)) --afl->ready_for_splicing_count;
+
+ }
+
+ memcpy(out_buf, in_buf, len);
+
+ /*********************
+ * PERFORMANCE SCORE *
+ *********************/
+
+ if (likely(!afl->old_seed_selection))
+ orig_perf = perf_score = afl->queue_cur->perf_score;
+ else
+ afl->queue_cur->perf_score = orig_perf = perf_score =
+ calculate_score(afl, afl->queue_cur);
+
+ if (unlikely(perf_score <= 0 && afl->active_items > 1)) {
+
+ goto abandon_entry;
+
+ }
+
+ if (unlikely(afl->shm.cmplog_mode &&
+ afl->queue_cur->colorized < afl->cmplog_lvl &&
+ (u32)len <= afl->cmplog_max_filesize)) {
+
+ if (unlikely(len < 4)) {
+
+ afl->queue_cur->colorized = CMPLOG_LVL_MAX;
+
+ } else {
+
+ if (afl->cmplog_lvl == 3 ||
+ (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) ||
+ afl->queue_cur->favored ||
+ !(afl->fsrv.total_execs % afl->queued_items) ||
+ get_cur_time() - afl->last_find_time > 300000) { // 300 seconds
+
+ if (input_to_state_stage(afl, in_buf, out_buf, len)) {
+
+ goto abandon_entry;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Skip right away if -d is given, if it has not been chosen sufficiently
+ often to warrant the expensive deterministic stage (fuzz_level), or
+ if it has gone through deterministic testing in earlier, resumed runs
+ (passed_det). */
+
+ if (likely(afl->queue_cur->passed_det) || likely(afl->skip_deterministic) ||
+ likely(perf_score <
+ (afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100
+ ? afl->queue_cur->depth * 30
+ : afl->havoc_max_mult * 100))) {
+
+ goto custom_mutator_stage;
+
+ }
+
+ /* Skip deterministic fuzzing if exec path checksum puts this out of scope
+ for this main instance. */
+
+ if (unlikely(afl->main_node_max &&
+ (afl->queue_cur->exec_cksum % afl->main_node_max) !=
+ afl->main_node_id - 1)) {
+
+ goto custom_mutator_stage;
+
+ }
+
+ doing_det = 1;
+
+ /*********************************************
+ * SIMPLE BITFLIP (+dictionary construction) *
+ *********************************************/
+
+#define FLIP_BIT(_ar, _b) \
+ do { \
+ \
+ u8 *_arf = (u8 *)(_ar); \
+ u32 _bf = (_b); \
+ _arf[(_bf) >> 3] ^= (128 >> ((_bf)&7)); \
+ \
+ } while (0)
+
+ /* Single walking bit. */
+
+ afl->stage_short = "flip1";
+ afl->stage_max = len << 3;
+ afl->stage_name = "bitflip 1/1";
+
+ afl->stage_val_type = STAGE_VAL_NONE;
+
+ orig_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ /* Get a clean cksum. */
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+ _prev_cksum = prev_cksum;
+
+ /* Now flip bits. */
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur >> 3;
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s FLIP_BIT1-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+
+ /* While flipping the least significant bit in every byte, pull of an extra
+ trick to detect possible syntax tokens. In essence, the idea is that if
+ you have a binary blob like this:
+
+ xxxxxxxxIHDRxxxxxxxx
+
+ ...and changing the leading and trailing bytes causes variable or no
+ changes in program flow, but touching any character in the "IHDR" string
+ always produces the same, distinctive path, it's highly likely that
+ "IHDR" is an atomically-checked magic value of special significance to
+ the fuzzed format.
+
+ We do this here, rather than as a separate stage, because it's a nice
+ way to keep the operation approximately "free" (i.e., no extra execs).
+
+ Empirically, performing the check when flipping the least significant bit
+ is advantageous, compared to doing it at the time of more disruptive
+ changes, where the program flow may be affected in more violent ways.
+
+ The caveat is that we won't generate dictionaries in the -d mode or -S
+ mode - but that's probably a fair trade-off.
+
+ This won't work particularly well with paths that exhibit variable
+ behavior, but fails gracefully, so we'll carry out the checks anyway.
+
+ */
+
+ if (!afl->non_instrumented_mode && (afl->stage_cur & 7) == 7) {
+
+ u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
+ if (afl->stage_cur == afl->stage_max - 1 && cksum == prev_cksum) {
+
+ /* If at end of file and we are still collecting a string, grab the
+ final character and force output. */
+
+ if (a_len < MAX_AUTO_EXTRA) {
+
+ a_collect[a_len] = out_buf[afl->stage_cur >> 3];
+
+ }
+
+ ++a_len;
+
+ if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
+
+ maybe_add_auto(afl, a_collect, a_len);
+
+ }
+
+ } else if (cksum != prev_cksum) {
+
+ /* Otherwise, if the checksum has changed, see if we have something
+ worthwhile queued up, and collect that if the answer is yes. */
+
+ if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
+
+ maybe_add_auto(afl, a_collect, a_len);
+
+ }
+
+ a_len = 0;
+ prev_cksum = cksum;
+
+ }
+
+ /* Continue collecting string, but only if the bit flip actually made
+ any difference - we don't want no-op tokens. */
+
+ if (cksum != _prev_cksum) {
+
+ if (a_len < MAX_AUTO_EXTRA) {
+
+ a_collect[a_len] = out_buf[afl->stage_cur >> 3];
+
+ }
+
+ ++a_len;
+
+ }
+
+ }
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP1] += afl->stage_max;
+
+ /* Two walking bits. */
+
+ afl->stage_name = "bitflip 2/1";
+ afl->stage_short = "flip2";
+ afl->stage_max = (len << 3) - 1;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur >> 3;
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s FLIP_BIT2-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP2] += afl->stage_max;
+
+ /* Four walking bits. */
+
+ afl->stage_name = "bitflip 4/1";
+ afl->stage_short = "flip4";
+ afl->stage_max = (len << 3) - 3;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur >> 3;
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+ FLIP_BIT(out_buf, afl->stage_cur + 2);
+ FLIP_BIT(out_buf, afl->stage_cur + 3);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s FLIP_BIT4-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+ FLIP_BIT(out_buf, afl->stage_cur + 2);
+ FLIP_BIT(out_buf, afl->stage_cur + 3);
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP4] += afl->stage_max;
+
+ /* Effector map setup. These macros calculate:
+
+ EFF_APOS - position of a particular file offset in the map.
+ EFF_ALEN - length of a map with a particular number of bytes.
+ EFF_SPAN_ALEN - map span for a sequence of bytes.
+
+ */
+
+#define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2)
+#define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1))
+#define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l))
+#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l)-1) - EFF_APOS(_p) + 1)
+
+ /* Initialize effector map for the next step (see comments below). Always
+ flag first and last byte as doing something. */
+
+ eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
+ if (unlikely(!eff_map)) { PFATAL("alloc"); }
+ eff_map[0] = 1;
+
+ if (EFF_APOS(len - 1) != 0) {
+
+ eff_map[EFF_APOS(len - 1)] = 1;
+ ++eff_cnt;
+
+ }
+
+ /* Walking byte. */
+
+ afl->stage_name = "bitflip 8/8";
+ afl->stage_short = "flip8";
+ afl->stage_max = len;
+
+ orig_hit_cnt = new_hit_cnt;
+ prev_cksum = _prev_cksum;
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur;
+
+ out_buf[afl->stage_cur] ^= 0xFF;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s FLIP_BIT8-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ /* We also use this stage to pull off a simple trick: we identify
+ bytes that seem to have no effect on the current execution path
+ even when fully flipped - and we skip them during more expensive
+ deterministic stages, such as arithmetics or known ints. */
+
+ if (!eff_map[EFF_APOS(afl->stage_cur)]) {
+
+ u64 cksum;
+
+ /* If in non-instrumented mode or if the file is very short, just flag
+ everything without wasting time on checksums. */
+
+ if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) {
+
+ cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
+ } else {
+
+ cksum = ~prev_cksum;
+
+ }
+
+ if (cksum != prev_cksum) {
+
+ eff_map[EFF_APOS(afl->stage_cur)] = 1;
+ ++eff_cnt;
+
+ }
+
+ }
+
+ out_buf[afl->stage_cur] ^= 0xFF;
+
+ }
+
+ /* If the effector map is more than EFF_MAX_PERC dense, just flag the
+ whole thing as worth fuzzing, since we wouldn't be saving much time
+ anyway. */
+
+ if (eff_cnt != (u32)EFF_ALEN(len) &&
+ eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) {
+
+ memset(eff_map, 1, EFF_ALEN(len));
+
+ afl->blocks_eff_select += EFF_ALEN(len);
+
+ } else {
+
+ afl->blocks_eff_select += eff_cnt;
+
+ }
+
+ afl->blocks_eff_total += EFF_ALEN(len);
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP8] += afl->stage_max;
+
+ /* Two walking bytes. */
+
+ if (len < 2) { goto skip_bitflip; }
+
+ afl->stage_name = "bitflip 16/8";
+ afl->stage_short = "flip16";
+ afl->stage_cur = 0;
+ afl->stage_max = len - 1;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 1; ++i) {
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ *(u16 *)(out_buf + i) ^= 0xFFFF;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s FLIP_BIT16-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ *(u16 *)(out_buf + i) ^= 0xFFFF;
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP16] += afl->stage_max;
+
+ if (len < 4) { goto skip_bitflip; }
+
+ /* Four walking bytes. */
+
+ afl->stage_name = "bitflip 32/8";
+ afl->stage_short = "flip32";
+ afl->stage_cur = 0;
+ afl->stage_max = len - 3;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 3; ++i) {
+
+ /* Let's consult the effector map... */
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
+ !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ *(u32 *)(out_buf + i) ^= 0xFFFFFFFF;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s FLIP_BIT32-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ *(u32 *)(out_buf + i) ^= 0xFFFFFFFF;
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP32] += afl->stage_max;
+
+skip_bitflip:
+
+ if (afl->no_arith) { goto skip_arith; }
+
+ /**********************
+ * ARITHMETIC INC/DEC *
+ **********************/
+
+ /* 8-bit arithmetics. */
+
+ afl->stage_name = "arith 8/8";
+ afl->stage_short = "arith8";
+ afl->stage_cur = 0;
+ afl->stage_max = 2 * len * ARITH_MAX;
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u8 orig = out_buf[i];
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)]) {
+
+ afl->stage_max -= 2 * ARITH_MAX;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 1; j <= ARITH_MAX; ++j) {
+
+ u8 r = orig ^ (orig + j);
+
+ /* Do arithmetic operations only if the result couldn't be a product
+ of a bitflip. */
+
+ if (!could_be_bitflip(r)) {
+
+ afl->stage_cur_val = j;
+ out_buf[i] = orig + j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH8+-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ r = orig ^ (orig - j);
+
+ if (!could_be_bitflip(r)) {
+
+ afl->stage_cur_val = -j;
+ out_buf[i] = orig - j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH8--%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ out_buf[i] = orig;
+
+ }
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_ARITH8] += afl->stage_max;
+
+ /* 16-bit arithmetics, both endians. */
+
+ if (len < 2) { goto skip_arith; }
+
+ afl->stage_name = "arith 16/8";
+ afl->stage_short = "arith16";
+ afl->stage_cur = 0;
+ afl->stage_max = 4 * (len - 1) * ARITH_MAX;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len - 1; ++i) {
+
+ u16 orig = *(u16 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
+
+ afl->stage_max -= 4 * ARITH_MAX;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 1; j <= ARITH_MAX; ++j) {
+
+ u16 r1 = orig ^ (orig + j), r2 = orig ^ (orig - j),
+ r3 = orig ^ SWAP16(SWAP16(orig) + j),
+ r4 = orig ^ SWAP16(SWAP16(orig) - j);
+
+ /* Try little endian addition and subtraction first. Do it only
+ if the operation would affect more than one byte (hence the
+ & 0xff overflow checks) and if it couldn't be a product of
+ a bitflip. */
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ if ((orig & 0xff) + j > 0xff && !could_be_bitflip(r1)) {
+
+ afl->stage_cur_val = j;
+ *(u16 *)(out_buf + i) = orig + j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH16+-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((orig & 0xff) < j && !could_be_bitflip(r2)) {
+
+ afl->stage_cur_val = -j;
+ *(u16 *)(out_buf + i) = orig - j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH16--%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ /* Big endian comes next. Same deal. */
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+ if ((orig >> 8) + j > 0xff && !could_be_bitflip(r3)) {
+
+ afl->stage_cur_val = j;
+ *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) + j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH16+BE-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((orig >> 8) < j && !could_be_bitflip(r4)) {
+
+ afl->stage_cur_val = -j;
+ *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) - j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH16_BE-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ *(u16 *)(out_buf + i) = orig;
+
+ }
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_ARITH16] += afl->stage_max;
+
+ /* 32-bit arithmetics, both endians. */
+
+ if (len < 4) { goto skip_arith; }
+
+ afl->stage_name = "arith 32/8";
+ afl->stage_short = "arith32";
+ afl->stage_cur = 0;
+ afl->stage_max = 4 * (len - 3) * ARITH_MAX;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len - 3; ++i) {
+
+ u32 orig = *(u32 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
+ !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
+
+ afl->stage_max -= 4 * ARITH_MAX;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 1; j <= ARITH_MAX; ++j) {
+
+ u32 r1 = orig ^ (orig + j), r2 = orig ^ (orig - j),
+ r3 = orig ^ SWAP32(SWAP32(orig) + j),
+ r4 = orig ^ SWAP32(SWAP32(orig) - j);
+
+ /* Little endian first. Same deal as with 16-bit: we only want to
+ try if the operation would have effect on more than two bytes. */
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ if ((orig & 0xffff) + j > 0xffff && !could_be_bitflip(r1)) {
+
+ afl->stage_cur_val = j;
+ *(u32 *)(out_buf + i) = orig + j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH32+-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((orig & 0xffff) < (u32)j && !could_be_bitflip(r2)) {
+
+ afl->stage_cur_val = -j;
+ *(u32 *)(out_buf + i) = orig - j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH32_-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ /* Big endian next. */
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+ if ((SWAP32(orig) & 0xffff) + j > 0xffff && !could_be_bitflip(r3)) {
+
+ afl->stage_cur_val = j;
+ *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) + j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH32+BE-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((SWAP32(orig) & 0xffff) < (u32)j && !could_be_bitflip(r4)) {
+
+ afl->stage_cur_val = -j;
+ *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) - j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s ARITH32_BE-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ *(u32 *)(out_buf + i) = orig;
+
+ }
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_ARITH32] += afl->stage_max;
+
+skip_arith:
+
+ /**********************
+ * INTERESTING VALUES *
+ **********************/
+
+ afl->stage_name = "interest 8/8";
+ afl->stage_short = "int8";
+ afl->stage_cur = 0;
+ afl->stage_max = len * sizeof(interesting_8);
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ /* Setting 8-bit integers. */
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u8 orig = out_buf[i];
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)]) {
+
+ afl->stage_max -= sizeof(interesting_8);
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < (u32)sizeof(interesting_8); ++j) {
+
+ /* Skip if the value could be a product of bitflips or arithmetics. */
+
+ if (could_be_bitflip(orig ^ (u8)interesting_8[j]) ||
+ could_be_arith(orig, (u8)interesting_8[j], 1)) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ afl->stage_cur_val = interesting_8[j];
+ out_buf[i] = interesting_8[j];
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s INTERESTING8_%u_%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ out_buf[i] = orig;
+ ++afl->stage_cur;
+
+ }
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max;
+
+ /* Setting 16-bit integers, both endians. */
+
+ if (afl->no_arith || len < 2) { goto skip_interest; }
+
+ afl->stage_name = "interest 16/8";
+ afl->stage_short = "int16";
+ afl->stage_cur = 0;
+ afl->stage_max = 2 * (len - 1) * (sizeof(interesting_16) >> 1);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 1; ++i) {
+
+ u16 orig = *(u16 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
+
+ afl->stage_max -= sizeof(interesting_16);
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < sizeof(interesting_16) / 2; ++j) {
+
+ afl->stage_cur_val = interesting_16[j];
+
+ /* Skip if this could be a product of a bitflip, arithmetics,
+ or single-byte interesting value insertion. */
+
+ if (!could_be_bitflip(orig ^ (u16)interesting_16[j]) &&
+ !could_be_arith(orig, (u16)interesting_16[j], 2) &&
+ !could_be_interest(orig, (u16)interesting_16[j], 2, 0)) {
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ *(u16 *)(out_buf + i) = interesting_16[j];
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s INTERESTING16_%u_%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) &&
+ !could_be_bitflip(orig ^ SWAP16(interesting_16[j])) &&
+ !could_be_arith(orig, SWAP16(interesting_16[j]), 2) &&
+ !could_be_interest(orig, SWAP16(interesting_16[j]), 2, 1)) {
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s INTERESTING16BE_%u_%u", afl->queue_cur->fname, i, j);
+#endif
+
+ *(u16 *)(out_buf + i) = SWAP16(interesting_16[j]);
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ }
+
+ *(u16 *)(out_buf + i) = orig;
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max;
+
+ if (len < 4) { goto skip_interest; }
+
+ /* Setting 32-bit integers, both endians. */
+
+ afl->stage_name = "interest 32/8";
+ afl->stage_short = "int32";
+ afl->stage_cur = 0;
+ afl->stage_max = 2 * (len - 3) * (sizeof(interesting_32) >> 2);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 3; i++) {
+
+ u32 orig = *(u32 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
+ !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
+
+ afl->stage_max -= sizeof(interesting_32) >> 1;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < sizeof(interesting_32) / 4; ++j) {
+
+ afl->stage_cur_val = interesting_32[j];
+
+ /* Skip if this could be a product of a bitflip, arithmetics,
+ or word interesting value insertion. */
+
+ if (!could_be_bitflip(orig ^ (u32)interesting_32[j]) &&
+ !could_be_arith(orig, interesting_32[j], 4) &&
+ !could_be_interest(orig, interesting_32[j], 4, 0)) {
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ *(u32 *)(out_buf + i) = interesting_32[j];
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s INTERESTING32_%u_%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) &&
+ !could_be_bitflip(orig ^ SWAP32(interesting_32[j])) &&
+ !could_be_arith(orig, SWAP32(interesting_32[j]), 4) &&
+ !could_be_interest(orig, SWAP32(interesting_32[j]), 4, 1)) {
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s INTERESTING32BE_%u_%u", afl->queue_cur->fname, i, j);
+#endif
+
+ *(u32 *)(out_buf + i) = SWAP32(interesting_32[j]);
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ }
+
+ *(u32 *)(out_buf + i) = orig;
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max;
+
+skip_interest:
+
+ /********************
+ * DICTIONARY STUFF *
+ ********************/
+
+ if (!afl->extras_cnt) { goto skip_user_extras; }
+
+ /* Overwrite with user-supplied extras. */
+
+ afl->stage_name = "user extras (over)";
+ afl->stage_short = "ext_UO";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->extras_cnt * len;
+
+ afl->stage_val_type = STAGE_VAL_NONE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u32 last_len = 0;
+
+ afl->stage_cur_byte = i;
+
+ /* Extras are sorted by size, from smallest to largest. This means
+ that we don't have to worry about restoring the buffer in
+ between writes at a particular offset determined by the outer
+ loop. */
+
+ for (j = 0; j < afl->extras_cnt; ++j) {
+
+ /* Skip extras probabilistically if afl->extras_cnt > AFL_MAX_DET_EXTRAS.
+ Also skip them if there's no room to insert the payload, if the token
+ is redundant, or if its entire span has no bytes set in the effector
+ map. */
+
+ if ((afl->extras_cnt > afl->max_det_extras &&
+ rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) ||
+ afl->extras[j].len > len - i ||
+ !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
+ !memchr(eff_map + EFF_APOS(i), 1,
+ EFF_SPAN_ALEN(i, afl->extras[j].len))) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ last_len = afl->extras[j].len;
+ memcpy(out_buf + i, afl->extras[j].data, last_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s EXTRAS_overwrite-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Restore all the clobbered memory. */
+ memcpy(out_buf + i, in_buf + i, last_len);
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max;
+
+ /* Insertion of user-supplied extras. */
+
+ afl->stage_name = "user extras (insert)";
+ afl->stage_short = "ext_UI";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->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->extras_cnt; ++j) {
+
+ if (len + afl->extras[j].len > MAX_FILE) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ /* Insert token */
+ memcpy(ex_tmp + i, afl->extras[j].data, afl->extras[j].len);
+
+ /* Copy tail */
+ memcpy(ex_tmp + i + afl->extras[j].len, out_buf + i, len - i);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s EXTRAS_insert-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, ex_tmp, len + afl->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_UI] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max;
+
+skip_user_extras:
+
+ if (!afl->a_extras_cnt) { goto skip_extras; }
+
+ afl->stage_name = "auto extras (over)";
+ afl->stage_short = "ext_AO";
+ afl->stage_cur = 0;
+ afl->stage_max = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS) * len;
+
+ afl->stage_val_type = STAGE_VAL_NONE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u32 last_len = 0;
+
+ afl->stage_cur_byte = i;
+
+ u32 min_extra_len = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS);
+ for (j = 0; j < min_extra_len; ++j) {
+
+ /* See the comment in the earlier code; extras are sorted by size. */
+
+ if (afl->a_extras[j].len > len - i ||
+ !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len) ||
+ !memchr(eff_map + EFF_APOS(i), 1,
+ EFF_SPAN_ALEN(i, afl->a_extras[j].len))) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ last_len = afl->a_extras[j].len;
+ memcpy(out_buf + i, afl->a_extras[j].data, last_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s AUTO_EXTRAS_overwrite-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Restore all the clobbered memory. */
+ memcpy(out_buf + i, in_buf + i, last_len);
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ 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,
+ we're properly done with deterministic steps and can mark it as such
+ in the .state/ directory. */
+
+ if (!afl->queue_cur->passed_det) { mark_as_det_done(afl, afl->queue_cur); }
+
+custom_mutator_stage:
+ /*******************
+ * CUSTOM MUTATORS *
+ *******************/
+
+ if (likely(!afl->custom_mutators_count)) { goto havoc_stage; }
+
+ afl->stage_name = "custom mutator";
+ afl->stage_short = "custom";
+ afl->stage_max = HAVOC_CYCLES * perf_score / afl->havoc_div / 100;
+ afl->stage_val_type = STAGE_VAL_NONE;
+ bool has_custom_fuzz = false;
+
+ if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
+
+ const u32 max_seed_size = MAX_FILE, saved_max = afl->stage_max;
+
+ orig_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+#ifdef INTROSPECTION
+ afl->mutation[0] = 0;
+#endif
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz) {
+
+ afl->current_custom_fuzz = el;
+
+ if (el->afl_custom_fuzz_count) {
+
+ afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
+
+ } else {
+
+ afl->stage_max = saved_max;
+
+ }
+
+ has_custom_fuzz = true;
+
+ afl->stage_short = el->name_short;
+
+ if (afl->stage_max) {
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
+ ++afl->stage_cur) {
+
+ struct queue_entry *target = NULL;
+ u32 tid;
+ u8 * new_buf = NULL;
+ u32 target_len = 0;
+
+ /* check if splicing makes sense yet (enough entries) */
+ if (likely(afl->ready_for_splicing_count > 1)) {
+
+ /* Pick a random other queue entry for passing to external API
+ that has the necessary length */
+
+ do {
+
+ tid = rand_below(afl, afl->queued_items);
+
+ } while (unlikely(tid == afl->current_entry ||
+
+ afl->queue_buf[tid]->len < 4));
+
+ target = afl->queue_buf[tid];
+ afl->splicing_with = tid;
+
+ /* Read the additional testcase into a new buffer. */
+ new_buf = queue_testcase_get(afl, target);
+ target_len = target->len;
+
+ }
+
+ u8 *mutated_buf = NULL;
+
+ size_t mutated_size =
+ el->afl_custom_fuzz(el->data, out_buf, len, &mutated_buf, new_buf,
+ target_len, max_seed_size);
+
+ if (unlikely(!mutated_buf)) {
+
+ FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size);
+
+ }
+
+ if (mutated_size > 0) {
+
+ if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
+
+ goto abandon_entry;
+
+ }
+
+ if (!el->afl_custom_fuzz_count) {
+
+ /* If we're finding new stuff, let's run for a bit longer, limits
+ permitting. */
+
+ if (afl->queued_items != havoc_queued) {
+
+ if (perf_score <= afl->havoc_max_mult * 100) {
+
+ afl->stage_max *= 2;
+ perf_score *= 2;
+
+ }
+
+ havoc_queued = afl->queued_items;
+
+ }
+
+ }
+
+ }
+
+ /* out_buf may have been changed by the call to custom_fuzz */
+ memcpy(out_buf, in_buf, len);
+
+ }
+
+ }
+
+ }
+
+ });
+
+ afl->current_custom_fuzz = NULL;
+
+ if (!has_custom_fuzz) goto havoc_stage;
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max;
+
+ if (likely(afl->custom_only)) {
+
+ /* Skip other stages */
+ ret_val = 0;
+ goto abandon_entry;
+
+ }
+
+ /****************
+ * RANDOM HAVOC *
+ ****************/
+
+havoc_stage:
+
+ afl->stage_cur_byte = -1;
+
+ /* The havoc stage mutation code is also invoked when splicing files; if the
+ splice_cycle variable is set, generate different descriptions and such. */
+
+ if (!splice_cycle) {
+
+ afl->stage_name = "havoc";
+ afl->stage_short = "havoc";
+ afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
+ perf_score / afl->havoc_div / 100;
+
+ } else {
+
+ perf_score = orig_perf;
+
+ snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle);
+ afl->stage_name = afl->stage_name_buf;
+ afl->stage_short = "splice";
+ afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
+
+ }
+
+ if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
+
+ temp_len = len;
+
+ orig_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ havoc_queued = afl->queued_items;
+
+ if (afl->custom_mutators_count) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->stacked_custom && el->afl_custom_havoc_mutation_probability) {
+
+ el->stacked_custom_prob =
+ el->afl_custom_havoc_mutation_probability(el->data);
+ if (el->stacked_custom_prob > 100) {
+
+ FATAL(
+ "The probability returned by "
+ "afl_custom_havoc_mutation_propability "
+ "has to be in the range 0-100.");
+
+ }
+
+ }
+
+ });
+
+ }
+
+ /* We essentially just do several thousand runs (depending on perf_score)
+ where we take the input file and make random stacked tweaks. */
+
+#define MAX_HAVOC_ENTRY 64
+#define MUTATE_ASCII_DICT 64
+
+ u32 r_max, r;
+
+ r_max = (MAX_HAVOC_ENTRY + 1) + (afl->extras_cnt ? 4 : 0) +
+ (afl->a_extras_cnt
+ ? (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)
+ ? MUTATE_ASCII_DICT
+ : 4)
+ : 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 */
+
+ r_max += 4;
+
+ }
+
+ if (unlikely(get_cur_time() - afl->last_find_time > 5000 /* 5 seconds */ &&
+ afl->ready_for_splicing_count > 1)) {
+
+ /* add expensive havoc cases here if there is no findings in the last 5s */
+
+ r_max += 4;
+
+ }
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ u32 use_stacking = 1 << (1 + rand_below(afl, afl->havoc_stack_pow2));
+
+ afl->stage_cur_val = use_stacking;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s HAVOC-%u",
+ afl->queue_cur->fname, use_stacking);
+#endif
+
+ for (i = 0; i < use_stacking; ++i) {
+
+ if (afl->custom_mutators_count) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->stacked_custom &&
+ rand_below(afl, 100) < el->stacked_custom_prob) {
+
+ u8 * custom_havoc_buf = NULL;
+ size_t new_len = el->afl_custom_havoc_mutation(
+ el->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
+ if (unlikely(!custom_havoc_buf)) {
+
+ FATAL("Error in custom_havoc (return %zu)", new_len);
+
+ }
+
+ if (likely(new_len > 0 && custom_havoc_buf)) {
+
+ temp_len = new_len;
+ if (out_buf != custom_havoc_buf) {
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len);
+ if (unlikely(!afl->out_buf)) { PFATAL("alloc"); }
+ memcpy(out_buf, custom_havoc_buf, temp_len);
+
+ }
+
+ }
+
+ }
+
+ });
+
+ }
+
+ switch ((r = rand_below(afl, r_max))) {
+
+ case 0 ... 3: {
+
+ /* Flip a single bit somewhere. Spooky! */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT1");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
+ break;
+
+ }
+
+ case 4 ... 7: {
+
+ /* Set byte to interesting value. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING8");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)] =
+ interesting_8[rand_below(afl, sizeof(interesting_8))];
+ break;
+
+ }
+
+ case 8 ... 9: {
+
+ /* Set word to interesting value, little endian. */
+
+ if (temp_len < 2) { break; }
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+ interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
+
+ break;
+
+ }
+
+ case 10 ... 11: {
+
+ /* Set word to interesting value, big endian. */
+
+ if (temp_len < 2) { break; }
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
+ interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
+
+ break;
+
+ }
+
+ case 12 ... 13: {
+
+ /* Set dword to interesting value, little endian. */
+
+ if (temp_len < 4) { break; }
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+ interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
+
+ break;
+
+ }
+
+ case 14 ... 15: {
+
+ /* Set dword to interesting value, big endian. */
+
+ if (temp_len < 4) { break; }
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
+ interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
+
+ break;
+
+ }
+
+ case 16 ... 19: {
+
+ /* Randomly subtract from byte. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8_");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
+ break;
+
+ }
+
+ case 20 ... 23: {
+
+ /* Randomly add to byte. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8+");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
+ break;
+
+ }
+
+ case 24 ... 25: {
+
+ /* Randomly subtract from word, little endian. */
+
+ if (temp_len < 2) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+
+ break;
+
+ }
+
+ case 26 ... 27: {
+
+ /* Randomly subtract from word, big endian. */
+
+ if (temp_len < 2) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ u16 num = 1 + rand_below(afl, ARITH_MAX);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16_BE-%u_%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) =
+ SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
+
+ break;
+
+ }
+
+ case 28 ... 29: {
+
+ /* Randomly add to word, little endian. */
+
+ if (temp_len < 2) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+
+ break;
+
+ }
+
+ case 30 ... 31: {
+
+ /* Randomly add to word, big endian. */
+
+ if (temp_len < 2) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ u16 num = 1 + rand_below(afl, ARITH_MAX);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+BE-%u_%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) =
+ SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
+
+ break;
+
+ }
+
+ case 32 ... 33: {
+
+ /* Randomly subtract from dword, little endian. */
+
+ if (temp_len < 4) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 3);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+
+ break;
+
+ }
+
+ case 34 ... 35: {
+
+ /* Randomly subtract from dword, big endian. */
+
+ if (temp_len < 4) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 3);
+ u32 num = 1 + rand_below(afl, ARITH_MAX);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_BE-%u-%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) =
+ SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
+
+ break;
+
+ }
+
+ case 36 ... 37: {
+
+ /* Randomly add to dword, little endian. */
+
+ if (temp_len < 4) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 3);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+
+ break;
+
+ }
+
+ case 38 ... 39: {
+
+ /* Randomly add to dword, big endian. */
+
+ if (temp_len < 4) { break; }
+
+ u32 pos = rand_below(afl, temp_len - 3);
+ u32 num = 1 + rand_below(afl, ARITH_MAX);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+BE-%u-%u", pos,
+ num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) =
+ SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
+
+ break;
+
+ }
+
+ case 40 ... 43: {
+
+ /* Just set a random byte to a random value. Because,
+ why not. We use XOR with 1-255 to eliminate the
+ possibility of a no-op. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " RAND8");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
+ break;
+
+ }
+
+ case 44 ... 46: {
+
+ if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+
+ /* Clone bytes. */
+
+ u32 clone_len = choose_block_len(afl, temp_len);
+ u32 clone_from = rand_below(afl, temp_len - clone_len + 1);
+ u32 clone_to = rand_below(afl, temp_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u-%u",
+ "clone", clone_from, clone_to, clone_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ u8 *new_buf =
+ afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+
+ /* Head */
+
+ memcpy(new_buf, out_buf, clone_to);
+
+ /* Inserted part */
+
+ memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
+
+ /* Tail */
+ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
+
+ out_buf = new_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
+
+ }
+
+ break;
+
+ }
+
+ case 47: {
+
+ if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+
+ /* Insert a block of constant bytes (25%). */
+
+ u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL);
+ u32 clone_to = rand_below(afl, temp_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE-%s-%u-%u",
+ "insert", clone_to, clone_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ u8 *new_buf =
+ afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+
+ /* Head */
+
+ memcpy(new_buf, out_buf, clone_to);
+
+ /* Inserted part */
+
+ memset(new_buf + clone_to,
+ rand_below(afl, 2) ? rand_below(afl, 256)
+ : out_buf[rand_below(afl, temp_len)],
+ clone_len);
+
+ /* Tail */
+ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
+
+ out_buf = new_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
+
+ }
+
+ break;
+
+ }
+
+ case 48 ... 50: {
+
+ /* Overwrite bytes with a randomly selected chunk bytes. */
+
+ if (temp_len < 2) { break; }
+
+ u32 copy_len = choose_block_len(afl, temp_len - 1);
+ u32 copy_from = rand_below(afl, temp_len - copy_len + 1);
+ u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
+
+ if (likely(copy_from != copy_to)) {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_COPY-%u-%u-%u",
+ copy_from, copy_to, copy_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+
+ }
+
+ break;
+
+ }
+
+ case 51: {
+
+ /* Overwrite bytes with fixed bytes. */
+
+ if (temp_len < 2) { break; }
+
+ u32 copy_len = choose_block_len(afl, temp_len - 1);
+ u32 copy_to = rand_below(afl, temp_len - copy_len + 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " OVERWRITE_FIXED-%u-%u",
+ copy_to, copy_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memset(out_buf + copy_to,
+ rand_below(afl, 2) ? rand_below(afl, 256)
+ : out_buf[rand_below(afl, temp_len)],
+ copy_len);
+
+ break;
+
+ }
+
+ case 52: {
+
+ /* Increase byte by 1. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ADDBYTE_");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)]++;
+ break;
+
+ }
+
+ case 53: {
+
+ /* Decrease byte by 1. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SUBBYTE_");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)]++;
+ break;
+
+ }
+
+ case 54: {
+
+ /* Flip byte. */
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP8_");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ out_buf[rand_below(afl, temp_len)] ^= 0xff;
+ break;
+
+ }
+
+ case 55 ... 56: {
+
+ if (temp_len < 4) { break; }
+
+ /* Switch bytes. */
+
+ u32 to_end, switch_to, switch_len, switch_from;
+ switch_from = rand_below(afl, temp_len);
+ do {
+
+ switch_to = rand_below(afl, temp_len);
+
+ } while (switch_from == switch_to);
+
+ if (switch_from < switch_to) {
+
+ switch_len = switch_to - switch_from;
+ to_end = temp_len - switch_to;
+
+ } else {
+
+ switch_len = switch_from - switch_to;
+ to_end = temp_len - switch_from;
+
+ }
+
+ switch_len = choose_block_len(afl, MIN(switch_len, to_end));
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SWITCH-%s-%u-%u-%u",
+ "switch", switch_from, switch_to, switch_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), switch_len);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+
+ /* Backup */
+
+ memcpy(new_buf, out_buf + switch_from, switch_len);
+
+ /* Switch 1 */
+
+ memcpy(out_buf + switch_from, out_buf + switch_to, switch_len);
+
+ /* Switch 2 */
+
+ memcpy(out_buf + switch_to, new_buf, switch_len);
+
+ break;
+
+ }
+
+ // MAX_HAVOC_ENTRY = 64
+ case 57 ... MAX_HAVOC_ENTRY: {
+
+ /* Delete bytes. */
+
+ if (temp_len < 2) { break; }
+
+ /* Don't delete too much. */
+
+ u32 del_len = choose_block_len(afl, temp_len - 1);
+ u32 del_from = rand_below(afl, temp_len - del_len + 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u-%u", del_from,
+ del_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + del_from, out_buf + del_from + del_len,
+ temp_len - del_from - del_len);
+
+ temp_len -= del_len;
+
+ break;
+
+ }
+
+ default:
+
+ r -= (MAX_HAVOC_ENTRY + 1);
+
+ if (afl->extras_cnt) {
+
+ if (r < 2) {
+
+ /* Use the dictionary. */
+
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
+
+ if (extra_len > temp_len) { break; }
+
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_OVERWRITE-%u-%u",
+ insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memcpy(out_buf + insert_at, afl->extras[use_extra].data,
+ extra_len);
+
+ break;
+
+ } else if (r < 4) {
+
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
+ if (temp_len + extra_len >= MAX_FILE) { break; }
+
+ u8 *ptr = afl->extras[use_extra].data;
+ u32 insert_at = rand_below(afl, temp_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
+ insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
+
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
+ temp_len += extra_len;
+
+ break;
+
+ } else {
+
+ r -= 4;
+
+ }
+
+ }
+
+ if (afl->a_extras_cnt) {
+
+ u32 r_cmp = 2;
+
+ if (unlikely(afl->cmplog_binary && afl->queue_cur->is_ascii)) {
+
+ r_cmp = MUTATE_ASCII_DICT >> 1;
+
+ }
+
+ if (r < r_cmp) {
+
+ /* Use the dictionary. */
+
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
+
+ if (extra_len > temp_len) { break; }
+
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+ extra_len);
+
+ break;
+
+ } else if (r < (r_cmp << 1)) {
+
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
+ if (temp_len + extra_len >= MAX_FILE) { break; }
+
+ u8 *ptr = afl->a_extras[use_extra].data;
+ u32 insert_at = rand_below(afl, temp_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
+
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
+ temp_len += extra_len;
+
+ break;
+
+ } else {
+
+ r -= (r_cmp << 1);
+
+ }
+
+ }
+
+ /* Splicing otherwise if we are still here.
+ Overwrite bytes with a randomly selected chunk from another
+ testcase or insert that chunk. */
+
+ /* Pick a random queue entry and seek to it. */
+
+ u32 tid;
+ do {
+
+ tid = rand_below(afl, afl->queued_items);
+
+ } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+
+ /* Get the testcase for splicing. */
+ struct queue_entry *target = afl->queue_buf[tid];
+ u32 new_len = target->len;
+ u8 * new_buf = queue_testcase_get(afl, target);
+
+ if ((temp_len >= 2 && r % 2) || temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+
+ /* overwrite mode */
+
+ 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);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
+ copy_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+
+ } else {
+
+ /* insert mode */
+
+ 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 + 1);
+
+ u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+ temp_len + clone_len + 1);
+ if (unlikely(!temp_buf)) { PFATAL("alloc"); }
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
+ clone_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ /* 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);
+
+ out_buf = temp_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
+
+ }
+
+ break;
+
+ // end of default
+
+ }
+
+ }
+
+ if (common_fuzz_stuff(afl, out_buf, temp_len)) { goto abandon_entry; }
+
+ /* out_buf might have been mangled a bit, so let's restore it to its
+ original size and shape. */
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ temp_len = len;
+ memcpy(out_buf, in_buf, len);
+
+ /* If we're finding new stuff, let's run for a bit longer, limits
+ permitting. */
+
+ if (afl->queued_items != havoc_queued) {
+
+ if (perf_score <= afl->havoc_max_mult * 100) {
+
+ afl->stage_max *= 2;
+ perf_score *= 2;
+
+ }
+
+ havoc_queued = afl->queued_items;
+
+ }
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ if (!splice_cycle) {
+
+ afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_HAVOC] += afl->stage_max;
+
+ } else {
+
+ afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_SPLICE] += afl->stage_max;
+
+ }
+
+#ifndef IGNORE_FINDS
+
+ /************
+ * SPLICING *
+ ************/
+
+ /* This is a last-resort strategy triggered by a full round with no findings.
+ It takes the current input file, randomly selects another input, and
+ splices them together at some offset, then relies on the havoc
+ code to mutate that blob. */
+
+retry_splicing:
+
+ if (afl->use_splicing && splice_cycle++ < SPLICE_CYCLES &&
+ afl->ready_for_splicing_count > 1 && afl->queue_cur->len >= 4) {
+
+ struct queue_entry *target;
+ u32 tid, split_at;
+ u8 * new_buf;
+ s32 f_diff, l_diff;
+
+ /* First of all, if we've modified in_buf for havoc, let's clean that
+ up... */
+
+ if (in_buf != orig_in) {
+
+ in_buf = orig_in;
+ len = afl->queue_cur->len;
+
+ }
+
+ /* Pick a random queue entry and seek to it. Don't splice with yourself. */
+
+ do {
+
+ tid = rand_below(afl, afl->queued_items);
+
+ } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+
+ /* Get the testcase */
+ afl->splicing_with = tid;
+ target = afl->queue_buf[tid];
+ new_buf = queue_testcase_get(afl, target);
+
+ /* Find a suitable splicing location, somewhere between the first and
+ the last differing byte. Bail out if the difference is just a single
+ byte or so. */
+
+ locate_diffs(in_buf, new_buf, MIN(len, (s64)target->len), &f_diff, &l_diff);
+
+ if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; }
+
+ /* Split somewhere between the first and last differing byte. */
+
+ split_at = f_diff + rand_below(afl, l_diff - f_diff);
+
+ /* Do the thing. */
+
+ len = target->len;
+ afl->in_scratch_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), len);
+ memcpy(afl->in_scratch_buf, in_buf, split_at);
+ memcpy(afl->in_scratch_buf + split_at, new_buf, len - split_at);
+ in_buf = afl->in_scratch_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(in), AFL_BUF_PARAM(in_scratch));
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ memcpy(out_buf, in_buf, len);
+
+ goto custom_mutator_stage;
+
+ }
+
+#endif /* !IGNORE_FINDS */
+
+ ret_val = 0;
+
+/* we are through with this queue entry - for this iteration */
+abandon_entry:
+
+ afl->splicing_with = -1;
+
+ /* Update afl->pending_not_fuzzed count if we made it through the calibration
+ cycle and have not seen this entry before. */
+
+ if (!afl->stop_soon && !afl->queue_cur->cal_failed &&
+ !afl->queue_cur->was_fuzzed && !afl->queue_cur->disabled) {
+
+ --afl->pending_not_fuzzed;
+ afl->queue_cur->was_fuzzed = 1;
+ afl->reinit_table = 1;
+ if (afl->queue_cur->favored) { --afl->pending_favored; }
+
+ }
+
+ ++afl->queue_cur->fuzz_level;
+ orig_in = NULL;
+ return ret_val;
+
+#undef FLIP_BIT
+
+}
+
+/* MOpt mode */
+static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
+
+ if (!MOpt_globals.is_pilot_mode) {
+
+ if (swarm_num == 1) {
+
+ afl->key_module = 2;
+ return 0;
+
+ }
+
+ }
+
+ u32 len, temp_len;
+ u32 i;
+ u32 j;
+ u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
+ u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, cur_ms_lv, prev_cksum,
+ _prev_cksum;
+ u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1;
+
+ u8 ret_val = 1, doing_det = 0;
+
+ u8 a_collect[MAX_AUTO_EXTRA];
+ u32 a_len = 0;
+
+#ifdef IGNORE_FINDS
+
+ /* In IGNORE_FINDS mode, skip any entries that weren't in the
+ initial data set. */
+
+ if (afl->queue_cur->depth > 1) return 1;
+
+#else
+
+ if (likely(afl->pending_favored)) {
+
+ /* If we have any favored, non-fuzzed new arrivals in the queue,
+ possibly skip to them at the expense of already-fuzzed or non-favored
+ cases. */
+
+ if ((afl->queue_cur->fuzz_level || !afl->queue_cur->favored) &&
+ rand_below(afl, 100) < SKIP_TO_NEW_PROB) {
+
+ return 1;
+
+ }
+
+ } else if (!afl->non_instrumented_mode && !afl->queue_cur->favored &&
+
+ afl->queued_items > 10) {
+
+ /* Otherwise, still possibly skip non-favored cases, albeit less often.
+ The odds of skipping stuff are higher for already-fuzzed inputs and
+ lower for never-fuzzed entries. */
+
+ if (afl->queue_cycle > 1 && !afl->queue_cur->fuzz_level) {
+
+ if (likely(rand_below(afl, 100) < SKIP_NFAV_NEW_PROB)) { return 1; }
+
+ } else {
+
+ if (likely(rand_below(afl, 100) < SKIP_NFAV_OLD_PROB)) { return 1; }
+
+ }
+
+ }
+
+#endif /* ^IGNORE_FINDS */
+
+ if (afl->not_on_tty) {
+
+ ACTF("Fuzzing test case #%u (%u total, %llu crashes saved)...",
+ afl->current_entry, afl->queued_items, afl->saved_crashes);
+ fflush(stdout);
+
+ }
+
+ /* Map the test case into memory. */
+ orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
+ len = afl->queue_cur->len;
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+ afl->subseq_tmouts = 0;
+
+ afl->cur_depth = afl->queue_cur->depth;
+
+ /*******************************************
+ * CALIBRATION (only if failed earlier on) *
+ *******************************************/
+
+ if (unlikely(afl->queue_cur->cal_failed)) {
+
+ u8 res = FSRV_RUN_TMOUT;
+
+ if (afl->queue_cur->cal_failed < CAL_CHANCES) {
+
+ afl->queue_cur->exec_cksum = 0;
+
+ res =
+ calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
+
+ if (res == FSRV_RUN_ERROR) {
+
+ FATAL("Unable to execute target application");
+
+ }
+
+ }
+
+ if (afl->stop_soon || res != afl->crash_mode) {
+
+ ++afl->cur_skipped_items;
+ goto abandon_entry;
+
+ }
+
+ }
+
+ /************
+ * TRIMMING *
+ ************/
+
+ if (unlikely(!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
+ !afl->disable_trim)) {
+
+ u32 old_len = afl->queue_cur->len;
+
+ u8 res = trim_case(afl, afl->queue_cur, in_buf);
+ orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
+
+ if (unlikely(res == FSRV_RUN_ERROR)) {
+
+ FATAL("Unable to execute target application");
+
+ }
+
+ if (unlikely(afl->stop_soon)) {
+
+ ++afl->cur_skipped_items;
+ goto abandon_entry;
+
+ }
+
+ /* Don't retry trimming, even if it failed. */
+
+ afl->queue_cur->trim_done = 1;
+
+ len = afl->queue_cur->len;
+
+ /* maybe current entry is not ready for splicing anymore */
+ if (unlikely(len <= 4 && old_len > 4)) --afl->ready_for_splicing_count;
+
+ }
+
+ memcpy(out_buf, in_buf, len);
+
+ /*********************
+ * PERFORMANCE SCORE *
+ *********************/
+
+ if (likely(!afl->old_seed_selection))
+ orig_perf = perf_score = afl->queue_cur->perf_score;
+ else
+ orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
+
+ if (unlikely(perf_score <= 0 && afl->active_items > 1)) {
+
+ goto abandon_entry;
+
+ }
+
+ if (unlikely(afl->shm.cmplog_mode &&
+ afl->queue_cur->colorized < afl->cmplog_lvl &&
+ (u32)len <= afl->cmplog_max_filesize)) {
+
+ if (unlikely(len < 4)) {
+
+ afl->queue_cur->colorized = CMPLOG_LVL_MAX;
+
+ } else {
+
+ if (afl->cmplog_lvl == 3 ||
+ (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) ||
+ !(afl->fsrv.total_execs % afl->queued_items) ||
+ get_cur_time() - afl->last_find_time > 300000) { // 300 seconds
+
+ if (input_to_state_stage(afl, in_buf, out_buf, len)) {
+
+ goto abandon_entry;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ /* Go to pacemker fuzzing if MOpt is doing well */
+
+ cur_ms_lv = get_cur_time();
+ if (!(afl->key_puppet == 0 &&
+ ((cur_ms_lv - afl->last_find_time < (u32)afl->limit_time_puppet) ||
+ (afl->last_crash_time != 0 &&
+ cur_ms_lv - afl->last_crash_time < (u32)afl->limit_time_puppet) ||
+ afl->last_find_time == 0))) {
+
+ afl->key_puppet = 1;
+ goto pacemaker_fuzzing;
+
+ }
+
+ /* Skip right away if -d is given, if we have done deterministic fuzzing on
+ this entry ourselves (was_fuzzed), or if it has gone through deterministic
+ testing in earlier, resumed runs (passed_det). */
+
+ if (likely(afl->skip_deterministic || afl->queue_cur->was_fuzzed ||
+ afl->queue_cur->passed_det)) {
+
+ goto havoc_stage;
+
+ }
+
+ /* Skip deterministic fuzzing if exec path checksum puts this out of scope
+ for this main instance. */
+
+ if (unlikely(afl->main_node_max &&
+ (afl->queue_cur->exec_cksum % afl->main_node_max) !=
+ afl->main_node_id - 1)) {
+
+ goto havoc_stage;
+
+ }
+
+ doing_det = 1;
+
+ /*********************************************
+ * SIMPLE BITFLIP (+dictionary construction) *
+ *********************************************/
+
+#define FLIP_BIT(_ar, _b) \
+ do { \
+ \
+ u8 *_arf = (u8 *)(_ar); \
+ u32 _bf = (_b); \
+ _arf[(_bf) >> 3] ^= (128 >> ((_bf)&7)); \
+ \
+ } while (0)
+
+ /* Single walking bit. */
+
+ afl->stage_short = "flip1";
+ afl->stage_max = len << 3;
+ afl->stage_name = "bitflip 1/1";
+
+ afl->stage_val_type = STAGE_VAL_NONE;
+
+ orig_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ /* Get a clean cksum. */
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+ _prev_cksum = prev_cksum;
+
+ /* Now flip bits. */
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur >> 3;
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_FLIP_BIT1-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+
+ /* While flipping the least significant bit in every byte, pull of an extra
+ trick to detect possible syntax tokens. In essence, the idea is that if
+ you have a binary blob like this:
+
+ xxxxxxxxIHDRxxxxxxxx
+
+ ...and changing the leading and trailing bytes causes variable or no
+ changes in program flow, but touching any character in the "IHDR" string
+ always produces the same, distinctive path, it's highly likely that
+ "IHDR" is an atomically-checked magic value of special significance to
+ the fuzzed format.
+
+ We do this here, rather than as a separate stage, because it's a nice
+ way to keep the operation approximately "free" (i.e., no extra execs).
+
+ Empirically, performing the check when flipping the least significant bit
+ is advantageous, compared to doing it at the time of more disruptive
+ changes, where the program flow may be affected in more violent ways.
+
+ The caveat is that we won't generate dictionaries in the -d mode or -S
+ mode - but that's probably a fair trade-off.
+
+ This won't work particularly well with paths that exhibit variable
+ behavior, but fails gracefully, so we'll carry out the checks anyway.
+
+ */
+
+ if (!afl->non_instrumented_mode && (afl->stage_cur & 7) == 7) {
+
+ u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
+ if (afl->stage_cur == afl->stage_max - 1 && cksum == prev_cksum) {
+
+ /* If at end of file and we are still collecting a string, grab the
+ final character and force output. */
+
+ if (a_len < MAX_AUTO_EXTRA) {
+
+ a_collect[a_len] = out_buf[afl->stage_cur >> 3];
+
+ }
+
+ ++a_len;
+
+ if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
+
+ maybe_add_auto(afl, a_collect, a_len);
+
+ }
+
+ } else if (cksum != prev_cksum) {
+
+ /* Otherwise, if the checksum has changed, see if we have something
+ worthwhile queued up, and collect that if the answer is yes. */
+
+ if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) {
+
+ maybe_add_auto(afl, a_collect, a_len);
+
+ }
+
+ a_len = 0;
+ prev_cksum = cksum;
+
+ }
+
+ /* Continue collecting string, but only if the bit flip actually made
+ any difference - we don't want no-op tokens. */
+
+ if (cksum != _prev_cksum) {
+
+ if (a_len < MAX_AUTO_EXTRA) {
+
+ a_collect[a_len] = out_buf[afl->stage_cur >> 3];
+
+ }
+
+ ++a_len;
+
+ }
+
+ } /* if (afl->stage_cur & 7) == 7 */
+
+ } /* for afl->stage_cur */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP1] += afl->stage_max;
+
+ /* Two walking bits. */
+
+ afl->stage_name = "bitflip 2/1";
+ afl->stage_short = "flip2";
+ afl->stage_max = (len << 3) - 1;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur >> 3;
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_FLIP_BIT2-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+
+ } /* for afl->stage_cur */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP2] += afl->stage_max;
+
+ /* Four walking bits. */
+
+ afl->stage_name = "bitflip 4/1";
+ afl->stage_short = "flip4";
+ afl->stage_max = (len << 3) - 3;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur >> 3;
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+ FLIP_BIT(out_buf, afl->stage_cur + 2);
+ FLIP_BIT(out_buf, afl->stage_cur + 3);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_FLIP_BIT4-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ FLIP_BIT(out_buf, afl->stage_cur);
+ FLIP_BIT(out_buf, afl->stage_cur + 1);
+ FLIP_BIT(out_buf, afl->stage_cur + 2);
+ FLIP_BIT(out_buf, afl->stage_cur + 3);
+
+ } /* for afl->stage_cur */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP4] += afl->stage_max;
+
+ /* Effector map setup. These macros calculate:
+
+ EFF_APOS - position of a particular file offset in the map.
+ EFF_ALEN - length of a map with a particular number of bytes.
+ EFF_SPAN_ALEN - map span for a sequence of bytes.
+
+ */
+
+#define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2)
+#define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1))
+#define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l))
+#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l)-1) - EFF_APOS(_p) + 1)
+
+ /* Initialize effector map for the next step (see comments below). Always
+ flag first and last byte as doing something. */
+
+ eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
+ if (unlikely(!eff_map)) { PFATAL("alloc"); }
+ eff_map[0] = 1;
+
+ if (EFF_APOS(len - 1) != 0) {
+
+ eff_map[EFF_APOS(len - 1)] = 1;
+ ++eff_cnt;
+
+ }
+
+ /* Walking byte. */
+
+ afl->stage_name = "bitflip 8/8";
+ afl->stage_short = "flip8";
+ afl->stage_max = len;
+
+ orig_hit_cnt = new_hit_cnt;
+ prev_cksum = _prev_cksum;
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+
+ afl->stage_cur_byte = afl->stage_cur;
+
+ out_buf[afl->stage_cur] ^= 0xFF;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_FLIP_BIT8-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ /* We also use this stage to pull off a simple trick: we identify
+ bytes that seem to have no effect on the current execution path
+ even when fully flipped - and we skip them during more expensive
+ deterministic stages, such as arithmetics or known ints. */
+
+ if (!eff_map[EFF_APOS(afl->stage_cur)]) {
+
+ u64 cksum;
+
+ /* If in non-instrumented mode or if the file is very short, just flag
+ everything without wasting time on checksums. */
+
+ if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) {
+
+ cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
+ } else {
+
+ cksum = ~prev_cksum;
+
+ }
+
+ if (cksum != prev_cksum) {
+
+ eff_map[EFF_APOS(afl->stage_cur)] = 1;
+ ++eff_cnt;
+
+ }
+
+ }
+
+ out_buf[afl->stage_cur] ^= 0xFF;
+
+ } /* for afl->stage_cur */
+
+ /* If the effector map is more than EFF_MAX_PERC dense, just flag the
+ whole thing as worth fuzzing, since we wouldn't be saving much time
+ anyway. */
+
+ if (eff_cnt != (u32)EFF_ALEN(len) &&
+ eff_cnt * 100 / EFF_ALEN(len) > EFF_MAX_PERC) {
+
+ memset(eff_map, 1, EFF_ALEN(len));
+
+ afl->blocks_eff_select += EFF_ALEN(len);
+
+ } else {
+
+ afl->blocks_eff_select += eff_cnt;
+
+ }
+
+ afl->blocks_eff_total += EFF_ALEN(len);
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP8] += afl->stage_max;
+
+ /* Two walking bytes. */
+
+ if (len < 2) { goto skip_bitflip; }
+
+ afl->stage_name = "bitflip 16/8";
+ afl->stage_short = "flip16";
+ afl->stage_cur = 0;
+ afl->stage_max = len - 1;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 1; ++i) {
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ *(u16 *)(out_buf + i) ^= 0xFFFF;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_FLIP_BIT16-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ *(u16 *)(out_buf + i) ^= 0xFFFF;
+
+ } /* for i = 0; i < len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP16] += afl->stage_max;
+
+ if (len < 4) { goto skip_bitflip; }
+
+ /* Four walking bytes. */
+
+ afl->stage_name = "bitflip 32/8";
+ afl->stage_short = "flip32";
+ afl->stage_cur = 0;
+ afl->stage_max = len - 3;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 3; ++i) {
+
+ /* Let's consult the effector map... */
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
+ !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ *(u32 *)(out_buf + i) ^= 0xFFFFFFFF;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_FLIP_BIT32-%u",
+ afl->queue_cur->fname, afl->stage_cur);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ *(u32 *)(out_buf + i) ^= 0xFFFFFFFF;
+
+ } /* for i = 0; i < len - 3 */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_FLIP32] += afl->stage_max;
+
+skip_bitflip:
+
+ if (afl->no_arith) { goto skip_arith; }
+
+ /**********************
+ * ARITHMETIC INC/DEC *
+ **********************/
+
+ /* 8-bit arithmetics. */
+
+ afl->stage_name = "arith 8/8";
+ afl->stage_short = "arith8";
+ afl->stage_cur = 0;
+ afl->stage_max = 2 * len * ARITH_MAX;
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u8 orig = out_buf[i];
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)]) {
+
+ afl->stage_max -= 2 * ARITH_MAX;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 1; j <= ARITH_MAX; ++j) {
+
+ u8 r = orig ^ (orig + j);
+
+ /* Do arithmetic operations only if the result couldn't be a product
+ of a bitflip. */
+
+ if (!could_be_bitflip(r)) {
+
+ afl->stage_cur_val = j;
+ out_buf[i] = orig + j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_ARITH8+-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ r = orig ^ (orig - j);
+
+ if (!could_be_bitflip(r)) {
+
+ afl->stage_cur_val = -j;
+ out_buf[i] = orig - j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_ARITH8_-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ out_buf[i] = orig;
+
+ }
+
+ } /* for i = 0; i < len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_ARITH8] += afl->stage_max;
+
+ /* 16-bit arithmetics, both endians. */
+
+ if (len < 2) { goto skip_arith; }
+
+ afl->stage_name = "arith 16/8";
+ afl->stage_short = "arith16";
+ afl->stage_cur = 0;
+ afl->stage_max = 4 * (len - 1) * ARITH_MAX;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 1; ++i) {
+
+ u16 orig = *(u16 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
+
+ afl->stage_max -= 4 * ARITH_MAX;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 1; j <= ARITH_MAX; ++j) {
+
+ u16 r1 = orig ^ (orig + j), r2 = orig ^ (orig - j),
+ r3 = orig ^ SWAP16(SWAP16(orig) + j),
+ r4 = orig ^ SWAP16(SWAP16(orig) - j);
+
+ /* Try little endian addition and subtraction first. Do it only
+ if the operation would affect more than one byte (hence the
+ & 0xff overflow checks) and if it couldn't be a product of
+ a bitflip. */
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ if ((orig & 0xff) + j > 0xff && !could_be_bitflip(r1)) {
+
+ afl->stage_cur_val = j;
+ *(u16 *)(out_buf + i) = orig + j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_ARITH16+-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((orig & 0xff) < j && !could_be_bitflip(r2)) {
+
+ afl->stage_cur_val = -j;
+ *(u16 *)(out_buf + i) = orig - j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_ARITH16_-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ /* Big endian comes next. Same deal. */
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+ if ((orig >> 8) + j > 0xff && !could_be_bitflip(r3)) {
+
+ afl->stage_cur_val = j;
+ *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) + j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_ARITH16+BE-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((orig >> 8) < j && !could_be_bitflip(r4)) {
+
+ afl->stage_cur_val = -j;
+ *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) - j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_ARITH16_BE+%u+%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ *(u16 *)(out_buf + i) = orig;
+
+ }
+
+ } /* for i = 0; i < len - 1 */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_ARITH16] += afl->stage_max;
+
+ /* 32-bit arithmetics, both endians. */
+
+ if (len < 4) { goto skip_arith; }
+
+ afl->stage_name = "arith 32/8";
+ afl->stage_short = "arith32";
+ afl->stage_cur = 0;
+ afl->stage_max = 4 * (len - 3) * ARITH_MAX;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 3; ++i) {
+
+ u32 orig = *(u32 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
+ !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
+
+ afl->stage_max -= 4 * ARITH_MAX;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 1; j <= ARITH_MAX; ++j) {
+
+ u32 r1 = orig ^ (orig + j), r2 = orig ^ (orig - j),
+ r3 = orig ^ SWAP32(SWAP32(orig) + j),
+ r4 = orig ^ SWAP32(SWAP32(orig) - j);
+
+ /* Little endian first. Same deal as with 16-bit: we only want to
+ try if the operation would have effect on more than two bytes. */
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ if ((orig & 0xffff) + j > 0xffff && !could_be_bitflip(r1)) {
+
+ afl->stage_cur_val = j;
+ *(u32 *)(out_buf + i) = orig + j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_ARITH32+-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((orig & 0xffff) < j && !could_be_bitflip(r2)) {
+
+ afl->stage_cur_val = -j;
+ *(u32 *)(out_buf + i) = orig - j;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_ARITH32_-%u-%u",
+ afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ /* Big endian next. */
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+ if ((SWAP32(orig) & 0xffff) + j > 0xffff && !could_be_bitflip(r3)) {
+
+ afl->stage_cur_val = j;
+ *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) + j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_ARITH32+BE-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((SWAP32(orig) & 0xffff) < j && !could_be_bitflip(r4)) {
+
+ afl->stage_cur_val = -j;
+ *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) - j);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_ARITH32_BE-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ *(u32 *)(out_buf + i) = orig;
+
+ }
+
+ } /* for i = 0; i < len - 3 */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_ARITH32] += afl->stage_max;
+
+skip_arith:
+
+ /**********************
+ * INTERESTING VALUES *
+ **********************/
+
+ afl->stage_name = "interest 8/8";
+ afl->stage_short = "int8";
+ afl->stage_cur = 0;
+ afl->stage_max = len * sizeof(interesting_8);
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ /* Setting 8-bit integers. */
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u8 orig = out_buf[i];
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)]) {
+
+ afl->stage_max -= sizeof(interesting_8);
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < sizeof(interesting_8); ++j) {
+
+ /* Skip if the value could be a product of bitflips or arithmetics. */
+
+ if (could_be_bitflip(orig ^ (u8)interesting_8[j]) ||
+ could_be_arith(orig, (u8)interesting_8[j], 1)) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ afl->stage_cur_val = interesting_8[j];
+ out_buf[i] = interesting_8[j];
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_INTERESTING8-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ out_buf[i] = orig;
+ ++afl->stage_cur;
+
+ }
+
+ } /* for i = 0; i < len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max;
+
+ /* Setting 16-bit integers, both endians. */
+
+ if (afl->no_arith || len < 2) { goto skip_interest; }
+
+ afl->stage_name = "interest 16/8";
+ afl->stage_short = "int16";
+ afl->stage_cur = 0;
+ afl->stage_max = 2 * (len - 1) * (sizeof(interesting_16) >> 1);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 1; ++i) {
+
+ u16 orig = *(u16 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
+
+ afl->stage_max -= sizeof(interesting_16);
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < sizeof(interesting_16) / 2; ++j) {
+
+ afl->stage_cur_val = interesting_16[j];
+
+ /* Skip if this could be a product of a bitflip, arithmetics,
+ or single-byte interesting value insertion. */
+
+ if (!could_be_bitflip(orig ^ (u16)interesting_16[j]) &&
+ !could_be_arith(orig, (u16)interesting_16[j], 2) &&
+ !could_be_interest(orig, (u16)interesting_16[j], 2, 0)) {
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ *(u16 *)(out_buf + i) = interesting_16[j];
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_INTERESTING16-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) &&
+ !could_be_bitflip(orig ^ SWAP16(interesting_16[j])) &&
+ !could_be_arith(orig, SWAP16(interesting_16[j]), 2) &&
+ !could_be_interest(orig, SWAP16(interesting_16[j]), 2, 1)) {
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_INTERESTING16BE-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ *(u16 *)(out_buf + i) = SWAP16(interesting_16[j]);
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ }
+
+ *(u16 *)(out_buf + i) = orig;
+
+ } /* for i = 0; i < len - 1 */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max;
+
+ if (len < 4) { goto skip_interest; }
+
+ /* Setting 32-bit integers, both endians. */
+
+ afl->stage_name = "interest 32/8";
+ afl->stage_short = "int32";
+ afl->stage_cur = 0;
+ afl->stage_max = 2 * (len - 3) * (sizeof(interesting_32) >> 2);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < len - 3; ++i) {
+
+ u32 orig = *(u32 *)(out_buf + i);
+
+ /* Let's consult the effector map... */
+
+ if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
+ !eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
+
+ afl->stage_max -= sizeof(interesting_32) >> 1;
+ continue;
+
+ }
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < sizeof(interesting_32) / 4; ++j) {
+
+ afl->stage_cur_val = interesting_32[j];
+
+ /* Skip if this could be a product of a bitflip, arithmetics,
+ or word interesting value insertion. */
+
+ if (!could_be_bitflip(orig ^ (u32)interesting_32[j]) &&
+ !could_be_arith(orig, interesting_32[j], 4) &&
+ !could_be_interest(orig, interesting_32[j], 4, 0)) {
+
+ afl->stage_val_type = STAGE_VAL_LE;
+
+ *(u32 *)(out_buf + i) = interesting_32[j];
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_INTERESTING32-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) &&
+ !could_be_bitflip(orig ^ SWAP32(interesting_32[j])) &&
+ !could_be_arith(orig, SWAP32(interesting_32[j]), 4) &&
+ !could_be_interest(orig, SWAP32(interesting_32[j]), 4, 1)) {
+
+ afl->stage_val_type = STAGE_VAL_BE;
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_INTERESTING32BE-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+ *(u32 *)(out_buf + i) = SWAP32(interesting_32[j]);
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+ ++afl->stage_cur;
+
+ } else {
+
+ --afl->stage_max;
+
+ }
+
+ }
+
+ *(u32 *)(out_buf + i) = orig;
+
+ } /* for i = 0; i < len - 3 */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max;
+
+skip_interest:
+
+ /********************
+ * DICTIONARY STUFF *
+ ********************/
+
+ if (!afl->extras_cnt) { goto skip_user_extras; }
+
+ /* Overwrite with user-supplied extras. */
+
+ afl->stage_name = "user extras (over)";
+ afl->stage_short = "ext_UO";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->extras_cnt * len;
+
+ afl->stage_val_type = STAGE_VAL_NONE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u32 last_len = 0;
+
+ afl->stage_cur_byte = i;
+
+ /* Extras are sorted by size, from smallest to largest. This means
+ that we don't have to worry about restoring the buffer in
+ between writes at a particular offset determined by the outer
+ loop. */
+
+ for (j = 0; j < afl->extras_cnt; ++j) {
+
+ /* Skip extras probabilistically if afl->extras_cnt > AFL_MAX_DET_EXTRAS.
+ Also skip them if there's no room to insert the payload, if the token
+ is redundant, or if its entire span has no bytes set in the effector
+ map. */
+
+ if ((afl->extras_cnt > afl->max_det_extras &&
+ rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) ||
+ afl->extras[j].len > len - i ||
+ !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
+ !memchr(eff_map + EFF_APOS(i), 1,
+ EFF_SPAN_ALEN(i, afl->extras[j].len))) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ last_len = afl->extras[j].len;
+ memcpy(out_buf + i, afl->extras[j].data, last_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_EXTRAS_overwrite-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Restore all the clobbered memory. */
+ memcpy(out_buf + i, in_buf + i, last_len);
+
+ } /* for i = 0; i < len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max;
+
+ /* Insertion of user-supplied extras. */
+
+ afl->stage_name = "user extras (insert)";
+ afl->stage_short = "ext_UI";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->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->extras_cnt; ++j) {
+
+ if (len + afl->extras[j].len > MAX_FILE) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ /* Insert token */
+ memcpy(ex_tmp + i, afl->extras[j].data, afl->extras[j].len);
+
+ /* Copy tail */
+ memcpy(ex_tmp + i + afl->extras[j].len, out_buf + i, len - i);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_EXTRAS_insert-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, ex_tmp, len + afl->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_UI] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max;
+
+skip_user_extras:
+
+ if (!afl->a_extras_cnt) { goto skip_extras; }
+
+ afl->stage_name = "auto extras (over)";
+ afl->stage_short = "ext_AO";
+ afl->stage_cur = 0;
+ afl->stage_max = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS) * len;
+
+ afl->stage_val_type = STAGE_VAL_NONE;
+
+ orig_hit_cnt = new_hit_cnt;
+
+ for (i = 0; i < (u32)len; ++i) {
+
+ u32 last_len = 0;
+
+ afl->stage_cur_byte = i;
+
+ u32 min_extra_len = MIN(afl->a_extras_cnt, (u32)USE_AUTO_EXTRAS);
+ for (j = 0; j < min_extra_len; ++j) {
+
+ /* See the comment in the earlier code; extras are sorted by size. */
+
+ if ((afl->a_extras[j].len) > (len - i) ||
+ !memcmp(afl->a_extras[j].data, out_buf + i, afl->a_extras[j].len) ||
+ !memchr(eff_map + EFF_APOS(i), 1,
+ EFF_SPAN_ALEN(i, afl->a_extras[j].len))) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ last_len = afl->a_extras[j].len;
+ memcpy(out_buf + i, afl->a_extras[j].data, last_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_AUTO_EXTRAS_overwrite-%u-%u", afl->queue_cur->fname, i,
+ j);
+#endif
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Restore all the clobbered memory. */
+ memcpy(out_buf + i, in_buf + i, last_len);
+
+ } /* for i = 0; i < len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ 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,
+ we're properly done with deterministic steps and can mark it as such
+ in the .state/ directory. */
+
+ if (!afl->queue_cur->passed_det) { mark_as_det_done(afl, afl->queue_cur); }
+
+ /****************
+ * RANDOM HAVOC *
+ ****************/
+
+havoc_stage:
+pacemaker_fuzzing:
+
+ afl->stage_cur_byte = -1;
+
+ /* The havoc stage mutation code is also invoked when splicing files; if the
+ splice_cycle variable is set, generate different descriptions and such. */
+
+ if (!splice_cycle) {
+
+ afl->stage_name = MOpt_globals.havoc_stagename;
+ afl->stage_short = MOpt_globals.havoc_stagenameshort;
+ afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
+ perf_score / afl->havoc_div / 100;
+
+ } else {
+
+ perf_score = orig_perf;
+
+ snprintf(afl->stage_name_buf, STAGE_BUF_SIZE,
+ MOpt_globals.splice_stageformat, splice_cycle);
+ afl->stage_name = afl->stage_name_buf;
+ afl->stage_short = MOpt_globals.splice_stagenameshort;
+ afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
+
+ }
+
+ s32 temp_len_puppet;
+
+ // for (; afl->swarm_now < swarm_num; ++afl->swarm_now)
+ {
+
+ if (afl->key_puppet == 1) {
+
+ if (unlikely(afl->orig_hit_cnt_puppet == 0)) {
+
+ afl->orig_hit_cnt_puppet = afl->queued_items + afl->saved_crashes;
+ afl->last_limit_time_start = get_cur_time();
+ afl->SPLICE_CYCLES_puppet =
+ (rand_below(
+ afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
+ SPLICE_CYCLES_puppet_low);
+
+ }
+
+ } /* if afl->key_puppet == 1 */
+
+ {
+
+#ifndef IGNORE_FINDS
+ havoc_stage_puppet:
+#endif
+
+ afl->stage_cur_byte = -1;
+
+ /* The havoc stage mutation code is also invoked when splicing files; if
+ the splice_cycle variable is set, generate different descriptions and
+ such. */
+
+ if (!splice_cycle) {
+
+ afl->stage_name = MOpt_globals.havoc_stagename;
+ afl->stage_short = MOpt_globals.havoc_stagenameshort;
+ afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
+ perf_score / afl->havoc_div / 100;
+
+ } else {
+
+ perf_score = orig_perf;
+ snprintf(afl->stage_name_buf, STAGE_BUF_SIZE,
+ MOpt_globals.splice_stageformat, splice_cycle);
+ afl->stage_name = afl->stage_name_buf;
+ afl->stage_short = MOpt_globals.splice_stagenameshort;
+ afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
+
+ }
+
+ if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
+
+ temp_len = len;
+
+ orig_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ havoc_queued = afl->queued_items;
+
+ u32 r_max, r;
+
+ r_max = 16 + ((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 any finds happened */
+
+ ++r_max;
+
+ }
+
+ for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
+ ++afl->stage_cur) {
+
+ u32 use_stacking = 1 << (1 + rand_below(afl, afl->havoc_stack_pow2));
+
+ afl->stage_cur_val = use_stacking;
+
+ for (i = 0; i < operator_num; ++i) {
+
+ MOpt_globals.cycles_v3[i] = MOpt_globals.cycles_v2[i];
+
+ }
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation), "%s MOPT_HAVOC-%u",
+ afl->queue_cur->fname, use_stacking);
+#endif
+
+ for (i = 0; i < use_stacking; ++i) {
+
+ switch (r = (select_algorithm(afl, r_max))) {
+
+ case 0:
+ /* Flip a single bit somewhere. Spooky! */
+ FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
+ MOpt_globals.cycles_v2[STAGE_FLIP1]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT1");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 1:
+ if (temp_len < 2) { break; }
+ temp_len_puppet = rand_below(afl, (temp_len << 3) - 1);
+ FLIP_BIT(out_buf, temp_len_puppet);
+ FLIP_BIT(out_buf, temp_len_puppet + 1);
+ MOpt_globals.cycles_v2[STAGE_FLIP2]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT2");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 2:
+ if (temp_len < 2) { break; }
+ temp_len_puppet = rand_below(afl, (temp_len << 3) - 3);
+ FLIP_BIT(out_buf, temp_len_puppet);
+ FLIP_BIT(out_buf, temp_len_puppet + 1);
+ FLIP_BIT(out_buf, temp_len_puppet + 2);
+ FLIP_BIT(out_buf, temp_len_puppet + 3);
+ MOpt_globals.cycles_v2[STAGE_FLIP4]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT4");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 3:
+ if (temp_len < 4) { break; }
+ out_buf[rand_below(afl, temp_len)] ^= 0xFF;
+ MOpt_globals.cycles_v2[STAGE_FLIP8]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT8");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 4:
+ if (temp_len < 8) { break; }
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) ^= 0xFFFF;
+ MOpt_globals.cycles_v2[STAGE_FLIP16]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT16");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 5:
+ if (temp_len < 8) { break; }
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) ^= 0xFFFFFFFF;
+ MOpt_globals.cycles_v2[STAGE_FLIP32]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP_BIT32");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 6:
+ out_buf[rand_below(afl, temp_len)] -=
+ 1 + rand_below(afl, ARITH_MAX);
+ out_buf[rand_below(afl, temp_len)] +=
+ 1 + rand_below(afl, ARITH_MAX);
+ MOpt_globals.cycles_v2[STAGE_ARITH8]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH8");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 7:
+ /* Randomly subtract from word, random endian. */
+ if (temp_len < 8) { break; }
+ if (rand_below(afl, 2)) {
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ *(u16 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+
+ } else {
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ u16 num = 1 + rand_below(afl, ARITH_MAX);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16BE-%u-%u",
+ pos, num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) =
+ SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
+
+ }
+
+ /* Randomly add to word, random endian. */
+ if (rand_below(afl, 2)) {
+
+ u32 pos = rand_below(afl, temp_len - 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16+-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+
+ } else {
+
+ u32 pos = rand_below(afl, temp_len - 1);
+ u16 num = 1 + rand_below(afl, ARITH_MAX);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH16BE+-%u-%u",
+ pos, num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + pos) =
+ SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_ARITH16]++;
+ break;
+
+ case 8:
+ /* Randomly subtract from dword, random endian. */
+ if (temp_len < 8) { break; }
+ if (rand_below(afl, 2)) {
+
+ u32 pos = rand_below(afl, temp_len - 3);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32_-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) -= 1 + rand_below(afl, ARITH_MAX);
+
+ } else {
+
+ u32 pos = rand_below(afl, temp_len - 3);
+ u32 num = 1 + rand_below(afl, ARITH_MAX);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32BE_-%u-%u",
+ pos, num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) =
+ SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
+
+ }
+
+ /* Randomly add to dword, random endian. */
+ // if (temp_len < 4) break;
+ if (rand_below(afl, 2)) {
+
+ u32 pos = rand_below(afl, temp_len - 3);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32+-%u", pos);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) += 1 + rand_below(afl, ARITH_MAX);
+
+ } else {
+
+ u32 pos = rand_below(afl, temp_len - 3);
+ u32 num = 1 + rand_below(afl, ARITH_MAX);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ARITH32BE+-%u-%u",
+ pos, num);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + pos) =
+ SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_ARITH32]++;
+ break;
+
+ case 9:
+ /* Set byte to interesting value. */
+ if (temp_len < 4) { break; }
+ out_buf[rand_below(afl, temp_len)] =
+ interesting_8[rand_below(afl, sizeof(interesting_8))];
+ MOpt_globals.cycles_v2[STAGE_INTEREST8]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING8");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 10:
+ /* Set word to interesting value, randomly choosing endian. */
+ if (temp_len < 8) { break; }
+ if (rand_below(afl, 2)) {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+ interesting_16[rand_below(afl,
+ sizeof(interesting_16) >> 1)];
+
+ } else {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16BE");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
+ SWAP16(interesting_16[rand_below(
+ afl, sizeof(interesting_16) >> 1)]);
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_INTEREST16]++;
+ break;
+
+ case 11:
+ /* Set dword to interesting value, randomly choosing endian. */
+
+ if (temp_len < 8) { break; }
+
+ if (rand_below(afl, 2)) {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+ interesting_32[rand_below(afl,
+ sizeof(interesting_32) >> 2)];
+
+ } else {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32BE");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
+ SWAP32(interesting_32[rand_below(
+ afl, sizeof(interesting_32) >> 2)]);
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_INTEREST32]++;
+ break;
+
+ case 12:
+
+ /* Just set a random byte to a random value. Because,
+ why not. We use XOR with 1-255 to eliminate the
+ possibility of a no-op. */
+
+ out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
+ MOpt_globals.cycles_v2[STAGE_RANDOMBYTE]++;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " RAND8");
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ break;
+
+ case 13: {
+
+ /* Delete bytes. We're making this a bit more likely
+ than insertion (the next option) in hopes of keeping
+ files reasonably small. */
+
+ u32 del_from, del_len;
+
+ if (temp_len < 2) { break; }
+
+ /* Don't delete too much. */
+
+ del_len = choose_block_len(afl, temp_len - 1);
+
+ del_from = rand_below(afl, temp_len - del_len + 1);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " DEL-%u%u", del_from,
+ del_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + del_from, out_buf + del_from + del_len,
+ temp_len - del_from - del_len);
+
+ temp_len -= del_len;
+ MOpt_globals.cycles_v2[STAGE_DELETEBYTE]++;
+ break;
+
+ }
+
+ case 14:
+
+ if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
+
+ /* Clone bytes (75%) or insert a block of constant bytes (25%).
+ */
+
+ u8 actually_clone = rand_below(afl, 4);
+ u32 clone_from, clone_to, clone_len;
+ u8 *new_buf;
+
+ if (likely(actually_clone)) {
+
+ clone_len = choose_block_len(afl, temp_len);
+ clone_from = rand_below(afl, temp_len - clone_len + 1);
+
+ } else {
+
+ clone_len = choose_block_len(afl, HAVOC_BLK_XL);
+ clone_from = 0;
+
+ }
+
+ clone_to = rand_below(afl, temp_len);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp), " CLONE_%s-%u-%u-%u",
+ actually_clone ? "clone" : "insert", clone_from,
+ clone_to, clone_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+ temp_len + clone_len);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+
+ /* Head */
+
+ memcpy(new_buf, out_buf, clone_to);
+
+ /* Inserted part */
+
+ if (actually_clone) {
+
+ memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
+
+ } else {
+
+ memset(new_buf + clone_to,
+ rand_below(afl, 2)
+ ? rand_below(afl, 256)
+ : out_buf[rand_below(afl, temp_len)],
+ clone_len);
+
+ }
+
+ /* Tail */
+ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
+
+ out_buf = new_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
+ MOpt_globals.cycles_v2[STAGE_Clone75]++;
+
+ }
+
+ break;
+
+ case 15: {
+
+ /* Overwrite bytes with a randomly selected chunk (75%) or fixed
+ bytes (25%). */
+
+ u32 copy_from, copy_to, copy_len;
+
+ if (temp_len < 2) { break; }
+
+ copy_len = choose_block_len(afl, temp_len - 1);
+
+ copy_from = rand_below(afl, temp_len - copy_len + 1);
+ copy_to = rand_below(afl, temp_len - copy_len + 1);
+
+ if (likely(rand_below(afl, 4))) {
+
+ if (likely(copy_from != copy_to)) {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " OVERWRITE_COPY-%u-%u-%u", copy_from, copy_to,
+ copy_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+
+ }
+
+ } else {
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " OVERWRITE_FIXED-%u-%u-%u", copy_from, copy_to,
+ copy_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memset(out_buf + copy_to,
+ rand_below(afl, 2) ? rand_below(afl, 256)
+ : out_buf[rand_below(afl, temp_len)],
+ copy_len);
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_OverWrite75]++;
+ break;
+
+ } /* case 15 */
+
+ default: {
+
+ /* Values 16 and 17 can be selected only if there are any extras
+ present in the dictionaries. */
+
+ r -= 16;
+
+ if (r == 0 && (afl->extras_cnt || afl->a_extras_cnt)) {
+
+ /* Overwrite bytes with an extra. */
+
+ if (!afl->extras_cnt ||
+ (afl->a_extras_cnt && rand_below(afl, 2))) {
+
+ /* No user-specified extras or odds in our favor. Let's use an
+ auto-detected one. */
+
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
+
+ if (extra_len > (u32)temp_len) break;
+
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+ extra_len);
+
+ } else {
+
+ /* No auto extras or odds in our favor. Use the dictionary. */
+
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
+
+ if (extra_len > (u32)temp_len) break;
+
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memcpy(out_buf + insert_at, afl->extras[use_extra].data,
+ extra_len);
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_OverWriteExtra]++;
+
+ break;
+
+ }
+
+ /* Insert an extra. */
+
+ else if (r == 1 && (afl->extras_cnt || afl->a_extras_cnt)) {
+
+ 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;
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+
+ } else {
+
+ use_extra = rand_below(afl, afl->extras_cnt);
+ 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);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+
+ }
+
+ if (temp_len + extra_len >= MAX_FILE) break;
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
+
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
+
+ temp_len += extra_len;
+ MOpt_globals.cycles_v2[STAGE_InsertExtra]++;
+ break;
+
+ } else {
+
+ if (unlikely(afl->ready_for_splicing_count < 2)) break;
+
+ u32 tid;
+ do {
+
+ tid = rand_below(afl, afl->queued_items);
+
+ } while (tid == afl->current_entry ||
+
+ afl->queue_buf[tid]->len < 4);
+
+ /* Get the testcase for splicing. */
+ struct queue_entry *target = afl->queue_buf[tid];
+ u32 new_len = target->len;
+ u8 * new_buf = queue_testcase_get(afl, target);
+
+ if ((temp_len >= 2 && rand_below(afl, 2)) ||
+ temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+
+ /* overwrite mode */
+
+ 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);
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
+ copy_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+
+ } else {
+
+ /* insert mode */
+
+ 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 + 1);
+
+ u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+ temp_len + clone_len + 1);
+ if (unlikely(!temp_buf)) { PFATAL("alloc"); }
+
+#ifdef INTROSPECTION
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
+ clone_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
+#endif
+ /* 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);
+
+ out_buf = temp_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
+
+ }
+
+ MOpt_globals.cycles_v2[STAGE_Splice]++;
+ break;
+
+ }
+
+ } // end of default:
+
+ } /* switch select_algorithm() */
+
+ } /* for i=0; i < use_stacking */
+
+ ++*MOpt_globals.pTime;
+
+ u64 temp_total_found = afl->queued_items + afl->saved_crashes;
+
+ if (common_fuzz_stuff(afl, out_buf, temp_len)) {
+
+ goto abandon_entry_puppet;
+
+ }
+
+ /* out_buf might have been mangled a bit, so let's restore it to its
+ original size and shape. */
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ temp_len = len;
+ memcpy(out_buf, in_buf, len);
+
+ /* If we're finding new stuff, let's run for a bit longer, limits
+ permitting. */
+
+ if (afl->queued_items != havoc_queued) {
+
+ if (perf_score <= afl->havoc_max_mult * 100) {
+
+ afl->stage_max *= 2;
+ perf_score *= 2;
+
+ }
+
+ havoc_queued = afl->queued_items;
+
+ }
+
+ if (unlikely(afl->queued_items + afl->saved_crashes >
+ temp_total_found)) {
+
+ u64 temp_temp_puppet =
+ afl->queued_items + afl->saved_crashes - temp_total_found;
+ afl->total_puppet_find = afl->total_puppet_find + temp_temp_puppet;
+
+ if (MOpt_globals.is_pilot_mode) {
+
+ for (i = 0; i < operator_num; ++i) {
+
+ if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) {
+
+ MOpt_globals.finds_v2[i] += temp_temp_puppet;
+
+ }
+
+ }
+
+ } else {
+
+ for (i = 0; i < operator_num; i++) {
+
+ if (afl->core_operator_cycles_puppet_v2[i] >
+ afl->core_operator_cycles_puppet_v3[i])
+
+ afl->core_operator_finds_puppet_v2[i] += temp_temp_puppet;
+
+ }
+
+ }
+
+ } /* if */
+
+ } /* for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
+
+ ++afl->stage_cur) { */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ if (MOpt_globals.is_pilot_mode) {
+
+ if (!splice_cycle) {
+
+ afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_HAVOC] += afl->stage_max;
+
+ } else {
+
+ afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_SPLICE] += afl->stage_max;
+
+ }
+
+ }
+
+#ifndef IGNORE_FINDS
+
+ /************
+ * SPLICING *
+ ************/
+
+ retry_splicing_puppet:
+
+ if (afl->use_splicing &&
+ splice_cycle++ < (u32)afl->SPLICE_CYCLES_puppet &&
+ afl->ready_for_splicing_count > 1 && afl->queue_cur->len >= 4) {
+
+ struct queue_entry *target;
+ u32 tid, split_at;
+ u8 * new_buf;
+ s32 f_diff, l_diff;
+
+ /* First of all, if we've modified in_buf for havoc, let's clean that
+ up... */
+
+ if (in_buf != orig_in) {
+
+ in_buf = orig_in;
+ len = afl->queue_cur->len;
+
+ }
+
+ /* Pick a random queue entry and seek to it. Don't splice with yourself.
+ */
+
+ do {
+
+ tid = rand_below(afl, afl->queued_items);
+
+ } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4);
+
+ afl->splicing_with = tid;
+ target = afl->queue_buf[tid];
+
+ /* Read the testcase into a new buffer. */
+ new_buf = queue_testcase_get(afl, target);
+
+ /* Find a suitable splicin g location, somewhere between the first and
+ the last differing byte. Bail out if the difference is just a single
+ byte or so. */
+
+ locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff);
+
+ if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
+
+ goto retry_splicing_puppet;
+
+ }
+
+ /* Split somewhere between the first and last differing byte. */
+
+ split_at = f_diff + rand_below(afl, l_diff - f_diff);
+
+ /* Do the thing. */
+
+ len = target->len;
+ afl->in_scratch_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), len);
+ memcpy(afl->in_scratch_buf, in_buf, split_at);
+ memcpy(afl->in_scratch_buf + split_at, new_buf, len - split_at);
+ in_buf = afl->in_scratch_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(in), AFL_BUF_PARAM(in_scratch));
+
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ memcpy(out_buf, in_buf, len);
+
+ goto havoc_stage_puppet;
+
+ } /* if splice_cycle */
+
+#endif /* !IGNORE_FINDS */
+
+ ret_val = 0;
+
+ abandon_entry:
+ abandon_entry_puppet:
+
+ if ((s64)splice_cycle >= afl->SPLICE_CYCLES_puppet) {
+
+ afl->SPLICE_CYCLES_puppet =
+ (rand_below(
+ afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) +
+ SPLICE_CYCLES_puppet_low);
+
+ }
+
+ afl->splicing_with = -1;
+
+ /* Update afl->pending_not_fuzzed count if we made it through the
+ calibration cycle and have not seen this entry before. */
+ /*
+ // TODO FIXME: I think we need this plus need an -L -1 check
+ if (!afl->stop_soon && !afl->queue_cur->cal_failed &&
+ (afl->queue_cur->was_fuzzed == 0 || afl->queue_cur->fuzz_level == 0)
+ && !afl->queue_cur->disabled) {
+
+ if (!afl->queue_cur->was_fuzzed) {
+
+ --afl->pending_not_fuzzed;
+ afl->queue_cur->was_fuzzed = 1;
+ if (afl->queue_cur->favored) { --afl->pending_favored; }
+
+ }
+
+ }
+
+ */
+
+ orig_in = NULL;
+
+ if (afl->key_puppet == 1) {
+
+ if (unlikely(
+ afl->queued_items + afl->saved_crashes >
+ ((afl->queued_items + afl->saved_crashes) * limit_time_bound +
+ afl->orig_hit_cnt_puppet))) {
+
+ afl->key_puppet = 0;
+ afl->orig_hit_cnt_puppet = 0;
+ afl->last_limit_time_start = 0;
+
+ }
+
+ }
+
+ if (unlikely(*MOpt_globals.pTime > MOpt_globals.period)) {
+
+ afl->total_pacemaker_time += *MOpt_globals.pTime;
+ *MOpt_globals.pTime = 0;
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ if (MOpt_globals.is_pilot_mode) {
+
+ afl->swarm_fitness[afl->swarm_now] =
+ (double)(afl->total_puppet_find - afl->temp_puppet_find) /
+ ((double)(afl->tmp_pilot_time) / afl->period_pilot_tmp);
+
+ }
+
+ afl->temp_puppet_find = afl->total_puppet_find;
+ for (i = 0; i < operator_num; ++i) {
+
+ if (MOpt_globals.is_pilot_mode) {
+
+ double temp_eff = 0.0;
+
+ if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles[i]) {
+
+ temp_eff =
+ (double)(MOpt_globals.finds_v2[i] - MOpt_globals.finds[i]) /
+ (double)(MOpt_globals.cycles_v2[i] - MOpt_globals.cycles[i]);
+
+ }
+
+ if (afl->eff_best[afl->swarm_now][i] < temp_eff) {
+
+ afl->eff_best[afl->swarm_now][i] = temp_eff;
+ afl->L_best[afl->swarm_now][i] = afl->x_now[afl->swarm_now][i];
+
+ }
+
+ }
+
+ MOpt_globals.finds[i] = MOpt_globals.finds_v2[i];
+ MOpt_globals.cycles[i] = MOpt_globals.cycles_v2[i];
+
+ } /* for i = 0; i < operator_num */
+
+ if (MOpt_globals.is_pilot_mode) {
+
+ afl->swarm_now = afl->swarm_now + 1;
+ if (afl->swarm_now == swarm_num) {
+
+ afl->key_module = 1;
+ for (i = 0; i < operator_num; ++i) {
+
+ afl->core_operator_cycles_puppet_v2[i] =
+ afl->core_operator_cycles_puppet[i];
+ afl->core_operator_cycles_puppet_v3[i] =
+ afl->core_operator_cycles_puppet[i];
+ afl->core_operator_finds_puppet_v2[i] =
+ afl->core_operator_finds_puppet[i];
+
+ }
+
+ double swarm_eff = 0.0;
+ afl->swarm_now = 0;
+ for (i = 0; i < swarm_num; ++i) {
+
+ if (afl->swarm_fitness[i] > swarm_eff) {
+
+ swarm_eff = afl->swarm_fitness[i];
+ afl->swarm_now = i;
+
+ }
+
+ }
+
+ if (afl->swarm_now < 0 || afl->swarm_now > swarm_num - 1) {
+
+ PFATAL("swarm_now error number %d", afl->swarm_now);
+
+ }
+
+ } /* if afl->swarm_now == swarm_num */
+
+ /* adjust pointers dependent on 'afl->swarm_now' */
+ afl->mopt_globals_pilot.finds =
+ afl->stage_finds_puppet[afl->swarm_now];
+ afl->mopt_globals_pilot.finds_v2 =
+ afl->stage_finds_puppet_v2[afl->swarm_now];
+ afl->mopt_globals_pilot.cycles =
+ afl->stage_cycles_puppet[afl->swarm_now];
+ afl->mopt_globals_pilot.cycles_v2 =
+ afl->stage_cycles_puppet_v2[afl->swarm_now];
+ afl->mopt_globals_pilot.cycles_v3 =
+ afl->stage_cycles_puppet_v3[afl->swarm_now];
+
+ } else {
+
+ for (i = 0; i < operator_num; i++) {
+
+ afl->core_operator_finds_puppet[i] =
+ afl->core_operator_finds_puppet_v2[i];
+ afl->core_operator_cycles_puppet[i] =
+ afl->core_operator_cycles_puppet_v2[i];
+
+ }
+
+ afl->key_module = 2;
+
+ afl->old_hit_count = new_hit_cnt;
+
+ } /* if pilot_mode */
+
+ } /* if (unlikely(*MOpt_globals.pTime > MOpt_globals.period)) */
+
+ } /* block */
+
+ } /* block */
+
+ return ret_val;
+
+}
+
+#undef FLIP_BIT
+
+u8 core_fuzzing(afl_state_t *afl) {
+
+ return mopt_common_fuzzing(afl, afl->mopt_globals_core);
+
+}
+
+u8 pilot_fuzzing(afl_state_t *afl) {
+
+ return mopt_common_fuzzing(afl, afl->mopt_globals_pilot);
+
+}
+
+void pso_updating(afl_state_t *afl) {
+
+ afl->g_now++;
+ 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->g_max) +
+ afl->w_end;
+ int tmp_swarm, i, j;
+ u64 temp_operator_finds_puppet = 0;
+ for (i = 0; i < operator_num; ++i) {
+
+ afl->operator_finds_puppet[i] = afl->core_operator_finds_puppet[i];
+
+ for (j = 0; j < swarm_num; ++j) {
+
+ afl->operator_finds_puppet[i] =
+ afl->operator_finds_puppet[i] + afl->stage_finds_puppet[j][i];
+
+ }
+
+ temp_operator_finds_puppet =
+ temp_operator_finds_puppet + afl->operator_finds_puppet[i];
+
+ }
+
+ for (i = 0; i < operator_num; ++i) {
+
+ if (afl->operator_finds_puppet[i]) {
+
+ afl->G_best[i] = (double)((double)(afl->operator_finds_puppet[i]) /
+ (double)(temp_operator_finds_puppet));
+
+ }
+
+ }
+
+ for (tmp_swarm = 0; tmp_swarm < swarm_num; ++tmp_swarm) {
+
+ double x_temp = 0.0;
+ for (i = 0; i < operator_num; ++i) {
+
+ afl->probability_now[tmp_swarm][i] = 0.0;
+ afl->v_now[tmp_swarm][i] =
+ afl->w_now * afl->v_now[tmp_swarm][i] +
+ RAND_C * (afl->L_best[tmp_swarm][i] - afl->x_now[tmp_swarm][i]) +
+ RAND_C * (afl->G_best[i] - afl->x_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) {
+
+ afl->x_now[tmp_swarm][i] = v_max;
+
+ } else if (afl->x_now[tmp_swarm][i] < v_min) {
+
+ afl->x_now[tmp_swarm][i] = v_min;
+
+ }
+
+ x_temp += afl->x_now[tmp_swarm][i];
+
+ }
+
+ for (i = 0; i < operator_num; ++i) {
+
+ afl->x_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i] / x_temp;
+ if (likely(i != 0)) {
+
+ afl->probability_now[tmp_swarm][i] =
+ afl->probability_now[tmp_swarm][i - 1] + afl->x_now[tmp_swarm][i];
+
+ } else {
+
+ afl->probability_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i];
+
+ }
+
+ }
+
+ if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 ||
+ afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) {
+
+ FATAL("ERROR probability");
+
+ }
+
+ }
+
+ afl->swarm_now = 0;
+ afl->key_module = 0;
+
+}
+
+/* larger change for MOpt implementation: the original fuzz_one was renamed
+ to fuzz_one_original. All documentation references to fuzz_one therefore
+ mean fuzz_one_original */
+
+u8 fuzz_one(afl_state_t *afl) {
+
+ int key_val_lv_1 = 0, key_val_lv_2 = 0;
+
+#ifdef _AFL_DOCUMENT_MUTATIONS
+
+ u8 path_buf[PATH_MAX];
+ if (afl->do_document == 0) {
+
+ snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir);
+ afl->do_document = mkdir(path_buf, 0700); // if it exists we do not care
+ afl->do_document = 1;
+
+ } else {
+
+ afl->do_document = 2;
+ afl->stop_soon = 2;
+
+ }
+
+#endif
+
+ // if limit_time_sig == -1 then both are run after each other
+
+ if (afl->limit_time_sig <= 0) { key_val_lv_1 = fuzz_one_original(afl); }
+
+ if (afl->limit_time_sig != 0) {
+
+ if (afl->key_module == 0) {
+
+ key_val_lv_2 = pilot_fuzzing(afl);
+
+ } else if (afl->key_module == 1) {
+
+ key_val_lv_2 = core_fuzzing(afl);
+
+ } else if (afl->key_module == 2) {
+
+ pso_updating(afl);
+
+ }
+
+ }
+
+ return (key_val_lv_1 | key_val_lv_2);
+
+}
+