about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/afl-fuzz.h13
-rw-r--r--src/afl-fuzz-init.c2
-rw-r--r--src/afl-fuzz-queue.c7
-rw-r--r--src/afl-fuzz.c224
4 files changed, 189 insertions, 57 deletions
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index e3e4e246..3f3d6da0 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -236,7 +236,6 @@ struct queue_entry {
       custom,                           /* Marker for custom mutators       */
       stats_mutated;                    /* stats: # of mutations performed  */
 
-  u8 *trace_mini;                       /* Trace bytes, if kept             */
   u32 tc_ref;                           /* Trace bytes ref count            */
 
 #ifdef INTROSPECTION
@@ -246,13 +245,11 @@ struct queue_entry {
   double perf_score,                    /* performance score                */
       weight;
 
-  u8 *testcase_buf;                     /* The testcase buffer, if loaded.  */
-
-  u8             *cmplog_colorinput;    /* the result buf of colorization   */
-  struct tainted *taint;                /* Taint information from CmpLog    */
-
-  struct queue_entry *mother;           /* queue entry this based on        */
-
+  struct queue_entry *mother;            /* queue entry this based on        */
+  u8                 *trace_mini;        /* Trace bytes, if kept             */
+  u8                 *testcase_buf;      /* The testcase buffer, if loaded.  */
+  u8                 *cmplog_colorinput; /* the result buf of colorization   */
+  struct tainted     *taint;             /* Taint information from CmpLog    */
   struct skipdet_entry *skipdet_e;
 
 };
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 7310e49f..98de26dd 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -1019,7 +1019,7 @@ void perform_dry_run(afl_state_t *afl) {
 
           }
 
-          if (!q->was_fuzzed) {
+          if (unlikely(!q->was_fuzzed)) {
 
             q->was_fuzzed = 1;
             afl->reinit_table = 1;
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index f4cb930d..a28172f9 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -401,7 +401,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
 
   } else {
 
-    if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); }
+    if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ }
 
   }
 
