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 - astieger@suse.com
+
+- 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