Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev

This commit is contained in:
Andrea Fioraldi
2020-12-08 22:43:05 +01:00
149 changed files with 1871 additions and 779 deletions

View File

@ -78,9 +78,9 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
static s32 dev_null_fd = -1; /* FD to /dev/null */
static u8 edges_only, /* Ignore hit counts? */
static bool edges_only, /* Ignore hit counts? */
use_hex_offsets, /* Show hex offsets? */
use_stdin = 1; /* Use stdin for program input? */
use_stdin = true; /* Use stdin for program input? */
static volatile u8 stop_soon, /* Ctrl-C pressed? */
child_timed_out; /* Child timed out? */

View File

@ -27,7 +27,7 @@
utility has right now is to be able to skip them gracefully and allow the
compilation process to continue.
That said, see examples/clang_asm_normalize/ for a solution that may
That said, see utils/clang_asm_normalize/ for a solution that may
allow clang users to make things work even with hand-crafted assembly. Just
note that there is no equivalent for GCC.

View File

@ -48,15 +48,16 @@
static u8 * obj_path; /* Path to runtime libraries */
static u8 **cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
static u8 clang_mode; /* Invoked as afl-clang*? */
static u8 llvm_fullpath[PATH_MAX];
static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode,
compiler_mode, plusplus_mode;
static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto;
static u8 *lto_flag = AFL_CLANG_FLTO, *argvnull;
static u8 debug;
static u8 cwd[4096];
static u8 cmplog_mode;
u8 use_stdin; /* dummy */
static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
static u8 compiler_mode, plusplus_mode, have_instr_env = 0;
static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0;
static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
static u8 debug;
static u8 cwd[4096];
static u8 cmplog_mode;
u8 use_stdin; /* dummy */
// static u8 *march_opt = CFLAGS_OPT;
enum {
@ -105,20 +106,43 @@ u8 *getthecwd() {
}
/* Try to find the runtime libraries. If that fails, abort. */
/* Try to find a specific runtime we need, returns NULL on fail. */
/*
in find_object() we look here:
1. if obj_path is already set we look there first
2. then we check the $AFL_PATH environment variable location if set
3. next we check argv[0] if it has path information and use it
a) we also check ../lib/afl
4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and
FreeBSD with procfs)
a) and check here in ../lib/afl too
5. we look into the AFL_PATH define (usually /usr/local/lib/afl)
6. we finally try the current directory
if all these attempts fail - we return NULL and the caller has to decide
what to do.
*/
static u8 *find_object(u8 *obj, u8 *argv0) {
u8 *afl_path = getenv("AFL_PATH");
u8 *slash = NULL, *tmp;
if (obj_path) {
tmp = alloc_printf("%s/%s", obj_path, obj);
if (!access(tmp, R_OK)) { return tmp; }
ck_free(tmp);
}
if (afl_path) {
#ifdef __ANDROID__
tmp = alloc_printf("%s/%s", afl_path, obj);
#else
tmp = alloc_printf("%s/%s", afl_path, obj);
#endif
if (!access(tmp, R_OK)) {
@ -131,128 +155,130 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
}
if (argv0) slash = strrchr(argv0, '/');
if (argv0) {
if (slash) {
slash = strrchr(argv0, '/');
u8 *dir;
if (slash) {
*slash = 0;
dir = ck_strdup(argv0);
*slash = '/';
u8 *dir = ck_strdup(argv0);
#ifdef __ANDROID__
tmp = alloc_printf("%s/%s", dir, obj);
#else
tmp = alloc_printf("%s/%s", dir, obj);
#endif
slash = strrchr(dir, '/');
*slash = 0;
if (!access(tmp, R_OK)) {
tmp = alloc_printf("%s/%s", dir, obj);
obj_path = dir;
return tmp;
if (!access(tmp, R_OK)) {
obj_path = dir;
return tmp;
}
ck_free(tmp);
tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);
if (!access(tmp, R_OK)) {
u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
obj_path = dir2;
ck_free(dir);
return tmp;
}
ck_free(tmp);
ck_free(dir);
}
ck_free(tmp);
ck_free(dir);
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
defined(__ANDROID__) || defined(__NetBSD__)
#define HAS_PROC_FS 1
#endif
#ifdef HAS_PROC_FS
else {
char *procname = NULL;
#if defined(__FreeBSD__) || defined(__DragonFly__)
procname = "/proc/curproc/file";
#elif defined(__linux__) || defined(__ANDROID__)
procname = "/proc/self/exe";
#elif defined(__NetBSD__)
procname = "/proc/curproc/exe";
#endif
if (procname) {
char exepath[PATH_MAX];
ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
if (exepath_len > 0 && exepath_len < PATH_MAX) {
exepath[exepath_len] = 0;
slash = strrchr(exepath, '/');
if (slash) {
*slash = 0;
tmp = alloc_printf("%s/%s", exepath, obj);
if (!access(tmp, R_OK)) {
u8 *dir = alloc_printf("%s", exepath);
obj_path = dir;
return tmp;
}
ck_free(tmp);
tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);
if (!access(tmp, R_OK)) {
u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
obj_path = dir;
return tmp;
}
}
}
}
}
#endif
#undef HAS_PROC_FS
}
tmp = alloc_printf("%s/%s", AFL_PATH, obj);
#ifdef __ANDROID__
if (!access(tmp, R_OK)) {
#else
if (!access(tmp, R_OK)) {
#endif
obj_path = AFL_PATH;
return tmp;
}
ck_free(tmp);
tmp = alloc_printf("./%s", obj);
if (!access(tmp, R_OK)) {
obj_path = ".";
return tmp;
}
ck_free(tmp);
return NULL;
}
/* Try to find the runtime libraries. If that fails, abort. */
static void find_obj(u8 *argv0) {
u8 *afl_path = getenv("AFL_PATH");
u8 *slash, *tmp;
if (afl_path) {
#ifdef __ANDROID__
tmp = alloc_printf("%s/afl-compiler-rt.so", afl_path);
#else
tmp = alloc_printf("%s/afl-compiler-rt.o", afl_path);
#endif
if (!access(tmp, R_OK)) {
obj_path = afl_path;
ck_free(tmp);
return;
}
ck_free(tmp);
}
slash = strrchr(argv0, '/');
if (slash) {
u8 *dir;
*slash = 0;
dir = ck_strdup(argv0);
*slash = '/';
#ifdef __ANDROID__
tmp = alloc_printf("%s/afl-compiler-rt.so", dir);
#else
tmp = alloc_printf("%s/afl-compiler-rt.o", dir);
#endif
if (!access(tmp, R_OK)) {
obj_path = dir;
ck_free(tmp);
return;
}
ck_free(tmp);
ck_free(dir);
}
#ifdef __ANDROID__
if (!access(AFL_PATH "/afl-compiler-rt.so", R_OK)) {
#else
if (!access(AFL_PATH "/afl-compiler-rt.o", R_OK)) {
#endif
obj_path = AFL_PATH;
return;
}
FATAL(
"Unable to find 'afl-compiler-rt.o' or 'afl-llvm-pass.so'. Please set "
"AFL_PATH");
}
/* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char **argv, char **envp) {
@ -288,7 +314,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (compiler_mode >= GCC_PLUGIN) {
alt_cxx = "g++";
if (compiler_mode == GCC) {
alt_cxx = clang_mode ? "clang++" : "g++";
} else {
alt_cxx = "g++";
}
} else {
@ -313,7 +347,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (compiler_mode >= GCC_PLUGIN) {
alt_cc = "gcc";
if (compiler_mode == GCC) {
alt_cc = clang_mode ? "clang" : "gcc";
} else {
alt_cc = "gcc";
}
} else {
@ -337,12 +379,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = obj_path;
if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
}
if (compiler_mode == GCC_PLUGIN) {
char *fplugin_arg =
alloc_printf("-fplugin=%s", find_object("afl-gcc-pass.so", argvnull));
char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
cc_params[cc_par_cnt++] = fplugin_arg;
}
@ -354,19 +397,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (lto_mode && plusplus_mode)
cc_params[cc_par_cnt++] = "-lc++"; // needed by fuzzbench, early
if (lto_mode) {
if (lto_mode && have_instr_env) {
if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
}
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
}
@ -508,11 +545,25 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] =
alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
if (have_instr_list) {
if (!be_quiet)
SAYF(
"Using unoptimized trace-pc-guard, due usage of "
"-fsanitize-coverage-allow/denylist, you can use "
"AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
} else {
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] =
alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
}
#else
#if LLVM_MAJOR >= 4
if (!be_quiet)
@ -590,6 +641,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;
if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list="))
have_instr_list = 1;
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
asan_set = 1;
@ -675,7 +729,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
getenv("LAF_TRANSFORM_COMPARES") || lto_mode) {
getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") ||
lto_mode) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
@ -826,7 +881,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
#ifndef __APPLE__
#if !defined(__APPLE__) && !defined(__sun)
if (!shared_linking)
cc_params[cc_par_cnt++] =
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
@ -856,6 +911,14 @@ int main(int argc, char **argv, char **envp) {
be_quiet = 1;
if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") ||
getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") ||
getenv("AFL_LLVM_BLOCKLIST")) {
have_instr_env = 1;
}
if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
argvnull = (u8 *)argv[0];
check_environment_vars(envp);
@ -915,7 +978,9 @@ int main(int argc, char **argv, char **envp) {
} else if (strncmp(callname, "afl-gcc", 7) == 0 ||
strncmp(callname, "afl-g++", 7) == 0) {
strncmp(callname, "afl-g++", 7) == 0 ||
strncmp(callname, "afl-clang", 9) == 0) {
compiler_mode = GCC;
@ -959,6 +1024,14 @@ int main(int argc, char **argv, char **envp) {
}
if (strncmp(callname, "afl-clang", 9) == 0) {
clang_mode = 1;
if (strncmp(callname, "afl-clang++", 11) == 0) { plusplus_mode = 1; }
}
for (i = 1; i < argc; i++) {
if (strncmp(argv[i], "--afl", 5) == 0) {
@ -1011,26 +1084,25 @@ int main(int argc, char **argv, char **envp) {
if (instrument_mode == 0)
instrument_mode = INSTRUMENT_PCGUARD;
else if (instrument_mode != INSTRUMENT_PCGUARD)
FATAL("you can not set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
}
if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) &&
getenv("AFL_DONT_OPTIMIZE"))
if (have_instr_env && getenv("AFL_DONT_OPTIMIZE")) {
WARNF(
"AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
"for file matching, only function matching!");
}
if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
getenv("INSTRIM_LIB")) {
if (instrument_mode == 0)
instrument_mode = INSTRUMENT_CFG;
else if (instrument_mode != INSTRUMENT_CFG)
FATAL(
"you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
}
@ -1307,15 +1379,20 @@ int main(int argc, char **argv, char **envp) {
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
"filename\n");
#if LLVM_MAJOR < 9
#define COUNTER_BEHAVIOUR \
" AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
#else
#define COUNTER_BEHAVIOUR \
" AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
#endif
if (have_llvm)
SAYF(
"\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
"variables:\n"
#if LLVM_MAJOR < 9
" AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
#else
" AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
#endif
COUNTER_BEHAVIOUR
" AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
"comparisons\n"
" AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
@ -1426,22 +1503,20 @@ int main(int argc, char **argv, char **envp) {
#if LLVM_MAJOR <= 6
instrument_mode = INSTRUMENT_AFL;
#else
if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
if (have_instr_env) {
instrument_mode = INSTRUMENT_AFL;
WARNF(
"switching to classic instrumentation because "
"AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use "
"-fsanitize-coverage-allowlist=allowlist.txt or "
"-fsanitize-coverage-blocklist=denylist.txt if you want to use "
"PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ "
"SanitizerCoverage.html#partially-disabling-instrumentation");
if (!be_quiet)
WARNF(
"Switching to classic instrumentation because "
"AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1.");
} else
#endif
instrument_mode = INSTRUMENT_PCGUARD;
#endif
}
@ -1487,18 +1562,16 @@ int main(int argc, char **argv, char **envp) {
"AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
"together");
if (instrument_mode == INSTRUMENT_PCGUARD &&
(getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) {
FATAL(
"Instrumentation type PCGUARD does not support "
"AFL_LLVM_ALLOWLIST/DENYLIST! Use "
"-fsanitize-coverage-allowlist=allowlist.txt or "
"-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm "
"12+), see "
"https://clang.llvm.org/docs/"
"SanitizerCoverage.html#partially-disabling-instrumentation");
"AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead.");
}
#endif
u8 *ptr2;
@ -1525,7 +1598,7 @@ int main(int argc, char **argv, char **envp) {
if (debug) {
SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
DEBUGF("cd '%s';", getthecwd());
for (i = 0; i < argc; i++)
SAYF(" '%s'", argv[i]);
SAYF("\n");
@ -1545,15 +1618,29 @@ int main(int argc, char **argv, char **envp) {
if (!be_quiet && cmplog_mode)
printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
#ifndef __ANDROID__
find_obj(argv[0]);
#ifdef __ANDROID__
ptr = find_object("afl-compiler-rt.so", argv[0]);
#else
ptr = find_object("afl-compiler-rt.o", argv[0]);
#endif
if (!ptr) {
FATAL(
"Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH "
"environment variable.");
}
if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
ck_free(ptr);
edit_params(argc, argv, envp);
if (debug) {
SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
DEBUGF("cd '%s';", getthecwd());
for (i = 0; i < (s32)cc_par_cnt; i++)
SAYF(" '%s'", cc_params[i]);
SAYF("\n");

View File

@ -46,7 +46,7 @@ u8 be_quiet = 0;
u8 *doc_path = "";
u8 last_intr = 0;
void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
u32 i = 0;
u8 cwd[PATH_MAX];
@ -63,7 +63,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
*use_stdin = 0;
*use_stdin = false;
if (prog_in[0] != 0) { // not afl-showmap special case

View File

@ -62,6 +62,7 @@ static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) {
execv(fsrv->target_path, argv);
WARNF("Execv failed in forkserver.");
}
/* Initializes the struct */
@ -76,8 +77,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->dev_urandom_fd = -1;
/* Settings */
fsrv->use_stdin = 1;
fsrv->no_unlink = 0;
fsrv->use_stdin = true;
fsrv->no_unlink = false;
fsrv->exec_tmout = EXEC_TIMEOUT;
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
fsrv->mem_limit = MEM_LIMIT;
@ -86,8 +87,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
/* exec related stuff */
fsrv->child_pid = -1;
fsrv->map_size = get_map_size();
fsrv->use_fauxsrv = 0;
fsrv->last_run_timed_out = 0;
fsrv->use_fauxsrv = false;
fsrv->last_run_timed_out = false;
fsrv->uses_crash_exitcode = false;
fsrv->uses_asan = false;
fsrv->init_child_func = fsrv_exec_child;
@ -109,6 +113,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->dev_urandom_fd = from->dev_urandom_fd;
fsrv_to->out_fd = from->out_fd; // not sure this is a good idea
fsrv_to->no_unlink = from->no_unlink;
fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
fsrv_to->crash_exitcode = from->crash_exitcode;
// These are forkserver specific.
fsrv_to->out_dir_fd = -1;
@ -116,7 +122,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->use_fauxsrv = 0;
fsrv_to->last_run_timed_out = 0;
fsrv_to->init_child_func = fsrv_exec_child;
fsrv_to->init_child_func = from->init_child_func;
// Note: do not copy ->add_extra_func
list_append(&fsrv_list, fsrv_to);
@ -272,7 +278,8 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
PFATAL("Execv failed in fauxserver.");
WARNF("Execv failed in fauxserver.");
break;
}
@ -286,13 +293,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
if (waitpid(child_pid, &status, 0) < 0) {
// Zombie Child could not be collected. Scary!
PFATAL("Fauxserver could not determin child's exit code. ");
WARNF("Fauxserver could not determine child's exit code. ");
}
/* Relay wait status to AFL pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(1); }
}
@ -330,7 +337,7 @@ static void report_error_and_exit(int error) {
"memory failed.");
break;
default:
FATAL("unknown error code %u from fuzzing target!", error);
FATAL("unknown error code %d from fuzzing target!", error);
}
@ -347,15 +354,16 @@ static void report_error_and_exit(int error) {
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output) {
int st_pipe[2], ctl_pipe[2];
s32 status;
s32 rlen;
int st_pipe[2], ctl_pipe[2];
s32 status;
s32 rlen;
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
if (!be_quiet) { ACTF("Spinning up the fork server..."); }
if (fsrv->use_fauxsrv) {
/* TODO: Come up with sone nice way to initialize this all */
/* TODO: Come up with some nice way to initialize this all */
if (fsrv->init_child_func != fsrv_exec_child) {
@ -519,8 +527,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
falling through. */
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
fprintf(stderr, "Error: execv to target failed\n");
exit(0);
FATAL("Error: execv to target failed\n");
}
@ -606,7 +613,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
fsrv->use_shmem_fuzz = 1;
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
if ((status & FS_OPT_AUTODICT) == 0) {
if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) {
u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) {
@ -659,16 +666,44 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) {
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
if (ignore_autodict) {
if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); }
} else {
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
// this is not afl-fuzz - or it is cmplog - we deny and return
if (fsrv->use_shmem_fuzz) {
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
} else {
status = (FS_OPT_ENABLED);
}
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed.");
}
return;
}
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
// this is not afl-fuzz - or it is cmplog - we deny and return
if (fsrv->use_shmem_fuzz) {
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
} else {
status = (FS_OPT_ENABLED);
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
}
@ -678,82 +713,62 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
return;
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
}
if (!be_quiet) { ACTF("Using AUTODICT feature."); }
if (fsrv->use_shmem_fuzz) {
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ);
} else {
status = (FS_OPT_ENABLED | FS_OPT_AUTODICT);
}
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed.");
}
if (read(fsrv->fsrv_st_fd, &status, 4) != 4) {
FATAL("Reading from forkserver failed.");
}
if (status < 2 || (u32)status > 0xffffff) {
FATAL("Dictionary has an illegal size: %d", status);
}
u32 offset = 0, count = 0;
u32 len = status;
u8 *dict = ck_alloc(len);
if (dict == NULL) {
FATAL("Could not allocate %u bytes of autodictionary memory", len);
}
while (len != 0) {
rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
if (rlen > 0) {
len -= rlen;
offset += rlen;
} else {
FATAL(
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, len);
FATAL("Reading from forkserver failed.");
}
}
if (status < 2 || (u32)status > 0xffffff) {
offset = 0;
while (offset < (u32)status &&
(u8)dict[offset] + offset < (u32)status) {
FATAL("Dictionary has an illegal size: %d", status);
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
(u8)dict[offset]);
offset += (1 + dict[offset]);
count++;
}
u32 offset = 0, count = 0;
u32 len = status;
u8 *dict = ck_alloc(len);
if (dict == NULL) {
FATAL("Could not allocate %u bytes of autodictionary memory", len);
}
while (len != 0) {
rlen = read(fsrv->fsrv_st_fd, dict + offset, len);
if (rlen > 0) {
len -= rlen;
offset += rlen;
} else {
FATAL(
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, len);
}
}
offset = 0;
while (offset < (u32)status &&
(u8)dict[offset] + offset < (u32)status) {
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
(u8)dict[offset]);
offset += (1 + dict[offset]);
count++;
}
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
ck_free(dict);
}
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
ck_free(dict);
}
}
@ -901,7 +916,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" estimate the required amount of virtual memory for the "
"binary.\n\n"
" - the target was compiled with afl-clang-lto and a constructor "
" - The target was compiled with afl-clang-lto and a constructor "
"was\n"
" instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
"your \n"
@ -1054,6 +1069,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (fsrv->child_pid <= 0) {
if (*stop_soon_p) { return 0; }
if ((fsrv->child_pid & FS_OPT_ERROR) &&
FS_OPT_GET_ERROR(fsrv->child_pid) == FS_ERROR_SHM_OPEN)
FATAL(
"Target reported shared memory access failed (perhaps increase "
"shared memory available).");
FATAL("Fork server is misbehaving (OOM?)");
}
@ -1126,10 +1148,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
/* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
must use a special exit code. */
/* MSAN in uses_asan mode uses a special exit code as it doesn't support
abort_on_error.
On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */
if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) {
if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
(fsrv->uses_crash_exitcode &&
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) {
fsrv->last_kill_signal = 0;
return FSRV_RUN_CRASH;
@ -1137,7 +1162,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
// Fauxserver should handle this now.
// if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
return FSRV_RUN_OK;

View File

@ -425,8 +425,10 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
/* Construct a file name for a new test case, capturing the operation
that led to its discovery. Returns a ptr to afl->describe_op_buf_256. */
u8 *describe_op(afl_state_t *afl, u8 hnb) {
u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
size_t real_max_len =
MIN(max_description_len, sizeof(afl->describe_op_buf_256));
u8 *ret = afl->describe_op_buf_256;
if (unlikely(afl->syncing_party)) {
@ -445,29 +447,66 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time);
sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
if (afl->current_custom_fuzz &&
afl->current_custom_fuzz->afl_custom_describe) {
if (afl->stage_cur_byte >= 0) {
/* We are currently in a custom mutator that supports afl_custom_describe,
* use it! */
sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
size_t len_current = strlen(ret);
ret[len_current++] = ',';
ret[len_current] = '\0';
if (afl->stage_val_type != STAGE_VAL_NONE) {
ssize_t size_left = real_max_len - len_current - strlen(",+cov") - 2;
if (unlikely(size_left <= 0)) FATAL("filename got too long");
sprintf(ret + strlen(ret), ",val:%s%+d",
(afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
afl->stage_cur_val);
const char *custom_description =
afl->current_custom_fuzz->afl_custom_describe(
afl->current_custom_fuzz->data, size_left);
if (!custom_description || !custom_description[0]) {
DEBUGF("Error getting a description from afl_custom_describe");
/* Take the stage name as description fallback */
sprintf(ret + len_current, "op:%s", afl->stage_short);
} else {
/* We got a proper custom description, use it */
strncat(ret + len_current, custom_description, size_left);
}
} else {
sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
/* Normal testcase descriptions start here */
sprintf(ret + strlen(ret), ",op:%s", afl->stage_short);
if (afl->stage_cur_byte >= 0) {
sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte);
if (afl->stage_val_type != STAGE_VAL_NONE) {
sprintf(ret + strlen(ret), ",val:%s%+d",
(afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "",
afl->stage_cur_val);
}
} else {
sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val);
}
}
}
if (hnb == 2) { strcat(ret, ",+cov"); }
if (new_bits == 2) { strcat(ret, ",+cov"); }
if (unlikely(strlen(ret) >= max_description_len))
FATAL("describe string is too long");
return ret;
@ -540,7 +579,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(len == 0)) { return 0; }
u8 *queue_fn = "";
u8 hnb = '\0';
u8 new_bits = '\0';
s32 fd;
u8 keeping = 0, res;
u64 cksum = 0;
@ -566,7 +605,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* Keep only if there are new bits in the map, add to queue for
future fuzzing, etc. */
if (!(hnb = has_new_bits(afl, afl->virgin_bits))) {
if (!(new_bits = has_new_bits(afl, afl->virgin_bits))) {
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
return 0;
@ -575,8 +614,9 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
afl->queued_paths, describe_op(afl, hnb));
queue_fn = alloc_printf(
"%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
describe_op(afl, new_bits, NAME_MAX - strlen("id:000000,")));
#else
@ -584,7 +624,10 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
#endif /* ^!SIMPLE_FILES */
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
ck_write(fd, mem, len, queue_fn);
close(fd);
add_to_queue(afl, queue_fn, len, 0);
#ifdef INTROSPECTION
@ -616,7 +659,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#endif
if (hnb == 2) {
if (new_bits == 2) {
afl->queue_top->has_new_cov = 1;
++afl->queued_with_cov;
@ -647,11 +690,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
ck_write(fd, mem, len, queue_fn);
close(fd);
if (likely(afl->q_testcase_max_cache_size)) {
queue_testcase_store_mem(afl, afl->queue_top, mem);
@ -744,7 +782,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
afl->unique_hangs, describe_op(afl, 0));
afl->unique_hangs,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
#else
@ -789,7 +828,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
afl->unique_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0));
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
#else

View File

@ -355,7 +355,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
for (i = 0; i < ncpus; i++) {
for (i = 0; i < (s32)ncpus; i++) {
k = kstat_lookup(m, "cpu_stat", i, NULL);
if (kstat_read(m, k, &cs)) {
@ -868,7 +868,19 @@ void perform_dry_run(afl_state_t *afl) {
if (skip_crashes) {
WARNF("Test case results in a crash (skipping)");
if (afl->fsrv.uses_crash_exitcode) {
WARNF(
"Test case results in a crash or AFL_CRASH_EXITCODE %d "
"(skipping)",
(int)(s8)afl->fsrv.crash_exitcode);
} else {
WARNF("Test case results in a crash (skipping)");
}
q->cal_failed = CAL_CHANCES;
++cal_failures;
break;
@ -954,7 +966,18 @@ void perform_dry_run(afl_state_t *afl) {
#undef MSG_ULIMIT_USAGE
#undef MSG_FORK_ON_APPLE
WARNF("Test case '%s' results in a crash, skipping", fn);
if (afl->fsrv.uses_crash_exitcode) {
WARNF(
"Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, "
"skipping",
fn, (int)(s8)afl->fsrv.crash_exitcode);
} else {
WARNF("Test case '%s' results in a crash, skipping", fn);
}
/* Remove from fuzzing queue but keep for splicing */
@ -2300,12 +2323,6 @@ void fix_up_sync(afl_state_t *afl) {
u8 *x = afl->sync_id;
if (afl->non_instrumented_mode) {
FATAL("-S / -M and -n are mutually exclusive");
}
while (*x) {
if (!isalnum(*x) && *x != '_' && *x != '-') {
@ -2503,7 +2520,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode) {
if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
afl->non_instrumented_mode) {
return;

View File

@ -151,7 +151,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
/* Mutator */
/* "afl_custom_init", optional for backward compatibility */
mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
if (!mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
if (!mutator->afl_custom_init) {
FATAL("Symbol 'afl_custom_init' not found.");
}
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
@ -161,49 +165,74 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'.");
mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator");
if (!mutator->afl_custom_fuzz)
if (!mutator->afl_custom_fuzz) {
WARNF("Symbol 'afl_custom_mutator' not found.");
}
}
/* "afl_custom_introspection", optional */
#ifdef INTROSPECTION
mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
if (!mutator->afl_custom_introspection)
if (!mutator->afl_custom_introspection) {
ACTF("optional symbol 'afl_custom_introspection' not found.");
}
#endif
/* "afl_custom_fuzz_count", optional */
mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
if (!mutator->afl_custom_fuzz_count)
if (!mutator->afl_custom_fuzz_count) {
ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
}
/* "afl_custom_deinit", optional for backward compatibility */
mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
if (!mutator->afl_custom_deinit)
if (!mutator->afl_custom_deinit) {
FATAL("Symbol 'afl_custom_deinit' not found.");
}
/* "afl_custom_post_process", optional */
mutator->afl_custom_post_process = dlsym(dh, "afl_custom_post_process");
if (!mutator->afl_custom_post_process)
if (!mutator->afl_custom_post_process) {
ACTF("optional symbol 'afl_custom_post_process' not found.");
}
u8 notrim = 0;
/* "afl_custom_init_trim", optional */
mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim");
if (!mutator->afl_custom_init_trim)
if (!mutator->afl_custom_init_trim) {
ACTF("optional symbol 'afl_custom_init_trim' not found.");
}
/* "afl_custom_trim", optional */
mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim");
if (!mutator->afl_custom_trim)
if (!mutator->afl_custom_trim) {
ACTF("optional symbol 'afl_custom_trim' not found.");
}
/* "afl_custom_post_trim", optional */
mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim");
if (!mutator->afl_custom_post_trim)
if (!mutator->afl_custom_post_trim) {
ACTF("optional symbol 'afl_custom_post_trim' not found.");
}
if (notrim) {
mutator->afl_custom_init_trim = NULL;
@ -217,31 +246,54 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
/* "afl_custom_havoc_mutation", optional */
mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation");
if (!mutator->afl_custom_havoc_mutation)
if (!mutator->afl_custom_havoc_mutation) {
ACTF("optional symbol 'afl_custom_havoc_mutation' not found.");
}
/* "afl_custom_havoc_mutation", optional */
mutator->afl_custom_havoc_mutation_probability =
dlsym(dh, "afl_custom_havoc_mutation_probability");
if (!mutator->afl_custom_havoc_mutation_probability)
if (!mutator->afl_custom_havoc_mutation_probability) {
ACTF("optional symbol 'afl_custom_havoc_mutation_probability' not found.");
}
/* "afl_custom_queue_get", optional */
mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get");
if (!mutator->afl_custom_queue_get)
if (!mutator->afl_custom_queue_get) {
ACTF("optional symbol 'afl_custom_queue_get' not found.");
}
/* "afl_custom_queue_new_entry", optional */
mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry");
if (!mutator->afl_custom_queue_new_entry)
if (!mutator->afl_custom_queue_new_entry) {
ACTF("optional symbol 'afl_custom_queue_new_entry' not found");
}
/* "afl_custom_describe", optional */
mutator->afl_custom_describe = dlsym(dh, "afl_custom_describe");
if (!mutator->afl_custom_describe) {
ACTF("Symbol 'afl_custom_describe' not found.");
}
OKF("Custom mutator '%s' installed successfully.", fn);
/* Initialize the custom mutator */
if (mutator->afl_custom_init)
if (mutator->afl_custom_init) {
mutator->data = mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
}
mutator->stacked_custom = (mutator && mutator->afl_custom_havoc_mutation);
mutator->stacked_custom_prob =
6; // like one of the default mutations in havoc

View File

@ -445,8 +445,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (unlikely(afl->not_on_tty)) {
ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...",
afl->current_entry, afl->queued_paths, afl->unique_crashes);
ACTF(
"Fuzzing test case #%u (%u total, %llu uniq crashes found, "
"perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u)...",
afl->current_entry, afl->queued_paths, afl->unique_crashes,
afl->queue_cur->perf_score, afl->queue_cur->exec_us,
likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
afl->queue_cur->bitmap_size);
fflush(stdout);
}
@ -1790,11 +1795,16 @@ custom_mutator_stage:
afl->current_custom_fuzz = el;
if (el->afl_custom_fuzz_count)
if (el->afl_custom_fuzz_count) {
afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
else
} else {
afl->stage_max = saved_max;
}
has_custom_fuzz = true;
afl->stage_short = el->name_short;

View File

@ -96,7 +96,7 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
mutated_size = PyByteArray_Size(py_value);
*out_buf = afl_realloc(BUF_PARAMS(fuzz), mutated_size);
if (unlikely(!out_buf)) { PFATAL("alloc"); }
if (unlikely(!*out_buf)) { PFATAL("alloc"); }
memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
Py_DECREF(py_value);
@ -111,6 +111,37 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
}
static const char *custom_describe_py(void * py_mutator,
size_t max_description_len) {
PyObject *py_args, *py_value;
py_args = PyTuple_New(1);
PyLong_FromSize_t(max_description_len);
/* add_buf */
py_value = PyLong_FromSize_t(max_description_len);
if (!py_value) {
Py_DECREF(py_args);
FATAL("Failed to convert arguments");
}
PyTuple_SetItem(py_args, 0, py_value);
py_value = PyObject_CallObject(
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DESCRIBE], py_args);
Py_DECREF(py_args);
if (py_value != NULL) { return PyBytes_AsString(py_value); }
return NULL;
}
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
(void)afl;
@ -134,6 +165,18 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject * py_module = py->py_module;
PyObject **py_functions = py->py_functions;
// initialize the post process buffer; ensures it's always valid
PyObject *unused_bytes = PyByteArray_FromStringAndSize("OHAI", 4);
if (!unused_bytes) { FATAL("allocation failed!"); }
if (PyObject_GetBuffer(unused_bytes, &py->post_process_buf, PyBUF_SIMPLE) ==
-1) {
FATAL("buffer initialization failed");
}
Py_DECREF(unused_bytes);
if (py_module != NULL) {
u8 py_notrim = 0, py_idx;
@ -144,6 +187,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
py_functions[PY_FUNC_DESCRIBE] =
PyObject_GetAttrString(py_module, "describe");
py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count");
if (!py_functions[PY_FUNC_FUZZ])
@ -313,7 +358,6 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
struct custom_mutator *mutator;
mutator = ck_alloc(sizeof(struct custom_mutator));
mutator->post_process_buf = NULL;
mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
@ -329,9 +373,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
if (py_functions[PY_FUNC_DEINIT]) { mutator->afl_custom_deinit = deinit_py; }
/* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
is quite different from the custom mutator. */
mutator->afl_custom_fuzz = fuzz_py;
if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
if (py_functions[PY_FUNC_DESCRIBE]) {
mutator->afl_custom_describe = custom_describe_py;
}
if (py_functions[PY_FUNC_POST_PROCESS]) {
@ -405,10 +453,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
u8 **out_buf) {
size_t py_out_buf_size;
PyObject * py_args, *py_value;
py_mutator_t *py = (py_mutator_t *)py_mutator;
// buffer returned previously must be released; initialized during init
// so we don't need to do comparisons
PyBuffer_Release(&py->post_process_buf);
py_args = PyTuple_New(1);
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
if (!py_value) {
@ -428,20 +479,20 @@ size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
if (py_value != NULL) {
py_out_buf_size = PyByteArray_Size(py_value);
if (PyObject_GetBuffer(py_value, &py->post_process_buf, PyBUF_SIMPLE) ==
-1) {
if (unlikely(!afl_realloc(BUF_PARAMS(post_process), py_out_buf_size))) {
PFATAL("alloc");
PyErr_Print();
FATAL(
"Python custom mutator: post_process call return value not a "
"bytes-like object");
}
memcpy(py->post_process_buf, PyByteArray_AsString(py_value),
py_out_buf_size);
Py_DECREF(py_value);
*out_buf = py->post_process_buf;
return py_out_buf_size;
*out_buf = (u8 *)py->post_process_buf.buf;
return py->post_process_buf.len;
} else {
@ -581,7 +632,7 @@ size_t trim_py(void *py_mutator, u8 **out_buf) {
ret = PyByteArray_Size(py_value);
*out_buf = afl_realloc(BUF_PARAMS(trim), ret);
if (unlikely(!out_buf)) { PFATAL("alloc"); }
if (unlikely(!*out_buf)) { PFATAL("alloc"); }
memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
Py_DECREF(py_value);
@ -647,7 +698,7 @@ size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
/* A new buf is needed... */
*out_buf = afl_realloc(BUF_PARAMS(havoc), mutated_size);
if (unlikely(!out_buf)) { PFATAL("alloc"); }
if (unlikely(!*out_buf)) { PFATAL("alloc"); }
}

View File

@ -42,11 +42,29 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
}
double compute_weight(afl_state_t *afl, struct queue_entry *q,
double avg_exec_us, double avg_bitmap_size) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (hits == 0) hits = 1;
double weight = 1.0;
weight *= avg_exec_us / q->exec_us;
weight *= log(q->bitmap_size) / avg_bitmap_size;
weight /= log10(hits) + 1;
if (q->favored) weight *= 5;
return weight;
}
/* create the alias table that allows weighted random selection - expensive */
void create_alias_table(afl_state_t *afl) {
u32 n = afl->queued_paths, i = 0, a, g;
u32 n = afl->queued_paths, i = 0, a, g;
double sum = 0;
afl->alias_table =
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
@ -56,26 +74,69 @@ void create_alias_table(afl_state_t *afl) {
int * S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
int * L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
if (!P || !S || !L) { FATAL("could not aquire memory for alias table"); }
memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
double sum = 0;
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
sum += q->perf_score;
FATAL("could not acquire memory for alias table");
}
for (i = 0; i < n; i++) {
memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
struct queue_entry *q = afl->queue_buf[i];
P[i] = (q->perf_score * n) / sum;
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
double avg_exec_us = 0.0;
double avg_bitmap_size = 0.0;
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
avg_exec_us += q->exec_us;
avg_bitmap_size += log(q->bitmap_size);
}
avg_exec_us /= afl->queued_paths;
avg_bitmap_size /= afl->queued_paths;
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
if (!q->disabled) {
q->weight = compute_weight(afl, q, avg_exec_us, avg_bitmap_size);
q->perf_score = calculate_score(afl, q);
}
sum += q->weight;
}
for (i = 0; i < n; i++) {
P[i] = (afl->queue_buf[i]->weight * n) / sum;
}
} else {
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
if (!q->disabled) { q->perf_score = calculate_score(afl, q); }
sum += q->perf_score;
}
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
P[i] = (q->perf_score * n) / sum;
}
}

View File

@ -79,7 +79,8 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
s32 doc_fd;
char fn[PATH_MAX];
snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir,
afl->document_counter++, describe_op(afl, 0));
afl->document_counter++,
describe_op(afl, 0, NAME_MAX - strlen("000000000:")));
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
@ -332,7 +333,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
afl->afl_env.afl_debug_child_output);
afl->afl_env.afl_debug_child);
if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) {
@ -484,7 +485,7 @@ void sync_fuzzers(afl_state_t *afl) {
DIR * sd;
struct dirent *sd_ent;
u32 sync_cnt = 0, synced = 0, entries = 0;
u8 path[PATH_MAX + 256];
u8 path[PATH_MAX + 1 + NAME_MAX];
sd = opendir(afl->sync_dir);
if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); }
@ -590,7 +591,7 @@ void sync_fuzzers(afl_state_t *afl) {
while (m < n) {
if (strcmp(namelist[m]->d_name, entry)) {
if (strncmp(namelist[m]->d_name, entry, 9)) {
m++;

View File

@ -268,11 +268,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_bench_until_crash =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
} else if (!strncmp(env, "AFL_DEBUG_CHILD",
afl_environment_variable_len) ||
!strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
afl_environment_variable_len)) {
afl->afl_env.afl_debug_child_output =
afl->afl_env.afl_debug_child =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_AUTORESUME",
@ -392,6 +394,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_statsd_tags_flavor =
(u8 *)get_afl_env(afl_environment_variables[i]);
} else if (!strncmp(env, "AFL_CRASH_EXITCODE",
afl_environment_variable_len)) {
afl->afl_env.afl_crash_exitcode =
(u8 *)get_afl_env(afl_environment_variables[i]);
}
} else {

View File

@ -26,6 +26,7 @@
#include "afl-fuzz.h"
#include "cmplog.h"
#include <limits.h>
#include <stdlib.h>
#ifndef USEMMAP
#include <sys/mman.h>
#include <sys/stat.h>
@ -40,7 +41,7 @@ extern u64 time_spent_working;
static void at_exit() {
int i;
s32 i, pid1 = 0, pid2 = 0;
char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
char *ptr;
@ -48,10 +49,10 @@ static void at_exit() {
if (ptr && *ptr) unlink(ptr);
ptr = getenv("__AFL_TARGET_PID1");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) kill(pid1, SIGTERM);
ptr = getenv("__AFL_TARGET_PID2");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) kill(pid2, SIGTERM);
i = 0;
while (list[i] != NULL) {
@ -75,6 +76,9 @@ static void at_exit() {
}
if (pid1 > 0) { kill(pid1, SIGKILL); }
if (pid2 > 0) { kill(pid2, SIGKILL); }
}
/* Display usage hints. */
@ -162,11 +166,12 @@ static void usage(u8 *argv0, int more_help) {
"AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
"AFL_BENCH_JUST_ONE: run the target just once\n"
"AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
"AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
"AFL_DEBUG_CHILD_OUTPUT: do not suppress stdout/stderr from target\n"
"AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
@ -184,6 +189,7 @@ static void usage(u8 *argv0, int more_help) {
" used. Defaults to 200.\n"
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
"AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
"AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
@ -350,6 +356,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 's': {
if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
rand_set_seed(afl, strtoul(optarg, 0L, 10));
afl->fixed_seed = 1;
break;
@ -419,6 +426,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'i': /* input dir */
if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
afl->in_dir = optarg;
if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
@ -435,9 +443,26 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *c;
if (afl->non_instrumented_mode) {
FATAL("-M is not supported in non-instrumented mode");
}
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
/* sanity check for argument: should not begin with '-' (possible
* option) */
if (optarg && *optarg == '-') {
FATAL(
"argument for -M started with a dash '-', which is used for "
"options");
}
afl->sync_id = ck_strdup(optarg);
afl->skip_deterministic = 0; // force determinsitic fuzzing
afl->skip_deterministic = 0; // force deterministic fuzzing
afl->old_seed_selection = 1; // force old queue walking seed selection
if ((c = strchr(afl->sync_id, ':'))) {
@ -464,7 +489,24 @@ int main(int argc, char **argv_orig, char **envp) {
case 'S': /* secondary sync id */
if (afl->non_instrumented_mode) {
FATAL("-S is not supported in non-instrumented mode");
}
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
/* sanity check for argument: should not begin with '-' (possible
* option) */
if (optarg && *optarg == '-') {
FATAL(
"argument for -M started with a dash '-', which is used for "
"options");
}
afl->sync_id = ck_strdup(optarg);
afl->is_secondary_node = 1;
break;
@ -620,6 +662,12 @@ int main(int argc, char **argv_orig, char **envp) {
case 'n': /* dumb mode */
if (afl->is_main_node || afl->is_secondary_node) {
FATAL("Non instrumented mode is not supported with -M / -S");
}
if (afl->non_instrumented_mode) {
FATAL("Multiple -n options not supported");
@ -656,7 +704,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'N': /* Unicorn mode */
if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
afl->fsrv.no_unlink = afl->no_unlink = 1;
afl->fsrv.no_unlink = (afl->no_unlink = true);
break;
@ -906,7 +954,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->power_name = power_names[afl->schedule];
if (!afl->sync_id) {
if (!afl->non_instrumented_mode && !afl->sync_id) {
auto_sync = 1;
afl->sync_id = ck_strdup("default");
@ -1089,6 +1137,23 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (afl->afl_env.afl_crash_exitcode) {
long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
exitcode < -127 || exitcode > 128) {
FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
afl->afl_env.afl_crash_exitcode);
}
afl->fsrv.uses_crash_exitcode = true;
// WEXITSTATUS is 8 bit unsigned
afl->fsrv.crash_exitcode = (u8)exitcode;
}
if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
@ -1338,7 +1403,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); }
if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
check_binary(afl, afl->cmplog_binary);
}
}
@ -1380,7 +1449,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
afl->afl_env.afl_debug_child_output);
afl->afl_env.afl_debug_child);
OKF("Cmplog forkserver successfully started");
}
@ -1436,9 +1505,12 @@ int main(int argc, char **argv_orig, char **envp) {
cull_queue(afl);
if (!afl->pending_not_fuzzed)
if (!afl->pending_not_fuzzed) {
FATAL("We need at least on valid input seed that does not crash!");
}
show_init_stats(afl);
if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);

View File

@ -182,12 +182,12 @@ static void edit_params(int argc, char **argv) {
instrim = 1;
if (debug)
SAYF(cMGN "[D] " cRST
"passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
"inst_present=%s rt_present=%s rt_lto_present=%s\n",
passthrough ? "true" : "false", instrim, gold_pos,
gold_present ? "true" : "false", inst_present ? "true" : "false",
rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
DEBUGF(
"passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s "
"inst_present=%s rt_present=%s rt_lto_present=%s\n",
passthrough ? "true" : "false", instrim, gold_pos,
gold_present ? "true" : "false", inst_present ? "true" : "false",
rt_present ? "true" : "false", rt_lto_present ? "true" : "false");
for (i = 1; i < argc; i++) {
@ -280,7 +280,7 @@ int main(int argc, char **argv) {
if (getcwd(thecwd, sizeof(thecwd)) != 0) strcpy(thecwd, ".");
SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd);
DEBUGF("cd \"%s\";", thecwd);
for (i = 0; i < argc; i++)
SAYF(" \"%s\"", argv[i]);
SAYF("\n");
@ -315,7 +315,7 @@ int main(int argc, char **argv) {
if (debug) {
SAYF(cMGN "[D]" cRST " cd \"%s\";", thecwd);
DEBUGF("cd \"%s\";", thecwd);
for (i = 0; i < ld_param_cnt; i++)
SAYF(" \"%s\"", ld_params[i]);
SAYF("\n");
@ -333,7 +333,7 @@ int main(int argc, char **argv) {
if (pid < 0) PFATAL("fork() failed");
if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");
if (debug) SAYF(cMGN "[D] " cRST "linker result: %d\n", status);
if (debug) DEBUGF("linker result: %d\n", status);
if (!just_version) {

View File

@ -667,6 +667,8 @@ static void usage(u8 *argv0) {
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
"inputs\n"
"AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n"
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
"crash\n"
"AFL_DEBUG: enable extra developer output\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
"size\n"
@ -904,7 +906,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_DEBUG")) {
SAYF(cMGN "[D]" cRST);
DEBUGF("");
for (i = 0; i < argc; i++)
SAYF(" %s", argv[i]);
SAYF("\n");
@ -1066,7 +1068,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) {
int i = optind;
SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path);
DEBUGF("%s:", fsrv->target_path);
while (argv[i] != NULL) {
SAYF(" \"%s\"", argv[i++]);
@ -1090,8 +1092,29 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (getenv("AFL_CRASH_EXITCODE")) {
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
exitcode < -127 || exitcode > 128) {
FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
getenv("AFL_CRASH_EXITCODE"));
}
fsrv->uses_crash_exitcode = true;
// WEXITSTATUS is 8 bit unsigned
fsrv->crash_exitcode = (u8)exitcode;
}
afl_fsrv_start(fsrv, use_argv, &stop_soon,
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
(get_afl_env("AFL_DEBUG_CHILD") ||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
? 1
: 0);
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)

View File

@ -51,6 +51,7 @@
#include <signal.h>
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/wait.h>
#include <sys/time.h>
@ -841,17 +842,17 @@ static void usage(u8 *argv0) {
"For additional tips, please consult %s/README.md.\n\n"
"Environment variables used:\n"
"TMPDIR: directory to use for temporary input files\n"
"ASAN_OPTIONS: custom settings for ASAN\n"
" (must contain abort_on_error=1 and symbolize=0)\n"
"MSAN_OPTIONS: custom settings for MSAN\n"
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
"ASAN_OPTIONS: custom settings for ASAN\n"
" (must contain abort_on_error=1 and symbolize=0)\n"
"MSAN_OPTIONS: custom settings for MSAN\n"
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
"TMPDIR: directory to use for temporary input files\n"
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
exit(1);
@ -1122,6 +1123,23 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (getenv("AFL_CRASH_EXITCODE")) {
long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
exitcode < -127 || exitcode > 128) {
FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
getenv("AFL_CRASH_EXITCODE"));
}
fsrv->uses_crash_exitcode = true;
// WEXITSTATUS is 8 bit unsigned
fsrv->crash_exitcode = (u8)exitcode;
}
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
/* initialize cmplog_mode */
@ -1141,8 +1159,11 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file();
afl_fsrv_start(fsrv, use_argv, &stop_soon,
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
afl_fsrv_start(
fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
? 1
: 0);
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);