aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-08-09 22:02:44 +0200
committervan Hauser <vh@thc.org>2020-08-09 22:02:44 +0200
commit558a82891abb7617eb51d49991a128fccdc9be6e (patch)
treeae58c1a3fb466d7c5993f34432604ba7b0be4ffb
parent4fc16b542e7839698f91dca46db52044fdaa9dd2 (diff)
downloadafl++-558a82891abb7617eb51d49991a128fccdc9be6e.tar.gz
finalize havoc
-rw-r--r--src/afl-fuzz-one.c805
1 files changed, 43 insertions, 762 deletions
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 5dc336dc..75381db8 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -489,7 +489,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
case 2: // fuzz only tainted bytes
fd = open(afl->taint_input_file, O_RDONLY);
- len = afl->taint_len = afl->queue_cur->taint_bytes_all;
+ temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_all;
orig_in = in_buf =
mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)in_buf == -1)
@@ -511,7 +511,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
case 0: // fuzz only newly tainted bytes
fd = open(afl->taint_input_file, O_RDONLY);
- len = afl->taint_len = afl->queue_cur->taint_bytes_new;
+ temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_new;
orig_in = in_buf =
mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (size_t)in_buf == -1)
@@ -659,7 +659,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
if it has gone through deterministic testing in earlier, resumed runs
(passed_det). */
- if (afl->taint_needs_splode) goto taint_havoc_stage;
+ // custom mutators would not work, deterministic is done -> so havoc!
+ if (afl->taint_needs_splode) goto havoc_stage;
if (likely(afl->queue_cur->passed_det) || likely(afl->skip_deterministic) ||
likely(perf_score <
@@ -2214,760 +2215,19 @@ havoc_stage:
if (actually_clone) {
- clone_len = choose_block_len(afl, temp_len);
- clone_from = rand_below(afl, temp_len - clone_len + 1);
+ if (unlikely(afl->taint_needs_splode)) {
- } else {
-
- clone_len = choose_block_len(afl, HAVOC_BLK_XL);
- clone_from = 0;
-
- }
-
- clone_to = rand_below(afl, temp_len);
-
- new_buf =
- ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
-
- /* 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);
-
- swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
- out_buf = new_buf;
- new_buf = NULL;
- temp_len += clone_len;
-
- }
-
- break;
-
- case 14: {
-
- /* 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 (rand_below(afl, 4)) {
-
- if (copy_from != copy_to) {
-
- memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
-
- }
-
- } else {
-
- memset(out_buf + copy_to,
- rand_below(afl, 2) ? rand_below(afl, 256)
- : out_buf[rand_below(afl, temp_len)],
- copy_len);
-
- }
-
- break;
-
- }
-
- default:
-
- if (likely(r <= 16 && (afl->extras_cnt || afl->a_extras_cnt))) {
-
- /* Values 15 and 16 can be selected only if there are any extras
- present in the dictionaries. */
-
- if (r == 15) {
-
- /* 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;
- u32 insert_at;
-
- if ((s32)extra_len > temp_len) { break; }
-
- insert_at = rand_below(afl, temp_len - extra_len + 1);
- memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
- extra_len);
+ clone_len = choose_block_len(afl, afl->queue_cur->len);
+ clone_from =
+ rand_below(afl, afl->queue_cur->len - clone_len + 1);
} 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;
- u32 insert_at;
-
- if ((s32)extra_len > temp_len) { break; }
-
- insert_at = rand_below(afl, temp_len - extra_len + 1);
- memcpy(out_buf + insert_at, afl->extras[use_extra].data,
- extra_len);
+ clone_len = choose_block_len(afl, temp_len);
+ clone_from = rand_below(afl, temp_len - clone_len + 1);
}
- break;
-
- } else { // case 16
-
- u32 use_extra, extra_len,
- insert_at = rand_below(afl, temp_len + 1);
- u8 *ptr;
-
- /* Insert an extra. Do the same dice-rolling stuff as for the
- previous case. */
-
- if (!afl->extras_cnt ||
- (afl->a_extras_cnt && rand_below(afl, 2))) {
-
- use_extra = rand_below(afl, afl->a_extras_cnt);
- extra_len = afl->a_extras[use_extra].len;
- ptr = afl->a_extras[use_extra].data;
-
- } else {
-
- use_extra = rand_below(afl, afl->extras_cnt);
- extra_len = afl->extras[use_extra].len;
- ptr = afl->extras[use_extra].data;
-
- }
-
- if (temp_len + extra_len >= MAX_FILE) { break; }
-
- out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len);
-
- /* Tail */
- memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
- temp_len - insert_at);
-
- /* Inserted part */
- memcpy(out_buf + insert_at, ptr, extra_len);
-
- temp_len += extra_len;
-
- break;
-
- }
-
- } else {
-
- /*
- switch (r) {
-
- case 15: // fall through
- case 16:
- case 17: {*/
-
- /* Overwrite bytes with a randomly selected chunk from another
- testcase or insert that chunk. */
-
- if (afl->queued_paths < 4) break;
-
- /* Pick a random queue entry and seek to it. */
-
- u32 tid;
- do
- tid = rand_below(afl, afl->queued_paths);
- while (tid == afl->current_entry);
-
- struct queue_entry *target = afl->queue_buf[tid];
-
- /* Make sure that the target has a reasonable length. */
-
- while (target && (target->len < 2 || target == afl->queue_cur))
- target = target->next;
-
- if (!target) break;
-
- /* Read the testcase into a new buffer. */
-
- fd = open(target->fname, O_RDONLY);
-
- if (unlikely(fd < 0)) {
-
- PFATAL("Unable to open '%s'", target->fname);
-
- }
-
- u32 new_len = target->len;
- u8 *new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len);
-
- ck_read(fd, new_buf, new_len, target->fname);
-
- close(fd);
-
- u8 overwrite = 0;
- if (temp_len >= 2 && rand_below(afl, 2))
- overwrite = 1;
- else if (temp_len + HAVOC_BLK_XL >= MAX_FILE) {
-
- if (temp_len >= 2)
- overwrite = 1;
- else
- break;
-
- }
-
- if (overwrite) {
-
- u32 copy_from, copy_to, copy_len;
-
- copy_len = choose_block_len(afl, new_len - 1);
- if ((s32)copy_len > temp_len) copy_len = temp_len;
-
- copy_from = rand_below(afl, new_len - copy_len + 1);
- copy_to = rand_below(afl, temp_len - copy_len + 1);
-
- memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
-
- } else {
-
- u32 clone_from, clone_to, clone_len;
-
- clone_len = choose_block_len(afl, new_len);
- clone_from = rand_below(afl, new_len - clone_len + 1);
-
- clone_to = rand_below(afl, temp_len);
-
- u8 *temp_buf =
- ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
-
- /* Head */
-
- memcpy(temp_buf, out_buf, clone_to);
-
- /* Inserted part */
-
- memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
-
- /* Tail */
- memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
- temp_len - clone_to);
-
- swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
- out_buf = temp_buf;
- temp_len += clone_len;
-
- }
-
- break;
-
- }
-
- // 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 = ck_maybe_grow(BUF_PARAMS(out), len);
- 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_paths != havoc_queued) {
-
- if (perf_score <= afl->havoc_max_mult * 100) {
-
- afl->stage_max *= 2;
- perf_score *= 2;
-
- }
-
- havoc_queued = afl->queued_paths;
-
- }
-
- }
-
- new_hit_cnt = afl->queued_paths + afl->unique_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->queued_paths > 1 && afl->queue_cur->len > 1) {
-
- 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_paths);
-
- } while (tid == afl->current_entry);
-
- afl->splicing_with = tid;
- target = afl->queue_buf[tid];
-
- /* Make sure that the target has a reasonable length. */
-
- while (target && (target->len < 2 || target == afl->queue_cur)) {
-
- target = target->next;
- ++afl->splicing_with;
-
- }
-
- if (!target) { goto retry_splicing; }
-
- /* Read the testcase into a new buffer. */
-
- fd = open(target->fname, O_RDONLY);
-
- if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); }
-
- new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
-
- ck_read(fd, new_buf, target->len, target->fname);
-
- close(fd);
-
- /* 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;
- memcpy(new_buf, in_buf, split_at);
- swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
- in_buf = new_buf;
-
- out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
- memcpy(out_buf, in_buf, len);
-
- goto custom_mutator_stage;
- /* ???: While integrating Python module, the author decided to jump to
- python stage, but the reason behind this is not clear.*/
- // goto havoc_stage;
-
- }
-
-#endif /* !IGNORE_FINDS */
-
- ret_val = 0;
-
- goto abandon_entry;
-
- /*******************************
- * same RANDOM HAVOC for taint *
- *******************************/
-
-taint_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_paths + afl->unique_crashes;
-
- havoc_queued = afl->queued_paths;
-
- 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. */
-
- if (unlikely(afl->expand_havoc)) {
-
- /* add expensive havoc cases here, they are activated after a full
- cycle without finds happened */
-
- r_max = 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
-
- } else {
-
- r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
-
- }
-
- for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
-
- u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
-
- afl->stage_cur_val = use_stacking;
-
- 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 %zd)", new_len);
-
- }
-
- if (likely(new_len > 0 && custom_havoc_buf)) {
-
- temp_len = new_len;
- if (out_buf != custom_havoc_buf) {
-
- ck_maybe_grow(BUF_PARAMS(out), temp_len);
- memcpy(out_buf, custom_havoc_buf, temp_len);
-
- }
-
- }
-
- }
-
- });
-
- }
-
- switch ((r = rand_below(afl, r_max))) {
-
- case 0:
-
- /* Flip a single bit somewhere. Spooky! */
-
- FLIP_BIT(out_buf, rand_below(afl, temp_len << 3));
- break;
-
- case 1:
-
- /* Set byte to interesting value. */
-
- out_buf[rand_below(afl, temp_len)] =
- interesting_8[rand_below(afl, sizeof(interesting_8))];
- break;
-
- case 2:
-
- /* Set word to interesting value, randomly choosing endian. */
-
- if (temp_len < 2) { break; }
-
- if (rand_below(afl, 2)) {
-
- *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) =
- interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)];
-
- } else {
-
- *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = SWAP16(
- interesting_16[rand_below(afl, sizeof(interesting_16) >> 1)]);
-
- }
-
- break;
-
- case 3:
-
- /* Set dword to interesting value, randomly choosing endian. */
-
- if (temp_len < 4) { break; }
-
- if (rand_below(afl, 2)) {
-
- *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) =
- interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)];
-
- } else {
-
- *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) = SWAP32(
- interesting_32[rand_below(afl, sizeof(interesting_32) >> 2)]);
-
- }
-
- break;
-
- case 4:
-
- /* Randomly subtract from byte. */
-
- out_buf[rand_below(afl, temp_len)] -= 1 + rand_below(afl, ARITH_MAX);
- break;
-
- case 5:
-
- /* Randomly add to byte. */
-
- out_buf[rand_below(afl, temp_len)] += 1 + rand_below(afl, ARITH_MAX);
- break;
-
- case 6:
-
- /* Randomly subtract from word, random endian. */
-
- if (temp_len < 2) { break; }
-
- if (rand_below(afl, 2)) {
-
- u32 pos = rand_below(afl, temp_len - 1);
-
- *(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);
-
- *(u16 *)(out_buf + pos) =
- SWAP16(SWAP16(*(u16 *)(out_buf + pos)) - num);
-
- }
-
- break;
-
- case 7:
-
- /* Randomly add to word, random endian. */
-
- if (temp_len < 2) { break; }
-
- if (rand_below(afl, 2)) {
-
- u32 pos = rand_below(afl, temp_len - 1);
-
- *(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);
-
- *(u16 *)(out_buf + pos) =
- SWAP16(SWAP16(*(u16 *)(out_buf + pos)) + num);
-
- }
-
- break;
-
- case 8:
-
- /* Randomly subtract from dword, random endian. */
-
- if (temp_len < 4) { break; }
-
- if (rand_below(afl, 2)) {
-
- u32 pos = rand_below(afl, temp_len - 3);
-
- *(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);
-
- *(u32 *)(out_buf + pos) =
- SWAP32(SWAP32(*(u32 *)(out_buf + pos)) - num);
-
- }
-
- break;
-
- case 9:
-
- /* Randomly add to dword, random endian. */
-
- if (temp_len < 4) { break; }
-
- if (rand_below(afl, 2)) {
-
- u32 pos = rand_below(afl, temp_len - 3);
-
- *(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);
-
- *(u32 *)(out_buf + pos) =
- SWAP32(SWAP32(*(u32 *)(out_buf + pos)) + num);
-
- }
-
- break;
-
- case 10:
-
- /* 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);
- break;
-
- case 11 ... 12: {
-
- /* 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);
-
- memmove(out_buf + del_from, out_buf + del_from + del_len,
- temp_len - del_from - del_len);
-
- temp_len -= del_len;
-
- break;
-
- }
-
- case 13:
-
- 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 (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);
@@ -2988,7 +2248,11 @@ taint_havoc_stage:
if (actually_clone) {
- memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
+ if (unlikely(afl->taint_needs_splode))
+ memcpy(new_buf + clone_to, afl->taint_src + clone_from,
+ clone_len);
+ else
+ memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
} else {
@@ -3021,16 +2285,29 @@ taint_havoc_stage:
if (temp_len < 2) { break; }
- copy_len = choose_block_len(afl, temp_len - 1);
+ if (unlikely(afl->taint_needs_splode)) {
+
+ copy_len = choose_block_len(afl, afl->queue_cur->len - 1);
+ copy_from = rand_below(afl, afl->queue_cur->len - copy_len + 1);
+
+ } else {
+
+ copy_len = choose_block_len(afl, temp_len - 1);
+ copy_from = rand_below(afl, temp_len - copy_len + 1);
+
+ }
- copy_from = rand_below(afl, temp_len - copy_len + 1);
copy_to = rand_below(afl, temp_len - copy_len + 1);
if (rand_below(afl, 4)) {
if (copy_from != copy_to) {
- memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
+ if (unlikely(afl->taint_needs_splode))
+ memmove(out_buf + copy_to, afl->taint_src + copy_from,
+ copy_len);
+ else
+ memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
}
@@ -3296,10 +2573,17 @@ taint_havoc_stage:
splices them together at some offset, then relies on the havoc
code to mutate that blob. */
-taint_retry_splicing:
+ u32 saved_len;
+
+ if (unlikely(afl->taint_needs_splode))
+ saved_len = afl->taint_len;
+ else
+ saved_len = afl->queue_cur->len;
+
+retry_splicing:
if (afl->use_splicing && splice_cycle++ < SPLICE_CYCLES &&
- afl->queued_paths > 1 && afl->queue_cur->len > 1) {
+ afl->queued_paths > 1 && saved_len > 1) {
struct queue_entry *target;
u32 tid, split_at;
@@ -3312,7 +2596,7 @@ taint_retry_splicing:
if (in_buf != orig_in) {
in_buf = orig_in;
- len = afl->queue_cur->len;
+ len = saved_len;
}
@@ -3336,7 +2620,7 @@ taint_retry_splicing:
}
- if (!target) { goto taint_retry_splicing; }
+ if (!target) { goto retry_splicing; }
/* Read the testcase into a new buffer. */
@@ -3356,7 +2640,7 @@ taint_retry_splicing:
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 taint_retry_splicing; }
+ if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; }
/* Split somewhere between the first and last differing byte. */
@@ -3381,13 +2665,10 @@ taint_retry_splicing:
#endif /* !IGNORE_FINDS */
-
-
ret_val = 0;
goto abandon_entry;
-
/* we are through with this queue entry - for this iteration */
abandon_entry: