|
|
|
@ -1895,6 +1895,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) {
|
|
|
|
|
these have_*, otherwise they may not work as expected.
|
|
|
|
|
*/
|
|
|
|
|
void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
if (getenv("AFL_USE_ASAN") || aflcc->have_asan) {
|
|
|
|
|
if (getenv("AFL_USE_MSAN") || aflcc->have_msan)
|
|
|
|
|
FATAL("ASAN and MSAN are mutually exclusive");
|
|
|
|
@ -1963,6 +1964,127 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
|
|
|
|
|
aflcc->have_cfisan = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_ASAN") || aflcc->have_asan) {
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_MSAN") || aflcc->have_msan)
|
|
|
|
|
FATAL("ASAN and MSAN are mutually exclusive");
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_HARDEN"))
|
|
|
|
|
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
|
|
|
|
|
|
|
|
|
|
if (aflcc->compiler_mode == GCC_PLUGIN && !aflcc->have_staticasan) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-static-libasan");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_defs_fortify(aflcc, 0);
|
|
|
|
|
if (!aflcc->have_asan) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fsanitize=address");
|
|
|
|
|
insert_param(aflcc, "-fno-common");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aflcc->have_asan = 1;
|
|
|
|
|
|
|
|
|
|
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_ASAN") || aflcc->have_asan)
|
|
|
|
|
FATAL("ASAN and MSAN are mutually exclusive");
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_HARDEN"))
|
|
|
|
|
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
|
|
|
|
|
|
|
|
|
|
add_defs_fortify(aflcc, 0);
|
|
|
|
|
if (!aflcc->have_msan) { insert_param(aflcc, "-fsanitize=memory"); }
|
|
|
|
|
aflcc->have_msan = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_UBSAN") || aflcc->have_ubsan) {
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_ubsan) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fsanitize=undefined");
|
|
|
|
|
insert_param(aflcc, "-fsanitize-undefined-trap-on-error");
|
|
|
|
|
insert_param(aflcc, "-fno-sanitize-recover=all");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_fp) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fno-omit-frame-pointer");
|
|
|
|
|
aflcc->have_fp = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aflcc->have_ubsan = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_TSAN") || aflcc->have_tsan) {
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_fp) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fno-omit-frame-pointer");
|
|
|
|
|
aflcc->have_fp = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_tsan) { insert_param(aflcc, "-fsanitize=thread"); }
|
|
|
|
|
aflcc->have_tsan = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_LSAN") && !aflcc->have_lsan) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fsanitize=leak");
|
|
|
|
|
add_defs_lsan_ctrl(aflcc);
|
|
|
|
|
aflcc->have_lsan = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) {
|
|
|
|
|
|
|
|
|
|
if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) {
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_fcf) { insert_param(aflcc, "-fcf-protection=full"); }
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
if (!aflcc->lto_mode && !aflcc->have_flto) {
|
|
|
|
|
|
|
|
|
|
uint32_t i = 0, found = 0;
|
|
|
|
|
while (envp[i] != NULL && !found) {
|
|
|
|
|
|
|
|
|
|
if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found) { insert_param(aflcc, "-flto"); }
|
|
|
|
|
aflcc->have_flto = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_cfisan) { insert_param(aflcc, "-fsanitize=cfi"); }
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_hidden) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fvisibility=hidden");
|
|
|
|
|
aflcc->have_hidden = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aflcc->have_cfisan = 1;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add params to enable LLVM SanCov, the native PCGUARD */
|
|
|
|
@ -3031,6 +3153,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
|
|
|
|
static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc,
|
|
|
|
|
char **argv) {
|
|
|
|
|
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
u8 skip_next = 0;
|
|
|
|
|
while (--argc) {
|
|
|
|
|
u8 *cur = *(++argv);
|
|
|
|
@ -3067,12 +3190,106 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc,
|
|
|
|
|
char *arg_buf = NULL;
|
|
|
|
|
u64 arg_len = 0;
|
|
|
|
|
enum fsm_state {
|
|
|
|
|
=======
|
|
|
|
|
// for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]);
|
|
|
|
|
|
|
|
|
|
/* Process the argument list. */
|
|
|
|
|
|
|
|
|
|
u8 skip_next = 0;
|
|
|
|
|
while (--argc) {
|
|
|
|
|
|
|
|
|
|
u8 *cur = *(++argv);
|
|
|
|
|
|
|
|
|
|
if (skip_next > 0) {
|
|
|
|
|
|
|
|
|
|
skip_next--;
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PARAM_MISS != parse_misc_params(aflcc, cur, scan)) continue;
|
|
|
|
|
|
|
|
|
|
if (PARAM_MISS != parse_fsanitize(aflcc, cur, scan)) continue;
|
|
|
|
|
|
|
|
|
|
if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* Response file support -----BEGIN-----
|
|
|
|
|
We have two choices - move everything to the command line or
|
|
|
|
|
rewrite the response files to temporary files and delete them
|
|
|
|
|
afterwards. We choose the first for easiness.
|
|
|
|
|
For clang, llvm::cl::ExpandResponseFiles does this, however it
|
|
|
|
|
only has C++ interface. And for gcc there is expandargv in libiberty,
|
|
|
|
|
written in C, but we can't simply copy-paste since its LGPL licensed.
|
|
|
|
|
So here we use an equivalent FSM as alternative, and try to be compatible
|
|
|
|
|
with the two above. See:
|
|
|
|
|
- https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html
|
|
|
|
|
- driver::expand_at_files in gcc.git/gcc/gcc.c
|
|
|
|
|
- expandargv in gcc.git/libiberty/argv.c
|
|
|
|
|
- llvm-project.git/clang/tools/driver/driver.cpp
|
|
|
|
|
- ExpandResponseFiles in
|
|
|
|
|
llvm-project.git/llvm/lib/Support/CommandLine.cpp
|
|
|
|
|
*/
|
|
|
|
|
if (*cur == '@') {
|
|
|
|
|
|
|
|
|
|
u8 *filename = cur + 1;
|
|
|
|
|
if (aflcc->debug) { DEBUGF("response file=%s\n", filename); }
|
|
|
|
|
|
|
|
|
|
// Check not found or empty? let the compiler complain if so.
|
|
|
|
|
FILE *f = fopen(filename, "r");
|
|
|
|
|
if (!f) {
|
|
|
|
|
|
|
|
|
|
if (!scan) insert_param(aflcc, cur);
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct stat st;
|
|
|
|
|
if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode) || st.st_size < 1) {
|
|
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
|
if (!scan) insert_param(aflcc, cur);
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Limit the number of response files, the max value
|
|
|
|
|
// just keep consistent with expandargv. Only do this in
|
|
|
|
|
// scan mode, and not touch rsp_count anymore in the next.
|
|
|
|
|
static u32 rsp_count = 2000;
|
|
|
|
|
if (scan) {
|
|
|
|
|
|
|
|
|
|
if (rsp_count == 0) FATAL("Too many response files provided!");
|
|
|
|
|
|
|
|
|
|
--rsp_count;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// argc, argv acquired from this rsp file. Note that
|
|
|
|
|
// process_params ignores argv[0], we need to put a const "" here.
|
|
|
|
|
u32 argc_read = 1;
|
|
|
|
|
char **argv_read = ck_alloc(sizeof(char *));
|
|
|
|
|
argv_read[0] = "";
|
|
|
|
|
|
|
|
|
|
char *arg_buf = NULL;
|
|
|
|
|
u64 arg_len = 0;
|
|
|
|
|
|
|
|
|
|
enum fsm_state {
|
|
|
|
|
|
|
|
|
|
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
|
|
|
|
|
fsm_whitespace, // whitespace seen so far
|
|
|
|
|
fsm_double_quote, // have unpaired double quote
|
|
|
|
|
fsm_single_quote, // have unpaired single quote
|
|
|
|
|
fsm_backslash, // a backslash is seen with no unpaired quote
|
|
|
|
|
fsm_normal // a normal char is seen
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
};
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Workaround to append c to arg buffer, and append the buffer to argv
|
|
|
|
|
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
|
|
|
|
|
#define ARG_ALLOC(c) \
|
|
|
|
|
do { \
|
|
|
|
|
\
|
|
|
|
@ -3255,6 +3472,7 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc,
|
|
|
|
|
/* Process each of the existing argv, also add a few new args. */
|
|
|
|
|
static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv,
|
|
|
|
|
char **envp) {
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
add_real_argv0(aflcc);
|
|
|
|
|
if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC) {
|
|
|
|
|
insert_param(aflcc, "-Wno-unused-command-line-argument");
|
|
|
|
@ -3301,6 +3519,107 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv,
|
|
|
|
|
load_llvm_pass(aflcc, "afl-llvm-pass.so");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
|
|
add_real_argv0(aflcc);
|
|
|
|
|
|
|
|
|
|
// prevent unnecessary build errors
|
|
|
|
|
if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-Wno-unused-command-line-argument");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) {
|
|
|
|
|
|
|
|
|
|
add_assembler(aflcc);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aflcc->compiler_mode == GCC_PLUGIN) { add_gcc_plugin(aflcc); }
|
|
|
|
|
|
|
|
|
|
if (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == LTO) {
|
|
|
|
|
|
|
|
|
|
if (aflcc->lto_mode && aflcc->have_instr_env) {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "afl-llvm-lto-instrumentlist.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("AFL_LLVM_DICT2FILE")) {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "afl-llvm-dict2file.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// laf
|
|
|
|
|
if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "split-switches-pass.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("LAF_TRANSFORM_COMPARES") ||
|
|
|
|
|
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "compare-transform-pass.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
|
|
|
|
|
getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "split-compares-pass.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// /laf
|
|
|
|
|
|
|
|
|
|
if (aflcc->cmplog_mode) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, "-fno-inline");
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "cmplog-switches-pass.so");
|
|
|
|
|
// reuse split switches from laf
|
|
|
|
|
load_llvm_pass(aflcc, "split-switches-pass.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// #if LLVM_MAJOR >= 13
|
|
|
|
|
// // Use the old pass manager in LLVM 14 which the AFL++ passes still
|
|
|
|
|
// use. insert_param(aflcc, "-flegacy-pass-manager");
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
if (aflcc->lto_mode) {
|
|
|
|
|
|
|
|
|
|
insert_param(aflcc, aflcc->lto_flag);
|
|
|
|
|
|
|
|
|
|
if (!aflcc->have_c) {
|
|
|
|
|
|
|
|
|
|
add_lto_linker(aflcc);
|
|
|
|
|
add_lto_passes(aflcc);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
if (aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
|
|
|
|
|
|
|
|
|
|
add_optimized_pcguard(aflcc);
|
|
|
|
|
|
|
|
|
|
} else if (aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) {
|
|
|
|
|
|
|
|
|
|
add_native_pcguard(aflcc);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "afl-llvm-pass.so");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
>>>>>>> e12b99bad19de97a02e9fe14b9b2c048338b2ab7
|
|
|
|
|
if (aflcc->cmplog_mode) {
|
|
|
|
|
|
|
|
|
|
load_llvm_pass(aflcc, "cmplog-instructions-pass.so");
|
|
|
|
|