Hello community,

here is the log from the commit of package afl for openSUSE:Factory checked in 
at 2016-07-28 23:46:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/afl (Old)
 and      /work/SRC/openSUSE:Factory/.afl.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "afl"

Changes:
--------
--- /work/SRC/openSUSE:Factory/afl/afl.changes  2016-07-01 09:59:30.000000000 
+0200
+++ /work/SRC/openSUSE:Factory/.afl.new/afl.changes     2016-07-28 
23:46:41.000000000 +0200
@@ -1,0 +2,15 @@
+Sat Jul 23 19:10:30 UTC 2016 - [email protected]
+
+- afl 2.21b:
+  * Minor UI fixes
+- includes changes from 2.20b:
+  * Revamp handling of variable paths
+  * Stablility improvements
+  * Include current input bitmap density in UI
+  * Add experimental support for parallelizing -M.
+- includes changes from 2.19b:
+  * Ensure auto CPU binding happens at non-overlapping times
+- includes changes from 2.18b
+  * Performance improvements
+
+-------------------------------------------------------------------

Old:
----
  afl-2.17b.tgz

New:
----
  afl-2.21b.tgz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ afl.spec ++++++
--- /var/tmp/diff_new_pack.oASzMh/_old  2016-07-28 23:46:42.000000000 +0200
+++ /var/tmp/diff_new_pack.oASzMh/_new  2016-07-28 23:46:42.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           afl
-Version:        2.17b
+Version:        2.21b
 Release:        0
 Summary:        American fuzzy lop is a security-oriented fuzzer
 License:        Apache-2.0

++++++ afl-2.17b.tgz -> afl-2.21b.tgz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/afl-as.h new/afl-2.21b/afl-as.h
--- old/afl-2.17b/afl-as.h      2016-06-21 06:44:52.000000000 +0200
+++ new/afl-2.21b/afl-as.h      2016-07-04 22:08:29.000000000 +0200
@@ -98,7 +98,7 @@
    of every .c file. This should have no impact in any practical sense.
 
    Another side effect of this design is that getenv() will be called once per
-   every .o file when running in non-instrumented mode; an since getenv() tends
+   every .o file when running in non-instrumented mode; and since getenv() 
tends
    to be optimized in funny ways, we need to be very careful to save every
    oddball register it may touch.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/afl-fuzz.c new/afl-2.21b/afl-fuzz.c
--- old/afl-2.17b/afl-fuzz.c    2016-06-28 07:22:19.000000000 +0200
+++ new/afl-2.21b/afl-fuzz.c    2016-07-23 01:21:04.000000000 +0200
@@ -112,12 +112,12 @@
            in_place_resume,           /* Attempt in-place resume?         */
            auto_changed,              /* Auto-generated tokens changed?   */
            no_cpu_meter_red,          /* Feng shui on the status screen   */
-           no_var_check,              /* Don't detect variable behavior   */
            shuffle_queue,             /* Shuffle input queue?             */
            bitmap_changed = 1,        /* Time to update bitmap?           */
            qemu_mode,                 /* Running in QEMU mode?            */
            skip_requested,            /* Skip request, via SIGUSR1        */
-           run_over10m;               /* Run time over 10 minutes?        */
+           run_over10m,               /* Run time over 10 minutes?        */
+           persistent_mode;           /* Running in persistent mode?      */
 
 static s32 out_fd,                    /* Persistent fd for out_file       */
            dev_urandom_fd = -1,       /* Persistent fd for /dev/urandom   */
@@ -135,6 +135,8 @@
            virgin_hang[MAP_SIZE],     /* Bits we haven't seen in hangs    */
            virgin_crash[MAP_SIZE];    /* Bits we haven't seen in crashes  */
 
+static u8  var_bytes[MAP_SIZE];       /* Bytes that appear to be variable */
+
 static s32 shm_id;                    /* ID of the SHM region             */
 
 static volatile u8 stop_soon,         /* Ctrl-C pressed?                  */
@@ -154,6 +156,7 @@
            cur_depth,                 /* Current path depth               */
            max_depth,                 /* Max path depth                   */
            useless_at_start,          /* Number of useless starting paths */
+           var_byte_count,            /* Bitmap bytes with var behavior   */
            current_entry,             /* Current queue entry ID           */
            havoc_div = 1;             /* Cycle count divisor for havoc    */
 
@@ -166,6 +169,7 @@
            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     */
            trim_execs,                /* Execs done to trim input files   */
@@ -183,6 +187,8 @@
 static s32 stage_cur, stage_max;      /* Stage progression                */
 static s32 splicing_with = -1;        /* Splicing with which test case?   */
 
+static u32 master_id, master_max;     /* Master instance job splitting    */
+
 static u32 syncing_case;              /* Syncing with case #...           */
 
 static s32 stage_cur_byte,            /* Byte offset of current stage op  */
