about summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/afl-as.h4
-rw-r--r--include/afl-fuzz.h241
-rw-r--r--include/afl-prealloc.h5
-rw-r--r--include/alloc-inl.h103
-rw-r--r--[-rwxr-xr-x]include/android-ashmem.h0
-rw-r--r--include/cmplog.h5
-rw-r--r--include/common.h64
-rw-r--r--include/config.h16
-rw-r--r--include/debug.h13
-rw-r--r--include/forkserver.h22
-rw-r--r--include/list.h51
-rw-r--r--include/snapshot-inl.h59
-rw-r--r--include/types.h24
13 files changed, 467 insertions, 140 deletions
diff --git a/include/afl-as.h b/include/afl-as.h
index 7fc00ffe..a2bf1f9c 100644
--- a/include/afl-as.h
+++ b/include/afl-as.h
@@ -152,7 +152,7 @@ static const u8 *trampoline_fmt_64 =
     "/* --- END --- */\n"
     "\n";
 
-static const u8*main_payload_32 = 
+static const u8 *main_payload_32 = 
 
   "\n"
   "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n"
@@ -409,7 +409,7 @@ static const u8*main_payload_32 =
 #define CALL_L64(str) "call " str "@PLT\n"
 #endif                                                        /* ^__APPLE__ */
 
-static const u8* main_payload_64 = 
+static const u8 *main_payload_64 = 
 
   "\n"
   "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n"
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 4e2deaa3..6cfb34ca 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -109,6 +109,8 @@
 #define CASE_PREFIX "id_"
 #endif                                                    /* ^!SIMPLE_FILES */
 
+#define STAGE_BUF_SIZE (64)  /* usable size for stage name buf in afl_state */
+
 extern s8  interesting_8[INTERESTING_8_LEN];
 extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
 extern s32
@@ -231,13 +233,12 @@ enum {
   /* 04 */ QUAD,    /* Quadratic schedule               */
   /* 05 */ EXPLOIT, /* AFL's exploitation-based const.  */
   /* 06 */ MMOPT,   /* Modified MOPT schedule           */
+  /* 07 */ RARE,    /* Rare edges                       */
 
   POWER_SCHEDULES_NUM
 
 };
 
-extern u8 *doc_path;                    /* gath to documentation dir        */
-
 /* Python stuff */
 #ifdef USE_PYTHON
 
@@ -278,10 +279,32 @@ enum {
   /* 07 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY,
   /* 08 */ PY_FUNC_QUEUE_GET,
   /* 09 */ PY_FUNC_QUEUE_NEW_ENTRY,
+  /* 10 */ PY_FUNC_DEINIT,
   PY_FUNC_COUNT
 
 };
 
