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.c193
1 files changed, 109 insertions, 84 deletions
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 6d399a03..dff1606a 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -384,17 +384,17 @@ u8 fuzz_one_original(afl_state_t *afl) {
 
 #else
 
-  if (unlikely(afl->mutator) && unlikely(afl->mutator->afl_custom_queue_get)) {
+  if (unlikely(afl->custom_mutators_count )) {
 
     /* The custom mutator will decide to skip this test case or not. */
 
-    if (!afl->mutator->afl_custom_queue_get(afl->mutator->data,
-                                            afl->queue_cur->fname)) {
+    LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
 
-      return 1;
-
-    }
+      if (el->afl_custom_queue_get && !el->afl_custom_queue_get(el->data, afl->queue_cur->fname)) {
+        return 1;
+      }
 
+    } );
   }
 
   if (likely(afl->pending_favored)) {
@@ -1646,13 +1646,13 @@ custom_mutator_stage:
    * CUSTOM MUTATORS *
    *******************/
 
-  if (likely(!afl->mutator)) { goto havoc_stage; }
-  if (likely(!afl->mutator->afl_custom_fuzz)) { goto havoc_stage; }
+  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; }
 
@@ -1660,98 +1660,111 @@ custom_mutator_stage:
 
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
-  for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
+  LIST_FOREACH (&afl->custom_mutator_list, struct custom_mutator, {
 
-    struct queue_entry *target;
-    u32                 tid;
-    u8 *                new_buf;
+    if ( el->afl_custom_fuzz ) {
 
-  retry_external_pick:
-    /* Pick a random other queue entry for passing to external API */
-    do {
+      has_custom_fuzz = true;
 
-      tid = rand_below(afl, afl->queued_paths);
+      for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
 
-    } while (tid == afl->current_entry && afl->queued_paths > 1);
+        struct queue_entry *target;
+        u32                 tid;
+        u8 *                new_buf;
 
-    target = afl->queue;
+      retry_external_pick:
+        /* Pick a random other queue entry for passing to external API */
+        do {
 
-    while (tid >= 100) {
+          tid = rand_below(afl, afl->queued_paths);
 
-      target = target->next_100;
-      tid -= 100;
+        } while (tid == afl->current_entry && afl->queued_paths > 1);
 
-    }
+        target = afl->queue;
 
-    while (tid--) {
+        while (tid >= 100) {
 
-      target = target->next;
+          target = target->next_100;
+          tid -= 100;
 
-    }
+        }
 
-    /* Make sure that the target has a reasonable length. */
+        while (tid--) {
 
-    while (target && (target->len < 2 || target == afl->queue_cur) &&
-           afl->queued_paths > 1) {
+          target = target->next;
 
-      target = target->next;
-      ++afl->splicing_with;
+        }
 
-    }
+        /* Make sure that the target has a reasonable length. */
 
-    if (!target) { goto retry_external_pick; }
+        while (target && (target->len < 2 || target == afl->queue_cur) &&
+              afl->queued_paths > 1) {
 
-    /* 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); }
+          target = target->next;
+          ++afl->splicing_with;
 
-    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;
+        if (!target) { goto retry_external_pick; }
 
-    size_t mutated_size = afl->mutator->afl_custom_fuzz(
-        afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len,
-        max_seed_size);
+        /* 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); }
 
-    if (unlikely(!mutated_buf)) {
+        new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
+        ck_read(fd, new_buf, target->len, target->fname);
+        close(fd);
 
-      FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
+        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 (mutated_size > 0) {
+        if (unlikely(!mutated_buf)) {
 
-      if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
+          FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
 
-        goto abandon_entry;
+        }
 
-      }
+        if (mutated_size > 0) {
+
+          if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
+
+            goto abandon_entry;
+
+          }
 
-      /* If we're finding new stuff, let's run for a bit longer, limits
-         permitting. */
+          /* If we're finding new stuff, let's run for a bit longer, limits
+            permitting. */
 
-      if (afl->queued_paths != havoc_queued) {
+          if (afl->queued_paths != havoc_queued) {
 
-        if (perf_score <= afl->havoc_max_mult * 100) {
+            if (perf_score <= afl->havoc_max_mult * 100) {
 
-          afl->stage_max *= 2;
-          perf_score *= 2;
+              afl->stage_max *= 2;
+              perf_score *= 2;
+
+            }
+
+            havoc_queued = afl->queued_paths;
+
+          }
 
         }
 
-        havoc_queued = afl->queued_paths;
+        /* `(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);
 
       }
 
     }
 
-    /* `(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);
 
-  }
+  } );
+
+  if (!has_custom_fuzz) goto havoc_stage;
 
   new_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
@@ -1803,20 +1816,25 @@ havoc_stage:
 
   havoc_queued = afl->queued_paths;
 
-  u8 stacked_custom = (afl->mutator && afl->mutator->afl_custom_havoc_mutation);
-  u8 stacked_custom_prob = 6;  // like one of the default mutations in havoc
+  if (afl->custom_mutators_count) {
 
-  if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) {
+    LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
 
-    stacked_custom_prob =
-        afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data);
-    if (stacked_custom_prob > 100) {
+      if (el->stacked_custom && el->afl_custom_havoc_mutation_probability) {
 
-      FATAL(
-          "The probability returned by afl_custom_havoc_mutation_propability "
-          "has to be in the range 0-100.");
+        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.");
+
+        }
+
+      }
+    
+    } );
 
   }
 
@@ -1831,29 +1849,36 @@ havoc_stage:
 
     for (i = 0; i < use_stacking; ++i) {
 
-      if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) {
+      if (afl->custom_mutators_count) {
+      
+        LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
 
-        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)) {
+          if (el->stacked_custom && rand_below(afl, 100) < el->stacked_custom_prob) {
 
-          FATAL("Error in custom_havoc (return %zd)", new_len);
+            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) {
+            if (likely(new_len > 0 && custom_havoc_buf)) {
 
-            ck_maybe_grow(BUF_PARAMS(out), temp_len);
-            memcpy(out_buf, custom_havoc_buf, temp_len);
+              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 (rand_below(