about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVitalii Akolzin <vva1994@ispras.ru>2020-09-24 18:25:32 +0300
committerVitalii Akolzin <vva1994@ispras.ru>2020-09-24 18:25:32 +0300
commit888d63748a3c6aafd974cb9d96cdb8d3916e82bb (patch)
treecd12b26c558e96c07938647ea1a6baeea3bb56a4
parent60ef1f730551eab66cdfecf4e9815cd841582561 (diff)
downloadafl++-888d63748a3c6aafd974cb9d96cdb8d3916e82bb.tar.gz
Fix potential endless loop in custom_mutator_stage
Co-authored-by: Ivan Gulakov <gulakov@ispras.ru>
-rw-r--r--include/afl-fuzz.h3
-rw-r--r--src/afl-fuzz-one.c64
-rw-r--r--src/afl-fuzz-queue.c2
-rw-r--r--src/afl-fuzz-state.c2
4 files changed, 46 insertions, 25 deletions
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 9404c417..0efd48ec 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -657,6 +657,9 @@ typedef struct afl_state {
    * they do not call another function */
   u8 *map_tmp_buf;
 
+  /* queue entries ready for splicing count (len > 1) */
+  u32 ready_for_splicing_count;
+
 } afl_state_t;
 
 struct custom_mutator {
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 5737c1f5..edae2a88 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1696,50 +1696,58 @@ custom_mutator_stage:
 
           struct queue_entry *target;
           u32                 tid;
-          u8 *                new_buf;
+          u8 *                new_buf = NULL;
+          u32                 target_len = 0;
 
-        retry_external_pick:
-          /* Pick a random other queue entry for passing to external API */
+          if (afl->ready_for_splicing_count > 1 ||
+              (afl->ready_for_splicing_count == 1 &&
+               afl->queue_cur->len == 1)) {
 
-          do {
+          retry_external_pick:
+            /* Pick a random other queue entry for passing to external API */
 
-            tid = rand_below(afl, afl->queued_paths);
+            do {
 
-          } while (tid == afl->current_entry && afl->queued_paths > 1);
+              tid = rand_below(afl, afl->queued_paths);
 
-          afl->splicing_with = tid;
-          target = afl->queue_buf[tid];
+            } while (tid == afl->current_entry && afl->queued_paths > 1);
 
-          /* Make sure that the target has a reasonable length. */
+            afl->splicing_with = tid;
+            target = afl->queue_buf[tid];
 
-          while (target && (target->len < 2 || target == afl->queue_cur) &&
-                 afl->queued_paths > 3) {
+            /* Make sure that the target has a reasonable length. */
 
-            target = target->next;
-            ++afl->splicing_with;
+            while (target && (target->len < 2 || target == afl->queue_cur) &&
+                   afl->queued_paths > 2) {
 
-          }
+              target = target->next;
+              ++afl->splicing_with;
 
-          if (!target) { goto retry_external_pick; }
+            }
 
-          /* Read the additional testcase into a new buffer. */
-          fd = open(target->fname, O_RDONLY);
-          if (unlikely(fd < 0)) {
+            if (!target) { goto retry_external_pick; }
 
-            PFATAL("Unable to open '%s'", target->fname);
+            /* 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 = afl_realloc(AFL_BUF_PARAM(out_scratch), target->len);
-          if (unlikely(!new_buf)) { PFATAL("alloc"); }
-          ck_read(fd, new_buf, target->len, target->fname);
-          close(fd);
+            }
+
+            new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), target->len);
+            if (unlikely(!new_buf)) { PFATAL("alloc"); }
+            ck_read(fd, new_buf, target->len, target->fname);
+            close(fd);
+            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);
+                                  target_len, max_seed_size);
 
           if (unlikely(!mutated_buf)) {
 
@@ -2738,6 +2746,8 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
   if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done) {
 
+    u32 old_len = afl->queue_cur->len;
+
     u8 res = trim_case(afl, afl->queue_cur, in_buf);
 
     if (res == FSRV_RUN_ERROR) {
@@ -2759,6 +2769,10 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
 
     len = afl->queue_cur->len;
 
+    /* maybe current entry stop being ready for splicing */
+    if (old_len > 1 && afl->queue_cur->len == 1)
+      afl->ready_for_splicing_count--;
+
   }
 
   memcpy(out_buf, in_buf, len);
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index ddd08f1c..14aa34fc 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -234,6 +234,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
 
   }
 
+  if (q->len > 1) afl->ready_for_splicing_count++;
+
   ++afl->queued_paths;
   ++afl->pending_not_fuzzed;
 
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index ae45d571..9f68bb51 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -155,6 +155,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
   afl->stats_last_execs = 0;
   afl->stats_avg_exec = -1;
 
+  afl->ready_for_splicing_count = 0;
+
   init_mopt_globals(afl);
 
   list_append(&afl_states, afl);