+typedef struct py_mutator {
+
+  PyObject *py_module;
+  PyObject *py_functions[PY_FUNC_COUNT];
+  void *    afl_state;
+  void *    py_data;
+
+  u8 *   fuzz_buf;
+  size_t fuzz_size;
+
+  u8 *   pre_save_buf;
+  size_t pre_save_size;
+
+  u8 *   trim_buf;
+  size_t trim_size;
+
+  u8 *   havoc_buf;
+  size_t havoc_size;
+
+} py_mutator_t;
+
 #endif
 
 typedef struct MOpt_globals {
@@ -308,7 +331,8 @@ typedef struct afl_env_vars {
   u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
       afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
       afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
-      afl_bench_until_crash, afl_debug_child_output, afl_autoresume;
+      afl_bench_until_crash, afl_debug_child_output, afl_autoresume,
+      afl_cal_fast;
 
   u8 *afl_tmpdir, *afl_post_library, *afl_custom_mutator_library,
       *afl_python_module, *afl_path, *afl_hang_tmout, *afl_skip_crashes,
@@ -420,7 +444,6 @@ typedef struct afl_state {
       no_arith,                         /* Skip most arithmetic ops         */
       shuffle_queue,                    /* Shuffle input queue?             */
       bitmap_changed,                   /* Time to update bitmap?           */
-      qemu_mode,                        /* Running in QEMU mode?            */
       unicorn_mode,                     /* Running in Unicorn mode?         */
       use_wine,                         /* Use WINE with QEMU mode          */
       skip_requested,                   /* Skip request, via SIGUSR1        */
@@ -463,11 +486,6 @@ typedef struct afl_state {
       unique_tmouts,                    /* Timeouts with unique signatures  */
       unique_hangs,                     /* Hangs with unique signatures     */
       total_execs,                      /* Total execve() calls             */
-      slowest_exec_ms,                  /* Slowest testcase non hang in ms  */
-      start_time,                       /* Unix start time (ms)             */
-      last_path_time,                   /* Time for most recent path (ms)   */
-      last_crash_time,                  /* Time for most recent crash (ms)  */
-      last_hang_time,                   /* Time for most recent hang (ms)   */
       last_crash_execs,                 /* Exec counter at last crash       */
       queue_cycle,                      /* Queue round counter              */
       cycles_wo_finds,                  /* Cycles without any new paths     */
@@ -475,15 +493,20 @@ typedef struct afl_state {
       bytes_trim_in,                    /* Bytes coming into the trimmer    */
       bytes_trim_out,                   /* Bytes coming outa the trimmer    */
       blocks_eff_total,                 /* Blocks subject to effector maps  */
-      blocks_eff_select;                /* Blocks selected as fuzzable      */
+      blocks_eff_select,                /* Blocks selected as fuzzable      */
+      start_time,                       /* Unix start time (ms)             */
+      last_path_time,                   /* Time for most recent path (ms)   */
+      last_crash_time,                  /* Time for most recent crash (ms)  */
+      last_hang_time;                   /* Time for most recent hang (ms)   */
 
-  u32 subseq_tmouts;                    /* Number of timeouts in a row      */
+  u32 slowest_exec_ms,                  /* Slowest testcase non hang in ms  */
+      subseq_tmouts;                    /* Number of timeouts in a row      */
 
   u8 *stage_name,                       /* Name of the current fuzz stage   */
       *stage_short,                     /* Short stage name                 */
       *syncing_party;                   /* Currently syncing with...        */
 
-  u8 stage_name_buf64[64];              /* A name buf with len 64 if needed */
+  u8 stage_name_buf[STAGE_BUF_SIZE];    /* reused stagename buf with len 64 */
 
   s32 stage_cur, stage_max;             /* Stage progression                */
   s32 splicing_with;                    /* Splicing with which test case?   */
@@ -532,35 +555,70 @@ typedef struct afl_state {
   struct extra_data *a_extras;          /* Automatically selected extras    */
   u32                a_extras_cnt;      /* Total number of tokens available */
 
-  u8 *(*post_handler)(u8 *buf, u32 *len);
+  /* afl_postprocess API */
+  void *(*post_init)(struct afl_state *afl);
+  size_t (*post_handler)(void *data, u8 *buf, u32 len, u8 **out_buf);
+  void *(*post_deinit)(void *data);
+  void *post_data;
 
   /* CmpLog */
 
-  char *cmplog_binary;
-  s32   cmplog_child_pid, cmplog_fsrv_pid;
+  char *           cmplog_binary;
+  afl_forkserver_t cmplog_fsrv;     /* cmplog has its own little forkserver */
 
   /* Custom mutators */
   struct custom_mutator *mutator;
 
   /* cmplog forkserver ids */
   s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd;
-  
+  u32 cmplog_prev_timed_out;
+
   struct afl_pass_stat* pass_stats;
 
   u8 describe_op_buf_256[256]; /* describe_op will use this to return a string
                                   up to 256 */
 
-#ifdef USE_PYTHON
-  /* Python Mutators */
-  PyObject *py_module;
-  PyObject *py_functions[PY_FUNC_COUNT];
-#endif
-
 #ifdef _AFL_DOCUMENT_MUTATIONS
   u8  do_document;
   u32 document_counter;
 #endif
 
+  void *maybe_add_auto;
+
+  /* statistics file */
+  double last_bitmap_cvg, last_stability, last_eps;
+
+  /* plot file saves from last run */
+  u32 plot_prev_qp, plot_prev_pf, plot_prev_pnf, plot_prev_ce, plot_prev_md;
+  u64 plot_prev_qc, plot_prev_uc, plot_prev_uh;
+
+  u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs;
+  double stats_avg_exec;
+
+  u8 clean_trace[MAP_SIZE];
+  u8 clean_trace_custom[MAP_SIZE];
+  u8 first_trace[MAP_SIZE];
+
+  /*needed for afl_fuzz_one */
+  // TODO: see which we can reuse
+  u8 *   out_buf;
+  size_t out_size;
+
+  u8 *   out_scratch_buf;
+  size_t out_scratch_size;
+
+  u8 *   eff_buf;
+  size_t eff_size;
+
+  u8 *   in_buf;
+  size_t in_size;
+
+  u8 *   in_scratch_buf;
+  size_t in_scratch_size;
+
+  u8 *   ex_buf;
+  size_t ex_size;
+
 } afl_state_t;
 
 /* A global pointer to all instances is needed (for now) for signals to arrive
@@ -572,33 +630,40 @@ struct custom_mutator {
 
   const char *name;
   void *      dh;
+  u8 *        pre_save_buf;
+  size_t      pre_save_size;
+
+  void *data;                                    /* custom mutator data ptr */
 
   /* hooks for the custom mutator function */
 
   /**
    * Initialize the custom mutator.
    *
-   * (Optional)
-   *
+   * @param afl AFL instance.
    * @param seed Seed used for the mutation.
+   * @return pointer to internal data or NULL on error
    */
-  void (*afl_custom_init)(afl_state_t *afl, unsigned int seed);
+  void *(*afl_custom_init)(afl_state_t *afl, unsigned int seed);
 
   /**
    * Perform custom mutations on a given input
    *
    * (Optional for now. Required in the future)
    *
-   * @param[inout] buf Pointer to the input data to be mutated and the mutated
+   * @param data pointer returned in afl_custom_init for this fuzz case
+   * @param[in] buf Pointer to the input data to be mutated and the mutated
    *     output
    * @param[in] buf_size Size of the input/output data
+   * @param[out] out_buf the new buffer. We may reuse *buf if large enough.
+   *             *out_buf = NULL is treated as FATAL.
    * @param[in] add_buf Buffer containing the additional test case
    * @param[in] add_buf_size Size of the additional test case
    * @param[in] max_size Maximum size of the mutated output. The mutation must
    * not produce data larger than max_size.
    * @return Size of the mutated output.
    */
-  size_t (*afl_custom_fuzz)(afl_state_t *afl, u8 **buf, size_t buf_size,
+  size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf,
                             u8 *add_buf, size_t add_buf_size, size_t max_size);
 
   /**
@@ -608,14 +673,15 @@ struct custom_mutator {
    * (Optional) If this functionality is not needed, simply don't define this
    * function.
    *
+   * @param[in] data pointer returned in afl_custom_init for this fuzz case
    * @param[in] buf Buffer containing the test case to be executed
    * @param[in] buf_size Size of the test case
-   * @param[out] out_buf Pointer to the buffer of storing the test case after
-   *     processing. External library should allocate memory for out_buf. AFL++
-   *     will release the memory after saving the test case.
-   * @return Size of the output buffer after processing
+   * @param[out] out_buf Pointer to the buffer storing the test case after
+   *     processing. External library should allocate memory for out_buf.
+   *     It can chose to alter buf in-place, if the space is large enough.
+   * @return Size of the output buffer.
    */
-  size_t (*afl_custom_pre_save)(afl_state_t *afl, u8 *buf, size_t buf_size,
+  size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size,
                                 u8 **out_buf);
 
   /**
@@ -634,11 +700,13 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param buf Buffer containing the test case
    * @param buf_size Size of the test case
-   * @return The amount of possible iteration steps to trim the input
+   * @return The amount of possible iteration steps to trim the input.
+   *        Negative on error.
    */
-  u32 (*afl_custom_init_trim)(afl_state_t *afl, u8 *buf, size_t buf_size);
+  s32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size);
 
   /**
    * This method is called for each trimming operation. It doesn't have any
@@ -651,12 +719,13 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param[out] out_buf Pointer to the buffer containing the trimmed test case.
-   *     External library should allocate memory for out_buf. AFL++ will release
-   *     the memory after saving the test case.
-   * @param[out] out_buf_size Pointer to the size of the trimmed test case
+   *             The library can reuse a buffer for each call
+   *             and will have to free the buf (for example in deinit)
+   * @return the size of the trimmed test case
    */
-  void (*afl_custom_trim)(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size);
+  size_t (*afl_custom_trim)(void *data, u8 **out_buf);
 
   /**
    * This method is called after each trim operation to inform you if your
@@ -665,11 +734,12 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param success Indicates if the last trim operation was successful.
    * @return The next trim iteration index (from 0 to the maximum amount of
-   *     steps returned in init_trim)
+   *     steps returned in init_trim). Negative on error.
    */
-  u32 (*afl_custom_post_trim)(afl_state_t *afl, u8 success);
+  s32 (*afl_custom_post_trim)(void *data, u8 success);
 
   /**
    * Perform a single custom mutation on a given input.
@@ -677,15 +747,18 @@ struct custom_mutator {
    *
    * (Optional)
    *
-   * @param[inout] buf Pointer to the input data to be mutated and the mutated
+   * @param[in] data pointer returned in afl_custom_init for this fuzz case
+   * @param[in] buf Pointer to the input data to be mutated and the mutated
    *     output
    * @param[in] buf_size Size of input data
+   * @param[out] out_buf The new buffer. It's legal to reuse *buf if it's <
+   * buf_size.
    * @param[in] max_size Maximum size of the mutated output. The mutation must
    *     not produce data larger than max_size.
-   * @return Size of the mutated output.
+   * @return Size of the mutated output (out_size).
    */
-  size_t (*afl_custom_havoc_mutation)(afl_state_t *afl, u8 **buf,
-                                      size_t buf_size, size_t max_size);
+  size_t (*afl_custom_havoc_mutation)(void *data, u8 *buf, size_t buf_size,
+                                      u8 **out_buf, size_t max_size);
 
   /**
    * Return the probability (in percentage) that afl_custom_havoc_mutation
@@ -693,20 +766,22 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @return The probability (0-100).
    */
-  u8 (*afl_custom_havoc_mutation_probability)(afl_state_t *afl);
+  u8 (*afl_custom_havoc_mutation_probability)(void *data);
 
   /**
    * Determine whether the fuzzer should fuzz the current queue entry or not.
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param filename File name of the test case in the queue entry
    * @return Return True(1) if the fuzzer will fuzz the queue entry, and
    *     False(0) otherwise.
    */
-  u8 (*afl_custom_queue_get)(afl_state_t *afl, const u8 *filename);
+  u8 (*afl_custom_queue_get)(void *data, const u8 *filename);
 
   /**
    * Allow for additional analysis (e.g. calling a different tool that does a
@@ -714,13 +789,19 @@ struct custom_mutator {
    *
    * (Optional)
    *
+   * @param data pointer returned in afl_custom_init for this fuzz case
    * @param filename_new_queue File name of the new queue entry
    * @param filename_orig_queue File name of the original queue entry. This
    *     argument can be NULL while initializing the fuzzer
    */
-  void (*afl_custom_queue_new_entry)(afl_state_t *afl,
-                                     const u8 *   filename_new_queue,
-                                     const u8 *   filename_orig_queue);
+  void (*afl_custom_queue_new_entry)(void *data, const u8 *filename_new_queue,
+                                     const u8 *filename_orig_queue);
+  /**
+   * Deinitialize the custom mutator.
+   *
+   * @param data pointer returned in afl_custom_init for this fuzz case
+   */
+  void (*afl_custom_deinit)(void *data);
 
 };
 
@@ -738,19 +819,17 @@ u8   trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf);
 /* Python */
 #ifdef USE_PYTHON
 
-int  init_py_module(afl_state_t *, u8 *);
-void finalize_py_module(afl_state_t *);
+void finalize_py_module(void *);
 
-void   init_py(afl_state_t *, unsigned int);
-size_t fuzz_py(afl_state_t *, u8 **, size_t, u8 *, size_t, size_t);
-size_t pre_save_py(afl_state_t *, u8 *, size_t, u8 **);
-u32    init_trim_py(afl_state_t *, u8 *, size_t);
-u32    post_trim_py(afl_state_t *, u8);
-void   trim_py(afl_state_t *, u8 **, size_t *);
-size_t havoc_mutation_py(afl_state_t *, u8 **, size_t, size_t);
-u8     havoc_mutation_probability_py(afl_state_t *);
-u8     queue_get_py(afl_state_t *, const u8 *);
-void   queue_new_entry_py(afl_state_t *, const u8 *, const u8 *);
+size_t pre_save_py(void *, u8 *, size_t, u8 **);
+s32    init_trim_py(void *, u8 *, size_t);
+s32    post_trim_py(void *, u8);
+size_t trim_py(void *, u8 **);
+size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
+u8     havoc_mutation_probability_py(void *);
+u8     queue_get_py(void *, const u8 *);
+void   queue_new_entry_py(void *, const u8 *, const u8 *);
+void   deinit_py(void *);
 
 #endif
 
@@ -769,36 +848,29 @@ u32  calculate_score(afl_state_t *, struct queue_entry *);
 
 void read_bitmap(afl_state_t *, u8 *);
 void write_bitmap(afl_state_t *);
-u32  count_bits(u8 *);
-u32  count_bytes(u8 *);
-u32  count_non_255_bytes(u8 *);
+u32  count_bits(afl_state_t *, u8 *);
+u32  count_bytes(afl_state_t *, u8 *);
+u32  count_non_255_bytes(afl_state_t *, u8 *);
 #ifdef WORD_SIZE_64
-void simplify_trace(u64 *);
-void classify_counts(u64 *);
+void simplify_trace(afl_state_t *, u64 *);
+void classify_counts(afl_state_t *, u64 *);
 #else
-void simplify_trace(u32 *);
-void classify_counts(u32 *);
+void simplify_trace(afl_state_t *, u32 *);
+void classify_counts(afl_state_t *, u32 *);
 #endif
 void init_count_class16(void);
-void minimize_bits(u8 *, u8 *);
+void minimize_bits(afl_state_t *, u8 *, u8 *);
 #ifndef SIMPLE_FILES
 u8 *describe_op(afl_state_t *, u8);
 #endif
 u8 save_if_interesting(afl_state_t *, void *, u32, u8);
 u8 has_new_bits(afl_state_t *, u8 *);
 
-/* Misc */
-
-u8 *DI(u64);
-u8 *DF(double);
-u8 *DMS(u64);
-u8 *DTD(u64, u64);
-
 /* Extras */
 
 void load_extras_file(afl_state_t *, u8 *, u32 *, u32 *, u32);
 void load_extras(afl_state_t *, u8 *);
-void maybe_add_auto(afl_state_t *, u8 *, u32);
+void maybe_add_auto(void *, u8 *, u32);
 void save_auto(afl_state_t *);
 void load_auto(afl_state_t *);
 void destroy_extras(afl_state_t *);
@@ -812,7 +884,7 @@ void show_init_stats(afl_state_t *);
 
 /* Run */
 
-u8   run_target(afl_state_t *, u32);
+u8   run_target(afl_state_t *, afl_forkserver_t *fsrv, u32);
 void write_to_testcase(afl_state_t *, void *, u32);
 u8   calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
 void sync_fuzzers(afl_state_t *);
@@ -856,8 +928,7 @@ void   save_cmdline(afl_state_t *, u32, char **);
 
 /* CmpLog */
 
-void init_cmplog_forkserver(afl_state_t *afl);
-u8   common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len);
+u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len);
 
 /* RedQueen */
 u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
