about summary refs log tree commit diff
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.c150
1 files changed, 74 insertions, 76 deletions
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index cc150cfe..b20bde90 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -347,6 +347,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
   u8  a_collect[MAX_AUTO_EXTRA];
   u32 a_len = 0;
 
+/* Not pretty, but saves a lot of writing */
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
 #ifdef IGNORE_FINDS
 
   /* In IGNORE_FINDS mode, skip any entries that weren't in the
@@ -360,7 +363,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
     /* The custom mutator will decide to skip this test case or not. */
 
-    if (!afl->mutator->afl_custom_queue_get(afl, afl->queue_cur->fname))
+    if (!afl->mutator->afl_custom_queue_get(afl->mutator->data,
+                                            afl->queue_cur->fname))
       return 1;
 
   }
@@ -426,7 +430,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
      single byte anyway, so it wouldn't give us any performance or memory usage
      benefits. */
 
-  out_buf = ck_alloc_nozero(len);
+  out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
 
   afl->subseq_tmouts = 0;
 
@@ -718,7 +722,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
   /* Initialize effector map for the next step (see comments below). Always
      flag first and last byte as doing something. */
 
-  eff_map = ck_alloc(EFF_ALEN(len));
+  eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -1442,7 +1446,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  ex_tmp = ck_alloc(len + MAX_DICT_FILE);
+  ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
   for (i = 0; i <= len; ++i) {
 
@@ -1465,7 +1469,6 @@ skip_interest:
 
       if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
 
-        ck_free(ex_tmp);
         goto abandon_entry;
 
       }
@@ -1479,8 +1482,6 @@ skip_interest:
 
   }
 
-  ck_free(ex_tmp);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
@@ -1606,18 +1607,23 @@ custom_mutator_stage:
     /* Read the additional 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_alloc_nozero(target->len);
+
+    new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
     ck_read(fd, new_buf, target->len, target->fname);
     close(fd);
 
+    u8 *mutated_buf = NULL;
+
     size_t mutated_size = afl->mutator->afl_custom_fuzz(
-        afl, &out_buf, len, new_buf, target->len, max_seed_size);
+        afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len,
+        max_seed_size);
 
-    ck_free(new_buf);
+    if (unlikely(!mutated_buf))
+      FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
 
     if (mutated_size > 0) {
 
-      if (common_fuzz_stuff(afl, out_buf, (u32)mutated_size)) {
+      if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
 
         goto abandon_entry;
 
@@ -1641,7 +1647,8 @@ custom_mutator_stage:
 
     }
 
-    if (mutated_size < len) out_buf = ck_realloc(out_buf, len);
+    /* `(afl->)out_buf` may have been changed by the call to custom_fuzz */
+    /* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs Memcpy. */
     memcpy(out_buf, in_buf, len);
 
   }
@@ -1702,7 +1709,7 @@ havoc_stage:
   if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) {
 
     stacked_custom_prob =
-        afl->mutator->afl_custom_havoc_mutation_probability(afl);
+        afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data);
     if (stacked_custom_prob > 100)
       FATAL(
           "The probability returned by afl_custom_havoc_mutation_propability "
@@ -1723,8 +1730,22 @@ havoc_stage:
 
       if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) {
 
-        temp_len = afl->mutator->afl_custom_havoc_mutation(afl, &out_buf,
-                                                           temp_len, MAX_FILE);
+        u8 *   custom_havoc_buf = NULL;
+        size_t new_len = afl->mutator->afl_custom_havoc_mutation(
+            afl->mutator->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);
+
+          }
+
+        }
 
       }
 
@@ -1954,7 +1975,8 @@ havoc_stage:
 
             clone_to = rand_below(afl, temp_len);
 
-            new_buf = ck_alloc_nozero(temp_len + clone_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
 
             /* Head */
 
@@ -1974,8 +1996,9 @@ havoc_stage:
             memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
                    temp_len - clone_to);
 
-            ck_free(out_buf);
+            swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
             out_buf = new_buf;