@@ -699,12 +699,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
 
 void destroy_queue(afl_state_t *afl) {
 
-  u32 i;
+  u32                 i;
+  struct queue_entry *q;
 
   for (i = 0; i < afl->queued_items; i++) {
 
-    struct queue_entry *q;
-
     q = afl->queue_buf[i];
     ck_free(q->fname);
     ck_free(q->trace_mini);
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index bb05c9c6..d8be5721 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -181,7 +181,7 @@ static void usage(u8 *argv0, int more_help) {
       "it.\n"
       "                  if using QEMU/FRIDA or the fuzzing target is "
       "compiled\n"
-      "                  for CmpLog then use '-c 0'. To disable Cmplog use '-c "
+      "                  for CmpLog then use '-c 0'. To disable CMPLOG use '-c "
       "-'.\n"
       "  -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
       "                  1=small files, 2=larger files (default), 3=all "
@@ -2116,7 +2116,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
       if (read(fr_fd, buf, 32) >= 16) {
 
-        sscanf(buf, "%p", (void**)&prev_target_hash);
+        sscanf(buf, "%p", (void **)&prev_target_hash);
 
       }
 
@@ -2126,7 +2126,6 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-
   write_setup_file(afl, argc, argv);
 
   if (afl->in_place_resume) {
@@ -2143,8 +2142,23 @@ int main(int argc, char **argv_orig, char **envp) {
       snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir);
       if ((fr_fd = open(fn, O_RDONLY)) >= 0) {
 
-        OKF("Performing FAST RESUME");
-        // fast_resume = 1;
+        u8   ver_string[8];
+        u64 *ver = (u64 *)ver_string;
+        u64  expect_ver =
+            afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
+
+        if (read(fr_fd, ver_string, sizeof(ver_string)) != sizeof(ver_string))
+          WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME");
+        else if (expect_ver != *ver)
+          WARNF(
+              "Different AFL++ version or feature usage, cannot perform FAST "
+              "RESUME");
+        else {
+
+          OKF("Will perform FAST RESUME");
+          fast_resume = 1;
+
+        }
 
       } else {
 
@@ -2156,42 +2170,34 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
-  if (fast_resume) {
+  read_testcases(afl, NULL);
 
-    // XXX
+  pivot_inputs(afl);
 
-  } else {
-
-    read_testcases(afl, NULL);
-
-    pivot_inputs(afl);
+  if (!afl->timeout_given) { find_timeout(afl); }  // only for resumes!
 
-    if (!afl->timeout_given) { find_timeout(afl); }  // only for resumes!
+  if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
 
-    if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
+    char tmpfile[PATH_MAX];
 
-      char tmpfile[PATH_MAX];
+    if (afl->file_extension) {
 
-      if (afl->file_extension) {
+      snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
+               afl->file_extension);
 
-        snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
-                 afl->file_extension);
-
-      } else {
-
-        snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
+    } else {
 
-      }
+      snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
 
-      /* there is still a race condition here, but well ... */
-      if (access(tmpfile, F_OK) != -1) {
+    }
 
-        FATAL(
-            "AFL_TMPDIR already has an existing temporary input file: %s - if "
-            "this is not from another instance, then just remove the file.",
-            tmpfile);
+    /* there is still a race condition here, but well ... */
+    if (access(tmpfile, F_OK) != -1) {
 
-      }
+      FATAL(
+          "AFL_TMPDIR already has an existing temporary input file: %s - if "
+          "this is not from another instance, then just remove the file.",
+          tmpfile);
 
     }
 
@@ -2474,7 +2480,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
-    OKF("Cmplog forkserver successfully started");
+    OKF("CMPLOG forkserver successfully started");
 
   }
 
@@ -2512,29 +2518,102 @@ int main(int argc, char **argv_orig, char **envp) {
   dedup_extras(afl);
   if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
 
-  // after we have the correct bitmap size we can read the bitmap -B option
-  // and set the virgin maps
-  if (afl->in_bitmap) {
+  if (unlikely(fast_resume)) {
 
-    read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
+    u64 resume_start = get_cur_time_us();
+    // if we get here then we should abort on errors
+    ck_read(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
+    ck_read(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout");
+    ck_read(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash");
+    ck_read(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes");
 
-  } else {
+    u8                  res[1] = {0};
+    u8                 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
+    u8                 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
+    u32                 r = 8 + afl->fsrv.map_size * 4;
+    u32                 q_len = o_end - o_start;
+    u32                 m_len = (afl->fsrv.map_size >> 3);
+    struct queue_entry *q;
 
-    memset(afl->virgin_bits, 255, map_size);
+    for (u32 i = 0; i < afl->queued_items; i++) {
 
-  }
+      q = afl->queue_buf[i];
+      ck_read(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
+      ck_read(fr_fd, res, 1, "check map");
+      if (res[0]) {
 
-  memset(afl->virgin_tmout, 255, map_size);
-  memset(afl->virgin_crash, 255, map_size);
+        q->trace_mini = ck_alloc(m_len);
+        ck_read(fr_fd, q->trace_mini, m_len, "trace_mini");
+        r += q_len + m_len + 1;
 
-  if (likely(!afl->afl_env.afl_no_startup_calibration)) {
+      } else {
+
+        r += q_len + 1;
+
+      }
+
+      afl->total_bitmap_size += q->bitmap_size;
+      ++afl->total_bitmap_entries;
+      update_bitmap_score(afl, q);
+
+      if (q->was_fuzzed) { --afl->pending_not_fuzzed; }
+
+      if (q->disabled) {
+
+        if (!q->was_fuzzed) { --afl->pending_not_fuzzed; }
+        --afl->active_items;
+
+      }
 
-    perform_dry_run(afl);
+      if (q->var_behavior) { ++afl->queued_variable; }
+      if (q->favored) {
+
+        ++afl->queued_favored;
+        if (!q->was_fuzzed) { ++afl->pending_favored; }
+
+      }
+
+    }
+
+    u8 buf[4];
+    if (read(fr_fd, buf, 3) > 0) {
+
+      FATAL("invalid trailing data in fastresume.bin");
+
+    }
+
+    OKF("Successfully loaded fastresume.bin (%u bytes)!", r);
+    close(fr_fd);
+    afl->reinit_table = 1;
+    update_calibration_time(afl, &resume_start);
 
   } else {
 
-    ACTF("skipping initial seed calibration due option override!");
-    usleep(1000);
+    // after we have the correct bitmap size we can read the bitmap -B option
+    // and set the virgin maps
+    if (afl->in_bitmap) {
+
+      read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
+
+    } else {
+
+      memset(afl->virgin_bits, 255, map_size);
+
+    }
+
+    memset(afl->virgin_tmout, 255, map_size);
+    memset(afl->virgin_crash, 255, map_size);
+
+    if (likely(!afl->afl_env.afl_no_startup_calibration)) {
+
+      perform_dry_run(afl);
+
+    } else {
+
+      ACTF("Skipping initial seed calibration due option override!");
+      usleep(1000);
+
+    }
 
   }
 
@@ -3125,6 +3204,63 @@ stop_fuzzing:
   fclose(afl->fsrv.det_plot_file);
   #endif
 
+  /* create fastresume.bin */
+  u8 fr[PATH_MAX];
+  snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir);
+  if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >=
+      0) {
+
+    u8   ver_string[8];
+    u32  w = 0;
+    u64 *ver = (u64 *)ver_string;
+    *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
+
+    w += write(fr_fd, ver_string, sizeof(ver_string));
+
+    w += write(fr_fd, afl->virgin_bits, afl->fsrv.map_size);
+    w += write(fr_fd, afl->virgin_tmout, afl->fsrv.map_size);
+    w += write(fr_fd, afl->virgin_crash, afl->fsrv.map_size);
+    w += write(fr_fd, afl->var_bytes, afl->fsrv.map_size);
+
+    u8                  on[1] = {1}, off[1] = {0};
+    u8                 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
+    u8                 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
+    u32                 q_len = o_end - o_start;
+    u32                 m_len = (afl->fsrv.map_size >> 3);
+    struct queue_entry *q;
+
+    afl->pending_not_fuzzed = afl->queued_items;
+    afl->active_items = afl->queued_items;
+
+    for (u32 i = 0; i < afl->queued_items; i++) {
+
+      q = afl->queue_buf[i];
+      ck_write(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
+      if (!q->trace_mini) {
+
+        ck_write(fr_fd, off, 1, "no_mini");
+        w += q_len + 1;
+
+      } else {
+
+        ck_write(fr_fd, on, 1, "yes_mini");
+        ck_write(fr_fd, q->trace_mini, m_len, "trace_mini");
+        w += q_len + m_len + 1;
+
+      }
+
+    }
+
+    close(fr_fd);
+    afl->var_byte_count = count_bytes(afl, afl->var_bytes);
+    OKF("Written fastresume.bin with %u bytes!", w);
+
+  } else {
+
+    WARNF("Could not create fastresume.bin");
+
+  }
+
   destroy_queue(afl);
   destroy_extras(afl);
   destroy_custom_mutators(afl);