about summary refs log tree commit diff
path: root/src/afl-fuzz-extras.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-fuzz-extras.c')
-rw-r--r--src/afl-fuzz-extras.c170
1 files changed, 106 insertions, 64 deletions
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 12771cd7..094c30b9 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -25,23 +25,28 @@
 
 #include "afl-fuzz.h"
 
-/* Helper function for load_extras. */
+/* helper function for auto_extras qsort */
+static int compare_auto_extras_len(const void *ae1, const void *ae2) {
+
+  return ((struct auto_extra_data *)ae1)->len -
+         ((struct auto_extra_data *)ae2)->len;
+
+}
 
-static int compare_extras_len(const void *p1, const void *p2) {
+/* descending order */
 
-  struct extra_data *e1 = (struct extra_data *)p1,
-                    *e2 = (struct extra_data *)p2;
+static int compare_auto_extras_use_d(const void *ae1, const void *ae2) {
 
-  return e1->len - e2->len;
+  return ((struct auto_extra_data *)ae2)->hit_cnt -
+         ((struct auto_extra_data *)ae1)->hit_cnt;
 
 }
 
-static int compare_extras_use_d(const void *p1, const void *p2) {
+/* Helper function for load_extras. */
 
-  struct extra_data *e1 = (struct extra_data *)p1,
-                    *e2 = (struct extra_data *)p2;
+static int compare_extras_len(const void *e1, const void *e2) {
 
-  return e2->hit_cnt - e1->hit_cnt;
+  return ((struct extra_data *)e1)->len - ((struct extra_data *)e2)->len;
 
 }
 
@@ -115,7 +120,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
     if (*lptr == '@') {
 
       ++lptr;
-      if (atoi(lptr) > dict_level) { continue; }
+      if (atoi(lptr) > (s32)dict_level) { continue; }
       while (isdigit(*lptr)) {
 
         ++lptr;
@@ -147,8 +152,10 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
     /* Okay, let's allocate memory and copy data between "...", handling
        \xNN escaping, \\, and \". */
 
-    afl->extras = ck_realloc_block(
-        afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data));
+    afl->extras =
+        afl_realloc((void **)&afl->extras,
+                    (afl->extras_cnt + 1) * sizeof(struct extra_data));
+    if (unlikely(!afl->extras)) { PFATAL("alloc"); }
 
     wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr);
 
@@ -220,6 +227,36 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len,
 
 }
 
+static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
+                                  u8 *dir) {
+
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
+
+  if (!afl->extras_cnt) { FATAL("No usable files in '%s'", dir); }
+
+  qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data),
+        compare_extras_len);
+
+  OKF("Loaded %u extra tokens, size range %s to %s.", afl->extras_cnt,
+      stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
+      stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
+
+  if (max_len > 32) {
+
+    WARNF("Some tokens are relatively large (%s) - consider trimming.",
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len));
+
+  }
+
+  if (afl->extras_cnt > MAX_DET_EXTRAS) {
+
+    WARNF("More than %d tokens - will use them probabilistically.",
+          MAX_DET_EXTRAS);
+
+  }
+
+}
+
 /* Read extras from the extras directory and sort them by size. */
 
 void load_extras(afl_state_t *afl, u8 *dir) {
@@ -249,7 +286,8 @@ void load_extras(afl_state_t *afl, u8 *dir) {
     if (errno == ENOTDIR) {
 
       load_extras_file(afl, dir, &min_len, &max_len, dict_level);
-      goto check_and_sort;
+      extras_check_and_sort(afl, min_len, max_len, dir);
+      return;
 
     }
 
@@ -291,8 +329,10 @@ void load_extras(afl_state_t *afl, u8 *dir) {
     if (min_len > st.st_size) { min_len = st.st_size; }
     if (max_len < st.st_size) { max_len = st.st_size; }
 
-    afl->extras = ck_realloc_block(
-        afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data));
+    afl->extras =
+        afl_realloc((void **)&afl->extras,
+                    (afl->extras_cnt + 1) * sizeof(struct extra_data));
+    if (unlikely(!afl->extras)) { PFATAL("alloc"); }
 
     afl->extras[afl->extras_cnt].data = ck_alloc(st.st_size);
     afl->extras[afl->extras_cnt].len = st.st_size;
@@ -312,56 +352,71 @@ void load_extras(afl_state_t *afl, u8 *dir) {
 
   closedir(d);
 
-check_and_sort:
+  extras_check_and_sort(afl, min_len, max_len, dir);
 
-  if (!afl->extras_cnt) { FATAL("No usable files in '%s'", dir); }
+}
 
-  qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data),
-        compare_extras_len);
+/* Helper function for maybe_add_auto(afl, ) */
 
-  OKF("Loaded %u extra tokens, size range %s to %s.", afl->extras_cnt,
-      stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len),
-      stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len));
+static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
 
-  if (max_len > 32) {
+  while (len--) {
 
-    WARNF("Some tokens are relatively large (%s) - consider trimming.",
-          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len));
+    if (tolower(*(m1++)) ^ tolower(*(m2++))) { return 1; }
 
   }
 