+            new_buf = NULL;
             temp_len += clone_len;
 
           }
@@ -2068,7 +2091,8 @@ havoc_stage:
 
             if (temp_len + extra_len >= MAX_FILE) break;
 
-            new_buf = ck_alloc_nozero(temp_len + extra_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
 
             /* Head */
             memcpy(new_buf, out_buf, insert_at);
@@ -2084,7 +2108,8 @@ havoc_stage:
 
             if (temp_len + extra_len >= MAX_FILE) break;
 
-            new_buf = ck_alloc_nozero(temp_len + extra_len);
+            new_buf =
+                ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
 
             /* Head */
             memcpy(new_buf, out_buf, insert_at);
@@ -2098,8 +2123,9 @@ havoc_stage:
           memcpy(new_buf + insert_at + extra_len, out_buf + insert_at,
                  temp_len - insert_at);
 
-          ck_free(out_buf);
+          swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
           out_buf = new_buf;
+          new_buf = NULL;
           temp_len += extra_len;
 
           break;
@@ -2115,7 +2141,7 @@ havoc_stage:
     /* out_buf might have been mangled a bit, so let's restore it to its
        original size and shape. */
 
-    if (temp_len < len) out_buf = ck_realloc(out_buf, len);
+    out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
     temp_len = len;
     memcpy(out_buf, in_buf, len);
 
@@ -2177,7 +2203,6 @@ retry_splicing:
 
     if (in_buf != orig_in) {
 
-      ck_free(in_buf);
       in_buf = orig_in;
       len = afl->queue_cur->len;
 
@@ -2221,7 +2246,7 @@ retry_splicing:
 
     if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
 
-    new_buf = ck_alloc_nozero(target->len);
+    new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
 
     ck_read(fd, new_buf, target->len, target->fname);
 
@@ -2233,12 +2258,7 @@ retry_splicing:
 
     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) {
-
-      ck_free(new_buf);
-      goto 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. */
 
@@ -2248,10 +2268,10 @@ retry_splicing:
 
     len = target->len;
     memcpy(new_buf, in_buf, split_at);
+    swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
     in_buf = new_buf;
 
-    ck_free(out_buf);
-    out_buf = ck_alloc_nozero(len);
+    out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
     memcpy(out_buf, in_buf, len);
 
     goto custom_mutator_stage;
@@ -2279,12 +2299,14 @@ radamsa_stage:
 
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
-  /* Read the additional testcase into a new buffer. */
-  u8 *save_buf = ck_alloc_nozero(len);
+  /* Read the additional testcase.
+  We'll reuse in_scratch, as it is free at this point.
+  */
+  u8 *save_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), len);
   memcpy(save_buf, out_buf, len);
 
   u32 max_len = len + choose_block_len(afl, HAVOC_BLK_XL);
-  u8 *new_buf = ck_alloc_nozero(max_len);
+  u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), max_len);
   u8 *tmp_buf;
 
   for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -2304,19 +2326,10 @@ radamsa_stage:
 
     }
 
-    if (common_fuzz_stuff(afl, tmp_buf, temp_len)) {
-
-      ck_free(save_buf);
-      ck_free(new_buf);
-      goto abandon_entry;
-
-    }
+    if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { goto abandon_entry; }
 
   }
 
-  ck_free(save_buf);
-  ck_free(new_buf);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_RADAMSA] += new_hit_cnt - orig_hit_cnt;
@@ -2346,10 +2359,6 @@ abandon_entry:
 
   munmap(orig_in, afl->queue_cur->len);
 
-  if (in_buf != orig_in) ck_free(in_buf);
-  ck_free(out_buf);
-  ck_free(eff_map);
-
   return ret_val;
 
 #undef FLIP_BIT
@@ -2448,7 +2457,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
      single byte anyway, so it wouldn't give us any performance or memory usage
      benefits. */
 
-  out_buf = ck_alloc_nozero(len);
+  out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
 
   afl->subseq_tmouts = 0;
 
@@ -2727,7 +2736,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
   /* Initialize effector map for the next step (see comments below). Always
          flag first and last byte as doing something. */
 