@@ -868,16 +939,16 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
 /* Generate a random number (from 0 to limit - 1). This may
    have slight bias. */
 
-static inline u32 UR(afl_state_t *afl, u32 limit) {
+static inline u32 rand_below(afl_state_t *afl, u32 limit) {
 
 #ifdef HAVE_ARC4RANDOM
-  if (afl->fixed_seed) { return random() % limit; }
+  if (unlikely(afl->fixed_seed)) { return random() % limit; }
 
   /* The boundary not being necessarily a power of 2,
      we need to ensure the result uniformity. */
   return arc4random_uniform(limit);
 #else
-  if (!afl->fixed_seed && unlikely(!afl->rand_cnt--)) {
+  if (unlikely(!afl->rand_cnt--) && likely(!afl->fixed_seed)) {
 
     ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed),
             "/dev/urandom");
@@ -893,7 +964,7 @@ static inline u32 UR(afl_state_t *afl, u32 limit) {
 
 static inline u32 get_rand_seed(afl_state_t *afl) {
 
-  if (afl->fixed_seed) return (u32)afl->init_seed;
+  if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed;
   return afl->rand_seed[0];
 
 }
@@ -901,7 +972,7 @@ static inline u32 get_rand_seed(afl_state_t *afl) {
 /* Find first power of two greater or equal to val (assuming val under
    2^63). */
 
-static u64 next_p2(u64 val) {
+static inline u64 next_p2(u64 val) {
 
   u64 ret = 1;
   while (val > ret)
diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h
index ab86f0d7..66e6aadf 100644
--- a/include/afl-prealloc.h
+++ b/include/afl-prealloc.h
@@ -44,9 +44,8 @@ typedef enum prealloc_status {
 
 /* Adds the entry used for prealloc bookkeeping to this struct */
 
-#define PREALLOCABLE \
-  ;                  \
-  pre_status_t pre_status;              /* prealloc status of this instance */
+/* prealloc status of this instance */
+#define PREALLOCABLE pre_status_t pre_status
 
 /* allocate an element of type *el_ptr, to this variable.
     Uses (and reuses) the given prealloc_buf before hitting libc's malloc.
diff --git a/include/alloc-inl.h b/include/alloc-inl.h
index c8783d96..d16e84bb 100644
--- a/include/alloc-inl.h
+++ b/include/alloc-inl.h
@@ -35,6 +35,9 @@
 #include "types.h"
 #include "debug.h"
 
+/* Initial size used for ck_maybe_grow */
+#define INITIAL_GROWTH_SIZE (64)
+
 // Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators
 
 #ifndef _WANT_ORIGINAL_AFL_ALLOC
@@ -82,7 +85,7 @@
 
 static inline void *DFL_ck_alloc_nozero(u32 size) {
 
-  u8 *ret;
+  void *ret;
 
   if (!size) return NULL;
 
@@ -124,7 +127,7 @@ static inline void DFL_ck_free(void *mem) {
 
 static inline void *DFL_ck_realloc(void *orig, u32 size) {
 
-  u8 *ret;
+  void *ret;
 
   if (!size) {
 
@@ -179,7 +182,7 @@ static inline u8 *DFL_ck_strdup(u8 *str) {
 
 static inline void *DFL_ck_memdup(void *mem, u32 size) {
 
-  u8 *ret;
+  void *ret;
 
   if (!mem || !size) return NULL;
 
@@ -764,5 +767,99 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func,
 
 #endif                                          /* _WANT_ORIGINAL_AFL_ALLOC */
 
+/* This function calculates the next power of 2 greater or equal its argument.
+ @return The rounded up power of 2 (if no overflow) or 0 on overflow.
+*/
+static inline size_t next_pow2(size_t in) {
+
+  if (in == 0 || in > (size_t)-1)
+    return 0;                  /* avoid undefined behaviour under-/overflow */
+  size_t out = in - 1;
+  out |= out >> 1;
+  out |= out >> 2;
+  out |= out >> 4;
+  out |= out >> 8;
+  out |= out >> 16;
+  return out + 1;
+
+}
+
+/* This function makes sure *size is > size_needed after call.
+ It will realloc *buf otherwise.
+ *size will grow exponentially as per:
+ https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
+ Will return NULL and free *buf if size_needed is <1 or realloc failed.
+ @return For convenience, this function returns *buf.
+ */
+static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
+
+  /* No need to realloc */
+  if (likely(size_needed && *size >= size_needed)) return *buf;
+
+  /* No initial size was set */
+  if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
+
+  /* grow exponentially */
+  size_t next_size = next_pow2(size_needed);
+
+  /* handle overflow and zero size_needed */
+  if (!next_size) { next_size = size_needed; }
+
+  /* alloc */
+  *buf = realloc(*buf, next_size);
+  *size = *buf ? next_size : 0;
+
+  return *buf;
+
+}
+
+/* This function makes sure *size is > size_needed after call.
+ It will realloc *buf otherwise.
+ *size will grow exponentially as per:
+ https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
+ Will FATAL if size_needed is <1.
+ @return For convenience, this function returns *buf.
+ */
+static inline void *ck_maybe_grow(void **buf, size_t *size,
+                                  size_t size_needed) {
+
+  /* Oops. found a bug? */
+  if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size");
+
+  /* No need to realloc */
+  if (likely(*size >= size_needed)) return *buf;
+
+  /* No initial size was set */
+  if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
+
+  /* grow exponentially */
+  size_t next_size = next_pow2(size_needed);
+
+  /* handle overflow */
+  if (!next_size) { next_size = size_needed; }
+
+  /* alloc */
+  *buf = ck_realloc(*buf, next_size);
+  *size = next_size;
+
+  return *buf;
+
+}
+
+/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
+static inline void swap_bufs(void **buf1, size_t *size1, void **buf2,
+                             size_t *size2) {
+
+  void * scratch_buf = *buf1;
+  size_t scratch_size = *size1;
+  *buf1 = *buf2;
+  *size1 = *size2;
+  *buf2 = scratch_buf;
+  *size2 = scratch_size;
+
+}
+
+#undef INITIAL_GROWTH_SIZE
+
 #endif                                               /* ! _HAVE_ALLOC_INL_H */
 
diff --git a/include/android-ashmem.h b/include/android-ashmem.h
index 3a0b9969..3a0b9969 100755..100644
--- a/include/android-ashmem.h
+++ b/include/android-ashmem.h
diff --git a/include/cmplog.h b/include/cmplog.h
index 36f8f2c5..74e6a3bb 100644
--- a/include/cmplog.h
+++ b/include/cmplog.h
@@ -29,6 +29,7 @@
 #define _AFL_CMPLOG_H
 
 #include "config.h"
+#include "forkserver.h"
 
 #define CMP_MAP_W 65536
 #define CMP_MAP_H 256
@@ -74,5 +75,9 @@ struct cmp_map {
 
 };
 
+/* Execs the child */
+
+void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv);
+
 #endif
 
diff --git a/include/common.h b/include/common.h
index 28c11049..8dd66355 100644
--- a/include/common.h
+++ b/include/common.h
@@ -27,10 +27,17 @@
 #ifndef __AFLCOMMON_H
 #define __AFLCOMMON_H
 
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 #include <sys/time.h>
 #include "types.h"
 #include "stdbool.h"
 
+/* STRINGIFY_VAL_SIZE_MAX will fit all stringify_ strings. */
+
+#define STRINGIFY_VAL_SIZE_MAX (16)
+
 void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin);
 void check_environment_vars(char **env);
 
@@ -41,31 +48,62 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
 char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
 char * get_afl_env(char *env);
 
+extern u8  be_quiet;
+extern u8 *doc_path;                    /* path to documentation dir        */
+
 /* Get unix time in milliseconds */
 
-static u64 get_cur_time(void) {
+u64 get_cur_time(void);
 
-  struct timeval  tv;
-  struct timezone tz;
+/* Get unix time in microseconds */
 
-  gettimeofday(&tv, &tz);
+u64 get_cur_time_us(void);
 
-  return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
+/* Describe integer. The buf should be
+   at least 6 bytes to fit all ints we randomly see.
+   Will return buf for convenience. */
 
-}
+u8 *stringify_int(u8 *buf, size_t len, u64 val);
 
-/* Get unix time in microseconds */
+/* Describe float. Similar as int. */
+
+u8 *stringify_float(u8 *buf, size_t len, double val);
+
+/* Describe integer as memory size. */
+
+u8 *stringify_mem_size(u8 *buf, size_t len, u64 val);
+
+/* Describe time delta as string.
+   Returns a pointer to buf for convenience. */
+
+u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms);
+
+/* Unsafe Describe integer. The buf sizes are not checked.
+   This is unsafe but fast.
+   Will return buf for convenience. */
+
+u8 *u_stringify_int(u8 *buf, u64 val);
+
+/* Unsafe describe float. Similar as unsafe int. */
+
+u8 *u_stringify_float(u8 *buf, double val);
 
-static u64 get_cur_time_us(void) {
+/* Unsafe describe integer as memory size. */
 
-  struct timeval  tv;
-  struct timezone tz;
+u8 *u_stringify_mem_size(u8 *buf, u64 val);
 
-  gettimeofday(&tv, &tz);
+/* Unsafe describe time delta as string.
+   Returns a pointer to buf for convenience. */
 
-  return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
+u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
 
-}
+/* Wrapper for select() and read(), reading exactly len bytes.
+  Returns the time passed to read.
+  stop_soon should point to a variable indicating ctrl+c was pressed.
+  If the wait times out, returns timeout_ms + 1;
+  Returns 0 if an error occurred (fd closed, signal, ...); */
+u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms,
+               volatile u8 *stop_soon_p);
 
 #endif
 
diff --git a/include/config.h b/include/config.h
index a87c5e84..f0274fd3 100644
--- a/include/config.h
+++ b/include/config.h
@@ -28,7 +28,7 @@
 /* Version string: */
 
 // c = release, d = volatile github dev, e = experimental branch
-#define VERSION "++2.62d"
+#define VERSION "++2.63d"
 
 /******************************************************
  *                                                    *
@@ -201,8 +201,8 @@
    (first value), and to keep in memory as candidates. The latter should be much
    higher than the former. */
 
-#define USE_AUTO_EXTRAS 50
-#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10)
+#define USE_AUTO_EXTRAS 128
+#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64)
 
 /* Scaling factor for the effector map used to skip some of the more
    expensive deterministic steps. The actual divisor is set to
@@ -400,5 +400,15 @@
 #endif
 #endif                           /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
 
+/* Extended forkserver option values */
+
+#define FS_OPT_ENABLED 0x8f000001
+#define FS_OPT_MAPSIZE 0x40000000
+#define FS_OPT_SNAPSHOT 0x20000000
+#define FS_OPT_AUTODICT 0x10000000
+#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
+#define FS_OPT_SET_MAPSIZE(x) \
+  (x <= 1 || x > MAP_SIZE || x > 0x1000000 ? 0 : ((x - 1) << 1))
+
 #endif                                                  /* ! _HAVE_CONFIG_H */
 
diff --git a/include/debug.h b/include/debug.h
index b3865c19..8824ff6b 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -28,10 +28,23 @@
 #include "types.h"
 #include "config.h"
 
+/* __FUNCTION__ is non-iso */
+#ifndef __FUNCTION__
+#ifdef __func__
+#define __FUNCTION__ __func__
+#else
+#define __FUNCTION__ "func_unknown"
+#endif
+#endif
+
 /*******************
  * Terminal colors *
  *******************/
 
+#ifndef MESSAGES_TO_STDOUT
+#define MESSAGES_TO_STDOUT
+#endif
+
 #ifdef USE_COLOR
 
 #define cBLK "\x1b[0;30m"
diff --git a/include/forkserver.h b/include/forkserver.h
index 9802b216..6fbaf612 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -51,6 +51,8 @@ typedef struct afl_forkserver {
       fsrv_st_fd;                       /* Fork server status pipe (read)   */
 
   u32 exec_tmout;                       /* Configurable exec timeout (ms)   */
+  u32 map_size;                         /* map size used by the target      */
+  u32 snapshot;                         /* is snapshot feature used         */
   u64 mem_limit;                        /* Memory cap for child (MB)        */
 
   u8 *out_file,                         /* File to fuzz, if any             */
@@ -62,13 +64,27 @@ typedef struct afl_forkserver {
 
   u8 use_fauxsrv;                       /* Fauxsrv for non-forking targets? */
 
+  u32 prev_timed_out;                   /* if prev forkserver run timed out */
+
+  u8 qemu_mode;                         /* if running in qemu mode or not   */
+
+  char *cmplog_binary;                  /* the name of the cmplog binary    */
+
+  /* Function to kick off the forkserver child */
+  void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
+
+  u8 *function_opt;                     /* for autodictionary: afl ptr      */
+
+  void (*function_ptr)(void *afl_tmp, u8 *mem, u32 len);
+
 } afl_forkserver_t;
 
-void handle_timeout(int sig);
 void afl_fsrv_init(afl_forkserver_t *fsrv);
-void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv);
+void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
+void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
+                    volatile u8 *stop_soon_p, u8 debug_child_output);
+void afl_fsrv_killall(void);
 void afl_fsrv_deinit(afl_forkserver_t *fsrv);
-void afl_fsrv_killall();
 
 #ifdef __APPLE__
 #define MSG_FORK_ON_APPLE                                                    \
diff --git a/include/list.h b/include/list.h
index 1190931f..bb985c4f 100644
--- a/include/list.h
+++ b/include/list.h
@@ -34,8 +34,8 @@
 #include "debug.h"
 #include "afl-prealloc.h"
 
-#define LIST_PREALLOC_SIZE \
-  (64)             /* How many elements to allocate before malloc is needed */
+/* How many elements to allocate before malloc is needed */
+#define LIST_PREALLOC_SIZE (64)
 
 typedef struct list_element {
 
@@ -50,23 +50,24 @@ typedef struct list_element {
 typedef struct list {
 
   element_t element_prealloc_buf[LIST_PREALLOC_SIZE];
-  u32       element_prealloc_count;
+  s32       element_prealloc_count;
 
 } list_t;
 
 static inline element_t *get_head(list_t *list) {
 
-  return &list->element_prealloc_buf[0];
+  /* The first element is the head */
+  return list->element_prealloc_buf;
 
 }
 
-static void list_free_el(list_t *list, element_t *el) {
+static inline void list_free_el(list_t *list, element_t *el) {
 
   PRE_FREE(el, list->element_prealloc_count);
 
 }
 
-static void list_append(list_t *list, void *el) {
+static inline void list_append(list_t *list, void *el) {
 
   element_t *head = get_head(list);
   if (!head->next) {
@@ -97,23 +98,23 @@ static void list_append(list_t *list, void *el) {
    A return from this block will return from calling func.
 */
 
-#define LIST_FOREACH(list, type, block)                    \
-  do {                                                     \
-                                                           \
-    list_t *   li = (list);                                \
-    element_t *head = get_head((li));                      \
-    element_t *el_box = (head)->next;                      \
-    if (!el_box) FATAL("foreach over uninitialized list"); \
-    while (el_box != head) {                               \
-                                                           \
-      type *el = (type *)((el_box)->data);                 \
-      /* get next so el_box can be unlinked */             \
-      element_t *next = el_box->next;                      \
-      {block};                                             \
-      el_box = next;                                       \
-                                                           \
-    }                                                      \
-                                                           \
+#define LIST_FOREACH(list, type, block)                            \
+  do {                                                             \
+                                                                   \
+    list_t *   li = (list);                                        \
+    element_t *head = get_head((li));                              \
+    element_t *el_box = (head)->next;                              \
+    if (!el_box) FATAL("foreach over uninitialized list");         \
+    while (el_box != head) {                                       \
+                                                                   \
+      __attribute__((unused)) type *el = (type *)((el_box)->data); \
+      /* get next so el_box can be unlinked */                     \
+      element_t *next = el_box->next;                              \
+      {block};                                                     \
+      el_box = next;                                               \
+                                                                   \
+    }                                                              \
+                                                                   \
   } while (0);
 
 /* In foreach: remove the current el from the list */
@@ -143,7 +144,7 @@ static void list_append(list_t *list, void *el) {
 
 /* remove an item from the list */
 
-static void list_remove(list_t *list, void *remove_me) {
+static inline void list_remove(list_t *list, void *remove_me) {
 
   LIST_FOREACH(list, void, {
 
@@ -165,7 +166,7 @@ static void list_remove(list_t *list, void *remove_me) {
 
 /* Returns true if el is in list */
 
-static bool list_contains(list_t *list, void *contains_me) {
+static inline bool list_contains(list_t *list, void *contains_me) {
 
   LIST_FOREACH(list, void, {
 
diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h
new file mode 100644
index 00000000..b73a001e
--- /dev/null
+++ b/include/snapshot-inl.h
@@ -0,0 +1,59 @@
+/*
+   american fuzzy lop++ - snapshot helpers routines
+   ------------------------------------------------
+
+   Originally written by Michal Zalewski
+
+   Forkserver design by Jann Horn <jannhorn@googlemail.com>
+
+   Now maintained by Marc Heuse <mh@mh-sec.de>,
+                     Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
+                     Andrea Fioraldi <andreafioraldi@gmail.com>,
+                     Dominik Maier <mail@dmnk.co>
+
+   Copyright 2016, 2017 Google Inc. All rights reserved.
+   Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ */
+
+// From AFL-Snapshot-LKM/include/afl_snapshot.h (must be kept synced)
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define AFL_SNAPSHOT_FILE_NAME "/dev/afl_snapshot"
+
+#define AFL_SNAPSHOT_IOCTL_MAGIC 44313
+
+#define AFL_SNAPSHOT_IOCTL_DO _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 1)
+#define AFL_SNAPSHOT_IOCTL_CLEAN _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 2)
+
+static int afl_snapshot_dev_fd;
+
+static int afl_snapshot_init(void) {
+
+  afl_snapshot_dev_fd = open(AFL_SNAPSHOT_FILE_NAME, 0);
+  return afl_snapshot_dev_fd;
+
+}
+
+static int afl_snapshot_do() {
+
+  return ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_DO);
+
+}
+
+static int afl_snapshot_clean(void) {
+
+  return ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_CLEAN);
+
+}
+
diff --git a/include/types.h b/include/types.h
index bd4bd05d..f2a12953 100644
--- a/include/types.h
+++ b/include/types.h
@@ -46,7 +46,7 @@ typedef uint32_t u32;
 
  */
 
-#ifdef __x86_64__
+#if defined(__x86_64__) || defined(__aarch64__)
 typedef unsigned long long u64;
 #else
 typedef uint64_t u64;
@@ -58,8 +58,22 @@ typedef int32_t s32;
 typedef int64_t s64;
 
 #ifndef MIN
-#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a))
-#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
+#define MIN(a, b)           \
+  ({                        \
+                            \
+    __typeof__(a) _a = (a); \
+    __typeof__(b) _b = (b); \
+    _a < _b ? _a : _b;      \
+                            \
+  })
+#define MAX(a, b)           \
+  ({                        \
+                            \
+    __typeof__(a) _a = (a); \
+    __typeof__(b) _b = (b); \
+    _a > _b ? _a : _b;      \
+                            \
+  })
 #endif                                                              /* !MIN */
 
 #define SWAP16(_x)                    \
@@ -120,9 +134,13 @@ typedef int64_t s64;
 #define likely(_x) (_x)
 #define unlikely(_x) (_x)
 #else
+#ifndef likely
 #define likely(_x) __builtin_expect(!!(_x), 1)
+#endif
+#ifndef unlikely
 #define unlikely(_x) __builtin_expect(!!(_x), 0)
 #endif
+#endif
 
 #endif                                                   /* ! _HAVE_TYPES_H */