-  if (afl->extras_cnt > MAX_DET_EXTRAS) {
+  return 0;
 
-    WARNF("More than %d tokens - will use them probabilistically.",
-          MAX_DET_EXTRAS);
+}
 
-  }
+/* Adds a new extra / dict entry. */
+void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
 
-}
+  u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
 
-/* Helper function for maybe_add_auto(afl, ) */
+  if (len > MAX_DICT_FILE) {
 
-static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
+    FATAL("Extra '%.*s' is too big (%s, limit is %s)", (int)len, mem,
+          stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len),
+          stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
 
-  while (len--) {
+  } else if (len > 32) {
 
-    if (tolower(*(m1++)) ^ tolower(*(m2++))) { return 1; }
+    WARNF("Extra '%.*s' is pretty large, consider trimming.", (int)len, mem);
 
   }
 
-  return 0;
+  afl->extras = afl_realloc((void **)&afl->extras,
+                            (afl->extras_cnt + 1) * sizeof(struct extra_data));
+  if (unlikely(!afl->extras)) { PFATAL("alloc"); }
+
+  afl->extras[afl->extras_cnt].data = ck_alloc(len);
+  afl->extras[afl->extras_cnt].len = len;
+
+  memcpy(afl->extras[afl->extras_cnt].data, mem, len);
+
+  afl->extras_cnt++;
+
+  qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data),
+        compare_extras_len);
+
+  /* We only want to print this once */
+
+  if (afl->extras_cnt == MAX_DET_EXTRAS + 1) {
+
+    WARNF("More than %d tokens - will use them probabilistically.",
+          MAX_DET_EXTRAS);
+
+  }
 
 }
 
 /* Maybe add automatic extra. */
-/* Ugly hack: afl state is transfered as u8* because we import data via
-   afl-forkserver.c - which is shared with other afl tools that do not
-   have the afl state struct */
 
-void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
+void maybe_add_auto(afl_state_t *afl, u8 *mem, u32 len) {
 
-  afl_state_t *afl = (afl_state_t *)afl_tmp;
-  u32          i;
+  u32 i;
 
   /* Allow users to specify that they don't want auto dictionaries. */
 
@@ -375,7 +430,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
 
   }
 
-  if (i == len) { return; }
+  if (i == len || unlikely(len > MAX_AUTO_EXTRA)) { return; }
 
   /* Reject builtin interesting values. */
 
@@ -402,7 +457,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
 
     while (i--) {
 
-      if (*((u32 *)mem) == interesting_32[i] ||
+      if (*((u32 *)mem) == (u32)interesting_32[i] ||
           *((u32 *)mem) == SWAP32(interesting_32[i])) {
 
         return;
@@ -452,10 +507,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
 
   if (afl->a_extras_cnt < MAX_AUTO_EXTRAS) {
 
-    afl->a_extras = ck_realloc_block(
-        afl->a_extras, (afl->a_extras_cnt + 1) * sizeof(struct extra_data));
-
-    afl->a_extras[afl->a_extras_cnt].data = ck_memdup(mem, len);
+    memcpy(afl->a_extras[afl->a_extras_cnt].data, mem, len);
     afl->a_extras[afl->a_extras_cnt].len = len;
     ++afl->a_extras_cnt;
 
@@ -463,9 +515,7 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) {
 
     i = MAX_AUTO_EXTRAS / 2 + rand_below(afl, (MAX_AUTO_EXTRAS + 1) / 2);
 
-    ck_free(afl->a_extras[i].data);
-
-    afl->a_extras[i].data = ck_memdup(mem, len);
+    memcpy(afl->a_extras[i].data, mem, len);
     afl->a_extras[i].len = len;
     afl->a_extras[i].hit_cnt = 0;
 
@@ -475,13 +525,13 @@ sort_a_extras:
 
   /* First, sort all auto extras by use count, descending order. */
 
-  qsort(afl->a_extras, afl->a_extras_cnt, sizeof(struct extra_data),
-        compare_extras_use_d);
+  qsort(afl->a_extras, afl->a_extras_cnt, sizeof(struct auto_extra_data),
+        compare_auto_extras_use_d);
 
   /* Then, sort the top USE_AUTO_EXTRAS entries by size. */
 
-  qsort(afl->a_extras, MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt),
-        sizeof(struct extra_data), compare_extras_len);
+  qsort(afl->a_extras, MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt),
+        sizeof(struct auto_extra_data), compare_auto_extras_len);
 
 }
 
@@ -494,7 +544,7 @@ void save_auto(afl_state_t *afl) {
   if (!afl->auto_changed) { return; }
   afl->auto_changed = 0;
 
-  for (i = 0; i < MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
+  for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
 
     u8 *fn =
         alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
@@ -544,7 +594,7 @@ void load_auto(afl_state_t *afl) {
 
     if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) {
 
-      maybe_add_auto((u8 *)afl, tmp, len);
+      maybe_add_auto(afl, tmp, len);
 
     }
 
@@ -579,13 +629,5 @@ void destroy_extras(afl_state_t *afl) {
 
   ck_free(afl->extras);
 
-  for (i = 0; i < afl->a_extras_cnt; ++i) {
-
-    ck_free(afl->a_extras[i].data);
-
-  }
-
-  ck_free(afl->a_extras);
-
 }