-  eff_map = ck_alloc(EFF_ALEN(len));
+  eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
   eff_map[0] = 1;
 
   if (EFF_APOS(len - 1) != 0) {
@@ -3451,7 +3460,7 @@ skip_interest:
 
   orig_hit_cnt = new_hit_cnt;
 
-  ex_tmp = ck_alloc(len + MAX_DICT_FILE);
+  ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
 
   for (i = 0; i <= len; ++i) {
 
@@ -3474,7 +3483,6 @@ skip_interest:
 
       if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
 
-        ck_free(ex_tmp);
         goto abandon_entry;
 
       }
@@ -3488,8 +3496,6 @@ skip_interest:
 
   }                                                  /* for i = 0; i <= len */
 
-  ck_free(ex_tmp);
-
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
   afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
@@ -3893,7 +3899,8 @@ pacemaker_fuzzing:
 
                 clone_to = rand_below(afl, temp_len);
 
-                new_buf = ck_alloc_nozero(temp_len + clone_len);
+                new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
+                                        temp_len + clone_len);
 
                 /* Head */
 
@@ -3914,7 +3921,7 @@ pacemaker_fuzzing:
                 memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
                        temp_len - clone_to);
 
-                ck_free(out_buf);
+                swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
                 out_buf = new_buf;
                 temp_len += clone_len;
                 MOpt_globals.cycles_v2[STAGE_Clone75] += 1;
@@ -3967,7 +3974,7 @@ pacemaker_fuzzing:
         /* out_buf might have been mangled a bit, so let's restore it to its
            original size and shape. */
 
-        if (temp_len < len) out_buf = ck_realloc(out_buf, len);
+        out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
         temp_len = len;
         memcpy(out_buf, in_buf, len);
 
@@ -4045,7 +4052,6 @@ pacemaker_fuzzing:
 
         if (in_buf != orig_in) {
 
-          ck_free(in_buf);
           in_buf = orig_in;
           len = afl->queue_cur->len;
 
@@ -4090,7 +4096,7 @@ pacemaker_fuzzing:
 
         if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
 
-        new_buf = ck_alloc_nozero(target->len);
+        new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
 
         ck_read(fd, new_buf, target->len, target->fname);
 
@@ -4104,7 +4110,6 @@ pacemaker_fuzzing:
 
         if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
 
-          ck_free(new_buf);
           goto retry_splicing_puppet;
 
         }
@@ -4117,9 +4122,9 @@ pacemaker_fuzzing:
 
         len = target->len;
         memcpy(new_buf, in_buf, split_at);
+        swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
         in_buf = new_buf;
-        ck_free(out_buf);
-        out_buf = ck_alloc_nozero(len);
+        out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
         memcpy(out_buf, in_buf, len);
 
         goto havoc_stage_puppet;
@@ -4154,10 +4159,6 @@ pacemaker_fuzzing:
 
       munmap(orig_in, afl->queue_cur->len);
 
-      if (in_buf != orig_in) ck_free(in_buf);
-      ck_free(out_buf);
-      ck_free(eff_map);
-
       if (afl->key_puppet == 1) {
 
         if (unlikely(
@@ -4379,18 +4380,13 @@ u8 fuzz_one(afl_state_t *afl) {
   int key_val_lv = 0;
 
 #ifdef _AFL_DOCUMENT_MUTATIONS
-  if (afl->do_document == 0) {
-
-    char *fn = alloc_printf("%s/mutations", afl->out_dir);
-    if (fn) {
 
-      afl->do_document = mkdir(fn, 0700);  // if it exists we do not care
-      afl->do_document = 1;
-      ck_free(fn);
-
-    } else
+  u8 path_buf[PATH_MAX];
+  if (afl->do_document == 0) {
 
-      PFATAL("malloc()");
+    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 {
 
@@ -4418,5 +4414,7 @@ u8 fuzz_one(afl_state_t *afl) {
 
   return key_val_lv;
 
+#undef BUF_PARAMS
+
 }