about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-as.c2
-rw-r--r--src/afl-forkserver.c16
-rw-r--r--src/afl-fuzz-extras.c20
-rw-r--r--src/afl-fuzz-init.c22
-rw-r--r--src/afl-fuzz-mutators.c5
-rw-r--r--src/afl-fuzz-one.c149
-rw-r--r--src/afl-fuzz-python.c59
-rw-r--r--src/afl-fuzz-state.c14
-rw-r--r--src/afl-fuzz.c38
-rw-r--r--src/afl-gcc.c2
-rw-r--r--src/afl-performance.c12
-rw-r--r--src/afl-showmap.c15
-rw-r--r--src/afl-tmin.c14
13 files changed, 255 insertions, 113 deletions
diff --git a/src/afl-as.c b/src/afl-as.c
index 0ed47d8c..7d70bfcd 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -152,7 +152,7 @@ static void edit_params(int argc, char **argv) {
 
     /* The Apple case is a bit different... */
 
-    if (!strcmp(argv[i], "-arch") && i + 1 < argc) {
+    if (!strcmp(argv[i], "-arch") && i + 1 < (u32)argc) {
 
       if (!strcmp(argv[i + 1], "x86_64"))
         use_64bit = 1;
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 8277116b..93203cb2 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -79,6 +79,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->use_stdin = 1;
   fsrv->no_unlink = 0;
   fsrv->exec_tmout = EXEC_TIMEOUT;
+  fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
   fsrv->mem_limit = MEM_LIMIT;
   fsrv->out_file = NULL;
 
@@ -101,6 +102,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->out_fd = from->out_fd;
   fsrv_to->dev_null_fd = from->dev_null_fd;
   fsrv_to->exec_tmout = from->exec_tmout;
+  fsrv_to->init_tmout = from->init_tmout;
   fsrv_to->mem_limit = from->mem_limit;
   fsrv_to->map_size = from->map_size;
   fsrv_to->support_shmem_fuzz = from->support_shmem_fuzz;
@@ -115,6 +117,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->out_file = NULL;
 
   fsrv_to->init_child_func = fsrv_exec_child;
+  // Note: do not copy ->add_extra_func
 
   list_append(&fsrv_list, fsrv_to);
 
@@ -516,15 +519,14 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
   rlen = 0;
   if (fsrv->exec_tmout) {
 
-    u32 time_ms =
-        read_s32_timed(fsrv->fsrv_st_fd, &status,
-                       fsrv->exec_tmout * FORK_WAIT_MULT, stop_soon_p);
+    u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
+                                 stop_soon_p);
 
     if (!time_ms) {
 
       kill(fsrv->fsrv_pid, SIGKILL);
 
-    } else if (time_ms > fsrv->exec_tmout * FORK_WAIT_MULT) {
+    } else if (time_ms > fsrv->init_tmout) {
 
       fsrv->last_run_timed_out = 1;
       kill(fsrv->fsrv_pid, SIGKILL);
@@ -632,7 +634,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
         if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
 
-          // this is not afl-fuzz - we deny and return
+          // this is not afl-fuzz - or it is cmplog - we deny and return
           if (fsrv->use_shmem_fuzz) {
 
             status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
@@ -939,7 +941,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
     s32 fd = fsrv->out_fd;
 
-    if (fsrv->out_file) {
+    if (!fsrv->use_stdin) {
 
       if (fsrv->no_unlink) {
 
@@ -962,7 +964,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
     ck_write(fd, buf, len, fsrv->out_file);
 
-    if (!fsrv->out_file) {
+    if (fsrv->use_stdin) {
 
       if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); }
       lseek(fd, 0, SEEK_SET);
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 1452c55e..d6c368d1 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -248,10 +248,10 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
 
   }
 
-  if (afl->extras_cnt > MAX_DET_EXTRAS) {
+  if (afl->extras_cnt > afl->max_det_extras) {
 
-    WARNF("More than %d tokens - will use them probabilistically.",
-          MAX_DET_EXTRAS);
+    OKF("More than %d tokens - will use them probabilistically.",
+        afl->max_det_extras);
 
   }
 
@@ -319,8 +319,8 @@ void load_extras(afl_state_t *afl, u8 *dir) {
 
     if (st.st_size > MAX_DICT_FILE) {
 
-      FATAL(
-          "Extra '%s' is too big (%s, limit is %s)", fn,
+      WARNF(
+          "Extra '%s' is very big (%s, limit is %s)", fn,
           stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
           stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
 
@@ -370,14 +370,14 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
 
 }
 
-/* Adds a new extra / dict entry. */
+/* Adds a new extra / dict entry. Used for LTO autodict. */
 void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
 
   u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
 
   if (len > MAX_DICT_FILE) {
 
-    FATAL("Extra '%.*s' is too big (%s, limit is %s)", (int)len, mem,
+    WARNF("Extra '%.*s' is very 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));
 
@@ -403,10 +403,10 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
 
   /* We only want to print this once */
 
-  if (afl->extras_cnt == MAX_DET_EXTRAS + 1) {
+  if (afl->extras_cnt == afl->max_det_extras + 1) {
 
-    WARNF("More than %d tokens - will use them probabilistically.",
-          MAX_DET_EXTRAS);
+    OKF("More than %d tokens - will use them probabilistically.",
+        afl->max_det_extras);
 
   }
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 350a8599..102f04b9 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -256,18 +256,18 @@ void bind_to_free_cpu(afl_state_t *afl) {
 
   }
 
-  for (i = 0; i < proccount; i++) {
+  for (i = 0; i < (s32)proccount; i++) {
 
     #if defined(__FreeBSD__)
 
     if (!strcmp(procs[i].ki_comm, "idle")) continue;
 
     // fix when ki_oncpu = -1
-    int oncpu;
+    s32 oncpu;
     oncpu = procs[i].ki_oncpu;
     if (oncpu == -1) oncpu = procs[i].ki_lastcpu;
 
-    if (oncpu != -1 && oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
+    if (oncpu != -1 && oncpu < (s32)sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
       cpu_used[oncpu] = 1;
 
     #elif defined(__DragonFly__)
@@ -1841,24 +1841,26 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) {
 
 void setup_stdio_file(afl_state_t *afl) {
 
-  u8 *fn;
   if (afl->file_extension) {
 
-    fn = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
+    afl->fsrv.out_file =
+        alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
 
   } else {
 
-    fn = alloc_printf("%s/.cur_input", afl->tmp_dir);
+    afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
 
   }
 
-  unlink(fn);                                              /* Ignore errors */
+  unlink(afl->fsrv.out_file);                              /* Ignore errors */
 
-  afl->fsrv.out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600);
+  afl->fsrv.out_fd = open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, 0600);
 
-  if (afl->fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fn); }
+  if (afl->fsrv.out_fd < 0) {
 
-  ck_free(fn);
+    PFATAL("Unable to create '%s'", afl->fsrv.out_file);
+
+  }
 
 }
 
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index 22578df9..d24b7db9 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -166,6 +166,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
 
   }
 
+  /* "afl_custom_fuzz_count", optional */
+  mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
+  if (!mutator->afl_custom_fuzz_count)
+    ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
+
   /* "afl_custom_deinit", optional for backward compatibility */
   mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
   if (!mutator->afl_custom_deinit)
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 3bf0c195..bf568c38 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1509,13 +1509,13 @@ skip_interest:
 
     for (j = 0; j < afl->extras_cnt; ++j) {
 
-      /* Skip extras probabilistically if afl->extras_cnt > MAX_DET_EXTRAS. Also
-         skip them if there's no room to insert the payload, if the token
+      /* Skip extras probabilistically if afl->extras_cnt > AFL_MAX_DET_EXTRAS.
+         Also skip them if there's no room to insert the payload, if the token
          is redundant, or if its entire span has no bytes set in the effector
          map. */
 
-      if ((afl->extras_cnt > MAX_DET_EXTRAS &&
-           rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
+      if ((afl->extras_cnt > afl->max_det_extras &&
+           rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) ||
           afl->extras[j].len > len - i ||
           !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
@@ -1672,7 +1672,7 @@ custom_mutator_stage:
 
   if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
 
-  const u32 max_seed_size = MAX_FILE;
+  const u32 max_seed_size = MAX_FILE, saved_max = afl->stage_max;
 
   orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
 
@@ -1680,104 +1680,123 @@ custom_mutator_stage:
 
     if (el->afl_custom_fuzz) {
 
+      if (el->afl_custom_fuzz_count)
+        afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
+      else
+        afl->stage_max = saved_max;
+
       has_custom_fuzz = true;
 
       afl->stage_short = el->name_short;
 
-      for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
-           ++afl->stage_cur) {
+      if (afl->stage_max) {
 
-        struct queue_entry *target;
-        u32                 tid;
-        u8 *                new_buf;
+        for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
+             ++afl->stage_cur) {
 
-      retry_external_pick:
-        /* Pick a random other queue entry for passing to external API */
+          struct queue_entry *target;
+          u32                 tid;
+          u8 *                new_buf;
 
-        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);
 
-        target = afl->queue;
+          } while (tid == afl->current_entry && afl->queued_paths > 1);
 
-        while (tid >= 100) {
+          target = afl->queue;
 
-          target = target->next_100;
-          tid -= 100;
+          while (tid >= 100) {
 
-        }
+            target = target->next_100;
+            tid -= 100;
 
-        while (tid--) {
-
-          target = target->next;
+          }
 
-        }
+          while (tid--) {
 
-        /* Make sure that the target has a reasonable length. */
+            target = target->next;
 
-        while (target && (target->len < 2 || target == afl->queue_cur) &&
-               afl->queued_paths > 3) {
+          }
 
-          target = target->next;
-          ++afl->splicing_with;
+          /* Make sure that the target has a reasonable length. */
 
-        }
+          while (target && (target->len < 2 || target == afl->queue_cur) &&
+                 afl->queued_paths > 3) {
 
-        if (!target) { goto retry_external_pick; }
+            target = target->next;
+            ++afl->splicing_with;
 
-        /* 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);
+          if (!target) { goto retry_external_pick; }
 
-        u8 *mutated_buf = NULL;
+          /* Read the additional testcase into a new buffer. */
+          fd = open(target->fname, O_RDONLY);
+          if (unlikely(fd < 0)) {
 
-        size_t mutated_size =
-            el->afl_custom_fuzz(el->data, out_buf, len, &mutated_buf, new_buf,
-                                target->len, max_seed_size);
+            PFATAL("Unable to open '%s'", target->fname);
 
-        if (unlikely(!mutated_buf)) {
+          }
 
-          FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
+          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);
 
-        }
+          u8 *mutated_buf = NULL;
 
-        if (mutated_size > 0) {
+          size_t mutated_size =
+              el->afl_custom_fuzz(el->data, out_buf, len, &mutated_buf, new_buf,
+                                  target->len, max_seed_size);
 
-          if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
+          if (unlikely(!mutated_buf)) {
 
-            goto abandon_entry;
+            FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
 
           }
 
-          /* If we're finding new stuff, let's run for a bit longer, limits
-            permitting. */
+          if (mutated_size > 0) {
 
-          if (afl->queued_paths != havoc_queued) {
+            if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
 
-            if (perf_score <= afl->havoc_max_mult * 100) {
-
-              afl->stage_max *= 2;
-              perf_score *= 2;
+              goto abandon_entry;
 
             }
 
-            havoc_queued = afl->queued_paths;
+            if (!el->afl_custom_fuzz_count) {
+
+              /* If we're finding new stuff, let's run for a bit longer, limits
+                permitting. */
+
+              if (afl->queued_paths != havoc_queued) {
+
+                if (perf_score <= afl->havoc_max_mult * 100) {
+
+                  afl->stage_max *= 2;
+                  perf_score *= 2;
+
+                }
+
+                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);
+        }
 
       }
 
@@ -3722,13 +3741,13 @@ skip_interest:
 
     for (j = 0; j < afl->extras_cnt; ++j) {
 
-      /* Skip extras probabilistically if afl->extras_cnt > MAX_DET_EXTRAS. Also
-         skip them if there's no room to insert the payload, if the token
+      /* Skip extras probabilistically if afl->extras_cnt > AFL_MAX_DET_EXTRAS.
+         Also skip them if there's no room to insert the payload, if the token
          is redundant, or if its entire span has no bytes set in the effector
          map. */
 
-      if ((afl->extras_cnt > MAX_DET_EXTRAS &&
-           rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
+      if ((afl->extras_cnt > afl->max_det_extras &&
+           rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) ||
           afl->extras[j].len > len - i ||
           !memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
           !memchr(eff_map + EFF_APOS(i), 1,
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index e540f548..adb92649 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -144,6 +144,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
     py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
     if (!py_functions[PY_FUNC_FUZZ])
       py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
+    py_functions[PY_FUNC_FUZZ_COUNT] =
+        PyObject_GetAttrString(py_module, "fuzz_count");
     if (!py_functions[PY_FUNC_FUZZ])
       WARNF("fuzz function not found in python module");
     py_functions[PY_FUNC_POST_PROCESS] =
@@ -169,27 +171,20 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
 
       if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
 
-        if (py_idx == PY_FUNC_POST_PROCESS) {
-
-          // Implenting the post_process API is optional for now
-          if (PyErr_Occurred()) { PyErr_Print(); }
-
-        } else if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
+        if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
 
           // Implementing the trim API is optional for now
           if (PyErr_Occurred()) { PyErr_Print(); }
           py_notrim = 1;
 
-        } else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) &&
+        } else if (py_idx >= PY_OPTIONAL) {
 
-                   (py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) {
+          // Only _init and _deinit are not optional currently
 
-          // Implenting the havoc and queue API is optional for now
           if (PyErr_Occurred()) { PyErr_Print(); }
 
         } else {
 
-          if (PyErr_Occurred()) { PyErr_Print(); }
           fprintf(stderr,
                   "Cannot find/call function with index %d in external "
                   "Python module.\n",
@@ -347,6 +342,12 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
 
   }
 
+  if (py_functions[PY_FUNC_FUZZ_COUNT]) {
+
+    mutator->afl_custom_fuzz_count = fuzz_count_py;
+
+  }
+
   if (py_functions[PY_FUNC_POST_TRIM]) {
 
     mutator->afl_custom_post_trim = post_trim_py;
@@ -477,6 +478,44 @@ s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
 
 }
 
+u32 fuzz_count_py(void *py_mutator, const u8 *buf, size_t buf_size) {
+
+  PyObject *py_args, *py_value;
+
+  py_args = PyTuple_New(1);
+  py_value = PyByteArray_FromStringAndSize(buf, buf_size);
+  if (!py_value) {
+
+    Py_DECREF(py_args);
+    FATAL("Failed to convert arguments");
+
+  }
+
+  PyTuple_SetItem(py_args, 0, py_value);
+
+  py_value = PyObject_CallObject(
+      ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ_COUNT], py_args);
+  Py_DECREF(py_args);
+
+  if (py_value != NULL) {
+
+  #if PY_MAJOR_VERSION >= 3
+    u32 retcnt = (u32)PyLong_AsLong(py_value);
+  #else
+    u32 retcnt = PyInt_AsLong(py_value);
+  #endif
+    Py_DECREF(py_value);
+    return retcnt;
+
+  } else {
+
+    PyErr_Print();
+    FATAL("Call failed");
+
+  }
+
+}
+
 s32 post_trim_py(void *py_mutator, u8 success) {
 
   PyObject *py_args, *py_value;
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index dd0e316c..577fc34f 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -349,6 +349,20 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_preload =
                 (u8 *)get_afl_env(afl_environment_variables[i]);
 
+          } else if (!strncmp(env, "AFL_MAX_DET_EXTRAS",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_max_det_extras =
+                (u8 *)get_afl_env(afl_environment_variables[i]);
+
+          } else if (!strncmp(env, "AFL_FORKSRV_INIT_TMOUT",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_forksrv_init_tmout =
+                (u8 *)get_afl_env(afl_environment_variables[i]);
+
           }
 
         } else {
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 5dd092f2..0df6c15c 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -173,10 +173,14 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
       "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
       "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
+      "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
       "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
       "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
       "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
       "              the target was compiled for\n"
+      "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
+      "                    then they are randomly selected instead all of them being\n"
+      "                    used. Defaults to 200.\n"
       "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
       "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
       "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
@@ -188,7 +192,7 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_QUIET: suppress forkserver status messages\n"
       "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
-      "AFL_SKIP_BIN_CHECK: skip the check, if the target is an excutable\n"
+      "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n"
       "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
       "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
       "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
@@ -949,8 +953,36 @@ int main(int argc, char **argv_orig, char **envp) {
 
   if (afl->afl_env.afl_hang_tmout) {
 
-    afl->hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
-    if (!afl->hang_tmout) { FATAL("Invalid value of AFL_HANG_TMOUT"); }
+    s32 hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
+    if (hang_tmout < 1) { FATAL("Invalid value for AFL_HANG_TMOUT"); }
+    afl->hang_tmout = (u32)hang_tmout;
+
+  }
+
+  if (afl->afl_env.afl_max_det_extras) {
+
+    s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
+    if (max_det_extras < 1) { FATAL("Invalid value for AFL_MAX_DET_EXTRAS"); }
+    afl->max_det_extras = (u32)max_det_extras;
+
+  } else {
+
+    afl->max_det_extras = MAX_DET_EXTRAS;
+
+  }
+
+  if (afl->afl_env.afl_forksrv_init_tmout) {
+
+    afl->fsrv.init_tmout = atoi(afl->afl_env.afl_forksrv_init_tmout);
+    if (!afl->fsrv.init_tmout) {
+
+      FATAL("Invalid value of AFL_FORKSRV_INIT_TMOUT");
+
+    }
+
+  } else {
+
+    afl->fsrv.init_tmout = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
 
   }
 
diff --git a/src/afl-gcc.c b/src/afl-gcc.c
index 22e6be8e..97564aea 100644
--- a/src/afl-gcc.c
+++ b/src/afl-gcc.c
@@ -415,7 +415,7 @@ int main(int argc, char **argv) {
       "AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n"
       "AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n";
 
-  if (argc == 2 && strcmp(argv[1], "-h") == 0) {
+  if (argc == 2 && strncmp(argv[1], "-h", 2) == 0) {
 
     printf("afl-cc" VERSION " by Michal Zalewski\n\n");
     printf("%s \n\n", argv[0]);
diff --git a/src/afl-performance.c b/src/afl-performance.c
index 0c1697a8..a9d7cefa 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -72,12 +72,12 @@ void jump(afl_state_t *afl) {
 
   static const uint64_t JUMP[] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c,
                                   0xa9582618e03fc9aa, 0x39abdc4529b1661c};
-  int                   i, b;
+  size_t                i, b;
   uint64_t              s0 = 0;
   uint64_t              s1 = 0;
   uint64_t              s2 = 0;
   uint64_t              s3 = 0;
-  for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
+  for (i = 0; i < (sizeof(JUMP) / sizeof(*JUMP)); i++)
     for (b = 0; b < 64; b++) {
 
       if (JUMP[i] & UINT64_C(1) << b) {
@@ -110,12 +110,12 @@ void long_jump(afl_state_t *afl) {
   static const uint64_t LONG_JUMP[] = {0x76e15d3efefdcbbf, 0xc5004e441c522fb3,
                                        0x77710069854ee241, 0x39109bb02acbe635};
 
-  int      i, b;
+  size_t   i, b;
   uint64_t s0 = 0;
   uint64_t s1 = 0;
   uint64_t s2 = 0;
   uint64_t s3 = 0;
-  for (i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++)
+  for (i = 0; i < (sizeof(LONG_JUMP) / sizeof(*LONG_JUMP)); i++)
     for (b = 0; b < 64; b++) {
 
       if (LONG_JUMP[i] & UINT64_C(1) << b) {
@@ -145,7 +145,7 @@ void long_jump(afl_state_t *afl) {
 u32 hash32(u8 *key, u32 len, u32 seed) {
 
 #else
-u32 inline hash32(u8 *key, u32 len, u32 seed) {
+inline u32 hash32(u8 *key, u32 len, u32 seed) {
 
 #endif
 
@@ -157,7 +157,7 @@ u32 inline hash32(u8 *key, u32 len, u32 seed) {
 u64 hash64(u8 *key, u32 len, u64 seed) {
 
 #else
-u64 inline hash64(u8 *key, u32 len, u64 seed) {
+inline u64 hash64(u8 *key, u32 len, u64 seed) {
 
 #endif
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 47c615d8..f4a7c336 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -636,6 +636,8 @@ static void usage(u8 *argv0) {
       "size\n"
       "              the target was compiled for\n"
       "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
+      "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
+      "startup (in milliseconds)\n"
       "AFL_QUIET: do not print extra informational output\n",
       argv0, MEM_LIMIT, doc_path);
 
@@ -1036,6 +1038,19 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+    if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
+
+      s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
+      if (forksrv_init_tmout < 1) {
+
+        FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
+
+      }
+
+      fsrv->init_tmout = (u32)forksrv_init_tmout;
+
+    }
+
     afl_fsrv_start(fsrv, use_argv, &stop_soon,
                    get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
     map_size = fsrv->map_size;
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index b50d8597..e1d08054 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -846,6 +846,7 @@ static void usage(u8 *argv0) {
       "              the target was compiled for\n"
       "AFL_PRELOAD:  LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
+      "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
 
       , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
 
@@ -1104,6 +1105,19 @@ int main(int argc, char **argv_orig, char **envp) {
 
   SAYF("\n");
 
+  if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
+
+    s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
+    if (forksrv_init_tmout < 1) {
+
+      FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
+
+    }
+
+    fsrv->init_tmout = (u32)forksrv_init_tmout;
+
+  }
+
   shm_fuzz = ck_alloc(sizeof(sharedmem_t));
 
   /* initialize cmplog_mode */