about summary refs log tree commit diff
path: root/src/afl-fuzz-run.c
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-08-14 13:23:14 +0200
committerGitHub <noreply@github.com>2020-08-14 13:23:14 +0200
commita7537b5511ad767d2240cf2dc6d3e261daa676f9 (patch)
tree2cd8418efff844e634425e050ef716301adfd84b /src/afl-fuzz-run.c
parent15e799f7ae666418e75c6a79db833c5316b21f97 (diff)
parent83281503b3f1d4109c6f7a6af62a2133d55f1150 (diff)
downloadafl++-a7537b5511ad767d2240cf2dc6d3e261daa676f9.tar.gz
Merge branch 'debug' into dev
Diffstat (limited to 'src/afl-fuzz-run.c')
-rw-r--r--src/afl-fuzz-run.c99
1 files changed, 70 insertions, 29 deletions
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index d3f823c9..5381723d 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -350,7 +350,9 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
 
   }
 
-  if (q->exec_cksum) {
+  if (unlikely(afl->taint_mode))
+    q->exec_cksum = 0;
+  else if (q->exec_cksum) {
 
     memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
     hnb = has_new_bits(afl, afl->virgin_bits);
@@ -753,56 +755,65 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
     while (remove_pos < q->len) {
 
       u32 trim_avail = MIN(remove_len, q->len - remove_pos);
-      u64 cksum;
 
-      write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail);
+      if (likely((!q->taint_bytes_highest) ||
+                 (q->len - trim_avail > q->taint_bytes_highest))) {
 
-      fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
-      ++afl->trim_execs;
+        u64 cksum;
 
-      if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
+        write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail);
 
-      /* Note that we don't keep track of crashes or hangs here; maybe TODO?
-       */
+        fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
+        ++afl->trim_execs;
+
+        if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
+
+        /* Note that we don't keep track of crashes or hangs here; maybe TODO?
+         */
+
+        cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+
+        /* If the deletion had no impact on the trace, make it permanent. This
+           isn't perfect for variable-path inputs, but we're just making a
+           best-effort pass, so it's not a big deal if we end up with false
+           negatives every now and then. */
+
+        if (cksum == q->exec_cksum) {
 
-      cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+          u32 move_tail = q->len - remove_pos - trim_avail;
 
-      /* If the deletion had no impact on the trace, make it permanent. This
-         isn't perfect for variable-path inputs, but we're just making a
-         best-effort pass, so it's not a big deal if we end up with false
-         negatives every now and then. */
+          q->len -= trim_avail;
+          len_p2 = next_pow2(q->len);
 
-      if (cksum == q->exec_cksum) {
+          memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail,
+                  move_tail);
 
-        u32 move_tail = q->len - remove_pos - trim_avail;
+          /* Let's save a clean trace, which will be needed by
+             update_bitmap_score once we're done with the trimming stuff. */
 
-        q->len -= trim_avail;
-        len_p2 = next_pow2(q->len);
+          if (!needs_write) {
 
-        memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail,
-                move_tail);
+            needs_write = 1;
+            memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
 
-        /* Let's save a clean trace, which will be needed by
-           update_bitmap_score once we're done with the trimming stuff. */
+          }
 
-        if (!needs_write) {
+        } else {
 
-          needs_write = 1;
-          memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
+          remove_pos += remove_len;
 
         }
 
+        /* Since this can be slow, update the screen every now and then. */
+        if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
+        ++afl->stage_cur;
+
       } else {
 
         remove_pos += remove_len;
 
       }
 
-      /* Since this can be slow, update the screen every now and then. */
-
-      if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
-      ++afl->stage_cur;
-
     }
 
     remove_len >>= 1;
@@ -855,6 +866,8 @@ abort_trimming:
 
 }
 
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
 /* Write a modified test case, run program, process results. Handle
    error conditions, returning 1 if it's time to bail out. This is
    a helper function for fuzz_one(). */
@@ -864,6 +877,32 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   u8 fault;
 
+  if (unlikely(afl->taint_needs_splode)) {
+
+    s32 new_len = afl->queue_cur->len + len - afl->taint_len;
+    if (new_len < 4)
+      new_len = 4;
+    else if (new_len > MAX_FILE)
+      new_len = MAX_FILE;
+    u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), new_len);
+
+    u32 i, taint = 0;
+    for (i = 0; i < (u32)new_len; i++) {
+
+      if (i >= afl->taint_len || i >= afl->queue_cur->len || afl->taint_map[i])
+        new_buf[i] = out_buf[taint++];
+      else
+        new_buf[i] = afl->taint_src[i];
+
+    }
+
+    swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
+
+    out_buf = new_buf;
+    len = new_len;
+
+  }
+
   write_to_testcase(afl, out_buf, len);
 
   fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
@@ -911,3 +950,5 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
 }
 
+#undef BUF_PARAMS
+