aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-07-21 13:15:59 +0200
committerGitHub <noreply@github.com>2020-07-21 13:15:59 +0200
commitb6e65f98827470745d7df5cf1e38b506b9e839b0 (patch)
tree602abd8c1a1929aebda3f80665ffe02b435fdd00 /src
parentfc5cfc6cb309b072a45b991be117c17396e46a89 (diff)
parentc2b04bdf6c596f5d220f27caead20d09452ed42d (diff)
downloadafl++-b6e65f98827470745d7df5cf1e38b506b9e839b0.tar.gz
Merge pull request #461 from AFLplusplus/new_splicing
New splicing
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c29
-rw-r--r--src/afl-common.c74
-rw-r--r--src/afl-forkserver.c29
-rw-r--r--src/afl-fuzz-init.c99
-rw-r--r--src/afl-fuzz-one.c681
-rw-r--r--src/afl-fuzz-queue.c121
-rw-r--r--src/afl-fuzz-redqueen.c28
-rw-r--r--src/afl-fuzz-state.c56
-rw-r--r--src/afl-fuzz.c35
-rw-r--r--src/afl-gcc.c5
-rw-r--r--src/afl-performance.c10
-rw-r--r--src/afl-showmap.c29
-rw-r--r--src/afl-tmin.c29
13 files changed, 448 insertions, 777 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index 56284f6f..e6dd0fca 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -772,15 +772,38 @@ static void set_up_environment(void) {
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
+ "allocator_may_return_null=1:"
"symbolize=0:"
- "allocator_may_return_null=1",
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
+ 0);
+
+ setenv("UBSAN_OPTIONS",
+ "halt_on_error=1:"
+ "abort_on_error=1:"
+ "malloc_context_size=0:"
+ "allocator_may_return_null=1:"
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "symbolize=0:"
"abort_on_error=1:"
+ "msan_track_origins=0"
"allocator_may_return_null=1:"
- "msan_track_origins=0", 0);
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0", 0);
if (get_afl_env("AFL_PRELOAD")) {
diff --git a/src/afl-common.c b/src/afl-common.c
index 79d419cd..c023789b 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -46,50 +46,6 @@ u8 be_quiet = 0;
u8 *doc_path = "";
u8 last_intr = 0;
-char *afl_environment_variables[] = {
-
- "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", "AFL_AS",
- "AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
- "AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CMIN_ALLOW_ANY",
- "AFL_CMIN_CRASHES_ONLY", "AFL_CODE_END", "AFL_CODE_START",
- "AFL_COMPCOV_BINNAME", "AFL_COMPCOV_LEVEL", "AFL_CUSTOM_MUTATOR_LIBRARY",
- "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CXX", "AFL_DEBUG", "AFL_DEBUG_CHILD_OUTPUT",
- "AFL_DEBUG_GDB",
- //"AFL_DEFER_FORKSRV", // not implemented anymore, so warn additionally
- "AFL_DISABLE_TRIM", "AFL_DONT_OPTIMIZE", "AFL_DUMB_FORKSRV",
- "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", "AFL_FAST_CAL", "AFL_FORCE_UI",
- "AFL_GCC_WHITELIST", "AFL_GCJ", "AFL_HANG_TMOUT", "AFL_HARDEN",
- "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IMPORT_FIRST",
- "AFL_INST_LIBS", "AFL_INST_RATIO", "AFL_KEEP_TRACES", "AFL_KEEP_ASSEMBLY",
- "AFL_LD_HARD_FAIL", "AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER",
- "AFL_LD_PASSTHROUGH", "AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE",
- "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CTX",
- "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD",
- "AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY",
- "AFL_LLVM_SKIPSINGLEBLOCK", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK",
- "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW",
- "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES",
- "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR",
- "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
- "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO",
- "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID",
- "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV",
- "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC",
- "AFL_NO_X86", // not really an env but we dont want to warn on it
- "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE",
- //"AFL_PERSISTENT", // not implemented anymore, so warn additionally
- "AFL_PRELOAD", "AFL_PYTHON_MODULE", "AFL_QEMU_COMPCOV",
- "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
- "AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT",
- "AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK",
- "AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
- "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH",
- "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
- "AFL_SKIP_CRASHES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
- "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
- "AFL_USE_UBSAN", "AFL_USE_CFISAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
- NULL};
-
void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
u32 i = 0;
@@ -449,14 +405,14 @@ void check_environment_vars(char **envp) {
if (be_quiet) { return; }
- int index = 0, found = 0;
+ int index = 0, issue_detected = 0;
char *env, *val;
while ((env = envp[index++]) != NULL) {
if (strncmp(env, "ALF_", 4) == 0) {
WARNF("Potentially mistyped AFL environment variable: %s", env);
- found++;
+ issue_detected = 1;
} else if (strncmp(env, "AFL_", 4) == 0) {
@@ -474,6 +430,7 @@ void check_environment_vars(char **envp) {
"AFL environment variable %s defined but is empty, this can "
"lead to unexpected consequences",
afl_environment_variables[i]);
+ issue_detected = 1;
}
@@ -485,10 +442,31 @@ void check_environment_vars(char **envp) {
}
+ i = 0;
+ while (match == 0 && afl_environment_deprecated[i] != NULL) {
+
+ if (strncmp(env, afl_environment_deprecated[i],
+ strlen(afl_environment_deprecated[i])) == 0 &&
+ env[strlen(afl_environment_deprecated[i])] == '=') {
+
+ match = 1;
+
+ WARNF("AFL environment variable %s is deprecated!",
+ afl_environment_deprecated[i]);
+ issue_detected = 1;
+
+ } else {
+
+ i++;
+
+ }
+
+ }
+
if (match == 0) {
WARNF("Mistyped AFL environment variable: %s", env);
- found++;
+ issue_detected = 1;
}
@@ -496,7 +474,7 @@ void check_environment_vars(char **envp) {
}
- if (found) { sleep(2); }
+ if (issue_detected) { sleep(2); }
}
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 419ce28e..47493eba 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -434,7 +434,27 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"detect_leaks=0:"
"malloc_context_size=0:"
"symbolize=0:"
- "allocator_may_return_null=1",
+ "allocator_may_return_null=1:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
+ 0);
+
+ /* Set sane defaults for UBSAN if nothing else specified. */
+
+ setenv("UBSAN_OPTIONS",
+ "halt_on_error=1:"
+ "abort_on_error=1:"
+ "malloc_context_size=0:"
+ "allocator_may_return_null=1:"
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
0);
/* MSAN is tricky, because it doesn't support abort_on_error=1 at this
@@ -446,7 +466,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
"abort_on_error=1:"
"malloc_context_size=0:"
"allocator_may_return_null=1:"
- "msan_track_origins=0",
+ "msan_track_origins=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
0);
fsrv->init_child_func(fsrv, argv);
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index a2e849dc..e95ae95f 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -36,14 +36,11 @@ void bind_to_free_cpu(afl_state_t *afl) {
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
cpu_set_t c;
#elif defined(__NetBSD__)
- cpuset_t * c;
+ cpuset_t *c;
#elif defined(__sun)
- psetid_t c;
+ psetid_t c;
#endif
- u8 cpu_used[4096] = {0};
- u32 i;
-
if (afl->cpu_core_count < 2) { return; }
if (afl->afl_env.afl_no_affinity) {
@@ -53,13 +50,46 @@ void bind_to_free_cpu(afl_state_t *afl) {
}
+ u8 cpu_used[4096] = {0}, lockfile[PATH_MAX] = "";
+ u32 i;
+
+ if (afl->sync_id) {
+
+ s32 lockfd, first = 1;
+
+ snprintf(lockfile, sizeof(lockfile), "%s/.affinity_lock", afl->sync_dir);
+ setenv(CPU_AFFINITY_ENV_VAR, lockfile, 1);
+
+ do {
+
+ if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
+
+ if (first) {
+
+ WARNF("CPU affinity lock file present, waiting ...");
+ first = 0;
+
+ }
+
+ usleep(1000);
+
+ }
+
+ } while (lockfd < 0);
+
+ close(lockfd);
+
+ }
+
#if defined(__linux__)
+
DIR * d;
struct dirent *de;
d = opendir("/proc");
if (!d) {
+ if (lockfile[0]) unlink(lockfile);
WARNF("Unable to access /proc - can't scan for free CPU cores.");
return;
@@ -67,11 +97,6 @@ void bind_to_free_cpu(afl_state_t *afl) {
ACTF("Checking CPU core loadout...");
- /* Introduce some jitter, in case multiple AFL tasks are doing the same
- thing at the same time... */
-
- usleep(R(1000) * 250);
-
/* Scan all /proc/<pid>/status entries, checking for Cpus_allowed_list.
Flag all processes bound to a specific CPU using cpu_used[]. This will
fail for some exotic binding setups, but is likely good enough in almost
@@ -114,20 +139,29 @@ void bind_to_free_cpu(afl_state_t *afl) {
}
closedir(d);
+
#elif defined(__FreeBSD__) || defined(__DragonFly__)
+
struct kinfo_proc *procs;
size_t nprocs;
size_t proccount;
int s_name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
size_t s_name_l = sizeof(s_name) / sizeof(s_name[0]);
- if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) return;
+ if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) {
+
+ if (lockfile[0]) unlink(lockfile);
+ return;
+
+ }
+
proccount = nprocs / sizeof(*procs);
nprocs = nprocs * 4 / 3;
procs = ck_alloc(nprocs);
if (sysctl(s_name, s_name_l, procs, &nprocs, NULL, 0) != 0) {
+ if (lockfile[0]) unlink(lockfile);
ck_free(procs);
return;
@@ -136,6 +170,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
for (i = 0; i < proccount; i++) {
#if defined(__FreeBSD__)
+
if (!strcmp(procs[i].ki_comm, "idle")) continue;
// fix when ki_oncpu = -1
@@ -145,16 +180,21 @@ void bind_to_free_cpu(afl_state_t *afl) {
if (oncpu != -1 && oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
cpu_used[oncpu] = 1;
+
#elif defined(__DragonFly__)
+
if (procs[i].kp_lwp.kl_cpuid < sizeof(cpu_used) &&
procs[i].kp_lwp.kl_pctcpu > 10)
cpu_used[procs[i].kp_lwp.kl_cpuid] = 1;
+
#endif
}
ck_free(procs);
+
#elif defined(__NetBSD__)
+
struct kinfo_proc2 *procs;
size_t nprocs;
size_t proccount;
@@ -163,13 +203,20 @@ void bind_to_free_cpu(afl_state_t *afl) {
CTL_KERN, KERN_PROC2, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), 0};
size_t s_name_l = sizeof(s_name) / sizeof(s_name[0]);
- if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) return;
+ if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) {
+
+ if (lockfile[0]) unlink(lockfile);
+ return;
+
+ }
+
proccount = nprocs / sizeof(struct kinfo_proc2);
procs = ck_alloc(nprocs * sizeof(struct kinfo_proc2));
s_name[5] = proccount;
if (sysctl(s_name, s_name_l, procs, &nprocs, NULL, 0) != 0) {
+ if (lockfile[0]) unlink(lockfile);
ck_free(procs);
return;
@@ -183,7 +230,9 @@ void bind_to_free_cpu(afl_state_t *afl) {
}
ck_free(procs);
+
#elif defined(__sun)
+
kstat_named_t *n;
kstat_ctl_t * m;
kstat_t * k;
@@ -198,6 +247,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
if (!k) {
+ if (lockfile[0]) unlink(lockfile);
kstat_close(m);
return;
@@ -205,6 +255,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
if (kstat_read(m, k, NULL)) {
+ if (lockfile[0]) unlink(lockfile);
kstat_close(m);
return;
@@ -220,6 +271,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
k = kstat_lookup(m, "cpu_stat", i, NULL);
if (kstat_read(m, k, &cs)) {
+ if (lockfile[0]) unlink(lockfile);
kstat_close(m);
return;
@@ -233,6 +285,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
}
kstat_close(m);
+
#else
#warning \
"For this platform we do not have free CPU binding code yet. If possible, please supply a PR to https://github.com/AFLplusplus/AFLplusplus"
@@ -241,7 +294,9 @@ void bind_to_free_cpu(afl_state_t *afl) {
size_t cpu_start = 0;
try:
+
#if !defined(__ANDROID__)
+
for (i = cpu_start; i < afl->cpu_core_count; i++) {
if (!cpu_used[i]) { break; }
@@ -251,6 +306,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
if (i == afl->cpu_core_count) {
#else
+
for (i = afl->cpu_core_count - cpu_start - 1; i > -1; i--)
if (!cpu_used[i]) break;
if (i == -1) {
@@ -274,18 +330,25 @@ void bind_to_free_cpu(afl_state_t *afl) {
afl->cpu_aff = i;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
+
CPU_ZERO(&c);
CPU_SET(i, &c);
+
#elif defined(__NetBSD__)
+
c = cpuset_create();
if (c == NULL) PFATAL("cpuset_create failed");
cpuset_set(i, c);
+
#elif defined(__sun)
+
pset_create(&c);
if (pset_assign(c, i, NULL)) PFATAL("pset_assign failed");
+
#endif
#if defined(__linux__)
+
if (sched_setaffinity(0, sizeof(c), &c)) {
if (cpu_start == afl->cpu_core_count) {
@@ -302,6 +365,7 @@ if (pset_assign(c, i, NULL)) PFATAL("pset_assign failed");
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
+
if (pthread_setaffinity_np(pthread_self(), sizeof(c), &c)) {
if (cpu_start == afl->cpu_core_count)
@@ -314,6 +378,7 @@ if (pset_assign(c, i, NULL)) PFATAL("pset_assign failed");
}
#elif defined(__NetBSD__)
+
if (pthread_setaffinity_np(pthread_self(), cpuset_size(c), c)) {
if (cpu_start == afl->cpu_core_count)
@@ -326,12 +391,14 @@ if (pthread_setaffinity_np(pthread_self(), cpuset_size(c), c)) {
}
cpuset_destroy(c);
+
#elif defined(__sun)
+
if (pset_bind(c, P_PID, getpid(), NULL)) {
if (cpu_start == afl->cpu_core_count)
PFATAL("pset_bind failed for cpu %d, exit", i);
- WARNF("pthread_setaffinity failed to CPU %d, trying next CPU", i);
+ WARNF("pset_bind failed to CPU %d, trying next CPU", i);
cpu_start++;
goto try
;
@@ -339,11 +406,17 @@ if (pset_bind(c, P_PID, getpid(), NULL)) {
}
pset_destroy(c);
+
#else
+
// this will need something for other platforms
// TODO: Solaris/Illumos has processor_bind ... might worth a try
+
#endif
+ if (lockfile[0]) unlink(lockfile);
+ // we leave the environment variable to ensure a cleanup for other processes
+
}
#endif /* HAVE_AFFINITY */
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 9e54815c..399bfcab 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -24,11 +24,6 @@
*/
#include "afl-fuzz.h"
-#include <string.h>
-
-static u8 *strnstr(const u8 *s, const u8 *find, size_t slen);
-static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from,
- u8 *to);
/* MOpt */
@@ -367,463 +362,6 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) {
#endif /* !IGNORE_FINDS */
-/* Not pretty, but saves a lot of writing */
-#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
-
-static u8 *strnstr(const u8 *s, const u8 *find, size_t slen) {
-
- char c, sc;
- size_t len;
-
- if ((c = *find++) != '\0') {
-
- len = strlen(find);
- do {
-
- do {
-
- if (slen-- < 1 || (sc = *s++) == '\0') return (NULL);
-
- } while (sc != c);
-
- if (len > slen) return (NULL);
-
- } while (strncmp(s, find, len) != 0);
-
- s--;
-
- }
-
- return ((u8 *)s);
-
-}
-
-/* replace between deliminators, if rep == NULL, then we will duplicate the
- * target */
-
-static u32 delim_replace(u8 **out_buf, s32 *temp_len, size_t pos,
- const u8 *ldelim, const u8 *rdelim, u8 *rep) {
-
- u8 *end_buf = *out_buf + *temp_len;
- u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, *temp_len - pos);
-
- if (ldelim_start != NULL) {
-
- u32 max = (end_buf - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN
- ? AFL_TXT_STRING_MAX_LEN
- : end_buf - ldelim_start - 1);
-
- if (max > 0) {
-
- u8 *rdelim_end = strnstr(ldelim_start + 1, rdelim, max);
-
- if (rdelim_end != NULL) {
-
- u32 rep_len, delim_space_len = rdelim_end - ldelim_start - 1, xtra = 0;
-
- if (rep != NULL) {
-
- rep_len = (u32)strlen(rep);
-
- } else { // NULL? then we copy the value in between the delimiters
-
- rep_len = delim_space_len;
- delim_space_len = 0;
- rep = ldelim_start + 1;
- xtra = rep_len;
-
- }
-
- if (rep_len != delim_space_len) {
-
- memmove(ldelim_start + rep_len + xtra + 1, rdelim_end,
- *temp_len - (rdelim_end - *out_buf));
-
- }
-
- memcpy(ldelim_start + 1, rep, rep_len);
- *temp_len = (*temp_len - delim_space_len + rep_len);
-
- return 1;
-
- }
-
- }
-
- }
-
- return 0;
-
-}
-
-static u32 delim_swap(u8 **out_buf, s32 *temp_len, size_t pos, const u8 *ldelim,
- const u8 *mdelim, const u8 *rdelim) {
-
- u8 *out_buf_end = *out_buf + *temp_len;
- u32 max = (*temp_len - pos > AFL_TXT_STRING_MAX_LEN ? AFL_TXT_STRING_MAX_LEN
- : *temp_len - pos);
- u8 *ldelim_start = strnstr(*out_buf + pos, ldelim, max);
-
- if (ldelim_start != NULL) {
-
- max = (out_buf_end - ldelim_start - 1 > AFL_TXT_STRING_MAX_LEN
- ? AFL_TXT_STRING_MAX_LEN
- : out_buf_end - ldelim_start - 1);
- if (max > 1) {
-
- u8 *mdelim_pos = strnstr(ldelim_start + 1, mdelim, max);
-
- if (mdelim_pos != NULL) {
-
- max = (out_buf_end - mdelim_pos - 1 > AFL_TXT_STRING_MAX_LEN
- ? AFL_TXT_STRING_MAX_LEN
- : out_buf_end - mdelim_pos - 1);
- if (max > 0) {
-
- u8 *rdelim_end = strnstr(mdelim + 1, rdelim, max);
-
- if (rdelim_end != NULL) {
-
- u32 first_len = mdelim_pos - ldelim_start - 1;
- u32 second_len = rdelim_end - mdelim_pos - 1;
- u8 scratch[AFL_TXT_STRING_MAX_LEN];
-
- memcpy(scratch, ldelim_start + 1, first_len);
-
- if (first_len != second_len) {
-
- memmove(ldelim_start + second_len + 1, mdelim_pos,
- out_buf_end - mdelim_pos);
-
- }
-
- memcpy(ldelim_start + 1, mdelim_pos + 1, second_len);
-
- if (first_len != second_len) {
-
- memmove(mdelim_pos + first_len + 1, rdelim_end,
- out_buf_end - rdelim_end);
-
- }
-
- memcpy(mdelim_pos + 1, scratch, first_len);
-
- return 1;
-
- }
-
- }
-
- }
-
- }
-
- }
-
- return 0;
-
-}
-
-static u32 string_replace(u8 **out_buf, s32 *temp_len, u32 pos, u8 *from,
- u8 *to) {
-
- u8 *start = strnstr(*out_buf + pos, from, *temp_len - pos);
-
- if (start) {
-
- u32 from_len = strlen(from);
- u32 to_len = strlen(to);
-
- if (from_len != to_len) {
-
- memmove(start + to_len, start + from_len,
- *temp_len - from_len - (start - *out_buf));
-
- }
-
- memcpy(start, to, to_len);
- *temp_len = (*temp_len - from_len + to_len);
-
- return 1;
-
- }
-
- return 0;
-
-}
-
-/* Returns 1 if a mutant was generated and placed in out_buf, 0 if none
- * generated. */
-
-static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) {
-
- s32 temp_len;
- u32 pos, yes = 0,
- mutations = rand_below(afl, AFL_TXT_STRING_MAX_MUTATIONS) + 1;
- u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
- *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS);
- temp_len = *orig_temp_len;
- memcpy(new_buf, *out_buf, temp_len);
-
- for (u32 i = 0; i < mutations; i++) {
-
- if (temp_len < AFL_TXT_MIN_LEN) {
-
- if (yes)
- return 1;
- else
- return 0;
-
- }
-
- pos = rand_below(afl, temp_len - 1);
- int choice = rand_below(afl, 76);
- switch (choice) {
-
- case 0:
- yes += string_replace(out_buf, &temp_len, pos, "*", " ");
- break;
- case 1:
- yes += string_replace(out_buf, &temp_len, pos, "(", "(!");
- break;
- case 2:
- yes += string_replace(out_buf, &temp_len, pos, "==", "!=");
- break;
- case 3:
- yes += string_replace(out_buf, &temp_len, pos, "!=", "==");
- break;
- case 4:
- yes += string_replace(out_buf, &temp_len, pos, "==", "<");
- break;
- case 5:
- yes += string_replace(out_buf, &temp_len, pos, "<", "==");
- break;
- case 6:
- yes += string_replace(out_buf, &temp_len, pos, "==", ">");
- break;
- case 7:
- yes += string_replace(out_buf, &temp_len, pos, ">", "==");
- break;
- case 8:
- yes += string_replace(out_buf, &temp_len, pos, "=", "<");
- break;
- case 9:
- yes += string_replace(out_buf, &temp_len, pos, "=", ">");
- break;
- case 10:
- yes += string_replace(out_buf, &temp_len, pos, "<", ">");
- break;
- case 11:
- yes += string_replace(out_buf, &temp_len, pos, ">", "<");
- break;
- case 12:
- yes += string_replace(out_buf, &temp_len, pos, "++", "--");
- break;
- case 13:
- yes += string_replace(out_buf, &temp_len, pos, "--", "++");
- break;
- case 14:
- yes += string_replace(out_buf, &temp_len, pos, "+", "-");
- break;
- case 15:
- yes += string_replace(out_buf, &temp_len, pos, "+", "*");
- break;
- case 16:
- yes += string_replace(out_buf, &temp_len, pos, "+", "/");
- break;
- case 17:
- yes += string_replace(out_buf, &temp_len, pos, "+", "%");
- break;
- case 18:
- yes += string_replace(out_buf, &temp_len, pos, "*", "-");
- break;
- case 19:
- yes += string_replace(out_buf, &temp_len, pos, "*", "+");
- break;
- case 20:
- yes += string_replace(out_buf, &temp_len, pos, "*", "/");
- break;
- case 21:
- yes += string_replace(out_buf, &temp_len, pos, "*", "%");
- break;
- case 22:
- yes += string_replace(out_buf, &temp_len, pos, "-", "+");
- break;
- case 23:
- yes += string_replace(out_buf, &temp_len, pos, "-", "*");
- break;
- case 24:
- yes += string_replace(out_buf, &temp_len, pos, "-", "/");
- break;
- case 25:
- yes += string_replace(out_buf, &temp_len, pos, "-", "%");
- break;
- case 26:
- yes += string_replace(out_buf, &temp_len, pos, "/", "-");
- break;
- case 27:
- yes += string_replace(out_buf, &temp_len, pos, "/", "*");
- break;
- case 28:
- yes += string_replace(out_buf, &temp_len, pos, "/", "+");
- break;
- case 29:
- yes += string_replace(out_buf, &temp_len, pos, "/", "%");
- break;
- case 30:
- yes += string_replace(out_buf, &temp_len, pos, "%", "-");
- break;
- case 31:
- yes += string_replace(out_buf, &temp_len, pos, "%", "*");
- break;
- case 32:
- yes += string_replace(out_buf, &temp_len, pos, "%", "/");
- break;
- case 33:
- yes += string_replace(out_buf, &temp_len, pos, "%", "+");
- break;
- case 34:
- yes += string_replace(out_buf, &temp_len, pos, "->", ".");
- break;
- case 35:
- yes += string_replace(out_buf, &temp_len, pos, ".", "->");
- break;
- case 36:
- yes += string_replace(out_buf, &temp_len, pos, "0", "1");
- break;
- case 37:
- yes += string_replace(out_buf, &temp_len, pos, "1", "0");
- break;
- case 38:
- yes += string_replace(out_buf, &temp_len, pos, "if", "while");
- break;
- case 39:
- yes += string_replace(out_buf, &temp_len, pos, "while", "if");
- break;
- case 40:
- yes += string_replace(out_buf, &temp_len, pos, "!", " ");
- break;
- case 41:
- yes += string_replace(out_buf, &temp_len, pos, "&&", "||");
- break;
- case 42:
- yes += string_replace(out_buf, &temp_len, pos, "||", "&&");
- break;
- case 43:
- yes += string_replace(out_buf, &temp_len, pos, "!", "");
- break;
- case 44:
- yes += string_replace(out_buf, &temp_len, pos, "==", "=");
- break;
- case 45:
- yes += string_replace(out_buf, &temp_len, pos, "--", "");
- break;
- case 46:
- yes += string_replace(out_buf, &temp_len, pos, "<<", "<");
- break;
- case 47:
- yes += string_replace(out_buf, &temp_len, pos, ">>", ">");
- break;
- case 48:
- yes += string_replace(out_buf, &temp_len, pos, "<", "<<");
- break;
- case 49:
- yes += string_replace(out_buf, &temp_len, pos, ">", ">>");
- break;
- case 50:
- yes += string_replace(out_buf, &temp_len, pos, "\"", "'");
- break;
- case 51:
- yes += string_replace(out_buf, &temp_len, pos, "'", "\"");
- break;
- case 52:
- yes += string_replace(out_buf, &temp_len, pos, "(", "\"");
- break;
- case 53:
- yes += string_replace(out_buf, &temp_len, pos, "\n", " ");
- break;
- case 54:
- yes += string_replace(out_buf, &temp_len, pos, "\n", ";");
- break;
- case 55:
- yes += string_replace(out_buf, &temp_len, pos, "\n", "<");
- break;
- case 56: /* Remove a semicolon delimited statement after a semicolon */
- yes += delim_replace(out_buf, &temp_len, pos, ";", ";", ";");
- break;
- case 57: /* Remove a semicolon delimited statement after a left curly
- brace */
- yes += delim_replace(out_buf, &temp_len, pos, "}", ";", "}");
- break;
- case 58: /* Remove a curly brace construct */
- yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "");
- break;
- case 59: /* Replace a curly brace construct with an empty one */
- yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "{}");
- break;
- case 60:
- yes += delim_swap(out_buf, &temp_len, pos, ";", ";", ";");
- break;
- case 61:
- yes += delim_swap(out_buf, &temp_len, pos, "}", ";", ";");
- break;
- case 62: /* Swap comma delimited things case 1 */
- yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ")");
- break;
- case 63: /* Swap comma delimited things case 2 */
- yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ",");
- break;
- case 64: /* Swap comma delimited things case 3 */
- yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ",");
- break;
- case 65: /* Swap comma delimited things case 4 */
- yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ")");
- break;
- case 66: /* Just delete a line */
- yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", "");
- break;
- case 67: /* Delete something like "const" case 1 */
- yes += delim_replace(out_buf, &temp_len, pos, " ", " ", "");
- break;
- case 68: /* Delete something like "const" case 2 */
- yes += delim_replace(out_buf, &temp_len, pos, "\n", " ", "");
- break;
- case 69: /* Delete something like "const" case 3 */
- yes += delim_replace(out_buf, &temp_len, pos, "(", " ", "");
- break;
- case 70: /* Swap space delimited things case 1 */
- yes += delim_swap(out_buf, &temp_len, pos, " ", " ", " ");
- break;
- case 71: /* Swap space delimited things case 2 */
- yes += delim_swap(out_buf, &temp_len, pos, " ", " ", ")");
- break;
- case 72: /* Swap space delimited things case 3 */
- yes += delim_swap(out_buf, &temp_len, pos, "(", " ", " ");
- break;
- case 73: /* Swap space delimited things case 4 */
- yes += delim_swap(out_buf, &temp_len, pos, "(", " ", ")");
- break;
- case 74: /* Duplicate a single line of code */
- yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", NULL);
- break;
- case 75: /* Duplicate a construct (most often, a non-nested for loop */
- yes += delim_replace(out_buf, &temp_len, pos, "\n", "}", NULL);
- break;
-
- }
-
- }
-
- if (yes == 0 || temp_len <= 0) { return 0; }
-
- swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
- *out_buf = new_buf;
- *orig_temp_len = temp_len;
-
- return 1;
-
-}
-
/* Take the current entry from the queue, fuzz it for a while. This
function is a tad too long... returns 0 if fuzzed successfully, 1 if
skipped or bailed out. */
@@ -840,6 +378,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
u8 a_collect[MAX_AUTO_EXTRA];
u32 a_len = 0;
+/* Not pretty, but saves a lot of writing */
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
+
#ifdef IGNORE_FINDS
/* In IGNORE_FINDS mode, skip any entries that weren't in the
@@ -2313,12 +1854,9 @@ havoc_stage:
/* We essentially just do several thousand runs (depending on perf_score)
where we take the input file and make random stacked tweaks. */
- u32 r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0) +
- (afl->queue_cur->is_ascii ? AFL_TXT_BIAS : 0);
-
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
- u32 r, use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
+ u32 use_stacking = 1 << (1 + rand_below(afl, HAVOC_STACK_POW2));
afl->stage_cur_val = use_stacking;
@@ -2358,9 +1896,8 @@ havoc_stage:
}
- retry_havoc:
-
- switch ((r = rand_below(afl, r_max))) {
+ switch (rand_below(
+ afl, 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0))) {
case 0:
@@ -2654,98 +2191,177 @@ havoc_stage:
break;
}
+
+ case 15: {
- // TODO: add splicing mutation here.
- // 15:
- // break;
+ /* Overwrite bytes with a randomly selected chunk from another
+ testcase or insert that chunk. */
- default:
- if (r == 15 && (afl->extras_cnt || afl->a_extras_cnt)) {
+ if (afl->queued_paths < 2) break;
- /* Values 15 and 16 can be selected only if there are any extras
- present in the dictionaries. */
+ /* Pick a random queue entry and seek to it. */
- /* Overwrite bytes with an extra. */
+ u32 tid;
+ do
+ tid = rand_below(afl, afl->queued_paths);
+ while (tid == afl->current_entry);
- if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
+ struct queue_entry* target = afl->queue_buf[tid];
- /* No user-specified extras or odds in our favor. Let's use an
- auto-detected one. */
+ /* Make sure that the target has a reasonable length. */
- u32 use_extra = rand_below(afl, afl->a_extras_cnt);
- u32 extra_len = afl->a_extras[use_extra].len;
- u32 insert_at;
+ while (target && (target->len < 2 || target == afl->queue_cur))
+ target = target->next;
- if (extra_len > temp_len) { break; }
+ if (!target) break;
- insert_at = rand_below(afl, temp_len - extra_len + 1);
- memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
- extra_len);
+ /* Read the testcase into a new buffer. */
- } else {
+ fd = open(target->fname, O_RDONLY);
- /* No auto extras or odds in our favor. Use the dictionary. */
+ if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); }
- u32 use_extra = rand_below(afl, afl->extras_cnt);
- u32 extra_len = afl->extras[use_extra].len;
- u32 insert_at;
+ u32 new_len = target->len;
+ u8 * new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), new_len);
- if (extra_len > temp_len) { break; }
+ ck_read(fd, new_buf, new_len, target->fname);
- insert_at = rand_below(afl, temp_len - extra_len + 1);
- memcpy(out_buf + insert_at, afl->extras[use_extra].data,
- extra_len);
+ close(fd);
- }
+ u8 overwrite = 0;
+ if (temp_len >= 2 && rand_below(afl, 2))
+ overwrite = 1;
+ else if (temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+ if (temp_len >= 2) overwrite = 1;
+ else break;
+ }
- } else if (r == 16 && (afl->extras_cnt || afl->a_extras_cnt)) {
+ if (overwrite) {
- u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1);
- u8 *ptr;
+ u32 copy_from, copy_to, copy_len;
- /* Insert an extra. Do the same dice-rolling stuff as for the
- previous case. */
+ copy_len = choose_block_len(afl, new_len - 1);
+ if (copy_len > temp_len) copy_len = temp_len;
- if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
+ copy_from = rand_below(afl, new_len - copy_len + 1);
+ copy_to = rand_below(afl, temp_len - copy_len + 1);
- use_extra = rand_below(afl, afl->a_extras_cnt);
- extra_len = afl->a_extras[use_extra].len;
- ptr = afl->a_extras[use_extra].data;
+ memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
- } else {
+ } else {
+
+ u32 clone_from, clone_to, clone_len;
+
+ clone_len = choose_block_len(afl, new_len);
+ clone_from = rand_below(afl, new_len - clone_len + 1);
+
+ clone_to = rand_below(afl, temp_len);
+
+ u8 * temp_buf =
+ ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
- use_extra = rand_below(afl, afl->extras_cnt);
- extra_len = afl->extras[use_extra].len;
- ptr = afl->extras[use_extra].data;
+ /* Head */
- }
+ memcpy(temp_buf, out_buf, clone_to);
- if (temp_len + extra_len >= MAX_FILE) { break; }
+ /* Inserted part */
- out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len);
+ memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
/* Tail */
- memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
- temp_len - insert_at);
+ memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
- /* Inserted part */
- memcpy(out_buf + insert_at, ptr, extra_len);
+ swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
+ out_buf = temp_buf;
+ temp_len += clone_len;
+
+ }
+
+ break;
+
+ }
- temp_len += extra_len;
+ /* Values 15 and 16 can be selected only if there are any extras
+ present in the dictionaries. */
+
+ case 16: {
+
+ /* Overwrite bytes with an extra. */
+
+ if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
+
+ /* No user-specified extras or odds in our favor. Let's use an
+ auto-detected one. */
+
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
+ u32 insert_at;
+
+ if (extra_len > temp_len) { break; }
+
+ insert_at = rand_below(afl, temp_len - extra_len + 1);
+ memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+ extra_len);
} else {
- // ascii mutations
- if (text_mutation(afl, &out_buf, &temp_len) == 0) goto retry_havoc;
+ /* No auto extras or odds in our favor. Use the dictionary. */
+
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
+ u32 insert_at;
- //#ifdef _AFL_DOCUMENT_MUTATIONS
- // fprintf(stderr, "MUTATED: %s/mutations/%09u:*\n",
- // afl->out_dir,
- // afl->document_counter);
- //#endif
+ if (extra_len > temp_len) { break; }
+
+ insert_at = rand_below(afl, temp_len - extra_len + 1);
+ memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len);
}
+ break;
+
+ }
+
+ case 17: {
+
+ u32 use_extra, extra_len, insert_at = rand_below(afl, temp_len + 1);
+ u8 *ptr;
+
+ /* Insert an extra. Do the same dice-rolling stuff as for the
+ previous case. */
+
+ if (!afl->extras_cnt || (afl->a_extras_cnt && rand_below(afl, 2))) {
+
+ use_extra = rand_below(afl, afl->a_extras_cnt);
+ extra_len = afl->a_extras[use_extra].len;
+ ptr = afl->a_extras[use_extra].data;
+
+ } else {
+
+ use_extra = rand_below(afl, afl->extras_cnt);
+ extra_len = afl->extras[use_extra].len;
+ ptr = afl->extras[use_extra].data;
+
+ }
+
+ if (temp_len + extra_len >= MAX_FILE) { break; }
+
+ out_buf = ck_maybe_grow(BUF_PARAMS(out), temp_len + extra_len);
+
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
+
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
+
+ temp_len += extra_len;
+
+ break;
+
+ }
+
}
}
@@ -2831,20 +2447,7 @@ retry_splicing:
} while (tid == afl->current_entry);
afl->splicing_with = tid;
- target = afl->queue;
-
- while (tid >= 100) {
-
- target = target->next_100;
- tid -= 100;
-
- }
-
- while (tid--) {
-
- target = target->next;
-
- }
+ target = afl->queue_buf[tid];
/* Make sure that the target has a reasonable length. */
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index da6b1eee..a96995e5 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -24,7 +24,8 @@
#include "afl-fuzz.h"
#include <limits.h>
-#include <ctype.h>
+
+#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
/* Mark deterministic checks as done for a particular queue entry. We use the
.state file to avoid repeating deterministic fuzzing when resuming aborted
@@ -101,119 +102,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
}
-/* check if ascii or UTF-8 */
-
-static u8 check_if_text(struct queue_entry *q) {
-
- if (q->len < AFL_TXT_MIN_LEN) return 0;
-
- u8 buf[MAX_FILE], bom[3] = {0xef, 0xbb, 0xbf};
- s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp;
-
- if ((fd = open(q->fname, O_RDONLY)) < 0) return 0;
- if ((comp = read(fd, buf, len)) != len) return 0;
- close(fd);
-
- while (offset < len) {
-
- // ASCII: <= 0x7F to allow ASCII control characters
- if ((buf[offset + 0] == 0x09 || buf[offset + 0] == 0x0A ||
- buf[offset + 0] == 0x0D ||
- (0x20 <= buf[offset + 0] && buf[offset + 0] <= 0x7E))) {
-
- offset++;
- utf8++;
- ascii++;
- continue;
-
- }
-
- if (isascii((int)buf[offset]) || isprint((int)buf[offset])) {
-
- ascii++;
- // we continue though as it can also be a valid utf8
-
- }
-
- // non-overlong 2-byte
- if (((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) &&
- (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) {
-
- offset += 2;
- utf8++;
- comp--;
- continue;
-
- }
-
- // excluding overlongs
- if ((buf[offset + 0] == 0xE0 &&
- (0xA0 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
- (0x80 <= buf[offset + 2] &&
- buf[offset + 2] <= 0xBF)) || // straight 3-byte
- (((0xE1 <= buf[offset + 0] && buf[offset + 0] <= 0xEC) ||
- buf[offset + 0] == 0xEE || buf[offset + 0] == 0xEF) &&
- (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
- (0x80 <= buf[offset + 2] &&
- buf[offset + 2] <= 0xBF)) || // excluding surrogates
- (buf[offset + 0] == 0xED &&
- (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x9F) &&
- (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF))) {
-
- offset += 3;
- utf8++;
- comp -= 2;
- continue;
-
- }
-
- // planes 1-3
- if ((buf[offset + 0] == 0xF0 &&
- (0x90 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
- (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
- (0x80 <= buf[offset + 3] &&
- buf[offset + 3] <= 0xBF)) || // planes 4-15
- ((0xF1 <= buf[offset + 0] && buf[offset + 0] <= 0xF3) &&
- (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF) &&
- (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
- (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF)) || // plane 16
- (buf[offset + 0] == 0xF4 &&
- (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0x8F) &&
- (0x80 <= buf[offset + 2] && buf[offset + 2] <= 0xBF) &&
- (0x80 <= buf[offset + 3] && buf[offset + 3] <= 0xBF))) {
-
- offset += 4;
- utf8++;
- comp -= 3;
- continue;
-
- }
-
- // handle utf8 bom
- if (buf[offset + 0] == bom[0] && buf[offset + 1] == bom[1] &&
- buf[offset + 2] == bom[2]) {
-
- offset += 3;
- utf8++;
- comp -= 2;
- continue;
-
- }
-
- offset++;
-
- }
-
- u32 percent_utf8 = (utf8 * 100) / comp;
- u32 percent_ascii = (ascii * 100) / len;
-
- if (percent_utf8 >= percent_ascii && percent_utf8 >= AFL_TXT_MIN_PERCENT)
- return 2;
- if (percent_ascii >= AFL_TXT_MIN_PERCENT) return 1;
- return 0;
-
-}
-
/* Append new test case to the queue. */
void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
@@ -251,6 +139,9 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
afl->q_prev100 = q;
}
+
+ struct queue_entry** queue_buf = ck_maybe_grow(BUF_PARAMS(queue), afl->queued_paths * sizeof(struct queue_entry*));
+ queue_buf[afl->queued_paths -1] = q;
afl->last_path_time = get_cur_time();
@@ -273,8 +164,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
}
- q->is_ascii = check_if_text(q);
-
}
/* Destroy the entire queue. */
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 43850eb5..c53e0e06 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -177,6 +177,9 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
afl->stage_cycles[STAGE_COLORIZATION] += afl->stage_cur;
ck_free(backup);
+ ck_free(rng);
+ rng = NULL;
+
while (ranges) {
rng = ranges;
@@ -186,9 +189,6 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum) {
}
- ck_free(rng);
- rng = NULL;
-
// save the input with the high entropy
if (needs_write) {
@@ -277,9 +277,9 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u8 * o_buf_8 = &orig_buf[idx];
u32 its_len = len - idx;
- *status = 0;
+ // *status = 0;
- if (SHAPE_BYTES(h->shape) == 8) {
+ if (SHAPE_BYTES(h->shape) >= 8) {
if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) {
@@ -290,7 +290,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
// reverse encoding
- if (do_reverse) {
+ if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl),
SWAP64(o_pattern), idx, orig_buf, buf,
@@ -304,7 +304,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- if (SHAPE_BYTES(h->shape) == 4 || *status == 2) {
+ if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) {
if (its_len >= 4 && *buf_32 == (u32)pattern &&
*o_buf_32 == (u32)o_pattern) {
@@ -316,7 +316,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
// reverse encoding
- if (do_reverse) {
+ if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl),
SWAP32(o_pattern), idx, orig_buf, buf,
@@ -330,7 +330,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- if (SHAPE_BYTES(h->shape) == 2 || *status == 2) {
+ if (SHAPE_BYTES(h->shape) >= 2 && *status != 1) {
if (its_len >= 2 && *buf_16 == (u16)pattern &&
*o_buf_16 == (u16)o_pattern) {
@@ -342,7 +342,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
// reverse encoding
- if (do_reverse) {
+ if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl),
SWAP16(o_pattern), idx, orig_buf, buf,
@@ -356,7 +356,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
- if (SHAPE_BYTES(h->shape) == 1 || *status == 2) {
+ if (SHAPE_BYTES(h->shape) >= 1 && *status != 1) {
if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) {
@@ -435,7 +435,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
u32 fails;
u8 found_one = 0;
- /* loop cmps are useless, detect and blacklist them */
+ /* loop cmps are useless, detect and ignore them */
u64 s_v0, s_v1;
u8 s_v0_fixed = 1, s_v1_fixed = 1;
u8 s_v0_inc = 1, s_v1_inc = 1;
@@ -482,6 +482,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
for (idx = 0; idx < len && fails < 8; ++idx) {
+ status = 0;
if (unlikely(cmp_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx,
orig_buf, buf, len, 1, &status))) {
@@ -499,6 +500,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) {
}
+ status = 0;
if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx,
orig_buf, buf, len, 1, &status))) {
@@ -743,7 +745,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
afl->pass_stats[k].faileds ||
afl->pass_stats[k].total == 0xff)) {
- afl->shm.cmp_map->headers[k].hits = 0; // blacklist this cmp
+ afl->shm.cmp_map->headers[k].hits = 0; // ignore this cmp
}
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index ece2d170..e56d122a 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -164,14 +164,14 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
void read_afl_environment(afl_state_t *afl, char **envp) {
- int index = 0, found = 0;
+ int index = 0, issue_detected = 0;
char *env;
while ((env = envp[index++]) != NULL) {
if (strncmp(env, "ALF_", 4) == 0) {
WARNF("Potentially mistyped AFL environment variable: %s", env);
- found++;
+ issue_detected = 1;
} else if (strncmp(env, "AFL_", 4) == 0) {
@@ -307,15 +307,6 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_tmpdir =
(u8 *)get_afl_env(afl_environment_variables[i]);
- } else if (!strncmp(env, "AFL_POST_LIBRARY",
-
- afl_environment_variable_len)) {
-
- FATAL(
- "AFL_POST_LIBRARY is deprecated, use "
- "AFL_CUSTOM_MUTATOR_LIBRARY instead, see "
- "docs/custom_mutators.md");
-
} else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_LIBRARY",
afl_environment_variable_len)) {
@@ -352,10 +343,48 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
+ i = 0;
+ while (match == 0 && afl_environment_variables[i] != NULL) {
+
+ if (strncmp(env, afl_environment_variables[i],
+ strlen(afl_environment_variables[i])) == 0 &&
+ env[strlen(afl_environment_variables[i])] == '=') {
+
+ match = 1;
+
+ } else {
+
+ i++;
+
+ }
+
+ }
+
+ i = 0;
+ while (match == 0 && afl_environment_deprecated[i] != NULL) {
+
+ if (strncmp(env, afl_environment_deprecated[i],
+ strlen(afl_environment_deprecated[i])) == 0 &&
+ env[strlen(afl_environment_deprecated[i])] == '=') {
+
+ match = 1;
+
+ WARNF("AFL environment variable %s is deprecated!",
+ afl_environment_deprecated[i]);
+ issue_detected = 1;
+
+ } else {
+
+ i++;
+
+ }
+
+ }
+
if (match == 0) {
WARNF("Mistyped AFL environment variable: %s", env);
- found++;
+ issue_detected = 1;
}
@@ -363,7 +392,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
- if (found) { sleep(2); }
+ if (issue_detected) { sleep(2); }
}
@@ -376,6 +405,7 @@ void afl_state_deinit(afl_state_t *afl) {
if (afl->pass_stats) { ck_free(afl->pass_stats); }
if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
+ if (afl->queue_buf) { free(afl->queue_buf); }
if (afl->out_buf) { free(afl->out_buf); }
if (afl->out_scratch_buf) { free(afl->out_scratch_buf); }
if (afl->eff_buf) { free(afl->eff_buf); }
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index f25f8bb6..872ed9ae 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -42,19 +42,21 @@ static void at_exit() {
int i;
char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
- char *ptr = getenv("__AFL_TARGET_PID1");
+ char *ptr;
+ ptr = getenv(CPU_AFFINITY_ENV_VAR);
+ if (ptr && *ptr) unlink(ptr);
+
+ ptr = getenv("__AFL_TARGET_PID1");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
ptr = getenv("__AFL_TARGET_PID2");
-
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
i = 0;
while (list[i] != NULL) {
ptr = getenv(list[i]);
-
if (ptr && *ptr) {
#ifdef USEMMAP
@@ -264,6 +266,8 @@ int main(int argc, char **argv_orig, char **envp) {
gettimeofday(&tv, &tz);
rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid());
+ afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
+
while ((opt = getopt(argc, argv,
"+c:i:I:o:f:m:t:T:dDnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) >
0) {
@@ -561,7 +565,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
afl->fsrv.qemu_mode = 1;
- afl->shmem_testcase_mode = 1;
if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
@@ -578,7 +581,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); }
afl->unicorn_mode = 1;
- afl->shmem_testcase_mode = 1;
if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; }
@@ -589,7 +591,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
afl->fsrv.qemu_mode = 1;
afl->use_wine = 1;
- afl->shmem_testcase_mode = 1;
if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
@@ -790,8 +791,8 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("afl++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus");
OKF("Power schedules from github.com/mboehme/aflfast");
- OKF("Python Mutator and llvm_mode whitelisting from github.com/choller/afl");
- OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL");
+ OKF("Python Mutator and llvm_mode instrument file list from "
+ "github.com/choller/afl");
OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL");
if (afl->sync_id && afl->is_main_node &&
@@ -1011,17 +1012,19 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ check_crash_handling();
+ check_cpu_governor(afl);
+
get_core_count(afl);
+ atexit(at_exit);
+
+ setup_dirs_fds(afl);
+
#ifdef HAVE_AFFINITY
bind_to_free_cpu(afl);
#endif /* HAVE_AFFINITY */
- check_crash_handling();
- check_cpu_governor(afl);
-
- atexit(at_exit);
-
afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
@@ -1038,12 +1041,10 @@ int main(int argc, char **argv_orig, char **envp) {
}
- setup_dirs_fds(afl);
-
if (afl->is_secondary_node && check_main_node_exists(afl) == 0) {
WARNF("no -M main node found. You need to run one main instance!");
- sleep(5);
+ sleep(3);
}
@@ -1280,7 +1281,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->is_main_node)) {
- if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 2))) { sync_fuzzers(afl); }
+ if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) { sync_fuzzers(afl); }
} else {
diff --git a/src/afl-gcc.c b/src/afl-gcc.c
index b8ff7e77..22e6be8e 100644
--- a/src/afl-gcc.c
+++ b/src/afl-gcc.c
@@ -132,6 +132,9 @@ static void edit_params(u32 argc, char **argv) {
name = argv[0];
+ /* This should never happen but fixes a scan-build warning */
+ if (!name) { FATAL("Empty argv set"); }
+
} else {
++name;
@@ -465,7 +468,7 @@ int main(int argc, char **argv) {
u32 map_size = atoi(ptr);
if (map_size != MAP_SIZE) {
- FATAL("AFL_MAP_SIZE is not supported by afl-gcc");
+ WARNF("AFL_MAP_SIZE is not supported by afl-gcc");
}
diff --git a/src/afl-performance.c b/src/afl-performance.c
index 6631f148..0c1697a8 100644
--- a/src/afl-performance.c
+++ b/src/afl-performance.c
@@ -44,12 +44,10 @@ void rand_set_seed(afl_state_t *afl, s64 init_seed) {
}
-uint32_t rand_next(afl_state_t *afl) {
+uint64_t rand_next(afl_state_t *afl) {
- const uint32_t result =
- (uint32_t)rotl(afl->rand_seed[0] + afl->rand_seed[3], 23) +
- afl->rand_seed[0];
- // const uint32_t result = (uint32_t) rotl(afl->rand_seed[1] * 5, 7) * 9;
+ const uint64_t result =
+ rotl(afl->rand_seed[0] + afl->rand_seed[3], 23) + afl->rand_seed[0];
const uint64_t t = afl->rand_seed[1] << 17;
@@ -62,7 +60,7 @@ uint32_t rand_next(afl_state_t *afl) {
afl->rand_seed[3] = rotl(afl->rand_seed[3], 45);
- return (uint32_t)result;
+ return result;
}
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 883398ff..71e975a1 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -456,15 +456,38 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
+ "allocator_may_return_null=1:"
"symbolize=0:"
- "allocator_may_return_null=1",
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
+ 0);
+
+ setenv("UBSAN_OPTIONS",
+ "halt_on_error=1:"
+ "abort_on_error=1:"
+ "malloc_context_size=0:"
+ "allocator_may_return_null=1:"
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "symbolize=0:"
"abort_on_error=1:"
+ "msan_track_origins=0"
"allocator_may_return_null=1:"
- "msan_track_origins=0", 0);
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0", 0);
if (get_afl_env("AFL_PRELOAD")) {
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 2db1eae7..68fcdd14 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -701,15 +701,38 @@ static void set_up_environment(afl_forkserver_t *fsrv) {
setenv("ASAN_OPTIONS",
"abort_on_error=1:"
"detect_leaks=0:"
+ "allocator_may_return_null=1:"
"symbolize=0:"
- "allocator_may_return_null=1",
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
+ 0);
+
+ setenv("UBSAN_OPTIONS",
+ "halt_on_error=1:"
+ "abort_on_error=1:"
+ "malloc_context_size=0:"
+ "allocator_may_return_null=1:"
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0",
0);
setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "symbolize=0:"
"abort_on_error=1:"
+ "msan_track_origins=0"
"allocator_may_return_null=1:"
- "msan_track_origins=0", 0);
+ "symbolize=0:"
+ "handle_segv=0:"
+ "handle_sigbus=0:"
+ "handle_abort=0:"
+ "handle_sigfpe=0:"
+ "handle_sigill=0", 0);
if (get_afl_env("AFL_PRELOAD")) {