@@ -343,7 +349,7 @@
 
 static inline u32 UR(u32 limit) {
 
-  if (!rand_cnt--) {
+  if (unlikely(!rand_cnt--)) {
 
     u32 seed[2];
 
@@ -863,9 +869,6 @@
    This function is called after every exec() on a fairly large buffer, so
    it needs to be fast. We do this in 32-bit and 64-bit flavors. */
 
-#define FFL(_b) (0xffULL << ((_b) << 3))
-#define FF(_b)  (0xff << ((_b) << 3))
-
 static inline u8 has_new_bits(u8* virgin_map) {
 
 #ifdef __x86_64__
@@ -888,53 +891,39 @@
 
   while (i--) {
 
-#ifdef __x86_64__
-
-    u64 cur = *current;
-    u64 vir = *virgin;
-
-#else
-
-    u32 cur = *current;
-    u32 vir = *virgin;
-
-#endif /* ^__x86_64__ */
+    /* Optimize for (*current & *virgin) == 0 - i.e., no bits in current bitmap
+       that have not been already cleared from the virgin map - since this will
+       almost always be the case. */
 
-    /* Optimize for *current == ~*virgin, since this will almost always be the
-       case. */
+    if (unlikely(*current) && unlikely(*current & *virgin)) {
 
-    if (cur & vir) {
+      if (likely(ret < 2)) {
 
-      if (ret < 2) {
+        u8* cur = (u8*)current;
+        u8* vir = (u8*)virgin;
 
-        /* This trace did not have any new bytes yet; see if there's any
-           current[] byte that is non-zero when virgin[] is 0xff. */
+        /* Looks like we have not found any new bytes yet; see if any non-zero
+           bytes in current[] are pristine in virgin[]. */
 
 #ifdef __x86_64__
 
-        if (((cur & FFL(0)) && (vir & FFL(0)) == FFL(0)) ||
-            ((cur & FFL(1)) && (vir & FFL(1)) == FFL(1)) ||
-            ((cur & FFL(2)) && (vir & FFL(2)) == FFL(2)) ||
-            ((cur & FFL(3)) && (vir & FFL(3)) == FFL(3)) ||
-            ((cur & FFL(4)) && (vir & FFL(4)) == FFL(4)) ||
-            ((cur & FFL(5)) && (vir & FFL(5)) == FFL(5)) ||
-            ((cur & FFL(6)) && (vir & FFL(6)) == FFL(6)) ||
-            ((cur & FFL(7)) && (vir & FFL(7)) == FFL(7))) ret = 2;
+        if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) ||
+            (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) ||
+            (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) ||
+            (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) ret = 2;
         else ret = 1;
 
 #else
 
-        if (((cur & FF(0)) && (vir & FF(0)) == FF(0)) ||
-            ((cur & FF(1)) && (vir & FF(1)) == FF(1)) ||
-            ((cur & FF(2)) && (vir & FF(2)) == FF(2)) ||
-            ((cur & FF(3)) && (vir & FF(3)) == FF(3))) ret = 2;
+        if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) ||
+            (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) ret = 2;
         else ret = 1;
 
 #endif /* ^__x86_64__ */
 
       }
 
-      *virgin = vir & ~cur;
+      *virgin &= ~*current;
 
     }
 
@@ -982,6 +971,8 @@
 }
 
 
+#define FF(_b)  (0xff << ((_b) << 3))
+
 /* Count the number of bytes set in the bitmap. Called fairly sporadically,
    mostly to update the status screen or calibrate and examine confirmed
    new paths. */
@@ -1060,7 +1051,7 @@
 
     /* Optimize for sparse bitmaps. */
 
-    if (*mem) {
+    if (unlikely(*mem)) {
 
       u8* mem8 = (u8*)mem;
 
@@ -1091,7 +1082,7 @@
 
     /* Optimize for sparse bitmaps. */
 
-    if (*mem) {
+    if (unlikely(*mem)) {
 
       u8* mem8 = (u8*)mem;
 
@@ -1114,7 +1105,7 @@
    preprocessing step for any newly acquired traces. Called on every exec,
    must be fast. */
 
-static const u8 count_class_lookup[256] = {
+static const u8 count_class_lookup8[256] = {
 
   [0]           = 0,
   [1]           = 1,
@@ -1128,6 +1119,22 @@
 
 };
 
+static u16 count_class_lookup16[65536];
+
+
+static void init_count_class16(void) {
+
+  u32 b1, b2;
+
+  for (b1 = 0; b1 < 256; b1++) 
+    for (b2 = 0; b2 < 256; b2++)
+      count_class_lookup16[(b1 << 8) + b2] = 
+        (count_class_lookup8[b1] << 8) |
+        count_class_lookup8[b2];
+
+}
+
+
 #ifdef __x86_64__
 
 static inline void classify_counts(u64* mem) {
@@ -1138,18 +1145,14 @@
 
     /* Optimize for sparse bitmaps. */
 
-    if (*mem) {
+    if (unlikely(*mem)) {
 
-      u8* mem8 = (u8*)mem;
+      u16* mem16 = (u16*)mem;
 
-      mem8[0] = count_class_lookup[mem8[0]];
-      mem8[1] = count_class_lookup[mem8[1]];
-      mem8[2] = count_class_lookup[mem8[2]];
-      mem8[3] = count_class_lookup[mem8[3]];
-      mem8[4] = count_class_lookup[mem8[4]];
-      mem8[5] = count_class_lookup[mem8[5]];
-      mem8[6] = count_class_lookup[mem8[6]];
-      mem8[7] = count_class_lookup[mem8[7]];
+      mem16[0] = count_class_lookup16[mem16[0]];
+      mem16[1] = count_class_lookup16[mem16[1]];
+      mem16[2] = count_class_lookup16[mem16[2]];
+      mem16[3] = count_class_lookup16[mem16[3]];
 
     }
 
@@ -1169,14 +1172,12 @@
 
     /* Optimize for sparse bitmaps. */
 
-    if (*mem) {
+    if (unlikely(*mem)) {
 
-      u8* mem8 = (u8*)mem;
+      u16* mem16 = (u16*)mem;
 
-      mem8[0] = count_class_lookup[mem8[0]];
-      mem8[1] = count_class_lookup[mem8[1]];
-      mem8[2] = count_class_lookup[mem8[2]];
-      mem8[3] = count_class_lookup[mem8[3]];
+      mem16[0] = count_class_lookup16[mem16[0]];
+      mem16[1] = count_class_lookup16[mem16[1]];
 
     }
 
@@ -2520,7 +2521,11 @@
 static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,
                          u32 handicap, u8 from_queue) {
 
-  u8  fault = 0, new_bits = 0, var_detected = 0, first_run = (q->exec_cksum == 
0);
+  static u8 first_trace[MAP_SIZE];
+
+  u8  fault = 0, new_bits = 0, var_detected = 0,
+      first_run = (q->exec_cksum == 0);
+
   u64 start_us, stop_us;
 
   s32 old_sc = stage_cur, old_sm = stage_max, old_tmout = exec_tmout;
@@ -2537,7 +2542,7 @@
   q->cal_failed++;
 
   stage_name = "calibration";
-  stage_max  = no_var_check ? CAL_CYCLES_NO_VAR : CAL_CYCLES;
+  stage_max  = CAL_CYCLES;
 
   /* Make sure the forkserver is up before we do anything, and let's not
      count its spin-up time toward binary calibration. */
@@ -2545,6 +2550,8 @@
   if (dumb_mode != 1 && !no_forkserver && !forksrv_pid)
     init_forkserver(argv);
 
+  if (q->exec_cksum) memcpy(first_trace, trace_bits, MAP_SIZE);
+
   start_us = get_cur_time_us();
 
   for (stage_cur = 0; stage_cur < stage_max; stage_cur++) {
@@ -2574,12 +2581,24 @@
       u8 hnb = has_new_bits(virgin_bits);
       if (hnb > new_bits) new_bits = hnb;
 
-      if (!no_var_check && q->exec_cksum) {
+      if (q->exec_cksum) {
+
+        u32 i;
+
+        for (i = 0; i < MAP_SIZE; i++) 
+          if (!var_bytes[i] && first_trace[i] != trace_bits[i]) {
+            var_bytes[i] = 1;
+            stage_max    = CAL_CYCLES_LONG;
+          }
 
         var_detected = 1;
-        stage_max    = CAL_CYCLES_LONG;
 
-      } else q->exec_cksum = cksum;
+      } else {
+
+        q->exec_cksum = cksum;
+        memcpy(first_trace, trace_bits, MAP_SIZE);
+
+      }
 
     }
 
@@ -2618,9 +2637,15 @@
 
   /* Mark variable paths. */
 
-  if (var_detected && !q->var_behavior) {
-    mark_as_variable(q);
-    queued_variable++;
+  if (var_detected) {
+
+    var_byte_count = count_bytes(var_bytes);
+
+    if (!q->var_behavior) {
+      mark_as_variable(q);
+      queued_variable++;
+    }
+
   }
 
   stage_name = old_sn;
@@ -3209,6 +3234,7 @@
       unique_crashes++;
 
       last_crash_time = get_cur_time();
+      last_crash_execs = total_execs;
 
       break;
 
@@ -3306,9 +3332,9 @@
 
 /* Update stats file for unattended monitoring. */
 
-static void write_stats_file(double bitmap_cvg, double eps) {
+static void write_stats_file(double bitmap_cvg, double stability, double eps) {
 
-  static double last_bcvg, last_eps;
+  static double last_bcvg, last_stab, last_eps;
 
   u8* fn = alloc_printf("%s/fuzzer_stats", out_dir);
   s32 fd;
@@ -3327,46 +3353,51 @@
   /* Keep last values in case we're called from another context
      where exec/sec stats and such are not readily available. */
 
-  if (!bitmap_cvg && !eps) {
+  if (!bitmap_cvg && !stability && !eps) {
     bitmap_cvg = last_bcvg;
+    stability  = last_stab;
     eps        = last_eps;
   } else {
     last_bcvg = bitmap_cvg;
+    last_stab = stability;
     last_eps  = eps;
   }
 
-  fprintf(f, "start_time     : %llu\n"
-             "last_update    : %llu\n"
-             "fuzzer_pid     : %u\n"
-             "cycles_done    : %llu\n"
-             "execs_done     : %llu\n"
-             "execs_per_sec  : %0.02f\n"
-             "paths_total    : %u\n"
-             "paths_favored  : %u\n"
-             "paths_found    : %u\n"
-             "paths_imported : %u\n"
-             "max_depth      : %u\n"
-             "cur_path       : %u\n"
-             "pending_favs   : %u\n"
-             "pending_total  : %u\n"
-             "variable_paths : %u\n"
-             "bitmap_cvg     : %0.02f%%\n"
-             "unique_crashes : %llu\n"
-             "unique_hangs   : %llu\n"
-             "last_path      : %llu\n"
-             "last_crash     : %llu\n"
-             "last_hang      : %llu\n"
-             "exec_timeout   : %u\n"
-             "afl_banner     : %s\n"
-             "afl_version    : " VERSION "\n"
-             "command_line   : %s\n",
+  fprintf(f, "start_time        : %llu\n"
+             "last_update       : %llu\n"
+             "fuzzer_pid        : %u\n"
+             "cycles_done       : %llu\n"
+             "execs_done        : %llu\n"
+             "execs_per_sec     : %0.02f\n"
+             "paths_total       : %u\n"
+             "paths_favored     : %u\n"
+             "paths_found       : %u\n"
+             "paths_imported    : %u\n"
+             "max_depth         : %u\n"
+             "cur_path          : %u\n"
+             "pending_favs      : %u\n"
+             "pending_total     : %u\n"
+             "variable_paths    : %u\n"
+             "stability         : %0.02f%%\n"
+             "bitmap_cvg        : %0.02f%%\n"
+             "unique_crashes    : %llu\n"
+             "unique_hangs      : %llu\n"
+             "last_path         : %llu\n"
+             "last_crash        : %llu\n"
+             "last_hang         : %llu\n"
+             "execs_since_crash : %llu\n"
+             "exec_timeout      : %u\n"
+             "afl_banner        : %s\n"
+             "afl_version       : " VERSION "\n"
+             "command_line      : %s\n",
              start_time / 1000, get_cur_time() / 1000, getpid(),
              queue_cycle ? (queue_cycle - 1) : 0, total_execs, eps,
              queued_paths, queued_favored, queued_discovered, queued_imported,
              max_depth, current_entry, pending_favored, pending_not_fuzzed,
-             queued_variable, bitmap_cvg, unique_crashes, unique_hangs,
-             last_path_time / 1000, last_crash_time / 1000,
-             last_hang_time / 1000, exec_tmout, use_banner, orig_cmdline);
+             queued_variable, stability, bitmap_cvg, unique_crashes,
+             unique_hangs, last_path_time / 1000, last_crash_time / 1000,
+             last_hang_time / 1000, total_execs - last_crash_execs,
+             exec_tmout, use_banner, orig_cmdline);
              /* ignore errors */
 
   fclose(f);
@@ -3789,7 +3820,7 @@
 
   static u64 last_stats_ms, last_plot_ms, last_ms, last_execs;
   static double avg_exec;
-  double t_byte_ratio;
+  double t_byte_ratio, stab_ratio;
 
   u64 cur_ms;
   u32 t_bytes, t_bits;
@@ -3842,12 +3873,17 @@
   t_bytes = count_non_255_bytes(virgin_bits);
   t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE;
 
+  if (t_bytes) 
+    stab_ratio = 100 - ((double)var_byte_count) * 100 / t_bytes;
+  else
+    stab_ratio = 100;
+
   /* Roughly every minute, update fuzzer stats and save auto tokens. */
 
   if (cur_ms - last_stats_ms > STATS_UPDATE_SEC * 1000) {
 
     last_stats_ms = cur_ms;
-    write_stats_file(t_byte_ratio, avg_exec);
+    write_stats_file(t_byte_ratio, stab_ratio, avg_exec);
     save_auto();
     write_bitmap();
 
@@ -4009,8 +4045,8 @@
 
   SAYF(bV bSTOP "  now processing : " cRST "%-17s " bSTG bV bSTOP, tmp);
 
-
-  sprintf(tmp, "%s (%0.02f%%)", DI(t_bytes), t_byte_ratio);
+  sprintf(tmp, "%0.02f%% / %0.02f%%", ((double)queue_cur->bitmap_size) * 
+          100 / MAP_SIZE, t_byte_ratio);
 
   SAYF("    map density : %s%-21s " bSTG bV "\n", t_byte_ratio > 70 ? cLRD : 
        ((t_bytes < 200 && !dumb_mode) ? cPIN : cRST), tmp);
@@ -4154,9 +4190,13 @@
           DI(stage_finds[STAGE_HAVOC]), DI(stage_cycles[STAGE_HAVOC]),
           DI(stage_finds[STAGE_SPLICE]), DI(stage_cycles[STAGE_SPLICE]));
 
-  SAYF(bV bSTOP "       havoc : " cRST "%-37s " bSTG bV bSTOP 
-       "  variable : %s%-10s " bSTG bV "\n", tmp, queued_variable ? cLRD : 
cRST,
-      no_var_check ? (u8*)"n/a" : DI(queued_variable));
+  SAYF(bV bSTOP "       havoc : " cRST "%-37s " bSTG bV bSTOP, tmp);
+
+  if (t_bytes) sprintf(tmp, "%0.02f%%", stab_ratio);
+    else strcpy(tmp, "n/a");
+
+  SAYF(" stability : %s%-10s " bSTG bV "\n", stab_ratio < 90 ? cLRD :
+          ((queued_variable && !persistent_mode) ? cMGN : cRST), tmp);
 
   if (!bytes_trim_out) {
 
@@ -4967,6 +5007,12 @@
   if (skip_deterministic || queue_cur->was_fuzzed || queue_cur->passed_det)
     goto havoc_stage;
 
+  /* Skip deterministic fuzzing if exec path checksum puts this out of scope
+     for this master instance. */
+
+  if (master_max && (queue_cur->exec_cksum % master_max) != master_id - 1)
+    goto havoc_stage;
+
   /*********************************************
    * SIMPLE BITFLIP (+dictionary construction) *
    *********************************************/
@@ -5136,7 +5182,7 @@
   /* Effector map setup. These macros calculate:
 
      EFF_APOS      - position of a particular file offset in the map.
-     EFF_ALEN      - length of an map with a particular number of bytes.
+     EFF_ALEN      - length of a map with a particular number of bytes.
      EFF_SPAN_ALEN - map span for a sequence of bytes.
 
    */
@@ -6567,8 +6613,14 @@
 
       path = alloc_printf("%s/%s", qd_path, qd_ent->d_name);
 
+      /* Allow this to fail in case the other fuzzer is resuming or so... */
+
       fd = open(path, O_RDONLY);
-      if (fd < 0) PFATAL("Unable to open '%s'", path);
+
+      if (fd < 0) {
+         ck_free(path);
+         continue;
+      }
 
       if (fstat(fd, &st)) PFATAL("fstat() failed");
 
@@ -6802,7 +6854,6 @@
 
     OKF(cPIN "Persistent mode binary detected.");
     setenv(PERSIST_ENV_VAR, "1", 1);
-    no_var_check = 1;
 
   } else if (getenv("AFL_PERSISTENT")) {
 
@@ -6814,6 +6865,7 @@
 
     OKF(cPIN "Deferred forkserver binary detected.");
     setenv(DEFER_ENV_VAR, "1", 1);
+    persistent_mode = 1;
 
   } else if (getenv("AFL_DEFER_FORKSRV")) {
 
@@ -7556,18 +7608,23 @@
   u8  *extras_dir = 0;
   u8  mem_limit_given = 0;
   u8  exit_1 = !!getenv("AFL_BENCH_JUST_ONE");
-
   char** use_argv;
 
+  struct timeval tv;
+  struct timezone tz;
+
   SAYF(cCYA "afl-fuzz " cBRI VERSION cRST " by <[email protected]>\n");
 
   doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
 
+  gettimeofday(&tv, &tz);
+  srandom(tv.tv_sec ^ tv.tv_usec ^ getpid());
+
   while ((opt = getopt(argc, argv, "+i:o:f:m:t:T:dnCB:S:M:x:Q")) > 0)
 
     switch (opt) {
 
-      case 'i':
+      case 'i': /* input dir */
 
         if (in_dir) FATAL("Multiple -i options not supported");
         in_dir = optarg;
@@ -7582,15 +7639,30 @@
         out_dir = optarg;
         break;
 
-      case 'M':
+      case 'M': /* master sync ID */
 
         force_deterministic = 1;
         /* Fall through */
 
-      case 'S': /* sync ID */
+      case 'S': { /* secondary sync ID */
+
+          u8* c;
+
+          if (sync_id) FATAL("Multiple -S or -M options not supported");
+          sync_id = optarg;
+
+          if ((c = strchr(sync_id, ':'))) {
+
+            *c = 0;
+
+            if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 ||
+                !master_id || !master_max || master_id > master_max ||
+                master_max > 1000000) FATAL("Bogus master ID passed to -M");
+
+          }
+
+        }
 
-        if (sync_id) FATAL("Multiple -S or -M options not supported");
-        sync_id = optarg;
         break;
 
       case 'f': /* target file */
@@ -7599,13 +7671,13 @@
         out_file = optarg;
         break;
 
-      case 'x':
+      case 'x': /* dictionary */
 
         if (extras_dir) FATAL("Multiple -x options not supported");
         extras_dir = optarg;
         break;
 
-      case 't': {
+      case 't': { /* timeout */
 
           u8 suffix = 0;
 
@@ -7622,7 +7694,7 @@
 
       }
 
-      case 'm': {
+      case 'm': { /* mem limit */
 
           u8 suffix = 'M';
 
@@ -7659,14 +7731,14 @@
 
         break;
 
-      case 'd':
+      case 'd': /* skip deterministic */
 
         if (skip_deterministic) FATAL("Multiple -d options not supported");
         skip_deterministic = 1;
         use_splicing = 1;
         break;
 
-      case 'B':
+      case 'B': /* load bitmap */
 
         /* This is a secret undocumented option! It is useful if you find
            an interesting test case during a normal fuzzing process, and want
@@ -7685,26 +7757,26 @@
         read_bitmap(in_bitmap);
         break;
 
-      case 'C':
+      case 'C': /* crash mode */
 
         if (crash_mode) FATAL("Multiple -C options not supported");
         crash_mode = FAULT_CRASH;
         break;
 
-      case 'n':
+      case 'n': /* dumb mode */
 
         if (dumb_mode) FATAL("Multiple -n options not supported");
         if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1;
 
         break;
 
-      case 'T':
+      case 'T': /* banner */
 
         if (use_banner) FATAL("Multiple -T options not supported");
         use_banner = optarg;
         break;
 
-      case 'Q':
+      case 'Q': /* QEMU mode */
 
         if (qemu_mode) FATAL("Multiple -Q options not supported");
         qemu_mode = 1;
@@ -7738,7 +7810,6 @@
 
   if (getenv("AFL_NO_FORKSRV"))    no_forkserver    = 1;
   if (getenv("AFL_NO_CPU_RED"))    no_cpu_meter_red = 1;
-  if (getenv("AFL_NO_VAR_CHECK"))  no_var_check     = 1;
   if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue    = 1;
 
   if (dumb_mode == 2 && no_forkserver)
@@ -7764,6 +7835,7 @@
 
   setup_post();
   setup_shm();
+  init_count_class16();
 
   setup_dirs_fds();
   read_testcases();
@@ -7796,7 +7868,7 @@
 
   seek_to = find_start_position();
 
-  write_stats_file(0, 0);
+  write_stats_file(0, 0, 0);
   save_auto();
 
   if (stop_soon) goto stop_fuzzing;
@@ -7872,7 +7944,7 @@
   if (queue_cur) show_stats();
 
   write_bitmap();
-  write_stats_file(0, 0);
+  write_stats_file(0, 0, 0);
   save_auto();
 
 stop_fuzzing:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/config.h new/afl-2.21b/config.h
--- old/afl-2.17b/config.h      2016-06-27 21:06:37.000000000 +0200
+++ new/afl-2.21b/config.h      2016-07-23 01:21:30.000000000 +0200
@@ -21,7 +21,7 @@
 
 /* Version string: */
 
-#define VERSION             "2.17b"
+#define VERSION             "2.21b"
 
 /******************************************************
  *                                                    *
@@ -61,13 +61,9 @@
 /* Number of calibration cycles per every new test case (and for test
    cases that show variable behavior): */
 
-#define CAL_CYCLES          10
+#define CAL_CYCLES          8
 #define CAL_CYCLES_LONG     40
 
-/* The same, but when AFL_NO_VAR_CHECK is set in the environment: */
-
-#define CAL_CYCLES_NO_VAR   4
-
 /* Number of subsequent hangs before abandoning an input file: */
 
 #define HANG_LIMIT          250
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/ChangeLog new/afl-2.21b/docs/ChangeLog
--- old/afl-2.17b/docs/ChangeLog        2016-06-28 04:17:51.000000000 +0200
+++ new/afl-2.21b/docs/ChangeLog        2016-07-23 01:21:22.000000000 +0200
@@ -13,10 +13,50 @@
 sending a mail to <[email protected]>.
 
 Not sure if you should upgrade? The lowest currently recommended version
-is 2.07b. If you're stuck on an earlier release, it's strongly advisable
+is 2.18b. If you're stuck on an earlier release, it's strongly advisable
 to get on with the times.
 
 --------------
+Version 2.21b:
+--------------
+
+  - Added some crash reporting notes for Solaris in docs/INSTALL, as
+    investigated by Martin Carpenter.
+
+  - Fixed a minor UI mix-up with havoc strategy stats.
+
+--------------
+Version 2.20b:
+--------------
+
+  - Revamped the handling of variable paths, replacing path count with a
+    "stability" score to give users a much better signal. Based on the
+    feedback from Vegard Nossum.
+
+  - Made a stability improvement to the syncing behavior with resuming
+    fuzzers. Based on the feedback from Vegard.
+
+  - Changed the UI to include current input bitmap density along with
+    total density. Ditto.
+
+  - Added experimental support for parallelizing -M.
+
+--------------
+Version 2.19b:
+--------------
+
+  - Made a fix to make sure that auto CPU binding happens at non-overlapping
+    times.
+
+--------------
+Version 2.18b:
+--------------
+
+  - Made several performance improvements to has_new_bits() and
+    classify_counts(). This should offer a robust performance bump with
+    fast targets.
+
+--------------
 Version 2.17b:
 --------------
 
@@ -1495,7 +1535,7 @@
   - Refactored the code slightly to make more frequent updates to fuzzer_stats
     and to provide more detail about synchronization.
 
-  - Added a fflush(stdout) call for non-tty operation, as requested by 
+  - Added an fflush(stdout) call for non-tty operation, as requested by 
     Joonas Kuorilehto.
 
   - Added some detail to fuzzer_stats for parity with plot_file.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/INSTALL new/afl-2.21b/docs/INSTALL
--- old/afl-2.17b/docs/INSTALL  2016-06-07 20:17:00.000000000 +0200
+++ new/afl-2.21b/docs/INSTALL  2016-07-22 20:48:18.000000000 +0200
@@ -140,11 +140,13 @@
 Do *not* specify --with-as=/usr/gnu/bin/as - this will produce a GCC binary 
that
 ignores the -B flag and you will be back to square one.
 
-If you have system-wide crash reporting enabled, you may run into problems
-similar to the gotchas for Linux and MacOS X, but I have not verified this.
-More information about AppCrash can be found here:
+Note that Solaris reportedly comes withe crash reporting enabled, which causes
+problems with crashes being misinterpreted as hangs, similarly to the gotchas
+for Linux and MacOS X. AFL does not auto-detect crash reporting on this
+particular platform, but you may need to run the following command:
 
-  
http://www.oracle.com/technetwork/server-storage/solaris10/app-crash-142906.html
+$ coreadm -d global -d global-setid -d process -d proc-setid \
+  -d kzone -d log
 
 User emulation mode of QEMU is not available on Solaris, so black-box
 instrumentation mode (-Q) will not work.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/README new/afl-2.21b/docs/README
--- old/afl-2.17b/docs/README   2016-06-19 00:24:18.000000000 +0200
+++ new/afl-2.21b/docs/README   2016-07-21 20:54:39.000000000 +0200
@@ -464,6 +464,7 @@
   Daniel Godas-Lopez                    Franjo Ivancic
   Austin Seipp                          Daniel Komaromy
   Daniel Binderman                      Jonathan Metzman
+  Vegard Nossum
 
 Thank you!
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/env_variables.txt 
new/afl-2.21b/docs/env_variables.txt
--- old/afl-2.17b/docs/env_variables.txt        2016-06-27 20:43:23.000000000 
+0200
+++ new/afl-2.21b/docs/env_variables.txt        2016-07-21 20:42:24.000000000 
+0200
@@ -99,11 +99,6 @@
     normally done when starting up the forkserver and causes a pretty
     significant performance drop.
 
-  - Setting AFL_NO_VAR_CHECK skips the detection of variable test cases,
-    greatly speeding up session resumption and path discovery for complex
-    multi-threaded apps (but depriving you of a potentially useful signal
-    in more orderly programs).
-
   - AFL_EXIT_WHEN_DONE causes afl-fuzz to terminate when all existing paths
     have been fuzzed and there were no new finds for a while. This would be
     normally indicated by the cycle counter in the UI turning green. May be
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/parallel_fuzzing.txt 
new/afl-2.21b/docs/parallel_fuzzing.txt
--- old/afl-2.17b/docs/parallel_fuzzing.txt     2016-04-23 08:54:06.000000000 
+0200
+++ new/afl-2.21b/docs/parallel_fuzzing.txt     2016-07-21 22:21:48.000000000 
+0200
@@ -51,13 +51,25 @@
 for any test cases found by other fuzzers - and will incorporate them into
 its own fuzzing when they are deemed interesting enough.
 
-The only difference between the -M and -S modes is that the master instance
-will still perform deterministic checks; while the secondary instances will
+The difference between the -M and -S modes is that the master instance will
+still perform deterministic checks; while the secondary instances will
 proceed straight to random tweaks. If you don't want to do deterministic
 fuzzing at all, it's OK to run all instances with -S. With very slow or complex
 targets, or when running heavily parallelized jobs, this is usually a good 
plan.
 
-You can monitor the progress of your jobs from the command line with the
+Note that running multiple -M instances is wasteful, although there is an
+experimental support for parallelizing the deterministic checks. To leverage
+that, you need to create -M instances like so:
+
+$ ./afl-fuzz -i testcase_dir -o sync_dir -M masterA:1/3 [...]
+$ ./afl-fuzz -i testcase_dir -o sync_dir -M masterB:2/3 [...]
+$ ./afl-fuzz -i testcase_dir -o sync_dir -M masterC:3/3 [...]
+
+...where the first value after ':' is the sequential ID of a particular master
+instance (starting at 1), and the second value is the total number of fuzzers 
to
+distribute the deterministic fuzzing across.
+
+You can also monitor the progress of your jobs from the command line with the
 provided afl-whatsup tool. When the instances are no longer finding new paths,
 it's probably time to stop.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/sister_projects.txt 
new/afl-2.21b/docs/sister_projects.txt
--- old/afl-2.17b/docs/sister_projects.txt      2016-06-27 21:33:46.000000000 
+0200
+++ new/afl-2.21b/docs/sister_projects.txt      2016-07-12 04:42:04.000000000 
+0200
@@ -78,6 +78,13 @@
 
   
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2016/june/project-triforce-run-afl-on-everything/
 
+WinAFL (Ivan Fratric)
+---------------------
+
+  As the name implies, allows you to fuzz Windows binaries (using DynamoRio).
+
+  https://github.com/ivanfratric/winafl
+
 ----------------
 Network fuzzing:
 ----------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/docs/status_screen.txt 
new/afl-2.21b/docs/status_screen.txt
--- old/afl-2.17b/docs/status_screen.txt        2016-02-21 01:01:37.000000000 
+0100
+++ new/afl-2.21b/docs/status_screen.txt        2016-07-21 22:37:18.000000000 
+0200
@@ -119,7 +119,7 @@
 ---------------
 
   +--------------------------------------+
-  |    map density : 4763 (29.07%)       |
+  |    map density : 10.15% / 29.07%     |
   | count coverage : 4.03 bits/tuple     |
   +--------------------------------------+
 
@@ -127,7 +127,11 @@
 instrumentation embedded in the target binary.
 
 The first line in the box tells you how many branch tuples we have already
-hit, in proportion to how much the bitmap can hold. Be wary of extremes:
+hit, in proportion to how much the bitmap can hold. The number on the left
+describes the current input; the one on the right is the value for the entire
+input corpus.
+
+Be wary of extremes:
 
   - Absolute numbers below 200 or so suggest one of three things: that the
     program is extremely simple; that it is not instrumented properly (e.g.,
@@ -271,7 +275,7 @@
   |  pend fav : 583     |
   | own finds : 0       |
   |  imported : 0       |
-  |  variable : 0       |
+  | stability : 100.00% |
   +---------------------+
 
 The first field in this section tracks the path depth reached through the
@@ -291,27 +295,33 @@
 imported from other fuzzer instances when doing parallelized fuzzing; and the
 number of inputs that produce seemingly variable behavior in the tested binary.
 
-That last bit is actually fairly interesting. There are four quasi-common
-explanations for variable behavior of the tested program:
-
-  - Use of uninitialized memory in conjunction with some intrinsic sources of
-    entropy in the tested binary. This can be indicative of a security bug.
-
-  - Attempts to create files that were already created during previous runs, or
-    otherwise interact with some form of persistent state. This is harmless,
-    but you may want to instruct the targeted program to write to stdout or to
-    /dev/null to avoid surprises (and disable the creation of temporary files
-    and similar artifacts, if applicable).
-
-  - Hitting functionality that is actually designed to behave randomly. For
-    example, when fuzzing sqlite, the fuzzer will dutifully detect variable
-    behavior once the mutation engine generates something like:
-
-    select random();
-
-  - Multiple threads executing at once in semi-random order. This is usually
-    just a nuisance, but if the number of variable paths is very high, try the
-    following options:
+That last bit is actually fairly interesting: it measures the consistency of
+observed traces. If a program always behaves the same for the same input data,
+it will earn a score of 100%. When the value is over 90%, the fuzzing process
+is still unlikely to be negatively affected. If it gets much lower, you may
+be in trouble, since AFL will have difficulty discerning between meaningful
+and "phantom" effects of tweaking the input file.
+
+Now, most targets will just get a 100% score, but when you see lower figures,
+there are several things to look at:
+
+  - The use of uninitialized memory in conjunction with some intrinsic sources
+    of entropy in the tested binary. Harmless to AFL, but could be indicative
+    of a security bug.
+
+  - Attempts to manipulate persistent resources, such as left over temporary
+    files or shared memory objects. This is usually harmless, but you may want
+    to double-check to make sure the program isn't bailing out prematurely.
+    Running out of disk space, SHM handles, or other global resources can
+    trigger this, too.
+
+  - Hitting some functionality that is actually designed to behave randomly.
+    Generally harmless. For example, when fuzzing sqlite, an input like
+    'select random();' will trigger a variable execution path.
+
+  - Multiple threads executing at once in semi-random order. This is harmless
+    when the 'stability' metric stays over 90% or so, but can become an issue
+    if not. Here's what to try:
 
     - Use afl-clang-fast from llvm_mode/ - it uses a thread-local tracking
       model that is less prone to concurrency issues,
@@ -323,17 +333,10 @@
     - Replace pthreads with GNU Pth (https://www.gnu.org/software/pth/), which
       allows you to use a deterministic scheduler.
 
-Less likely causes may include running out of disk space, SHM handles, or other
-globally limited resources.
-
 The paths where variable behavior is detected are marked with a matching entry
 in the <out_dir>/queue/.state/variable_behavior/ directory, so you can look
 them up easily.
 
-If you can't suppress variable behavior and don't want to see these warnings,
-simply set AFL_NO_VAR_CHECK=1 in the environment before running afl-fuzz. This
-will also dramatically speed up session resumption.
-
 9) CPU load
 -----------
 
@@ -378,6 +381,7 @@
   - cur_path       - currently processed entry number
   - pending_favs   - number of favored entries still waiting to be fuzzed
   - pending_total  - number of all entries waiting to be fuzzed
+  - stability      - percentage of bitmap bytes that behave consistently
   - variable_paths - number of test cases showing variable behavior
   - unique_crashes - number of unique crashes recorded
   - unique_hangs   - number of unique hangs encountered
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/llvm_mode/README.llvm 
new/afl-2.21b/llvm_mode/README.llvm
--- old/afl-2.17b/llvm_mode/README.llvm 2016-06-07 20:14:22.000000000 +0200
+++ new/afl-2.21b/llvm_mode/README.llvm 2016-07-21 20:42:06.000000000 +0200
@@ -163,8 +163,8 @@
 
 When running in this mode, the execution paths will inherently vary a bit
 depending on whether the input loop is being entered for the first time or
-executed again. To avoid spurious warnings, the feature implies 
-AFL_NO_VAR_CHECK and hides the "variable path" warnings in the UI.
+executed again. This can cause the "stability" metric in the UI to dip
+slightly under 100%.
 
 PS. Because there are task switches still involved, the mode isn't as fast as
 "pure" in-process fuzzing offered, say, by LLVM's LibFuzzer; but it is a lot
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/afl-2.17b/types.h new/afl-2.21b/types.h
--- old/afl-2.17b/types.h       2015-02-09 06:06:27.000000000 +0100
+++ new/afl-2.21b/types.h       2016-07-03 06:32:05.000000000 +0200
@@ -76,4 +76,7 @@
 #define MEM_BARRIER() \
   asm volatile("" ::: "memory")
 
+#define likely(_x)   __builtin_expect(!!(_x), 1)
+#define unlikely(_x)  __builtin_expect(!!(_x), 0)
+
 #endif /* ! _HAVE_TYPES_H */


Reply via email to