From 3e84d6a2ae7df5f6b9073a91ccc6acef50b45aab Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 27 Apr 2023 11:49:00 +0200 Subject: afl++ -> AFL++ --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index d1001187..99ce39d4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -642,7 +642,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } //#if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the afl++ passes still + // // Use the old pass manager in LLVM 14 which the AFL++ passes still // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; //#endif -- cgit 1.4.1 From e956f23a77b776a5c11344889503c833adbf1052 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 28 Apr 2023 11:35:22 +0200 Subject: Source Code Coverage support for Nyx (Part 1) (#1720) * Additional source code reformatting in afl-compiler-rt * Add source code coverage support to afl-compiler-rt (for use with Nyx) --- GNUmakefile.llvm | 5 + instrumentation/README.llvm.md | 24 ++++ instrumentation/afl-compiler-rt.o.c | 261 +++++++++++++++++++++++++++++++++++- src/afl-cc.c | 26 +++- 4 files changed, 308 insertions(+), 8 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index c1b006ba..2bb4e7f8 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -274,6 +274,11 @@ ifndef LLVM_DEBUG CFLAGS_SAFE += -Wno-deprecated endif +ifdef CODE_COVERAGE + override CFLAGS_SAFE += -D__AFL_CODE_COVERAGE=1 + override LDFLAGS += -ldl +endif + override CFLAGS += $(CFLAGS_SAFE) ifdef AFL_TRACE_PC diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md index c0677474..126cf1a2 100644 --- a/instrumentation/README.llvm.md +++ b/instrumentation/README.llvm.md @@ -280,3 +280,27 @@ Please note that the default counter implementations are not thread safe! Support for thread safe counters in mode LLVM CLASSIC can be activated with setting `AFL_LLVM_THREADSAFE_INST=1`. + +## 8) Source code coverage through instrumentation + +Measuring source code coverage is a common task in fuzzing, but it is very +difficut to do in some situations (e.g. when using snapshot fuzzing). + +When using the `AFL_LLVM_INSTRUMENT=llvm-codecov` option, afl-cc will use +native trace-pc-guard instrumentation but additionally select options that +are required to utilize the instrumentation for source code coverage. + +In particular, it will switch the instrumentation to be per basic block +instead of instrumenting edges, disable all guard pruning and enable the +experimental pc-table support that allows the runtime to gather 100% of +instrumented basic blocks at start, including their locations. + +Note: You must compile AFL with the `CODE_COVERAGE=1` option to enable the +respective parts in the AFL compiler runtime. Support is currently only +implemented for Nyx, but can in theory also work without Nyx. + +Note: You might have to adjust `MAP_SIZE_POW2` in include/config.h to ensure +that your coverage map is large enough to hold all basic blocks of your +target program without any collisions. + +More documentation on how to utilize this with Nyx will follow. diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 0912e52b..3f8b519b 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -14,6 +14,16 @@ */ +#ifdef __AFL_CODE_COVERAGE + #ifndef _GNU_SOURCE + #define _GNU_SOURCE + #endif + #ifndef __USE_GNU + #define __USE_GNU + #endif + #include +#endif + #ifdef __ANDROID__ #include "android-ashmem.h" #endif @@ -105,6 +115,44 @@ u32 __afl_dictionary_len; u64 __afl_map_addr; u32 __afl_first_final_loc; +#ifdef __AFL_CODE_COVERAGE +typedef struct afl_module_info_t afl_module_info_t; + +struct afl_module_info_t { + + // A unique id starting with 0 + u32 id; + + // Name and base address of the module + char *name; + uintptr_t base_address; + + // PC Guard start/stop + u32 start; + u32 stop; + + // PC Table begin/end + const uintptr_t *pcs_beg; + const uintptr_t *pcs_end; + + u8 mapped; + + afl_module_info_t *next; + +}; + +typedef struct { + + uintptr_t PC, PCFlags; + +} PCTableEntry; + +afl_module_info_t *__afl_module_info = NULL; + +u32 __afl_pcmap_size = 0; +uintptr_t *__afl_pcmap_ptr = NULL; +#endif // __AFL_CODE_COVERAGE + /* 1 if we are running in afl, and the forkserver was started, else 0 */ u32 __afl_connected = 0; @@ -496,11 +544,12 @@ static void __afl_map_shm(void) { if (__afl_map_size && __afl_map_size > MAP_SIZE) { - u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE"); - if (!map_env || atoi((char *)map_env) < MAP_SIZE) { + u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE"); + if (!map_env || atoi((char *)map_env) < MAP_SIZE) { - send_forkserver_error(FS_ERROR_MAP_SIZE); - _exit(1); + fprintf(stderr, "FS_ERROR_MAP_SIZE\n"); + send_forkserver_error(FS_ERROR_MAP_SIZE); + _exit(1); } @@ -512,13 +561,13 @@ static void __afl_map_shm(void) { if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) { - if (__afl_map_addr) + if (__afl_map_addr) send_forkserver_error(FS_ERROR_MAP_ADDR); else send_forkserver_error(FS_ERROR_SHMAT); perror("shmat for map"); - _exit(1); + _exit(1); } @@ -678,6 +727,27 @@ static void __afl_map_shm(void) { } +#ifdef __AFL_CODE_COVERAGE + char *pcmap_id_str = getenv("__AFL_PCMAP_SHM_ID"); + + if (pcmap_id_str) { + + __afl_pcmap_size = __afl_map_size * sizeof(void *); + u32 shm_id = atoi(pcmap_id_str); + + __afl_pcmap_ptr = (uintptr_t *)shmat(shm_id, NULL, 0); + + if (__afl_debug) { + + fprintf(stderr, "DEBUG: Received %p via shmat for pcmap\n", + __afl_pcmap_ptr); + + } + + } + +#endif // __AFL_CODE_COVERAGE + } /* unmap SHM. */ @@ -686,6 +756,17 @@ static void __afl_unmap_shm(void) { if (!__afl_already_initialized_shm) return; +#ifdef __AFL_CODE_COVERAGE + if (__afl_pcmap_size) { + + shmdt((void *)__afl_pcmap_ptr); + __afl_pcmap_ptr = NULL; + __afl_pcmap_size = 0; + + } + +#endif // __AFL_CODE_COVERAGE + char *id_str = getenv(SHM_ENV_VAR); if (id_str) { @@ -1507,6 +1588,102 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { } +#ifdef __AFL_CODE_COVERAGE +void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, + const uintptr_t *pcs_end) { + + if (__afl_debug) { + + fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init called\n"); + + } + + // If for whatever reason, we cannot get dlinfo here, then pc_guard_init also + // couldn't get it and we'd end up attributing to the wrong module. + Dl_info dlinfo; + if (!dladdr(__builtin_return_address(0), &dlinfo)) { + + fprintf(stderr, + "WARNING: Ignoring __sanitizer_cov_pcs_init callback due to " + "missing module info\n"); + return; + + } + + afl_module_info_t *last_module_info = __afl_module_info; + while (last_module_info && last_module_info->next) { + + last_module_info = last_module_info->next; + + } + + if (!last_module_info) { + + fprintf(stderr, + "ERROR: __sanitizer_cov_pcs_init called with no module info?!\n"); + abort(); + + } + + last_module_info->pcs_beg = pcs_beg; + last_module_info->pcs_end = pcs_end; + + // Now update the pcmap. If this is the last module coming in, after all + // pre-loaded code, then this will also map all of our delayed previous + // modules. + + if (!__afl_pcmap_ptr) { return; } + + for (afl_module_info_t *mod_info = __afl_module_info; mod_info; + mod_info = mod_info->next) { + + if (mod_info->mapped) { continue; } + + PCTableEntry *start = (PCTableEntry *)(mod_info->pcs_beg); + PCTableEntry *end = (PCTableEntry *)(mod_info->pcs_end); + + u32 in_module_index = 0; + + while (start < end) { + + if (mod_info->start + in_module_index >= __afl_map_size) { + + fprintf(stderr, "ERROR: __sanitizer_cov_pcs_init out of bounds?!\n"); + abort(); + + } + + uintptr_t PC = start->PC; + + // This is what `GetPreviousInstructionPc` in sanitizer runtime does + // for x86/x86-64. Needs more work for ARM and other archs. + PC = PC - 1; + + // Calculate relative offset in module + PC = PC - mod_info->base_address; + + __afl_pcmap_ptr[mod_info->start + in_module_index] = PC; + + start++; + in_module_index++; + + } + + mod_info->mapped = 1; + + if (__afl_debug) { + + fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init initialized %u PCs\n", + in_module_index); + + } + + } + +} + +#endif // __AFL_CODE_COVERAGE + /* Init callback. Populates instrumentation IDs. Note that we're using ID of 0 as a special value to indicate non-instrumented bits. That may still touch the bitmap, but in a fairly harmless way. */ @@ -1538,6 +1715,62 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (start == stop || *start) { return; } +#ifdef __AFL_CODE_COVERAGE + u32 *orig_start = start; + afl_module_info_t *mod_info = NULL; + + Dl_info dlinfo; + if (dladdr(__builtin_return_address(0), &dlinfo)) { + + if (__afl_already_initialized_forkserver) { + + fprintf(stderr, "[pcmap] Error: Module was not preloaded: %s\n", + dlinfo.dli_fname); + + } else { + + afl_module_info_t *last_module_info = __afl_module_info; + while (last_module_info && last_module_info->next) { + + last_module_info = last_module_info->next; + + } + + mod_info = malloc(sizeof(afl_module_info_t)); + + mod_info->id = last_module_info ? last_module_info->id + 1 : 0; + mod_info->name = strdup(dlinfo.dli_fname); + mod_info->base_address = (uintptr_t)dlinfo.dli_fbase; + mod_info->start = 0; + mod_info->stop = 0; + mod_info->pcs_beg = NULL; + mod_info->pcs_end = NULL; + mod_info->mapped = 0; + mod_info->next = NULL; + + if (last_module_info) { + + last_module_info->next = mod_info; + + } else { + + __afl_module_info = mod_info; + + } + + fprintf(stderr, "[pcmap] Module: %s Base Address: %p\n", dlinfo.dli_fname, + dlinfo.dli_fbase); + + } + + } else { + + fprintf(stderr, "[pcmap] dladdr call failed\n"); + + } + +#endif // __AFL_CODE_COVERAGE + x = getenv("AFL_INST_RATIO"); if (x) { @@ -1625,6 +1858,22 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } +#ifdef __AFL_CODE_COVERAGE + if (mod_info) { + + mod_info->start = *orig_start; + mod_info->stop = *(stop - 1); + if (__afl_debug) { + + fprintf(stderr, "DEBUG: [pcmap] Start Index: %u Stop Index: %u\n", + mod_info->start, mod_info->stop); + + } + + } + +#endif // __AFL_CODE_COVERAGE + if (__afl_debug) { fprintf(stderr, diff --git a/src/afl-cc.c b/src/afl-cc.c index 99ce39d4..b11a041d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -76,6 +76,7 @@ enum { INSTRUMENT_OPT_NGRAM = 16, INSTRUMENT_OPT_CALLER = 32, INSTRUMENT_OPT_CTX_K = 64, + INSTRUMENT_OPT_CODECOV = 128, }; @@ -751,7 +752,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { #if LLVM_MAJOR >= 4 - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + #if LLVM_MAJOR >= 6 + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; + #else + FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+"); + #endif + } else { + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + } #else FATAL("pcguard instrumentation requires llvm 4.0.1+"); #endif @@ -1682,6 +1691,18 @@ int main(int argc, char **argv, char **envp) { } + if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || + strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { + + if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + instrument_mode = INSTRUMENT_LLVMNATIVE; + instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + } else + FATAL("main instrumentation mode already set with %s", + instrument_mode_string[instrument_mode]); + + } + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { @@ -2241,7 +2262,8 @@ int main(int argc, char **argv, char **envp) { "(requires LLVM 11 or higher)"); #endif - if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC) + if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV && + instrument_mode != INSTRUMENT_CLASSIC) FATAL( "CALLER, CTX and NGRAM instrumentation options can only be used with " "the LLVM CLASSIC instrumentation mode."); -- cgit 1.4.1 From 5813a4319c88848b2a1c47c12fe27f5e14dcad44 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 28 Apr 2023 11:42:21 +0200 Subject: doc, code format --- GNUmakefile | 3 ++- docs/INSTALL.md | 10 ++++------ instrumentation/afl-compiler-rt.o.c | 14 +++++++------- src/afl-cc.c | 31 +++++++++++++++++++++++-------- 4 files changed, 36 insertions(+), 22 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile b/GNUmakefile index 5900ad61..56b8bb42 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -379,6 +379,7 @@ help: @echo Known build environment options: @echo "==========================================" @echo STATIC - compile AFL++ static + @echo CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md) @echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes @echo UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes @echo DEBUG - no optimization, -ggdb3, all warnings and -Werror @@ -394,7 +395,7 @@ help: @echo AFL_NO_X86 - if compiling on non-intel/amd platforms @echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)" @echo "==========================================" - @echo e.g.: make ASAN_BUILD=1 + @echo e.g.: make LLVM_CONFIG=llvm-config-16 .PHONY: test_x86 ifndef AFL_NO_X86 diff --git a/docs/INSTALL.md b/docs/INSTALL.md index c54cb9ad..637e8658 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -79,22 +79,20 @@ make STATIC=1 These build options exist: * STATIC - compile AFL++ static +* CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md) * ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes -* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for - debug purposes +* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes * DEBUG - no optimization, -ggdb3, all warnings and -Werror * LLVM_DEBUG - shows llvm deprecation warnings * PROFILING - compile afl-fuzz with profiling information * INTROSPECTION - compile afl-fuzz with mutation introspection * NO_PYTHON - disable python support -* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for - normal fuzzing +* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing * NO_NYX - disable building nyx mode dependencies * NO_CORESIGHT - disable building coresight (arm64 only) * NO_UNICORN_ARM64 - disable building unicorn on arm64 * AFL_NO_X86 - if compiling on non-intel/amd platforms -* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config - (e.g., Debian) +* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian) e.g.: `make LLVM_CONFIG=llvm-config-14` diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 3f8b519b..5372fae0 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -544,12 +544,12 @@ static void __afl_map_shm(void) { if (__afl_map_size && __afl_map_size > MAP_SIZE) { - u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE"); - if (!map_env || atoi((char *)map_env) < MAP_SIZE) { + u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE"); + if (!map_env || atoi((char *)map_env) < MAP_SIZE) { - fprintf(stderr, "FS_ERROR_MAP_SIZE\n"); - send_forkserver_error(FS_ERROR_MAP_SIZE); - _exit(1); + fprintf(stderr, "FS_ERROR_MAP_SIZE\n"); + send_forkserver_error(FS_ERROR_MAP_SIZE); + _exit(1); } @@ -561,13 +561,13 @@ static void __afl_map_shm(void) { if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) { - if (__afl_map_addr) + if (__afl_map_addr) send_forkserver_error(FS_ERROR_MAP_ADDR); else send_forkserver_error(FS_ERROR_SHMAT); perror("shmat for map"); - _exit(1); + _exit(1); } diff --git a/src/afl-cc.c b/src/afl-cc.c index b11a041d..19314555 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -752,15 +752,21 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { #if LLVM_MAJOR >= 4 - if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + #if LLVM_MAJOR >= 6 - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; + cc_params[cc_par_cnt++] = + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; #else FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+"); #endif - } else { + + } else { + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - } + + } + #else FATAL("pcguard instrumentation requires llvm 4.0.1+"); #endif @@ -1660,13 +1666,17 @@ int main(int argc, char **argv, char **envp) { instrument_mode = INSTRUMENT_CLASSIC; lto_mode = 1; - } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) + } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) { instrument_mode = INSTRUMENT_AFL; - else + + } else { + FATAL("main instrumentation mode already set with %s", instrument_mode_string[instrument_mode]); + } + } if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || @@ -1695,12 +1705,17 @@ int main(int argc, char **argv, char **envp) { strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + instrument_mode = INSTRUMENT_LLVMNATIVE; - instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; - } else + instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + + } else { + FATAL("main instrumentation mode already set with %s", instrument_mode_string[instrument_mode]); + } + } if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || -- cgit 1.4.1 From 93c821aaa3df0cf20f892ce72447ff022161c8ab Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 12 May 2023 08:39:11 +0200 Subject: afl-clang-lto incomptable with -flto=thin --- docs/Changelog.md | 1 + src/afl-cc.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'src/afl-cc.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index e85de763..799c13af 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -13,6 +13,7 @@ - afl-cc: - new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM (https://github.com/fgsect/WAFL) project + - error and print help if afl-clan-lto is used with lto=thin - afl-showmap: - added custom mutator post_process and send support - add `-I filelist` option, an alternative to `-i in_dir` diff --git a/src/afl-cc.c b/src/afl-cc.c index 19314555..13ca751e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -853,6 +853,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (cur[0] != '-') { non_dash = 1; } if (!strncmp(cur, "--afl", 5)) continue; + + if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); + + } + if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; if (!strncmp(cur, "-fno-unroll", 11)) continue; -- cgit 1.4.1 From 7f636dbfc247fbe75910fa8fb681ea55d230ba79 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 12 May 2023 15:58:20 +0200 Subject: add @responsefile support for afl-cc --- docs/Changelog.md | 1 + src/afl-cc.c | 460 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 300 insertions(+), 161 deletions(-) (limited to 'src/afl-cc.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 799c13af..3602af50 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,6 +11,7 @@ - new env `AFL_IGNORE_PROBLEMS_COVERAGE` to ignore coverage from loaded libs after forkserver initialization (required by Mozilla) - afl-cc: + - added @responsefile support - new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM (https://github.com/fgsect/WAFL) project - error and print help if afl-clan-lto is used with lto=thin diff --git a/src/afl-cc.c b/src/afl-cc.c index 13ca751e..972ac8cd 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #if (LLVM_MAJOR - 0 == 0) #undef LLVM_MAJOR @@ -376,15 +378,304 @@ void parse_fsanitize(char *string) { } +static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, + shared_linking = 0, preprocessor_only = 0, have_unroll = 0, + have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, + non_dash = 0; + +static void process_params(u32 argc, char **argv) { + + if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); } + + if (lto_mode && argc > 1) { + + u32 idx; + for (idx = 1; idx < argc; idx++) { + + if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; + + } + + } + + // 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) { + + skip_next = 0; + continue; + + } + + if (cur[0] != '-') { non_dash = 1; } + if (!strncmp(cur, "--afl", 5)) continue; + + if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); + + } + + if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; + if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; + if (!strncmp(cur, "-fno-unroll", 11)) continue; + if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; + if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || + !strcmp(cur, "--no-undefined")) { + + continue; + + } + + if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } + + if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { + + u8 *param = *(argv + 1); + if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { + + skip_next = 1; + continue; + + } + + } + + if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && + !strncmp(cur, "-stdlib=", 8)) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } + continue; + + } + + if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { + + have_instr_list = 1; + + } + + if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && + strchr(cur, ',')) { + + parse_fsanitize(cur); + if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } + + } else if ((!strncmp(cur, "-fsanitize=fuzzer-", + + strlen("-fsanitize=fuzzer-")) || + !strncmp(cur, "-fsanitize-coverage", + strlen("-fsanitize-coverage"))) && + (strncmp(cur, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + instrument_mode != INSTRUMENT_LLVMNATIVE)) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } + continue; + + } + + if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { + + u8 *afllib = find_object("libAFLDriver.a", argv[0]); + + if (!be_quiet) { + + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + + } + + if (!afllib) { + + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); + + } + + } else { + + cc_params[cc_par_cnt++] = afllib; + +#ifdef __APPLE__ + cc_params[cc_par_cnt++] = "-undefined"; + cc_params[cc_par_cnt++] = "dynamic_lookup"; +#endif + + } + + if (need_aflpplib) { + + need_aflpplib = 0; + + } else { + + continue; + + } + + } + + if (!strcmp(cur, "-m32")) bit_mode = 32; + if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; + if (!strcmp(cur, "-m64")) bit_mode = 64; + + if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) + asan_set = 1; + + if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + + if (!strcmp(cur, "-x")) x_set = 1; + if (!strcmp(cur, "-E")) preprocessor_only = 1; + if (!strcmp(cur, "-shared")) shared_linking = 1; + if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; + if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; + if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; + if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; + if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; + if (!strcmp(cur, "-r")) partial_linking = 1; + if (!strcmp(cur, "--relocatable")) partial_linking = 1; + if (!strcmp(cur, "-c")) have_c = 1; + + if (!strncmp(cur, "-O", 2)) have_o = 1; + if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; + + if (*cur == '@') { + + // response file support. + // 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. + // We do *not* support quotes in the rsp files to cope with spaces in + // filenames etc! If you need that then send a patch! + u8 *filename = cur + 1; + if (debug) { DEBUGF("response file=%s\n", filename); } + FILE *f = fopen(filename, "r"); + struct stat st; + + // Check not found or empty? let the compiler complain if so. + if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + + cc_params[cc_par_cnt++] = cur; + continue; + + } + + u8 *tmpbuf = malloc(st.st_size + 1), *ptr; + char **args = malloc(sizeof(char *) * (st.st_size >> 1)); + int count = 1, cont = 0, cont_act = 0; + + while (fgets(tmpbuf, st.st_size, f)) { + + ptr = tmpbuf; + // no leading whitespace + while (isspace(*ptr)) { + + ++ptr; + cont_act = 0; + + } + + // no comments, no empty lines + if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } + // remove LF + if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } + // remove CR + if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } + // handle \ at end of line + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + + cont = 1; + ptr[strlen(ptr) - 1] = 0; + + } + + // remove whitespace at end + while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + + ptr[strlen(ptr) - 1] = 0; + cont = 0; + + } + + if (*ptr) { + + do { + + u8 *value = ptr; + while (*ptr && !isspace(*ptr)) { + + ++ptr; + + } + + while (*ptr && isspace(*ptr)) { + + *ptr++ = 0; + + } + + if (cont_act) { + + u32 len = strlen(args[count - 1]) + strlen(value) + 1; + u8 *tmp = malloc(len); + snprintf(tmp, len, "%s%s", args[count - 1], value); + free(args[count - 1]); + args[count - 1] = tmp; + cont_act = 0; + + } else { + + args[count++] = strdup(value); + + } + + } while (*ptr); + + } + + if (cont) { + + cont_act = 1; + cont = 0; + + } + + } + + if (count) { process_params(count, args); } + + // we cannot free args[] + free(tmpbuf); + + continue; + + } + + cc_params[cc_par_cnt++] = cur; + + } + +} + /* Copy argv to cc_params, making the necessary edits. */ static void edit_params(u32 argc, char **argv, char **envp) { - u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0, - preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0, - have_c = 0, partial_linking = 0; - - cc_params = ck_alloc((argc + 128) * sizeof(u8 *)); + cc_params = ck_alloc(1024 * sizeof(u8 *)); if (lto_mode) { @@ -831,168 +1122,15 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC"; - } } - /* Detect stray -v calls from ./configure scripts. */ - - u8 skip_next = 0, non_dash = 0; - while (--argc) { - - u8 *cur = *(++argv); - - if (skip_next) { - - skip_next = 0; - continue; - - } - - if (cur[0] != '-') { non_dash = 1; } - if (!strncmp(cur, "--afl", 5)) continue; - - if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { - - FATAL( - "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " - "use afl-clang-fast!"); - - } - - if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; - if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - if (!strncmp(cur, "-fno-unroll", 11)) continue; - if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; - if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || - !strcmp(cur, "--no-undefined")) { - - continue; - - } + /* Inspect the command line parameters. */ - if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } - - if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { + process_params(argc, argv); - u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { - - skip_next = 1; - continue; - - } - - } - - if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && - !strncmp(cur, "-stdlib=", 8)) { - - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; - - } - - if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { - - have_instr_list = 1; - - } - - if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && - strchr(cur, ',')) { - - parse_fsanitize(cur); - if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } - - } else if ((!strncmp(cur, "-fsanitize=fuzzer-", - - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - instrument_mode != INSTRUMENT_LLVMNATIVE)) { - - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; - - } - - if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { - - u8 *afllib = find_object("libAFLDriver.a", argv[0]); - - if (!be_quiet) { - - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); - - } - - if (!afllib) { - - if (!be_quiet) { - - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); - - } - - } else { - - cc_params[cc_par_cnt++] = afllib; - -#ifdef __APPLE__ - cc_params[cc_par_cnt++] = "-undefined"; - cc_params[cc_par_cnt++] = "dynamic_lookup"; -#endif - - } - - if (need_aflpplib) { - - need_aflpplib = 0; - - } else { - - continue; - - } - - } - - if (!strcmp(cur, "-m32")) bit_mode = 32; - if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; - if (!strcmp(cur, "-m64")) bit_mode = 64; - - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) - asan_set = 1; - - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; - - if (!strcmp(cur, "-x")) x_set = 1; - if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; - if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; - if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; - if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; - if (!strcmp(cur, "--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-c")) have_c = 1; - - if (!strncmp(cur, "-O", 2)) have_o = 1; - if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; - - cc_params[cc_par_cnt++] = cur; - - } + if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory -- cgit 1.4.1 From 029e039cbcbf9e30f35eb255162679b8d609d25d Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 21 May 2023 17:49:14 +0200 Subject: code format --- .custom-format.py | 2 +- frida_mode/src/lib/lib_apple.c | 4 +-- include/config.h | 2 +- instrumentation/SanitizerCoverageLTO.so.cc | 4 +-- instrumentation/SanitizerCoveragePCGUARD.so.cc | 4 +-- instrumentation/afl-compiler-rt.o.c | 14 +++++----- instrumentation/afl-llvm-lto-instrumentlist.so.cc | 2 +- instrumentation/cmplog-routines-pass.cc | 4 +-- instrumentation/compare-transform-pass.so.cc | 2 +- instrumentation/split-compares-pass.so.cc | 2 +- qemu_mode/libcompcov/libcompcov.so.c | 6 ++++- src/afl-cc.c | 8 +++--- src/afl-fuzz-redqueen.c | 32 +++++++++++------------ utils/afl_untracer/afl-untracer.c | 2 +- utils/libtokencap/libtokencap.so.c | 6 ++++- utils/socket_fuzzing/socketfuzz.c | 3 ++- 16 files changed, 53 insertions(+), 44 deletions(-) (limited to 'src/afl-cc.c') diff --git a/.custom-format.py b/.custom-format.py index 1295ce55..1d5c8839 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -24,7 +24,7 @@ import importlib.metadata # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use -CURRENT_LLVM = os.getenv('LLVM_VERSION', 14) +CURRENT_LLVM = os.getenv('LLVM_VERSION', 15) CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c index 634e0e30..d29d0303 100644 --- a/frida_mode/src/lib/lib_apple.c +++ b/frida_mode/src/lib/lib_apple.c @@ -17,8 +17,8 @@ static gboolean lib_get_main_module(const GumModuleDetails *details, GumDarwinModule **ret = (GumDarwinModule **)user_data; GumDarwinModule *module = gum_darwin_module_new_from_memory( - details->path, mach_task_self(), details->range->base_address, - GUM_DARWIN_MODULE_FLAGS_NONE, NULL); + details->path, mach_task_self(), details->range->base_address, + GUM_DARWIN_MODULE_FLAGS_NONE, NULL); FVERBOSE("Found main module: %s", module->name); diff --git a/include/config.h b/include/config.h index 764c29dc..194786f7 100644 --- a/include/config.h +++ b/include/config.h @@ -81,7 +81,7 @@ will be kept and written to the crash/ directory as RECORD:... files. Note that every crash will be written, not only unique ones! */ -//#define AFL_PERSISTENT_RECORD +// #define AFL_PERSISTENT_RECORD /* console output colors: There are three ways to configure its behavior * 1. default: colored outputs fixed on: defined USE_COLOR && defined diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index b3b0d2cd..d7b03634 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1478,8 +1478,8 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreateFunctionLocalArrayInSection( ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); auto Array = new GlobalVariable( - *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(ArrayTy), "__sancov_gen_"); + *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(ArrayTy), "__sancov_gen_"); #if LLVM_VERSION_MAJOR >= 13 if (TargetTriple.supportsCOMDAT() && diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 41c38283..8fed2042 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -714,8 +714,8 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection( ArrayType *ArrayTy = ArrayType::get(Ty, NumElements); auto Array = new GlobalVariable( - *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, - Constant::getNullValue(ArrayTy), "__sancov_gen_"); + *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, + Constant::getNullValue(ArrayTy), "__sancov_gen_"); #if LLVM_VERSION_MAJOR >= 13 if (TargetTriple.supportsCOMDAT() && diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 5372fae0..3f8b519b 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -544,12 +544,12 @@ static void __afl_map_shm(void) { if (__afl_map_size && __afl_map_size > MAP_SIZE) { - u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE"); - if (!map_env || atoi((char *)map_env) < MAP_SIZE) { + u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE"); + if (!map_env || atoi((char *)map_env) < MAP_SIZE) { - fprintf(stderr, "FS_ERROR_MAP_SIZE\n"); - send_forkserver_error(FS_ERROR_MAP_SIZE); - _exit(1); + fprintf(stderr, "FS_ERROR_MAP_SIZE\n"); + send_forkserver_error(FS_ERROR_MAP_SIZE); + _exit(1); } @@ -561,13 +561,13 @@ static void __afl_map_shm(void) { if (!__afl_area_ptr || __afl_area_ptr == (void *)-1) { - if (__afl_map_addr) + if (__afl_map_addr) send_forkserver_error(FS_ERROR_MAP_ADDR); else send_forkserver_error(FS_ERROR_SHMAT); perror("shmat for map"); - _exit(1); + _exit(1); } diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index db5bd55e..61f97d77 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -45,7 +45,7 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" -//#include "llvm/Transforms/IPO/PassManagerBuilder.h" +// #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/IR/PassManager.h" diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 39db5aa4..c3fbed8d 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -542,7 +542,7 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v3Pbitcast = IRB.CreateBitCast( - v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits())); + v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits())); Value *v3Pcasted = IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false); args.push_back(v1Pcasted); @@ -608,7 +608,7 @@ bool CmpLogRoutines::hookRtns(Module &M) { Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy); Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy); Value *v3Pbitcast = IRB.CreateBitCast( - v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits())); + v3P, IntegerType::get(C, v3P->getType()->getPrimitiveSizeInBits())); Value *v3Pcasted = IRB.CreateIntCast(v3Pbitcast, IntegerType::get(C, 64), false); args.push_back(v1Pcasted); diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index efc99d20..5dd705cf 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -623,7 +623,7 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, IRBuilder<> cur_lenchk_IRB(&*(cur_lenchk_bb->getFirstInsertionPt())); Value *icmp = cur_lenchk_IRB.CreateICmpEQ( - sizedValue, ConstantInt::get(sizedValue->getType(), i)); + sizedValue, ConstantInt::get(sizedValue->getType(), i)); cur_lenchk_IRB.CreateCondBr(icmp, end_bb, cur_cmp_bb); cur_lenchk_bb->getTerminator()->eraseFromParent(); diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 8a07610c..aec6758e 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -60,7 +60,7 @@ using namespace llvm; // uncomment this toggle function verification at each step. horribly slow, but // helps to pinpoint a potential problem in the splitting code. -//#define VERIFY_TOO_MUCH 1 +// #define VERIFY_TOO_MUCH 1 namespace { diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index b6ee0019..b57e9701 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -68,7 +68,11 @@ static int debug_fd = -1; #define MAX_MAPPINGS 1024 -static struct mapping { void *st, *en; } __compcov_ro[MAX_MAPPINGS]; +static struct mapping { + + void *st, *en; + +} __compcov_ro[MAX_MAPPINGS]; static u32 __compcov_ro_cnt; diff --git a/src/afl-cc.c b/src/afl-cc.c index 972ac8cd..e3cc04dd 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -933,10 +933,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - //#if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the AFL++ passes still - // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; - //#endif + // #if LLVM_MAJOR >= 13 + // // Use the old pass manager in LLVM 14 which the AFL++ passes still + // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; + // #endif if (lto_mode && !have_c) { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 6e4a655b..d9dc50df 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -28,8 +28,8 @@ #include "afl-fuzz.h" #include "cmplog.h" -//#define _DEBUG -//#define CMPLOG_INTROSPECTION +// #define _DEBUG +// #define CMPLOG_INTROSPECTION // CMP attribute enum enum { @@ -571,7 +571,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } -//#ifdef CMPLOG_SOLVE_TRANSFORM +// #ifdef CMPLOG_SOLVE_TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -771,7 +771,7 @@ static void to_base64(u8 *src, u8 *dst, u32 dst_len) { #endif -//#endif +// #endif static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, @@ -803,8 +803,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // o_pattern, pattern, repl, changed_val, idx, taint_len, // hshape, attr); - //#ifdef CMPLOG_SOLVE_TRANSFORM - // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 + // #ifdef CMPLOG_SOLVE_TRANSFORM + // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (afl->cmplog_enable_transform && (lvl & LVL3)) { u8 *endptr; @@ -1120,7 +1120,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - //#endif + // #endif // we only allow this for ascii2integer (above) so leave if this is the case if (unlikely(pattern == o_pattern)) { return 0; } @@ -1275,7 +1275,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // 16 = modified float, 32 = modified integer (modified = wont match // in original buffer) - //#ifdef CMPLOG_SOLVE_ARITHMETIC + // #ifdef CMPLOG_SOLVE_ARITHMETIC if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) { return 0; @@ -1440,8 +1440,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } - //#endif /* - // CMPLOG_SOLVE_ARITHMETIC + // #endif /* + // CMPLOG_SOLVE_ARITHMETIC return 0; @@ -1948,9 +1948,9 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, #ifndef CMPLOG_COMBINE (void)(cbuf); #endif - //#ifndef CMPLOG_SOLVE_TRANSFORM - // (void)(changed_val); - //#endif + // #ifndef CMPLOG_SOLVE_TRANSFORM + // (void)(changed_val); + // #endif if (afl->fsrv.total_execs - last_update > screen_update) { @@ -2418,7 +2418,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry, } - //#endif + // #endif return 0; @@ -2818,9 +2818,9 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } else if ((lvl & LVL1) - //#ifdef CMPLOG_SOLVE_TRANSFORM + // #ifdef CMPLOG_SOLVE_TRANSFORM || ((lvl & LVL3) && afl->cmplog_enable_transform) - //#endif + // #endif ) { if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index a18e314e..e1038212 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -288,7 +288,7 @@ library_list_t *find_library(char *name) { #pragma GCC optimize("O0") void breakpoint(void) { - if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n"); + if (debug) fprintf(stderr, "Breakpoint function \"breakpoint\" reached.\n"); } diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index 299056ab..b21f3068 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -81,7 +81,11 @@ void *(*__libc_memmem)(const void *haystack, size_t haystack_len, #define MAX_MAPPINGS 1024 -static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS]; +static struct mapping { + + void *st, *en; + +} __tokencap_ro[MAX_MAPPINGS]; static u32 __tokencap_ro_cnt; static u8 __tokencap_ro_loaded; diff --git a/utils/socket_fuzzing/socketfuzz.c b/utils/socket_fuzzing/socketfuzz.c index 3ec8383b..7497519e 100644 --- a/utils/socket_fuzzing/socketfuzz.c +++ b/utils/socket_fuzzing/socketfuzz.c @@ -23,7 +23,8 @@ #include #include #include -//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: " +// #include "logging.h" // switched from preeny_info() to fprintf(stderr, "Info: +// " // // originals -- cgit 1.4.1 From dd736126dc9da78d6828cdf76f7eb8b389af7ed3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 09:06:29 +0200 Subject: allow llvm_instrument native --- src/afl-cc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index e3cc04dd..64c0ce66 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1838,7 +1838,8 @@ int main(int argc, char **argv, char **envp) { } if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0) { + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || + strncasecmp(ptr2, "native", strlen("native")) == 0) { if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) instrument_mode = INSTRUMENT_LLVMNATIVE; -- cgit 1.4.1 From 22837b5ad2d1cc6313c706ac9cb7fcd005cd3c2c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 23 May 2023 12:14:58 +0200 Subject: response file fix --- src/afl-cc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 64c0ce66..84fe70ec 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -574,14 +574,15 @@ static void process_params(u32 argc, char **argv) { } - u8 *tmpbuf = malloc(st.st_size + 1), *ptr; + u8 *tmpbuf = malloc(st.st_size + 2), *ptr; char **args = malloc(sizeof(char *) * (st.st_size >> 1)); int count = 1, cont = 0, cont_act = 0; - while (fgets(tmpbuf, st.st_size, f)) { + while (fgets(tmpbuf, st.st_size + 1, f)) { ptr = tmpbuf; - // no leading whitespace + // fprintf(stderr, "1: %s\n", ptr); + // no leading whitespace while (isspace(*ptr)) { ++ptr; @@ -603,6 +604,8 @@ static void process_params(u32 argc, char **argv) { } + // fprintf(stderr, "2: %s\n", ptr); + // remove whitespace at end while (*ptr && isspace(ptr[strlen(ptr) - 1])) { @@ -611,6 +614,7 @@ static void process_params(u32 argc, char **argv) { } + // fprintf(stderr, "3: %s\n", ptr); if (*ptr) { do { -- cgit 1.4.1 From 9324f3f6289c62451e2add1f7553a7eda0d7d642 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Jun 2023 12:19:45 +0200 Subject: rewrote PCGUARD --- GNUmakefile.llvm | 4 +- TODO.md | 2 - afl-cmin.bash | 4 +- docs/Changelog.md | 5 +- instrumentation/SanitizerCoveragePCGUARD.so.cc | 603 +++++++++---------------- src/afl-cc.c | 31 +- 6 files changed, 249 insertions(+), 400 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 2bb4e7f8..6c68f1f3 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -49,7 +49,7 @@ LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[ LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[5-9]' && echo 1 || echo 0 ) LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 ) -LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 ) +LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 ) LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]' && echo 1 || echo 0 ) LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) @@ -422,7 +422,7 @@ endif $(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o ./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps -ifeq "$(LLVM_10_OK)" "1" +ifeq "$(LLVM_13_OK)" "1" -$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o endif diff --git a/TODO.md b/TODO.md index dc02a914..2b7e8fcf 100644 --- a/TODO.md +++ b/TODO.md @@ -2,9 +2,7 @@ ## Should - - redo PCGUARD + LTO for llvm 15+ - test cmplog for less than 16bit - - splicing selection weighted? - support persistent and deferred fork server in afl-showmap? - better autodetection of shifting runtime timeout values - Update afl->pending_not_fuzzed for MOpt diff --git a/afl-cmin.bash b/afl-cmin.bash index d390ff65..dc6d5342 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -206,7 +206,7 @@ fi # Check for obvious errors. -if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" -a ! "$NYX_MODE" == 1 ]; then +if [ ! "$T_ARG" = "" -a -n "$F_ARG" -a ! "$NYX_MODE" == 1 ]; then echo "[-] Error: -T and -f can not be used together." 1>&2 exit 1 fi @@ -323,7 +323,7 @@ if [ ! "$T_ARG" = "" ]; then fi fi else - if [ "$F_ARG" = ""]; then + if [ -z "$F_ARG" ]; then echo "[*] Are you aware of the '-T all' parallelize option that massively improves the speed?" fi fi diff --git a/docs/Changelog.md b/docs/Changelog.md index e99747f6..facf2196 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,13 +15,16 @@ - new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM (https://github.com/fgsect/WAFL) project - error and print help if afl-clan-lto is used with lto=thin + - rewrote our PCGUARD pass to be compatible with LLVM 15+ shenanigans, + requires LLVM 13+ now instead of 10.0.1+ + - fallback to native LLVM PCGUARD if our PCGUARD is unavailable - afl-showmap: - added custom mutator post_process and send support - add `-I filelist` option, an alternative to `-i in_dir` - afl-cmin + afl-cmin.bash: - `-T threads` parallel task support, can be a huge speedup! - qemu_mode: - - Persistent mode +QASAN support for ppc32 tragets by @worksbutnottested + - Persistent mode + QASAN support for ppc32 targets by @worksbutnottested - a new grammar custom mutator atnwalk was submitted by @voidptr127 ! - two new custom mutators are now available: - TritonDSE in custom_mutators/aflpp_tritondse diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 8fed2042..2abc58ec 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -13,42 +13,64 @@ #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#if LLVM_VERSION_MAJOR >= 15 + #if LLVM_VERSION_MAJOR < 17 + #include "llvm/ADT/Triple.h" + #endif +#endif #if LLVM_VERSION_MAJOR < 17 - #include "llvm/ADT/Triple.h" #include "llvm/Analysis/EHPersonalities.h" -#else - #include "llvm/IR/EHPersonalities.h" #endif #include "llvm/Analysis/PostDominators.h" -#include "llvm/IR/CFG.h" +#if LLVM_VERSION_MAJOR < 15 + #include "llvm/IR/CFG.h" +#endif #include "llvm/IR/Constant.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugInfo.h" +#if LLVM_VERSION_MAJOR < 15 + #include "llvm/IR/DebugInfo.h" +#endif #include "llvm/IR/Dominators.h" +#if LLVM_VERSION_MAJOR >= 17 + #include "llvm/Analysis/EHPersonalities.h" +#endif #include "llvm/IR/Function.h" -#include "llvm/IR/GlobalVariable.h" +#if LLVM_VERSION_MAJOR >= 16 + #include "llvm/IR/GlobalVariable.h" +#endif #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InlineAsm.h" +#if LLVM_VERSION_MAJOR < 15 + #include "llvm/IR/InlineAsm.h" +#endif #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Mangler.h" +#if LLVM_VERSION_MAJOR < 15 + #include "llvm/IR/MDBuilder.h" + #include "llvm/IR/Mangler.h" +#endif #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" #include "llvm/IR/Type.h" -#include "llvm/InitializePasses.h" +#if LLVM_VERSION_MAJOR < 17 + #include "llvm/InitializePasses.h" +#endif #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/VirtualFileSystem.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Instrumentation.h" +#if LLVM_VERSION_MAJOR < 15 + #include "llvm/Support/raw_ostream.h" +#endif +#if LLVM_VERSION_MAJOR < 17 + #include "llvm/Transforms/Instrumentation.h" +#else + #include "llvm/TargetParser/Triple.h" +#endif #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h" -#include "llvm/Passes/PassPlugin.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/IR/PassManager.h" #include "config.h" #include "debug.h" @@ -58,7 +80,8 @@ using namespace llvm; #define DEBUG_TYPE "sancov" -const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir"; +static const uint64_t SanCtorAndDtorPriority = 2; + const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc"; const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1"; const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2"; @@ -68,22 +91,13 @@ const char SanCovTraceConstCmp1[] = "__sanitizer_cov_trace_const_cmp1"; const char SanCovTraceConstCmp2[] = "__sanitizer_cov_trace_const_cmp2"; const char SanCovTraceConstCmp4[] = "__sanitizer_cov_trace_const_cmp4"; const char SanCovTraceConstCmp8[] = "__sanitizer_cov_trace_const_cmp8"; -const char SanCovTraceDiv4[] = "__sanitizer_cov_trace_div4"; -const char SanCovTraceDiv8[] = "__sanitizer_cov_trace_div8"; -const char SanCovTraceGep[] = "__sanitizer_cov_trace_gep"; const char SanCovTraceSwitchName[] = "__sanitizer_cov_trace_switch"; + const char SanCovModuleCtorTracePcGuardName[] = "sancov.module_ctor_trace_pc_guard"; -const char SanCovModuleCtor8bitCountersName[] = - "sancov.module_ctor_8bit_counters"; -const char SanCovModuleCtorBoolFlagName[] = "sancov.module_ctor_bool_flag"; -static const uint64_t SanCtorAndDtorPriority = 2; +const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init"; const char SanCovTracePCGuardName[] = "__sanitizer_cov_trace_pc_guard"; -const char SanCovTracePCGuardInitName[] = "__sanitizer_cov_trace_pc_guard_init"; -const char SanCov8bitCountersInitName[] = "__sanitizer_cov_8bit_counters_init"; -const char SanCovBoolFlagInitName[] = "__sanitizer_cov_bool_flag_init"; -const char SanCovPCsInitName[] = "__sanitizer_cov_pcs_init"; const char SanCovGuardsSectionName[] = "sancov_guards"; const char SanCovCountersSectionName[] = "sancov_cntrs"; @@ -99,27 +113,9 @@ namespace { SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { - // Sets CoverageType and IndirectCalls. - // SanitizerCoverageOptions CLOpts = getOptions(ClCoverageLevel); - Options.CoverageType = - SanitizerCoverageOptions::SCK_Edge; // std::max(Options.CoverageType, - // CLOpts.CoverageType); - Options.IndirectCalls = false; // CLOpts.IndirectCalls; - Options.TraceCmp = false; //|= ClCMPTracing; - Options.TraceDiv = false; //|= ClDIVTracing; - Options.TraceGep = false; //|= ClGEPTracing; - Options.TracePC = false; //|= ClTracePC; - Options.TracePCGuard = true; // |= ClTracePCGuard; - Options.Inline8bitCounters = 0; //|= ClInline8bitCounters; - // Options.InlineBoolFlag = 0; //|= ClInlineBoolFlag; - Options.PCTable = false; //|= ClCreatePCTable; - Options.NoPrune = false; //|= !ClPruneBlocks; - Options.StackDepth = false; //|= ClStackDepth; - if (!Options.TracePCGuard && !Options.TracePC && - !Options.Inline8bitCounters && !Options.StackDepth /*&& - !Options.InlineBoolFlag*/) - Options.TracePCGuard = true; // TracePCGuard is default. - + Options.CoverageType = SanitizerCoverageOptions::SCK_Edge; + // Options.NoPrune = true; + Options.TracePCGuard = true; // TracePCGuard is default. return Options; } @@ -139,20 +135,13 @@ class ModuleSanitizerCoverageAFL } PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); - - bool instrumentModule(Module &M, DomTreeCallback DTCallback, - PostDomTreeCallback PDTCallback); + bool instrumentModule(Module &M, DomTreeCallback DTCallback, + PostDomTreeCallback PDTCallback); private: void instrumentFunction(Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback); - void InjectCoverageForIndirectCalls(Function &F, - ArrayRef IndirCalls); void InjectTraceForCmp(Function &F, ArrayRef CmpTraceTargets); - void InjectTraceForDiv(Function &F, - ArrayRef DivTraceTargets); - void InjectTraceForGep(Function &F, - ArrayRef GepTraceTargets); void InjectTraceForSwitch(Function &F, ArrayRef SwitchTraceTargets); bool InjectCoverage(Function &F, ArrayRef AllBlocks, @@ -173,20 +162,23 @@ class ModuleSanitizerCoverageAFL void SetNoSanitizeMetadata(Instruction *I) { +#if LLVM_VERSION_MAJOR == 15 + I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, None)); +#elif LLVM_VERSION_MAJOR >= 16 + I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt)); +#else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), MDNode::get(*C, None)); +#endif } std::string getSectionName(const std::string &Section) const; std::string getSectionStart(const std::string &Section) const; std::string getSectionEnd(const std::string &Section) const; - FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC, SanCovTracePCGuard; FunctionCallee SanCovTraceCmpFunction[4]; FunctionCallee SanCovTraceConstCmpFunction[4]; - FunctionCallee SanCovTraceDivFunction[2]; - FunctionCallee SanCovTraceGepFunction; FunctionCallee SanCovTraceSwitchFunction; GlobalVariable *SanCovLowestStack; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, @@ -215,18 +207,16 @@ class ModuleSanitizerCoverageAFL } // namespace -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo() { - return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.1", + return {LLVM_PLUGIN_API_VERSION, "SanitizerCoveragePCGUARD", "v0.2", /* lambda to insert our pass into the pass pipeline. */ [](PassBuilder &PB) { - #if LLVM_VERSION_MAJOR <= 13 +#if LLVM_VERSION_MAJOR == 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; - #endif +#endif PB.registerOptimizerLastEPCallback( [](ModulePassManager &MPM, OptimizationLevel OL) { @@ -238,8 +228,7 @@ llvmGetPassPluginInfo() { } -#endif - +#if LLVM_VERSION_MAJOR == 1 PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M, ModuleAnalysisManager &MAM) { @@ -257,34 +246,65 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M, }; + if (!ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) + return PreservedAnalyses::all(); + + PreservedAnalyses PA = PreservedAnalyses::none(); + // GlobalsAA is considered stateless and does not get invalidated unless + // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers + // make changes that require GlobalsAA to be invalidated. + PA.abandon(); + return PA; + +} + +#else + #if LLVM_VERSION_MAJOR >= 16 +PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M, + ModuleAnalysisManager &MAM) { + + #else +PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M, + ModuleAnalysisManager &MAM) { + + #endif + ModuleSanitizerCoverageAFL ModuleSancov(Options); + auto &FAM = MAM.getResult(M).getManager(); + auto DTCallback = [&FAM](Function &F) -> const DominatorTree * { + + return &FAM.getResult(F); + + }; + + auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * { + + return &FAM.getResult(F); + + }; + if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback)) return PreservedAnalyses::none(); return PreservedAnalyses::all(); } +#endif + std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd( Module &M, const char *Section, Type *Ty) { - GlobalVariable *SecStart = - new GlobalVariable(M, -#if LLVM_VERSION_MAJOR >= 15 - Ty, -#else - Ty->getPointerElementType(), -#endif - false, GlobalVariable::ExternalWeakLinkage, nullptr, - getSectionStart(Section)); + // Use ExternalWeak so that if all sections are discarded due to section + // garbage collection, the linker will not report undefined symbol errors. + // Windows defines the start/stop symbols in compiler-rt so no need for + // ExternalWeak. + GlobalValue::LinkageTypes Linkage = TargetTriple.isOSBinFormatCOFF() + ? GlobalVariable::ExternalLinkage + : GlobalVariable::ExternalWeakLinkage; + GlobalVariable *SecStart = new GlobalVariable(M, Ty, false, Linkage, nullptr, + getSectionStart(Section)); SecStart->setVisibility(GlobalValue::HiddenVisibility); - GlobalVariable *SecEnd = - new GlobalVariable(M, -#if LLVM_VERSION_MAJOR >= 15 - Ty, -#else - Ty->getPointerElementType(), -#endif - false, GlobalVariable::ExternalWeakLinkage, nullptr, - getSectionEnd(Section)); + GlobalVariable *SecEnd = new GlobalVariable(M, Ty, false, Linkage, nullptr, + getSectionEnd(Section)); SecEnd->setVisibility(GlobalValue::HiddenVisibility); IRBuilder<> IRB(M.getContext()); if (!TargetTriple.isOSBinFormatCOFF()) @@ -295,7 +315,8 @@ std::pair ModuleSanitizerCoverageAFL::CreateSecStartEnd( auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, ConstantInt::get(IntptrTy, sizeof(uint64_t))); - return std::make_pair(IRB.CreatePointerCast(GEP, Ty), SecEnd); + return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)), + SecEnd); } @@ -307,8 +328,9 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections( auto SecStart = SecStartEnd.first; auto SecEnd = SecStartEnd.second; Function *CtorFunc; + Type *PtrTy = PointerType::getUnqual(Ty); std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions( - M, CtorName, InitFunctionName, {Ty, Ty}, {SecStart, SecEnd}); + M, CtorName, InitFunctionName, {PtrTy, PtrTy}, {SecStart, SecEnd}); assert(CtorFunc->getName() == CtorName); if (TargetTriple.supportsCOMDAT()) { @@ -332,7 +354,6 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections( // to include the sancov constructor. This way the linker can deduplicate // the constructors but always leave one copy. CtorFunc->setLinkage(GlobalValue::WeakODRLinkage); - appendToUsed(M, CtorFunc); } @@ -344,37 +365,25 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { setvbuf(stdout, NULL, _IONBF, 0); - if (getenv("AFL_DEBUG")) debug = 1; + + if (getenv("AFL_DEBUG")) { debug = 1; } if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n"); - } else + } else { be_quiet = 1; + } + skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO"); use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST"); initInstrumentList(); scanForDangerousFunctions(&M); - if (debug) { - - fprintf(stderr, - "SANCOV: covtype:%u indirect:%d stack:%d noprune:%d " - "createtable:%d tracepcguard:%d tracepc:%d\n", - Options.CoverageType, Options.IndirectCalls == true ? 1 : 0, - Options.StackDepth == true ? 1 : 0, Options.NoPrune == true ? 1 : 0, - // Options.InlineBoolFlag == true ? 1 : 0, - Options.PCTable == true ? 1 : 0, - Options.TracePCGuard == true ? 1 : 0, - Options.TracePC == true ? 1 : 0); - - } - - if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false; C = &(M.getContext()); DL = &M.getDataLayout(); CurModule = &M; @@ -397,16 +406,14 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); - LLVMContext &Ctx = M.getContext(); + LLVMContext &Ctx = M.getContext(); AFLMapPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); One = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 1); Zero = ConstantInt::get(IntegerType::getInt8Ty(Ctx), 0); - SanCovTracePCIndir = - M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy); // Make sure smaller parameters are zero-extended to i64 if required by the // target ABI. AttributeList SanCovTraceCmpZeroExtAL; @@ -436,26 +443,13 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( SanCovTraceConstCmpFunction[3] = M.getOrInsertFunction(SanCovTraceConstCmp8, VoidTy, Int64Ty, Int64Ty); - { - - AttributeList AL; - AL = AL.addParamAttribute(*C, 0, Attribute::ZExt); - SanCovTraceDivFunction[0] = - M.getOrInsertFunction(SanCovTraceDiv4, AL, VoidTy, IRB.getInt32Ty()); - - } - - SanCovTraceDivFunction[1] = - M.getOrInsertFunction(SanCovTraceDiv8, VoidTy, Int64Ty); - SanCovTraceGepFunction = - M.getOrInsertFunction(SanCovTraceGep, VoidTy, IntptrTy); SanCovTraceSwitchFunction = M.getOrInsertFunction(SanCovTraceSwitchName, VoidTy, Int64Ty, Int64PtrTy); Constant *SanCovLowestStackConstant = M.getOrInsertGlobal(SanCovLowestStackName, IntptrTy); SanCovLowestStack = dyn_cast(SanCovLowestStackConstant); - if (!SanCovLowestStack) { + if (!SanCovLowestStack || SanCovLowestStack->getValueType() != IntptrTy) { C->emitError(StringRef("'") + SanCovLowestStackName + "' should not be declared by the user"); @@ -465,8 +459,6 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( SanCovLowestStack->setThreadLocalMode( GlobalValue::ThreadLocalMode::InitialExecTLSModel); - if (Options.StackDepth && !SanCovLowestStack->isDeclaration()) - SanCovLowestStack->setInitializer(Constant::getAllOnesValue(IntptrTy)); SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy); SanCovTracePCGuard = @@ -481,40 +473,25 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( Ctor = CreateInitCallsForSections(M, SanCovModuleCtorTracePcGuardName, SanCovTracePCGuardInitName, Int32PtrTy, SanCovGuardsSectionName); - if (Function8bitCounterArray) - Ctor = CreateInitCallsForSections(M, SanCovModuleCtor8bitCountersName, - SanCov8bitCountersInitName, Int8PtrTy, - SanCovCountersSectionName); - if (FunctionBoolArray) { - - Ctor = CreateInitCallsForSections(M, SanCovModuleCtorBoolFlagName, - SanCovBoolFlagInitName, Int1PtrTy, - SanCovBoolFlagSectionName); - } - - if (Ctor && Options.PCTable) { + if (Ctor && debug) { - auto SecStartEnd = CreateSecStartEnd(M, SanCovPCsSectionName, IntptrPtrTy); - FunctionCallee InitFunction = declareSanitizerInitFunction( - M, SanCovPCsInitName, {IntptrPtrTy, IntptrPtrTy}); - IRBuilder<> IRBCtor(Ctor->getEntryBlock().getTerminator()); - IRBCtor.CreateCall(InitFunction, {SecStartEnd.first, SecStartEnd.second}); + fprintf(stderr, "SANCOV: installed pcguard_init in ctor\n"); } - // We don't reference these arrays directly in any of our runtime functions, - // so we need to prevent them from being dead stripped. - if (TargetTriple.isOSBinFormatMachO()) appendToUsed(M, GlobalsToAppendToUsed); + appendToUsed(M, GlobalsToAppendToUsed); appendToCompilerUsed(M, GlobalsToAppendToCompilerUsed); if (!be_quiet) { - if (!instr) + if (!instr) { + WARNF("No instrumentation targets found."); - else { - char modeline[100]; + } else { + + char modeline[128]; snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s", getenv("AFL_HARDEN") ? "hardened" : "non-hardened", getenv("AFL_USE_ASAN") ? ", ASAN" : "", @@ -535,39 +512,36 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( } // True if block has successors and it dominates all of them. -bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) { +static bool isFullDominator(const BasicBlock *BB, const DominatorTree *DT) { - if (succ_begin(BB) == succ_end(BB)) return false; + if (succ_empty(BB)) return false; - for (const BasicBlock *SUCC : make_range(succ_begin(BB), succ_end(BB))) { + return llvm::all_of(successors(BB), [&](const BasicBlock *SUCC) { - if (!DT->dominates(BB, SUCC)) return false; + return DT->dominates(BB, SUCC); - } - - return true; + }); } // True if block has predecessors and it postdominates all of them. -bool isFullPostDominator(const BasicBlock *BB, const PostDominatorTree *PDT) { +static bool isFullPostDominator(const BasicBlock *BB, + const PostDominatorTree *PDT) { - if (pred_begin(BB) == pred_end(BB)) return false; + if (pred_empty(BB)) return false; - for (const BasicBlock *PRED : make_range(pred_begin(BB), pred_end(BB))) { + return llvm::all_of(predecessors(BB), [&](const BasicBlock *PRED) { - if (!PDT->dominates(BB, PRED)) return false; + return PDT->dominates(BB, PRED); - } - - return true; + }); } -bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, - const DominatorTree *DT, - const PostDominatorTree *PDT, - const SanitizerCoverageOptions &Options) { +static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, + const DominatorTree *DT, + const PostDominatorTree *PDT, + const SanitizerCoverageOptions &Options) { // Don't insert coverage for blocks containing nothing but unreachable: we // will never call __sanitizer_cov() for them, so counting them in @@ -582,10 +556,6 @@ bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, if (Options.NoPrune || &F.getEntryBlock() == BB) return true; - if (Options.CoverageType == SanitizerCoverageOptions::SCK_Function && - &F.getEntryBlock() != BB) - return false; - // Do not instrument full dominators, or full post-dominators with multiple // predecessors. return !isFullDominator(BB, DT) && @@ -597,38 +567,47 @@ bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB, // A twist here is that we treat From->To as a backedge if // * To dominates From or // * To->UniqueSuccessor dominates From -bool IsBackEdge(BasicBlock *From, BasicBlock *To, const DominatorTree *DT) { +#if 0 +static bool IsBackEdge(BasicBlock *From, BasicBlock *To, + const DominatorTree *DT) { - if (DT->dominates(To, From)) return true; + if (DT->dominates(To, From)) + return true; if (auto Next = To->getUniqueSuccessor()) - if (DT->dominates(Next, From)) return true; + if (DT->dominates(Next, From)) + return true; return false; } +#endif + // Prunes uninteresting Cmp instrumentation: // * CMP instructions that feed into loop backedge branch. // // Note that Cmp pruning is controlled by the same flag as the // BB pruning. -bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, - const SanitizerCoverageOptions &Options) { +#if 0 +static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT, + const SanitizerCoverageOptions &Options) { if (!Options.NoPrune) if (CMP->hasOneUse()) if (auto BR = dyn_cast(CMP->user_back())) for (BasicBlock *B : BR->successors()) - if (IsBackEdge(BR->getParent(), B, DT)) return false; + if (IsBackEdge(BR->getParent(), B, DT)) + return false; return true; } +#endif + void ModuleSanitizerCoverageAFL::instrumentFunction( Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (F.empty()) return; if (!isInInstrumentList(&F, FMNAME)) return; - if (F.getName().find(".module_ctor") != std::string::npos) return; // Should not instrument sanitizer init functions. if (F.getName().startswith("__sanitizer_")) @@ -647,15 +626,13 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( if (F.hasPersonalityFn() && isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; + if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges( F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); - SmallVector IndirCalls; - SmallVector BlocksToInstrument; - SmallVector CmpTraceTargets; - SmallVector SwitchTraceTargets; - SmallVector DivTraceTargets; - SmallVector GepTraceTargets; + SmallVector BlocksToInstrument; + SmallVector CmpTraceTargets; + SmallVector SwitchTraceTargets; const DominatorTree *DT = DTCallback(F); const PostDominatorTree *PDT = PDTCallback(F); @@ -665,47 +642,28 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( if (shouldInstrumentBlock(F, &BB, DT, PDT, Options)) BlocksToInstrument.push_back(&BB); - for (auto &Inst : BB) { - - if (Options.IndirectCalls) { - - CallBase *CB = dyn_cast(&Inst); - if (CB && !CB->getCalledFunction()) IndirCalls.push_back(&Inst); - - } + /* + for (auto &Inst : BB) { - if (Options.TraceCmp) { + if (Options.TraceCmp) { - if (ICmpInst *CMP = dyn_cast(&Inst)) - if (IsInterestingCmp(CMP, DT, Options)) - CmpTraceTargets.push_back(&Inst); - if (isa(&Inst)) SwitchTraceTargets.push_back(&Inst); + if (ICmpInst *CMP = dyn_cast(&Inst)) + if (IsInterestingCmp(CMP, DT, Options)) + CmpTraceTargets.push_back(&Inst); + if (isa(&Inst)) + SwitchTraceTargets.push_back(&Inst); - } + } - if (Options.TraceDiv) - if (BinaryOperator *BO = dyn_cast(&Inst)) - if (BO->getOpcode() == Instruction::SDiv || - BO->getOpcode() == Instruction::UDiv) - DivTraceTargets.push_back(BO); - if (Options.TraceGep) - if (GetElementPtrInst *GEP = dyn_cast(&Inst)) - GepTraceTargets.push_back(GEP); - if (Options.StackDepth) - if (isa(Inst) || - (isa(Inst) && !isa(Inst))) - IsLeafFunc = false; + } - } + */ } InjectCoverage(F, BlocksToInstrument, IsLeafFunc); - InjectCoverageForIndirectCalls(F, IndirCalls); - InjectTraceForCmp(F, CmpTraceTargets); - InjectTraceForSwitch(F, SwitchTraceTargets); - InjectTraceForDiv(F, DivTraceTargets); - InjectTraceForGep(F, GepTraceTargets); + // InjectTraceForCmp(F, CmpTraceTargets); + // InjectTraceForSwitch(F, SwitchTraceTargets); } @@ -717,33 +675,30 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection( *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, Constant::getNullValue(ArrayTy), "__sancov_gen_"); -#if LLVM_VERSION_MAJOR >= 13 if (TargetTriple.supportsCOMDAT() && (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) Array->setComdat(Comdat); -#else - if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) - if (auto Comdat = - GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) - Array->setComdat(Comdat); -#endif - Array->setSection(getSectionName(Section)); -#if (LLVM_VERSION_MAJOR >= 11) || \ - (LLVM_VERSION_MAJOR == 10 && LLVM_VERSION_MINOR >= 1) - #if LLVM_VERSION_MAJOR >= 16 +#if LLVM_VERSION_MAJOR >= 16 Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedValue())); - #else - Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); - #endif #else - Array->setAlignment(Align(4)); // cheating + Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); #endif - GlobalsToAppendToUsed.push_back(Array); - GlobalsToAppendToCompilerUsed.push_back(Array); - MDNode *MD = MDNode::get(F.getContext(), ValueAsMetadata::get(&F)); - Array->addMetadata(LLVMContext::MD_associated, *MD); + + // sancov_pcs parallels the other metadata section(s). Optimizers (e.g. + // GlobalOpt/ConstantMerge) may not discard sancov_pcs and the other + // section(s) as a unit, so we conservatively retain all unconditionally in + // the compiler. + // + // With comdat (COFF/ELF), the linker can guarantee the associated sections + // will be retained or discarded as a unit, so llvm.compiler.used is + // sufficient. Otherwise, conservatively make all of them retained by the + // linker. + if (Array->hasComdat()) + GlobalsToAppendToCompilerUsed.push_back(Array); + else + GlobalsToAppendToUsed.push_back(Array); return Array; @@ -768,8 +723,12 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( PCs.push_back((Constant *)IRB.CreatePointerCast( BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); +#if LLVM_VERSION_MAJOR >= 16 + PCs.push_back(Constant::getNullValue(IntptrPtrTy)); +#else PCs.push_back((Constant *)IRB.CreateIntToPtr( ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); +#endif } @@ -792,21 +751,13 @@ void ModuleSanitizerCoverageAFL::CreateFunctionLocalArrays( FunctionGuardArray = CreateFunctionLocalArrayInSection( AllBlocks.size() + special, F, Int32Ty, SanCovGuardsSectionName); - if (Options.Inline8bitCounters) - Function8bitCounterArray = CreateFunctionLocalArrayInSection( - AllBlocks.size(), F, Int8Ty, SanCovCountersSectionName); - /* - if (Options.InlineBoolFlag) - FunctionBoolArray = CreateFunctionLocalArrayInSection( - AllBlocks.size(), F, Int1Ty, SanCovBoolFlagSectionName); - */ - if (Options.PCTable) FunctionPCsArray = CreatePCArray(F, AllBlocks); - } bool ModuleSanitizerCoverageAFL::InjectCoverage( Function &F, ArrayRef AllBlocks, bool IsLeafFunc) { + if (AllBlocks.empty()) return false; + uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; static uint32_t first = 1; @@ -855,7 +806,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( } -#if (LLVM_VERSION_MAJOR >= 12) else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { FixedVectorType *tt = dyn_cast(t); @@ -868,16 +818,14 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( } -#endif - } } } - /* Create PCGUARD array */ CreateFunctionLocalArrays(F, AllBlocks, first + cnt_cov + cnt_sel_inc); + if (first) { first = 0; } selects += cnt_sel; @@ -889,12 +837,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( CallInst *callInst = nullptr; - /* - std::string errMsg; - raw_string_ostream os(errMsg); - IN.print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ if ((callInst = dyn_cast(&IN))) { Function *Callee = callInst->getCalledFunction(); @@ -1033,12 +975,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( } - /* - std::string errMsg; - raw_string_ostream os(errMsg); - x->print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ result = IRB.CreateSelect(condition, x, y); } @@ -1063,13 +999,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); ModuleSanitizerCoverageAFL::SetNoSanitizeMetadata(MapPtr); - /* - std::string errMsg; - raw_string_ostream os(errMsg); - result->print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ - while (1) { /* Get CurLoc */ @@ -1159,29 +1088,6 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( } -// On every indirect call we call a run-time function -// __sanitizer_cov_indir_call* with two parameters: -// - callee address, -// - global cache array that contains CacheSize pointers (zero-initialized). -// The cache is used to speed up recording the caller-callee pairs. -// The address of the caller is passed implicitly via caller PC. -// CacheSize is encoded in the name of the run-time function. -void ModuleSanitizerCoverageAFL::InjectCoverageForIndirectCalls( - Function &F, ArrayRef IndirCalls) { - - if (IndirCalls.empty()) return; - for (auto I : IndirCalls) { - - IRBuilder<> IRB(I); - CallBase &CB = cast(*I); - Value *Callee = CB.getCalledOperand(); - if (isa(Callee)) continue; - IRB.CreateCall(SanCovTracePCIndir, IRB.CreatePointerCast(Callee, IntptrTy)); - - } - -} - // For every switch statement we insert a call: // __sanitizer_cov_trace_switch(CondValue, // {NumCases, ValueSizeInBits, Case0Value, Case1Value, Case2Value, ... }) @@ -1237,41 +1143,6 @@ void ModuleSanitizerCoverageAFL::InjectTraceForSwitch( } -void ModuleSanitizerCoverageAFL::InjectTraceForDiv( - Function &, ArrayRef DivTraceTargets) { - - for (auto BO : DivTraceTargets) { - - IRBuilder<> IRB(BO); - Value *A1 = BO->getOperand(1); - if (isa(A1)) continue; - if (!A1->getType()->isIntegerTy()) continue; - uint64_t TypeSize = DL->getTypeStoreSizeInBits(A1->getType()); - int CallbackIdx = TypeSize == 32 ? 0 : TypeSize == 64 ? 1 : -1; - if (CallbackIdx < 0) continue; - auto Ty = Type::getIntNTy(*C, TypeSize); - IRB.CreateCall(SanCovTraceDivFunction[CallbackIdx], - {IRB.CreateIntCast(A1, Ty, true)}); - - } - -} - -void ModuleSanitizerCoverageAFL::InjectTraceForGep( - Function &, ArrayRef GepTraceTargets) { - - for (auto GEP : GepTraceTargets) { - - IRBuilder<> IRB(GEP); - for (Use &Idx : GEP->indices()) - if (!isa(Idx) && Idx->getType()->isIntegerTy()) - IRB.CreateCall(SanCovTraceGepFunction, - {IRB.CreateIntCast(Idx, IntptrTy, true)}); - - } - -} - void ModuleSanitizerCoverageAFL::InjectTraceForCmp( Function &, ArrayRef CmpTraceTargets) { @@ -1321,27 +1192,44 @@ void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function &F, BasicBlock::iterator IP = BB.getFirstInsertionPt(); bool IsEntryBB = &BB == &F.getEntryBlock(); + DebugLoc EntryLoc; if (IsEntryBB) { - // Keep allocas and llvm.localescape calls in the entry block. Even + if (auto SP = F.getSubprogram()) + EntryLoc = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP); + // Keep static allocas and llvm.localescape calls in the entry block. Even // if we aren't splitting the block, it's nice for allocas to be before // calls. IP = PrepareToSplitEntryBlock(BB, IP); +#if LLVM_VERSION_MAJOR < 15 - } - - IRBuilder<> IRB(&*IP); - - if (Options.TracePC) { + } else { - IRB.CreateCall(SanCovTracePC); - // ->setCannotMerge(); // gets the PC using GET_CALLER_PC. + EntryLoc = IP->getDebugLoc(); + if (!EntryLoc) + if (auto *SP = F.getSubprogram()) + EntryLoc = DILocation::get(SP->getContext(), 0, 0, SP); +#endif } +#if LLVM_VERSION_MAJOR >= 15 + InstrumentationIRBuilder IRB(&*IP); +#else + IRBuilder<> IRB(&*IP); +#endif + if (EntryLoc) IRB.SetCurrentDebugLocation(EntryLoc); if (Options.TracePCGuard) { + /* + auto GuardPtr = IRB.CreateIntToPtr( + IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, Idx * 4)), + Int32PtrTy); + IRB.CreateCall(SanCovTracePCGuard, GuardPtr)->setCannotMerge(); + */ + /* Get CurLoc */ Value *GuardPtr = IRB.CreateIntToPtr( @@ -1399,57 +1287,6 @@ void ModuleSanitizerCoverageAFL::InjectCoverageAtBlock(Function &F, } - if (Options.Inline8bitCounters) { - - auto CounterPtr = IRB.CreateGEP( - Function8bitCounterArray->getValueType(), Function8bitCounterArray, - {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); - auto Load = IRB.CreateLoad(Int8Ty, CounterPtr); - auto Inc = IRB.CreateAdd(Load, ConstantInt::get(Int8Ty, 1)); - auto Store = IRB.CreateStore(Inc, CounterPtr); - SetNoSanitizeMetadata(Load); - SetNoSanitizeMetadata(Store); - - } - - /* - if (Options.InlineBoolFlag) { - - auto FlagPtr = IRB.CreateGEP( - FunctionBoolArray->getValueType(), FunctionBoolArray, - {ConstantInt::get(IntptrTy, 0), ConstantInt::get(IntptrTy, Idx)}); - auto Load = IRB.CreateLoad(Int1Ty, FlagPtr); - auto ThenTerm = - SplitBlockAndInsertIfThen(IRB.CreateIsNull(Load), &*IP, false); - IRBuilder<> ThenIRB(ThenTerm); - auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); - SetNoSanitizeMetadata(Load); - SetNoSanitizeMetadata(Store); - - } - - */ - - if (Options.StackDepth && IsEntryBB && !IsLeafFunc) { - - // Check stack depth. If it's the deepest so far, record it. - Module *M = F.getParent(); - Function *GetFrameAddr = Intrinsic::getDeclaration( - M, Intrinsic::frameaddress, - IRB.getInt8PtrTy(M->getDataLayout().getAllocaAddrSpace())); - auto FrameAddrPtr = - IRB.CreateCall(GetFrameAddr, {Constant::getNullValue(Int32Ty)}); - auto FrameAddrInt = IRB.CreatePtrToInt(FrameAddrPtr, IntptrTy); - auto LowestStack = IRB.CreateLoad(IntptrTy, SanCovLowestStack); - auto IsStackLower = IRB.CreateICmpULT(FrameAddrInt, LowestStack); - auto ThenTerm = SplitBlockAndInsertIfThen(IsStackLower, &*IP, false); - IRBuilder<> ThenIRB(ThenTerm); - auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); - SetNoSanitizeMetadata(LowestStack); - SetNoSanitizeMetadata(Store); - - } - } std::string ModuleSanitizerCoverageAFL::getSectionName( diff --git a/src/afl-cc.c b/src/afl-cc.c index 84fe70ec..9e56828c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -997,7 +997,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (instrument_mode == INSTRUMENT_PCGUARD) { -#if LLVM_MAJOR >= 11 +#if LLVM_MAJOR >= 13 #if defined __ANDROID__ || ANDROID cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; instrument_mode = INSTRUMENT_LLVMNATIVE; @@ -1014,7 +1014,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else { - #if LLVM_MAJOR >= 11 /* use new pass manager */ + #if LLVM_MAJOR >= 13 /* use new pass manager */ #if LLVM_MAJOR < 16 cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; #endif @@ -1035,12 +1035,12 @@ static void edit_params(u32 argc, char **argv, char **envp) { #if LLVM_MAJOR >= 4 if (!be_quiet) SAYF( - "Using unoptimized trace-pc-guard, upgrade to llvm 10.0.1+ for " + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " "enhanced version.\n"); cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; instrument_mode = INSTRUMENT_LLVMNATIVE; #else - FATAL("pcguard instrumentation requires llvm 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif #endif @@ -1053,7 +1053,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; #else - FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+"); + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #endif } else { @@ -1063,7 +1063,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #else - FATAL("pcguard instrumentation requires llvm 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif } else { @@ -2031,7 +2031,7 @@ int main(int argc, char **argv, char **envp) { if (!compiler_mode) { // lto is not a default because outside of afl-cc RANLIB and AR have to - // be set to llvm versions so this would work + // be set to LLVM versions so this would work if (have_llvm) compiler_mode = LLVM; else if (have_gcc_plugin) @@ -2050,6 +2050,17 @@ int main(int argc, char **argv, char **envp) { } + /* if our PCGUARD implementation is not available then silently switch to + native LLVM PCGUARD */ + if (compiler_mode == CLANG && + (instrument_mode == INSTRUMENT_DEFAULT || + instrument_mode == INSTRUMENT_PCGUARD) && + find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) { + + instrument_mode = INSTRUMENT_LLVMNATIVE; + + } + if (compiler_mode == GCC) { if (clang_mode) { @@ -2096,12 +2107,12 @@ int main(int argc, char **argv, char **envp) { "-------------|\n" "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" - " [LTO] llvm LTO: %s%s\n" + " [LTO] LLVM LTO: %s%s\n" " PCGUARD DEFAULT yes yes yes yes yes " " yes\n" " CLASSIC yes yes yes yes yes " " yes\n" - " [LLVM] llvm: %s%s\n" + " [LLVM] LLVM: %s%s\n" " PCGUARD %s yes yes module yes yes " "yes\n" " CLASSIC %s no yes module yes yes " @@ -2171,7 +2182,7 @@ int main(int argc, char **argv, char **envp) { " (instrumentation/README.lto.md)\n" " PERSIST: persistent mode support [code] (huge speed increase!)\n" " (instrumentation/README.persistent_mode.md)\n" - " DICT: dictionary in the target [yes=automatic or llvm module " + " DICT: dictionary in the target [yes=automatic or LLVM module " "pass]\n" " (instrumentation/README.lto.md + " "instrumentation/README.llvm.md)\n" -- cgit 1.4.1 From 32d5ccb92dd3f646db327d2b7c1ec5fa74b4d656 Mon Sep 17 00:00:00 2001 From: Siqi Chen Date: Tue, 27 Jun 2023 01:15:54 +0800 Subject: Increase the number of afl-cc supported params --- src/afl-cc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 9e56828c..58d44e5d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -383,9 +383,11 @@ static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, non_dash = 0; +#define MAX_PARAMS_NUM 2048 + static void process_params(u32 argc, char **argv) { - if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); } + if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); } if (lto_mode && argc > 1) { @@ -679,7 +681,7 @@ static void process_params(u32 argc, char **argv) { static void edit_params(u32 argc, char **argv, char **envp) { - cc_params = ck_alloc(1024 * sizeof(u8 *)); + cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); if (lto_mode) { -- cgit 1.4.1 From 0966957631c3d537d38ae8f1c5cfdcbcc2779712 Mon Sep 17 00:00:00 2001 From: Eli Kobrin Date: Mon, 3 Jul 2023 15:03:45 +0300 Subject: Fix max_params define. --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 58d44e5d..07c2a2d3 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -383,7 +383,9 @@ static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, non_dash = 0; +#ifndef MAX_PARAMS_NUM #define MAX_PARAMS_NUM 2048 +#endif static void process_params(u32 argc, char **argv) { -- cgit 1.4.1 From da3351085519acf73dc8ddde3cf0b526b816551b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 4 Jul 2023 11:34:13 +0200 Subject: nits --- src/afl-cc.c | 14 +++++++------- src/afl-fuzz.c | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 07c2a2d3..ec460f17 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2111,11 +2111,6 @@ int main(int argc, char **argv, char **envp) { "-------------|\n" "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" - " [LTO] LLVM LTO: %s%s\n" - " PCGUARD DEFAULT yes yes yes yes yes " - " yes\n" - " CLASSIC yes yes yes yes yes " - " yes\n" " [LLVM] LLVM: %s%s\n" " PCGUARD %s yes yes module yes yes " "yes\n" @@ -2125,16 +2120,21 @@ int main(int argc, char **argv, char **envp) { " - CALLER\n" " - CTX\n" " - NGRAM-{2-16}\n" + " [LTO] LLVM LTO: %s%s\n" + " PCGUARD DEFAULT yes yes yes yes yes " + " yes\n" + " CLASSIC yes yes yes yes yes " + " yes\n" " [GCC_PLUGIN] gcc plugin: %s%s\n" " CLASSIC DEFAULT no yes no no no " "yes\n" " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - have_lto ? "AVAILABLE" : "unavailable!", - compiler_mode == LTO ? " [SELECTED]" : "", have_llvm ? "AVAILABLE" : "unavailable!", compiler_mode == LLVM ? " [SELECTED]" : "", + have_lto ? "AVAILABLE" : "unavailable!", + compiler_mode == LTO ? " [SELECTED]" : "", LLVM_MAJOR >= 7 ? "DEFAULT" : " ", LLVM_MAJOR >= 7 ? " " : "DEFAULT", have_gcc_plugin ? "AVAILABLE" : "unavailable!", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ab7d6534..70258e33 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1281,6 +1281,10 @@ int main(int argc, char **argv_orig, char **envp) { } + WARNF( + "Note that the MOpt mode is not maintained and is not as effective " + "normal havoc mode."); + } break; case 'h': -- cgit 1.4.1 From f37c4c86622c5e0ea10e0a0249e203c412c2db2e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 5 Jul 2023 13:03:17 +0200 Subject: update llvm recommendations --- GNUmakefile.llvm | 12 +++++++----- instrumentation/README.llvm.md | 2 +- src/afl-cc.c | 17 +++++++++++++++-- src/afl-fuzz.c | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 6ffac68f..f298060e 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -47,6 +47,7 @@ LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' ) LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' ) LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-7]\.' && echo 1 || echo 0 ) LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[7-9]' && echo 1 || echo 0 ) +LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 ) LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 ) LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 ) @@ -69,6 +70,12 @@ ifeq "$(LLVM_TOO_NEW)" "1" $(warning you are using an in-development llvm version - this might break llvm_mode!) endif +ifeq "$(LLVM_TOO_OLD)" "1" + $(warning you are using an outdated LLVM version! Please use at least LLVM 13 or newer!) + $(shell sleep 2) +endif + +# No switching the meaning of LLVM_TOO_OLD LLVM_TOO_OLD=1 ifeq "$(LLVM_MAJOR)" "9" @@ -87,11 +94,6 @@ ifeq "$(LLVM_NEWER_API)" "1" LLVM_STDCXX = c++17 endif -ifeq "$(LLVM_TOO_OLD)" "1" - $(info [!] llvm_mode detected an old version of llvm, upgrade to at least 9 or preferable 11!) - $(shell sleep 1) -endif - ifeq "$(LLVM_HAVE_LTO)" "1" $(info [+] llvm_mode detected llvm 11+, enabling afl-lto LTO implementation) LLVM_LTO = 1 diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md index 126cf1a2..34b80c85 100644 --- a/instrumentation/README.llvm.md +++ b/instrumentation/README.llvm.md @@ -7,7 +7,7 @@ For the GCC-based instrumentation, see ## 1) Introduction -! llvm_mode works with llvm versions 3.8 up to 13 ! +! llvm_mode works with llvm versions 3.8 up to 17 - but 13+ is recommended ! The code in this directory allows you to instrument programs for AFL++ using true compiler-level instrumentation, instead of the more crude assembly-level diff --git a/src/afl-cc.c b/src/afl-cc.c index ec460f17..86b81459 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -384,12 +384,16 @@ static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, non_dash = 0; #ifndef MAX_PARAMS_NUM -#define MAX_PARAMS_NUM 2048 + #define MAX_PARAMS_NUM 2048 #endif static void process_params(u32 argc, char **argv) { - if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); } + if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { + + FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); + + } if (lto_mode && argc > 1) { @@ -2350,6 +2354,15 @@ int main(int argc, char **argv, char **envp) { "AFL_LLVM_CMPLOG and " "AFL_LLVM_DICT2FILE+AFL_LLVM_DICT2FILE_NO_MAIN.\n\n"); + if (LLVM_MAJOR < 13) { + + SAYF( + "Warning: It is highly recommended to use at least LLVM version 13 " + "(or better, higher) rather than %d!\n\n", + LLVM_MAJOR); + + } + exit(1); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 70258e33..9afece66 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1283,7 +1283,7 @@ int main(int argc, char **argv_orig, char **envp) { WARNF( "Note that the MOpt mode is not maintained and is not as effective " - "normal havoc mode."); + "as normal havoc mode."); } break; -- cgit 1.4.1 From 88ca5c75634d8edfa268005f2e1855a35a5b9e2e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 31 Aug 2023 14:42:08 +0200 Subject: nit --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 86b81459..12707007 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -317,7 +317,7 @@ void parse_fsanitize(char *string) { char *p, *ptr = string + strlen("-fsanitize="); char *new = malloc(strlen(string) + 1); - char *tmp = malloc(strlen(ptr)); + char *tmp = malloc(strlen(ptr) + 1); u32 count = 0, len, ende = 0; if (!new || !tmp) { FATAL("could not acquire memory"); } -- cgit 1.4.1 From 5f7c3a1ee0d6f20e42a207a7e75e0f19e726a0f5 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 27 Sep 2023 16:32:55 +0200 Subject: fix afl-cc help output --- src/afl-cc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 12707007..037a5c30 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2118,6 +2118,8 @@ int main(int argc, char **argv, char **envp) { " [LLVM] LLVM: %s%s\n" " PCGUARD %s yes yes module yes yes " "yes\n" + " NATIVE AVAILABLE no yes no no " + "part. yes\n" " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" @@ -2137,10 +2139,10 @@ int main(int argc, char **argv, char **envp) { "no\n\n", have_llvm ? "AVAILABLE" : "unavailable!", compiler_mode == LLVM ? " [SELECTED]" : "", + have_llvm ? "AVAILABLE" : "unavailable!", + have_llvm ? "AVAILABLE" : "unavailable!", have_lto ? "AVAILABLE" : "unavailable!", compiler_mode == LTO ? " [SELECTED]" : "", - LLVM_MAJOR >= 7 ? "DEFAULT" : " ", - LLVM_MAJOR >= 7 ? " " : "DEFAULT", have_gcc_plugin ? "AVAILABLE" : "unavailable!", compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", have_gcc ? "AVAILABLE" : "unavailable!", -- cgit 1.4.1 From cf458a7d25dc3448b94ffe08d3d89531fc8d4818 Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Thu, 19 Oct 2023 17:14:31 -0400 Subject: Add an env to afl-clang-fast to disable setting rpath if LLVM path isn't recognized --- docs/env_variables.md | 6 ++++++ include/envs.h | 1 + src/afl-cc.c | 27 ++++++++++++++++----------- 3 files changed, 23 insertions(+), 11 deletions(-) (limited to 'src/afl-cc.c') diff --git a/docs/env_variables.md b/docs/env_variables.md index 3bb4e844..a7636511 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -135,6 +135,12 @@ subset of the settings discussed in section 1, with the exception of: - `TMPDIR` and `AFL_KEEP_ASSEMBLY`, since no temporary assembly files are created. + - LLVM modes compiling C++ will normally set rpath in the binary if LLVM is + not in a usual location (/usr or /lib). Setting `AFL_LLVM_NO_RPATH=1` + disables this behaviour in case it isn't desired. For example, the compiling + toolchain might be in a custom location, but the target machine has LLVM + runtime libs in the search path. + Then there are a few specific features that are only available in instrumentation mode: diff --git a/include/envs.h b/include/envs.h index 734b1707..93e49e34 100644 --- a/include/envs.h +++ b/include/envs.h @@ -162,6 +162,7 @@ static char *afl_environment_variables[] = { "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", + "AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE", "AFL_LLVM_THREADSAFE_INST", diff --git a/src/afl-cc.c b/src/afl-cc.c index 037a5c30..5f8f278f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1144,19 +1144,22 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - u8 *libdir = strdup(LLVM_LIBDIR); - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { + if (!getenv("AFL_LLVM_NO_RPATH")) { + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + u8 *libdir = strdup(LLVM_LIBDIR); + if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { - cc_params[cc_par_cnt++] = "-Wl,-rpath"; - cc_params[cc_par_cnt++] = libdir; + cc_params[cc_par_cnt++] = "-Wl,-rpath"; + cc_params[cc_par_cnt++] = libdir; - } else { + } else { - free(libdir); + free(libdir); + + } } @@ -2289,7 +2292,9 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_CTX: use full context sensitive coverage (for " "CLASSIC)\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " - "CLASSIC)\n"); + "CLASSIC)\n" + " AFL_LLVM_NO_RPATH: disable rpath setting for custom LLVM " + "locations\n"); #ifdef AFL_CLANG_FLTO if (have_lto) -- cgit 1.4.1 From f7fab7915550196366e47204d882886671d5bbf9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 24 Oct 2023 11:52:02 +0200 Subject: code format --- src/afl-cc.c | 1 + src/afl-fuzz-bitmap.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5f8f278f..c3c677b4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1145,6 +1145,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } if (!getenv("AFL_LLVM_NO_RPATH")) { + // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory // might not be in the search path. Add it if so. diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d76158ce..568c5274 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -866,7 +866,8 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); } u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string( - afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, afl->fsrv.nyx_aux_string_len); + afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, + afl->fsrv.nyx_aux_string_len); ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log); close(fd); -- cgit 1.4.1 From 0e7afb75dd02efebc5518505d06667fde0467c7e Mon Sep 17 00:00:00 2001 From: vincenzo MEZZELA Date: Mon, 4 Dec 2023 16:39:10 +0100 Subject: removing options "-Wl,-rpath" "LLVM_LIBDIR" when using gcc --- src/afl-cc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index c3c677b4..6faed538 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1144,7 +1144,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } - if (!getenv("AFL_LLVM_NO_RPATH")) { + if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && + !getenv("AFL_LLVM_NO_RPATH")) { // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory -- cgit 1.4.1 From 6c04d4cc80b55efee8bb005bbd616a0aaeede395 Mon Sep 17 00:00:00 2001 From: vincenzo MEZZELA Date: Mon, 4 Dec 2023 16:41:21 +0100 Subject: fixing -Wl,-rpath= --- src/afl-cc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 6faed538..ceea61f2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1150,16 +1150,12 @@ static void edit_params(u32 argc, char **argv, char **envp) { // in case LLVM is installed not via a package manager or "make install" // e.g. compiled download or compiled from github then its ./lib directory // might not be in the search path. Add it if so. - u8 *libdir = strdup(LLVM_LIBDIR); + const char *libdir = LLVM_LIBDIR; if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && strncmp(libdir, "/lib", 4)) { - cc_params[cc_par_cnt++] = "-Wl,-rpath"; - cc_params[cc_par_cnt++] = libdir; - - } else { - - free(libdir); + u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); + cc_params[cc_par_cnt++] = libdir_opt; } -- cgit 1.4.1 From bb1d4a24917fd95f5389ed6f406c99811e0ed6eb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 7 Dec 2023 16:15:18 +0100 Subject: afl-cc fixes --- src/afl-cc.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index ceea61f2..6242ece0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -395,12 +395,16 @@ static void process_params(u32 argc, char **argv) { } + // reset + have_instr_list = 0; + have_c = 0; + if (lto_mode && argc > 1) { u32 idx; for (idx = 1; idx < argc; idx++) { - if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; + if (!strncasecmp(argv[idx], "-fpic", 5)) { have_pic = 1; } } @@ -689,6 +693,18 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + for (u32 c = 1; c < argc; ++c) { + + if (!strcmp(argv[c], "-c")) have_c = 1; + if (!strncmp(argv[c], "-fsanitize-coverage-", 20) && + strstr(argv[c], "list=")) { + + have_instr_list = 1; + + } + + } + if (lto_mode) { if (lto_flag[0] != '-') @@ -1125,24 +1141,18 @@ static void edit_params(u32 argc, char **argv, char **envp) { // cc_params[cc_par_cnt++] = "-Qunused-arguments"; - if (lto_mode && argc > 1) { - - u32 idx; - for (idx = 1; idx < argc; idx++) { - - if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1; - - } - - } - } /* Inspect the command line parameters. */ process_params(argc, argv); - if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; } + if (!have_pic) { + + cc_params[cc_par_cnt++] = "-fPIC"; + have_pic = 1; + + } if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && !getenv("AFL_LLVM_NO_RPATH")) { -- cgit 1.4.1 From 520daf5e0f8b6e7df9fa3b77b7c1b8268b0dcd0f Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 10 Dec 2023 13:23:59 +0100 Subject: nit --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 6242ece0..22cce2cd 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2313,7 +2313,7 @@ int main(int argc, char **argv, char **envp) { "0x10000\n" " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding " "functions\n" - " into this file\n" + " into this file (LTO mode)\n" " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " "global var\n" " AFL_LLVM_LTO_STARTID: from which ID to start counting from for " -- cgit 1.4.1 From 1fc1b32db261b27cf14f0d1d7f77a06854b7376c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 27 Dec 2023 13:53:11 +0100 Subject: initial simple injection detection support --- GNUmakefile | 5 ++-- GNUmakefile.llvm | 5 +++- include/envs.h | 4 ++++ injections.dic | 7 ++++++ instrumentation/afl-compiler-rt.o.c | 48 +++++++++++++++++++++++++++++++++++++ src/afl-cc.c | 20 ++++++++++++++++ 6 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 injections.dic (limited to 'src/afl-cc.c') diff --git a/GNUmakefile b/GNUmakefile index 364cdde1..b67f9c15 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -782,7 +782,7 @@ install: all $(MANPAGES) @rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh @rm -f $${DESTDIR}$(BIN_PATH)/afl-as @rm -f $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH)/afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o - @for i in afl-llvm-dict2file.so afl-llvm-lto-instrumentlist.so afl-llvm-pass.so cmplog-instructions-pass.so cmplog-routines-pass.so cmplog-switches-pass.so compare-transform-pass.so libcompcov.so libdislocator.so libnyx.so libqasan.so libtokencap.so SanitizerCoverageLTO.so SanitizerCoveragePCGUARD.so split-compares-pass.so split-switches-pass.so; do echo rm -fv $${DESTDIR}$(HELPER_PATH)/$${i}; done + @for i in afl-llvm-dict2file.so afl-llvm-lto-instrumentlist.so afl-llvm-pass.so cmplog-instructions-pass.so cmplog-routines-pass.so cmplog-switches-pass.so compare-transform-pass.so libcompcov.so libdislocator.so libnyx.so libqasan.so libtokencap.so SanitizerCoverageLTO.so SanitizerCoveragePCGUARD.so split-compares-pass.so split-switches-pass.so injection-pass.so; do echo rm -fv $${DESTDIR}$(HELPER_PATH)/$${i}; done install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH) @if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi @if [ -f utils/plot_ui/afl-plot-ui ]; then install -m 755 utils/plot_ui/afl-plot-ui $${DESTDIR}$(BIN_PATH); fi @@ -813,11 +813,12 @@ endif install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH) cp -r testcases/ $${DESTDIR}$(MISC_PATH) cp -r dictionaries/ $${DESTDIR}$(MISC_PATH) + cp injections.dic $${DESTDIR}$(MISC_PATH) .PHONY: uninstall uninstall: -cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-client afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto* - -cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt + -cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt injections.dic -rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries -sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f" -cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 0845ae3a..c704d772 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -341,7 +341,7 @@ ifeq "$(TEST_MMAP)" "1" endif PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o -PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so +PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so ./injection-pass.so # If prerequisites are not given, warn, do not build anything, and exit with code 0 ifeq "$(LLVMVER)" "" @@ -469,6 +469,9 @@ endif afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o +./injection-pass.so: instrumentation/injection-pass.cc instrumentation/afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o + .PHONY: document document: $(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c instrumentation/afl-compiler-rt.o.c -o ./afl-compiler-rt.o diff --git a/include/envs.h b/include/envs.h index 560092d9..75b2e13d 100644 --- a/include/envs.h +++ b/include/envs.h @@ -151,6 +151,10 @@ static char *afl_environment_variables[] = { "AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY", "AFL_LLVM_SKIPSINGLEBLOCK", + "AFL_LLVM_INJECTIONS_ALL", + "AFL_LLVM_INJECTIONS_SQL", + "AFL_LLVM_INJECTIONS_LDAP", + "AFL_LLVM_INJECTIONS_XSS", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", diff --git a/injections.dic b/injections.dic new file mode 100644 index 00000000..4063cd17 --- /dev/null +++ b/injections.dic @@ -0,0 +1,7 @@ +"1'\" OR \"1\"=\"1" +"1\"' OR '1'='1" +"'\"> Date: Thu, 4 Jan 2024 21:35:25 +0800 Subject: Output afl-clang-fast stuffs only if necessary (#1912) * afl-cc header * afl-cc common declarations - Add afl-cc-state.c - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c - Use debugf_args in main - Modify execvp stuffs to fit new aflcc struct * afl-cc show usage * afl-cc mode selecting 1. compiler_mode by callname in argv[0] 2. compiler_mode by env "AFL_CC_COMPILER" 3. compiler_mode/instrument_mode by command line options "--afl-..." 4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT" 5. final checking steps 6. print "... - mode: %s-%s\n" 7. determine real argv[0] according to compiler_mode * afl-cc macro defs * afl-cc linking behaviors * afl-cc fsanitize behaviors * afl-cc misc * afl-cc body update * afl-cc all-in-one formated with custom-format.py * nits --------- Co-authored-by: vanhauser-thc --- src/afl-cc.c | 3264 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 1838 insertions(+), 1426 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 54c733c9..08348d2c 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -47,23 +47,22 @@ #define LLVM_MINOR 0 #endif -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, ctx_k, lto_mode; -static u8 compiler_mode, plusplus_mode, have_instr_env = 0, need_aflpplib = 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 int passthrough; -// static u8 *march_opt = CFLAGS_OPT; - -enum { +#ifndef MAX_PARAMS_NUM + #define MAX_PARAMS_NUM 2048 +#endif + +/* Global declarations */ + +typedef enum { + + PARAM_MISS, // not matched + PARAM_SCAN, // scan only + PARAM_KEEP, // kept as-is + PARAM_DROP, // ignored + +} param_st; + +typedef enum { INSTRUMENT_DEFAULT = 0, INSTRUMENT_CLASSIC = 1, @@ -80,7 +79,20 @@ enum { INSTRUMENT_OPT_CTX_K = 64, INSTRUMENT_OPT_CODECOV = 128, -}; +} instrument_mode_id; + +typedef enum { + + UNSET = 0, + LTO = 1, + LLVM = 2, + GCC_PLUGIN = 3, + GCC = 4, + CLANG = 5 + +} compiler_mode_id; + +static u8 cwd[4096]; char instrument_mode_string[18][18] = { @@ -105,17 +117,6 @@ char instrument_mode_string[18][18] = { }; -enum { - - UNSET = 0, - LTO = 1, - LLVM = 2, - GCC_PLUGIN = 3, - GCC = 4, - CLANG = 5 - -}; - char compiler_mode_string[7][12] = { "AUTOSELECT", "LLVM-LTO", "LLVM", "GCC_PLUGIN", @@ -123,6 +124,18 @@ char compiler_mode_string[7][12] = { }; +u8 *instrument_mode_2str(instrument_mode_id i) { + + return instrument_mode_string[i]; + +} + +u8 *compiler_mode_2str(compiler_mode_id i) { + + return compiler_mode_string[i]; + +} + u8 *getthecwd() { if (getcwd(cwd, sizeof(cwd)) == NULL) { @@ -136,26 +149,228 @@ u8 *getthecwd() { } -/* Try to find a specific runtime we need, returns NULL on fail. */ +typedef struct aflcc_state { + + u8 **cc_params; /* Parameters passed to the real CC */ + u32 cc_par_cnt; /* Param count, including argv0 */ + + u8 *argv0; /* Original argv0 (by strdup) */ + u8 *callname; /* Executable file argv0 indicated */ + + u8 debug; + + u8 compiler_mode, plusplus_mode, lto_mode; + + u8 *lto_flag; + + u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k; + + u8 cmplog_mode; + + u8 have_instr_env, have_gcc, have_llvm, have_gcc_plugin, have_lto, + have_optimized_pcguard, have_instr_list; + + u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, + have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + + // u8 *march_opt; + u8 need_aflpplib; + int passthrough; + + u8 use_stdin; /* dummy */ + u8 *argvnull; /* dummy */ + +} aflcc_state_t; + +void aflcc_state_init(aflcc_state_t *, u8 *argv0); + +/* Try to find a specific runtime we need, the path to obj would be + allocated and returned. Otherwise it returns NULL on fail. */ +u8 *find_object(aflcc_state_t *, u8 *obj); + +void find_built_deps(aflcc_state_t *); + +static inline void limit_params(aflcc_state_t *aflcc, u32 add) { + + if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); + +} + +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { + + aflcc->cc_params[aflcc->cc_par_cnt++] = param; + +} + +static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, + u8 *msg) { + + u8 *_obj_path = find_object(aflcc, obj); + if (!_obj_path) { + + if (msg) + FATAL("%s", msg); + else + FATAL("Unable to find '%s'", obj); + + } else { + + if (fmt) { + + u8 *_obj_path_fmt = alloc_printf(fmt, _obj_path); + ck_free(_obj_path); + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path_fmt; + + } else { + + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path; + + } + + } + +} + +static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { + +#if LLVM_MAJOR >= 11 /* use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, pass, "-fpass-plugin=%s", 0); +#else + insert_param(aflcc, "-Xclang"); + insert_param(aflcc, "-load"); + insert_param(aflcc, "-Xclang"); + insert_object(aflcc, pass, 0, 0); +#endif + +} + +static inline void debugf_args(int argc, char **argv) { + + DEBUGF("cd '%s';", getthecwd()); + for (int i = 0; i < argc; i++) + SAYF(" '%s'", argv[i]); + SAYF("\n"); + fflush(stdout); + fflush(stderr); + +} + +void compiler_mode_by_callname(aflcc_state_t *); +void compiler_mode_by_environ(aflcc_state_t *); +void compiler_mode_by_cmdline(aflcc_state_t *, int argc, char **argv); +void instrument_mode_by_environ(aflcc_state_t *); +void mode_final_checkout(aflcc_state_t *, int argc, char **argv); +void mode_notification(aflcc_state_t *); + +void add_real_argv0(aflcc_state_t *); + +void add_defs_common(aflcc_state_t *); +void add_defs_selective_instr(aflcc_state_t *); +void add_defs_persistent_mode(aflcc_state_t *); +void add_defs_fortify(aflcc_state_t *, u8); +void add_defs_lsan_ctrl(aflcc_state_t *); + +param_st parse_fsanitize(aflcc_state_t *, u8 *, u8); +void add_sanitizers(aflcc_state_t *, char **envp); +void add_optimized_pcguard(aflcc_state_t *); +void add_native_pcguard(aflcc_state_t *); + +void add_assembler(aflcc_state_t *); +void add_gcc_plugin(aflcc_state_t *); + +param_st parse_misc_params(aflcc_state_t *, u8 *, u8); +void add_misc_params(aflcc_state_t *); + +param_st parse_linking_params(aflcc_state_t *, u8 *, u8, u8 *skip_next, + char **argv); + +void add_lto_linker(aflcc_state_t *); +void add_lto_passes(aflcc_state_t *); +void add_runtime(aflcc_state_t *); + +/* Working state */ + +void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { + + // Default NULL/0 is a good start + memset(aflcc, 0, sizeof(aflcc_state_t)); + + aflcc->cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + aflcc->cc_par_cnt = 1; + + aflcc->lto_flag = AFL_CLANG_FLTO; + + // aflcc->march_opt = CFLAGS_OPT; + + /* callname & if C++ mode */ + + aflcc->argv0 = ck_strdup(argv0); + + char *cname = NULL; + + if ((cname = strrchr(aflcc->argv0, '/')) != NULL) { + + cname++; + + } else { + + cname = aflcc->argv0; + + } + + aflcc->callname = cname; + + if (strlen(cname) > 2 && (strncmp(cname + strlen(cname) - 2, "++", 2) == 0 || + strstr(cname, "-g++") != NULL)) { + + aflcc->plusplus_mode = 1; + + } + + /* debug */ + + if (getenv("AFL_DEBUG")) { + + aflcc->debug = 1; + if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); + + } else if (getenv("AFL_QUIET")) { + + be_quiet = 1; + + } + + if ((getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) && (!aflcc->debug)) { + + be_quiet = 1; + + } + +} /* 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 + 1. firstly we check the $AFL_PATH environment variable location if set + 2. 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 + 3. if 2. 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 + 4. we look into the AFL_PATH define (usually /usr/local/lib/afl) + 5. we finally try the current directory if all these attempts fail - we return NULL and the caller has to decide - what to do. + what to do. Otherwise the path to obj would be allocated and returned. */ -static u8 *find_object(u8 *obj, u8 *argv0) { +u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { + + u8 *argv0 = aflcc->argv0; u8 *afl_path = getenv("AFL_PATH"); u8 *slash = NULL, *tmp; @@ -164,14 +379,9 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", afl_path, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { - - obj_path = afl_path; - return tmp; + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); @@ -190,11 +400,11 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - obj_path = dir; + ck_free(dir); return tmp; } @@ -202,12 +412,10 @@ static u8 *find_object(u8 *obj, u8 *argv0) { ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - u8 *dir2 = alloc_printf("%s/../lib/afl", dir); - obj_path = dir2; ck_free(dir); return tmp; @@ -247,26 +455,16 @@ static u8 *find_object(u8 *obj, u8 *argv0) { *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; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - u8 *dir = alloc_printf("%s/../lib/afl/", exepath); - obj_path = dir; - return tmp; + if (!access(tmp, R_OK)) { return tmp; } - } + ck_free(tmp); } @@ -283,1844 +481,1911 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", AFL_PATH, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = AFL_PATH; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - tmp = alloc_printf("./%s", obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = "."; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - if (debug) DEBUGF("Trying ... giving up\n"); + if (aflcc->debug) DEBUGF("Trying ... giving up\n"); return NULL; } -void parse_fsanitize(char *string) { +void find_built_deps(aflcc_state_t *aflcc) { - char *p, *ptr = string + strlen("-fsanitize="); - char *new = malloc(strlen(string) + 1); - char *tmp = malloc(strlen(ptr) + 1); - u32 count = 0, len, ende = 0; + char *ptr = NULL; - if (!new || !tmp) { FATAL("could not acquire memory"); } - strcpy(new, "-fsanitize="); + if ((ptr = find_object(aflcc, "as")) != NULL) { - do { + aflcc->have_gcc = 1; + ck_free(ptr); - p = strchr(ptr, ','); - if (!p) { + } - p = ptr + strlen(ptr) + 1; - ende = 1; + if ((ptr = find_object(aflcc, "SanitizerCoveragePCGUARD.so")) != NULL) { - } + aflcc->have_optimized_pcguard = 1; + ck_free(ptr); - len = p - ptr; - if (len) { + } - strncpy(tmp, ptr, len); - tmp[len] = 0; - // fprintf(stderr, "Found: %s\n", tmp); - ptr += len + 1; - if (*tmp) { +#if (LLVM_MAJOR >= 3) - u32 copy = 1; - if (!strcmp(tmp, "fuzzer")) { + if ((ptr = find_object(aflcc, "SanitizerCoverageLTO.so")) != NULL) { - need_aflpplib = 1; - copy = 0; + aflcc->have_lto = 1; + ck_free(ptr); - } else if (!strncmp(tmp, "fuzzer", 6)) { + } - copy = 0; + if ((ptr = find_object(aflcc, "cmplog-routines-pass.so")) != NULL) { - } + aflcc->have_llvm = 1; + ck_free(ptr); - if (copy) { + } - if (count) { strcat(new, ","); } - strcat(new, tmp); - ++count; +#endif - } +#ifdef __ANDROID__ + aflcc->have_llvm = 1; +#endif - } + if ((ptr = find_object(aflcc, "afl-gcc-pass.so")) != NULL) { - } else { + aflcc->have_gcc_plugin = 1; + ck_free(ptr); - ptr++; /*fprintf(stderr, "NO!\n"); */ + } - } +#if !defined(__ANDROID__) && !defined(ANDROID) + ptr = find_object(aflcc, "afl-compiler-rt.o"); - } while (!ende); + if (!ptr) { - strcpy(string, new); - // fprintf(stderr, "string: %s\n", string); - // fprintf(stderr, "new: %s\n", new); + FATAL( + "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " + "environment variable."); -} + } -static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - shared_linking = 0, preprocessor_only = 0, have_unroll = 0, - have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, - non_dash = 0; + if (aflcc->debug) { DEBUGF("rt=%s\n", ptr); } -#ifndef MAX_PARAMS_NUM - #define MAX_PARAMS_NUM 2048 + ck_free(ptr); #endif -static void process_params(u32 argc, char **argv) { +} - if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { +/* compiler_mode & instrument_mode selecting */ - FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); +void compiler_mode_by_callname(aflcc_state_t *aflcc) { - } + if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { - // reset - have_instr_list = 0; - have_c = 0; + /* afl-clang-fast is always created there by makefile + just like afl-clang, burdened with special purposes: + - If llvm-config is not available (i.e. LLVM_MAJOR is 0), + or too old, it falls back to LLVM-NATIVE mode and let + the actual compiler complain if doesn't work. + - Otherwise try default llvm instruments except LTO. + */ +#if (LLVM_MAJOR >= 3) + aflcc->compiler_mode = LLVM; +#else + aflcc->compiler_mode = CLANG; +#endif - if (lto_mode && argc > 1) { + } else - u32 idx; - for (idx = 1; idx < argc; idx++) { +#if (LLVM_MAJOR >= 3) - if (!strncasecmp(argv[idx], "-fpic", 5)) { have_pic = 1; } + if (strncmp(aflcc->callname, "afl-clang-lto", 13) == 0 || - } + strncmp(aflcc->callname, "afl-lto", 7) == 0) { - } + aflcc->compiler_mode = LTO; - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); + } else - /* Process the argument list. */ +#endif - u8 skip_next = 0; - while (--argc) { + if (strncmp(aflcc->callname, "afl-gcc-fast", 12) == 0 || - u8 *cur = *(++argv); + strncmp(aflcc->callname, "afl-g++-fast", 12) == 0) { - if (skip_next) { + aflcc->compiler_mode = GCC_PLUGIN; - skip_next = 0; - continue; + } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || - } + strncmp(aflcc->callname, "afl-g++", 7) == 0) { - if (cur[0] != '-') { non_dash = 1; } - if (!strncmp(cur, "--afl", 5)) continue; + aflcc->compiler_mode = GCC; - if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + } else if (strcmp(aflcc->callname, "afl-clang") == 0 || - FATAL( - "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " - "use afl-clang-fast!"); + strcmp(aflcc->callname, "afl-clang++") == 0) { - } + aflcc->compiler_mode = CLANG; - if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; - if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - if (!strncmp(cur, "-fno-unroll", 11)) continue; - if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; - if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || - !strcmp(cur, "--no-undefined")) { + } - continue; +} - } +void compiler_mode_by_environ(aflcc_state_t *aflcc) { - if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } + if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { - if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { + aflcc->passthrough = 1; - u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { + } - skip_next = 1; - continue; + char *ptr = getenv("AFL_CC_COMPILER"); - } + if (!ptr) { return; } - } + if (aflcc->compiler_mode) { - if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && - !strncmp(cur, "-stdlib=", 8)) { + if (!be_quiet) { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + WARNF( + "\"AFL_CC_COMPILER\" is set but a specific compiler was already " + "selected by command line parameter or symlink, ignoring the " + "environment variable!"); } - if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { + } else { - have_instr_list = 1; + if (strncasecmp(ptr, "LTO", 3) == 0) { - } + aflcc->compiler_mode = LTO; - if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && - strchr(cur, ',')) { + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - parse_fsanitize(cur); - if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } + aflcc->compiler_mode = LLVM; - } else if ((!strncmp(cur, "-fsanitize=fuzzer-", + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - instrument_mode != INSTRUMENT_LLVMNATIVE)) { + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + aflcc->compiler_mode = GCC_PLUGIN; - } + } else if (strcasecmp(ptr, "GCC") == 0) { - if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { + aflcc->compiler_mode = GCC; - u8 *afllib = find_object("libAFLDriver.a", argv[0]); + } else if (strcasecmp(ptr, "CLANG") == 0) { - if (!be_quiet) { + aflcc->compiler_mode = CLANG; - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + } else - } + FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); - if (!afllib) { + } - if (!be_quiet) { +} - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); +// If it can be inferred, instrument_mode would also be set +void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { - } + char *ptr = NULL; - } else { + for (int i = 1; i < argc; i++) { - cc_params[cc_par_cnt++] = afllib; + if (strncmp(argv[i], "--afl", 5) == 0) { -#ifdef __APPLE__ - cc_params[cc_par_cnt++] = "-undefined"; - cc_params[cc_par_cnt++] = "dynamic_lookup"; -#endif - - } + if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { - if (need_aflpplib) { + aflcc->passthrough = 1; + argv[i] = "-g"; // we have to overwrite it, -g is always good + continue; - need_aflpplib = 0; + } - } else { + if (aflcc->compiler_mode && !be_quiet) { - continue; + WARNF( + "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " + "symlink compiler selection!"); } - } + ptr = argv[i]; + ptr += 5; + while (*ptr == '-') + ptr++; - if (!strcmp(cur, "-m32")) bit_mode = 32; - if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; - if (!strcmp(cur, "-m64")) bit_mode = 64; + if (strncasecmp(ptr, "LTO", 3) == 0) { - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) - asan_set = 1; + aflcc->compiler_mode = LTO; - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - if (!strcmp(cur, "-x")) x_set = 1; - if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; - if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; - if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; - if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; - if (!strcmp(cur, "--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-c")) have_c = 1; + aflcc->compiler_mode = LLVM; - if (!strncmp(cur, "-O", 2)) have_o = 1; - if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; + } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || - if (*cur == '@') { + strncasecmp(ptr, "PC-GUARD", 8) == 0) { - // response file support. - // 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. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! - u8 *filename = cur + 1; - if (debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + } else if (strcasecmp(ptr, "INSTRIM") == 0 || - cc_params[cc_par_cnt++] = cur; - continue; + strcasecmp(ptr, "CFG") == 0) { - } + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + } else if (strcasecmp(ptr, "AFL") == 0 || - while (fgets(tmpbuf, st.st_size + 1, f)) { + strcasecmp(ptr, "CLASSIC") == 0) { - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_CLASSIC; - ++ptr; - cont_act = 0; + } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || - } + strcasecmp(ptr, "NATIVE") == 0 || + strcasecmp(ptr, "LLVM-NATIVE") == 0) { - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - cont = 1; - ptr[strlen(ptr) - 1] = 0; + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - } + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - // fprintf(stderr, "2: %s\n", ptr); + aflcc->compiler_mode = GCC_PLUGIN; - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + } else if (strcasecmp(ptr, "GCC") == 0) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + aflcc->compiler_mode = GCC; - } + } else if (strncasecmp(ptr, "CLANG", 5) == 0) { - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + aflcc->compiler_mode = CLANG; - do { + } else - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); - ++ptr; + } - } + } - while (*ptr && isspace(*ptr)) { +} - *ptr++ = 0; +static void instrument_mode_old_environ(aflcc_state_t *aflcc) { - } + if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || + getenv("INSTRIM_LIB")) { - if (cont_act) { + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " + "(default in afl-cc).\n"); - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; + } - } else { + if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || + getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { - args[count++] = strdup(value); + if (aflcc->instrument_mode == 0) + aflcc->instrument_mode = INSTRUMENT_PCGUARD; + else if (aflcc->instrument_mode != INSTRUMENT_PCGUARD) + FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); - } + } - } while (*ptr); + if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + if (getenv("AFL_LLVM_CALLER")) + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - } + if (getenv("AFL_LLVM_NGRAM_SIZE")) { - if (cont) { + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; + aflcc->ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) + FATAL( + "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " + "(%u)", + NGRAM_SIZE_MAX); - cont_act = 1; - cont = 0; + } - } + if (getenv("AFL_LLVM_CTX_K")) { - } + aflcc->ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", + CTX_MAX_K); + if (aflcc->ctx_k == 1) { - if (count) { process_params(count, args); } + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - // we cannot free args[] - free(tmpbuf); + } else { - continue; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; } - cc_params[cc_par_cnt++] = cur; - } } -/* Copy argv to cc_params, making the necessary edits. */ - -static void edit_params(u32 argc, char **argv, char **envp) { +// compiler_mode would also be set if depended by the instrument_mode +static void instrument_mode_new_environ(aflcc_state_t *aflcc) { - cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } - for (u32 c = 1; c < argc; ++c) { + u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); - if (!strcmp(argv[c], "-c")) have_c = 1; - if (!strncmp(argv[c], "-fsanitize-coverage-", 20) && - strstr(argv[c], "list=")) { + while (ptr2) { - have_instr_list = 1; - - } + if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || + strncasecmp(ptr2, "classic", strlen("classic")) == 0) { - } + if (aflcc->instrument_mode == INSTRUMENT_LTO) { - if (lto_mode) { + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->lto_mode = 1; - if (lto_flag[0] != '-') - FATAL( - "Using afl-clang-lto is not possible because Makefile magic did not " - "identify the correct -flto flag"); - else - compiler_mode = LTO; + } else if (!aflcc->instrument_mode || - } + aflcc->instrument_mode == INSTRUMENT_AFL) { - if (plusplus_mode) { + aflcc->instrument_mode = INSTRUMENT_AFL; - u8 *alt_cxx = getenv("AFL_CXX"); + } else { - if (!alt_cxx) { + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - if (compiler_mode >= GCC_PLUGIN) { + } - if (compiler_mode == GCC) { + } - alt_cxx = clang_mode ? "clang++" : "g++"; + if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || + strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { - } else if (compiler_mode == CLANG) { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) - alt_cxx = "clang++"; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - } else { + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - alt_cxx = "g++"; + } - } + if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || + strncasecmp(ptr2, "native", strlen("native")) == 0) { - } else { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); - alt_cxx = llvm_fullpath; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } - cc_params[0] = alt_cxx; - - } else { + if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || + strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { - u8 *alt_cc = getenv("AFL_CC"); + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) { - if (!alt_cc) { + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; - if (compiler_mode >= GCC_PLUGIN) { + } else { - if (compiler_mode == GCC) { + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - alt_cc = clang_mode ? "clang" : "gcc"; + } - } else if (compiler_mode == CLANG) { + } - alt_cc = "clang"; + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || + strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { - } else { + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); - alt_cc = "gcc"; + } - } + if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { - } else { + aflcc->lto_mode = 1; + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_LTO) - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s", CLANG_BIN); - alt_cc = llvm_fullpath; + aflcc->instrument_mode = INSTRUMENT_LTO; - } + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } - cc_params[0] = alt_cc; - - } + if (strcasecmp(ptr2, "gcc") == 0) { - if (compiler_mode == GCC || compiler_mode == CLANG) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) - cc_params[cc_par_cnt++] = "-B"; - cc_params[cc_par_cnt++] = obj_path; + aflcc->instrument_mode = INSTRUMENT_GCC; - if (clang_mode || compiler_mode == CLANG) { + else if (aflcc->instrument_mode != INSTRUMENT_GCC) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - cc_params[cc_par_cnt++] = "-no-integrated-as"; + aflcc->compiler_mode = GCC; } - } + if (strcasecmp(ptr2, "clang") == 0) { - if (compiler_mode == GCC_PLUGIN) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) - char *fplugin_arg; + aflcc->instrument_mode = INSTRUMENT_CLANG; - if (cmplog_mode) { + else if (aflcc->instrument_mode != INSTRUMENT_CLANG) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmplog-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmptrs-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; + aflcc->compiler_mode = CLANG; } - fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - cc_params[cc_par_cnt++] = "-fno-if-conversion"; - cc_params[cc_par_cnt++] = "-fno-if-conversion2"; - - } + if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || + strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || + strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { - if (compiler_mode == LLVM || compiler_mode == LTO) { + u8 *ptr3 = ptr2; + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) + ptr3++; - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + if (!*ptr3) { - if (lto_mode && have_instr_env) { + if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) + FATAL( + "you must set the K-CTX K with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ctx-2"); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path); -#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/afl-llvm-lto-instrumentlist.so", obj_path); -#endif + } - } + aflcc->ctx_k = atoi(ptr3); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL( + "K-CTX instrumentation option must be between 1 and CTX_MAX_K " + "(%u)", + CTX_MAX_K); - if (getenv("AFL_LLVM_DICT2FILE")) { + if (aflcc->ctx_k == 1) { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path); -#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/afl-llvm-dict2file.so", obj_path); -#endif + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); - } + } else { - // laf - if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); + u8 *ptr4 = alloc_printf("%u", aflcc->ctx_k); + setenv("AFL_LLVM_CTX_K", ptr4, 1); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#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/split-switches-pass.so", obj_path); -#endif + } } - if (getenv("LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + if (strcasecmp(ptr2, "ctx") == 0) { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path); -#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/compare-transform-pass.so", obj_path); -#endif + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + setenv("AFL_LLVM_CTX", "1", 1); } - if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || - getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { + if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); -#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/split-compares-pass.so", obj_path); -#endif + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); } - // /laf + if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { - unsetenv("AFL_LD"); - unsetenv("AFL_LD_CALLER"); + u8 *ptr3 = ptr2 + strlen("ngram"); + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) { - if (cmplog_mode) { + ptr3++; - cc_params[cc_par_cnt++] = "-fno-inline"; + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#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/cmplog-switches-pass.so", obj_path); + if (!*ptr3) { - // reuse split switches from laf - 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/split-switches-pass.so", obj_path); -#endif + if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) + FATAL( + "you must set the NGRAM size with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ngram-2"); - } + } - // #if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the AFL++ passes still - // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; - // #endif + aflcc->ngram_size = atoi(ptr3); - if (lto_mode && !have_c) { + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) { - u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { + FATAL( + "NGRAM instrumentation option must be between 2 and " + "NGRAM_SIZE_MAX (%u)", + NGRAM_SIZE_MAX); - ld_path = strdup(getenv("AFL_REAL_LD")); + } - } else { + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); + u8 *ptr4 = alloc_printf("%u", aflcc->ngram_size); + setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); - ld_path = strdup(AFL_REAL_LD); + } - } + ptr2 = strtok(NULL, ":,;"); - if (!ld_path || !*ld_path) { + } - if (ld_path) { +} - // Freeing empty string - free(ld_path); +void instrument_mode_by_environ(aflcc_state_t *aflcc) { - } + if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || + getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || + getenv("AFL_LLVM_BLOCKLIST")) { - ld_path = strdup("ld.lld"); + aflcc->have_instr_env = 1; - } + } - if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 - cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path); -#else - cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path); -#endif - free(ld_path); - -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 - // The NewPM implementation only works fully since LLVM 15. - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,--load-pass-plugin=%s/SanitizerCoverageLTO.so", obj_path); -#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#endif + if (aflcc->have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { - cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; - cc_params[cc_par_cnt++] = lto_flag; + WARNF( + "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " + "for file matching, only function matching!"); - } else { + } - if (instrument_mode == INSTRUMENT_PCGUARD) { + instrument_mode_old_environ(aflcc); + instrument_mode_new_environ(aflcc); -#if LLVM_MAJOR >= 13 - #if defined __ANDROID__ || ANDROID - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - 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"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - - } else { - - #if LLVM_MAJOR >= 13 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path); - #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); - #endif +} - } +static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { - #endif -#else - #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - #endif -#endif + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { - } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { + FATAL("you cannot set CTX and CALLER together"); -#if LLVM_MAJOR >= 4 - if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + } - #if LLVM_MAJOR >= 6 - cc_params[cc_par_cnt++] = - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; - #else - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); - #endif + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { - } else { + FATAL("you cannot set CTX and K-CTX together"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + } - } + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { -#else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#endif + FATAL("you cannot set CALLER and K-CTX together"); - } else { + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); -#else + if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM) + FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); - 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-pass.so", obj_path); -#endif + if (aflcc->instrument_opt_mode && + aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV && + aflcc->instrument_mode != INSTRUMENT_CLASSIC) + FATAL( + "CALLER, CTX and NGRAM instrumentation options can only be used with " + "the LLVM CLASSIC instrumentation mode."); - } +} - } +void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { - if (cmplog_mode) { + if (aflcc->instrument_opt_mode && + aflcc->instrument_mode == INSTRUMENT_DEFAULT && + (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == UNSET)) { -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); -#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/cmplog-instructions-pass.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/cmplog-routines-pass.so", obj_path); -#endif + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->compiler_mode = LLVM; - } + } - if (getenv("AFL_LLVM_INJECTIONS_ALL") || - getenv("AFL_LLVM_INJECTIONS_SQL") || - getenv("AFL_LLVM_INJECTIONS_LDAP") || - getenv("AFL_LLVM_INJECTIONS_XSS")) { + if (!aflcc->compiler_mode) { -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/injection-pass.so", obj_path); + // lto is not a default because outside of afl-cc RANLIB and AR have to + // be set to LLVM versions so this would work + if (aflcc->have_llvm) + aflcc->compiler_mode = LLVM; + else if (aflcc->have_gcc_plugin) + aflcc->compiler_mode = GCC_PLUGIN; + else if (aflcc->have_gcc) +#ifdef __APPLE__ + // on OSX clang masquerades as GCC + aflcc->compiler_mode = CLANG; #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/injection-pass.so", obj_path); + aflcc->compiler_mode = GCC; #endif - - } - - // cc_params[cc_par_cnt++] = "-Qunused-arguments"; + else if (aflcc->have_lto) + aflcc->compiler_mode = LTO; + else + FATAL("no compiler mode available"); } - /* Inspect the command line parameters. */ - - process_params(argc, argv); - - if (!have_pic) { + if (aflcc->compiler_mode == GCC) { aflcc->instrument_mode = INSTRUMENT_GCC; } - cc_params[cc_par_cnt++] = "-fPIC"; - have_pic = 1; + if (aflcc->compiler_mode == CLANG) { - } + /* if our PCGUARD implementation is not available then silently switch to + native LLVM PCGUARD. Or classic asm instrument is explicitly preferred. */ + if (!aflcc->have_optimized_pcguard && + (aflcc->instrument_mode == INSTRUMENT_DEFAULT || + aflcc->instrument_mode == INSTRUMENT_PCGUARD)) { - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && - !getenv("AFL_LLVM_NO_RPATH")) { + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - const char *libdir = LLVM_LIBDIR; - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { + } else { - u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); - cc_params[cc_par_cnt++] = libdir_opt; + aflcc->instrument_mode = INSTRUMENT_CLANG; + setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as } } - if (getenv("AFL_HARDEN")) { - - cc_params[cc_par_cnt++] = "-fstack-protector-all"; - - if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; + if (aflcc->compiler_mode == LTO) { - } + if (aflcc->instrument_mode == 0 || + aflcc->instrument_mode == INSTRUMENT_LTO || + aflcc->instrument_mode == INSTRUMENT_CFG || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) { - if (!asan_set) { + aflcc->lto_mode = 1; + // force CFG + // if (!aflcc->instrument_mode) { - if (getenv("AFL_USE_ASAN")) { + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + // } - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + } else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) { - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=address"; + aflcc->lto_mode = 1; - } else if (getenv("AFL_USE_MSAN")) { + } else { - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (!be_quiet) { - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + WARNF("afl-clang-lto called with mode %s, using that mode instead", + instrument_mode_2str(aflcc->instrument_mode)); - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=memory"; + } } } - if (getenv("AFL_USE_UBSAN")) { + if (aflcc->instrument_mode == 0 && aflcc->compiler_mode < GCC_PLUGIN) { - cc_params[cc_par_cnt++] = "-fsanitize=undefined"; - cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error"; - cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; +#if LLVM_MAJOR >= 7 + #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) + if (aflcc->have_instr_env) { - } + aflcc->instrument_mode = INSTRUMENT_AFL; + if (!be_quiet) { - if (getenv("AFL_USE_TSAN")) { + WARNF( + "Switching to classic instrumentation because " + "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); - cc_params[cc_par_cnt++] = "-fsanitize=thread"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + } - } + } else - if (getenv("AFL_USE_LSAN")) { + #endif + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - cc_params[cc_par_cnt++] = "-fsanitize=leak"; - cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h"; - cc_params[cc_par_cnt++] = - "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " - "_exit(23); }"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_OFF()=__lsan_disable();"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_ON()=__lsan_enable();"; +#else + aflcc->instrument_mode = INSTRUMENT_AFL; +#endif } - if (getenv("AFL_USE_CFISAN")) { - - if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) { - - cc_params[cc_par_cnt++] = "-fcf-protection=full"; + if (!aflcc->instrument_opt_mode && aflcc->lto_mode && + aflcc->instrument_mode == INSTRUMENT_CFG) { - } else { - - if (!lto_mode) { + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) - if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) cc_params[cc_par_cnt++] = "-flto"; + } - } +#ifndef AFL_CLANG_FLTO + if (aflcc->lto_mode) + FATAL( + "instrumentation mode LTO specified but LLVM support not available " + "(requires LLVM 11 or higher)"); +#endif - cc_params[cc_par_cnt++] = "-fsanitize=cfi"; - cc_params[cc_par_cnt++] = "-fvisibility=hidden"; + if (aflcc->lto_mode) { - } + if (aflcc->lto_flag[0] != '-') + FATAL( + "Using afl-clang-lto is not possible because Makefile magic did not " + "identify the correct -flto flag"); + else + aflcc->compiler_mode = LTO; } - if (!getenv("AFL_DONT_OPTIMIZE")) { - - cc_params[cc_par_cnt++] = "-g"; - if (!have_o) cc_params[cc_par_cnt++] = "-O3"; - if (!have_unroll) cc_params[cc_par_cnt++] = "-funroll-loops"; - // if (strlen(march_opt) > 1 && march_opt[0] == '-') - // cc_params[cc_par_cnt++] = march_opt; + if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) + FATAL( + "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " + "together"); - } +#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || - getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") || - lto_mode) { + if (aflcc->instrument_mode == INSTRUMENT_PCGUARD && aflcc->have_instr_env) { - cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-bcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; + FATAL( + "Instrumentation type PCGUARD does not support " + "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); } -#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; #endif - cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; - cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; - - /* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ - if (compiler_mode != GCC && compiler_mode != CLANG) { - - cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; + instrument_opt_mode_exclude(aflcc); - /* When the user tries to use persistent or deferred forkserver modes by - appending a single line to the program, we want to reliably inject a - signature into the binary (to be picked up by afl-fuzz) and we want - to call a function from the runtime .o file. This is unnecessarily - painful for three reasons: - - 1) We need to convince the compiler not to optimize out the signature. - This is done with __attribute__((used)). - - 2) We need to convince the linker, when called with -Wl,--gc-sections, - not to do the same. This is done by forcing an assignment to a - 'volatile' pointer. + u8 *ptr2; - 3) We need to declare __afl_persistent_loop() in the global namespace, - but doing this within a method in a class is hard - :: and extern "C" - are forbidden and __attribute__((alias(...))) doesn't work. Hence the - __asm__ aliasing trick. + if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') + FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); - */ + if (getenv("AFL_LLVM_LAF_ALL")) { - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_INIT()=" - "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" - "unsigned char __afl_fuzz_alt[1048576];" - "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; + setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); + setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); } - if (plusplus_mode) { + aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || + getenv("AFL_GCC_CMPLOG"); - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "extern \"C\" void __afl_coverage_discard();" - "extern \"C\" void __afl_coverage_skip();" - "extern \"C\" void __afl_coverage_on();" - "extern \"C\" void __afl_coverage_off();"; +} - } else { +void mode_notification(aflcc_state_t *aflcc) { - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "void __afl_coverage_discard();" - "void __afl_coverage_skip();" - "void __afl_coverage_on();" - "void __afl_coverage_off();"; + char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); + char *ptr3 = alloc_printf(" + K-CTX-%u", aflcc->ctx_k); - } + char *ptr1 = alloc_printf( + "%s%s%s%s%s", instrument_mode_2str(aflcc->instrument_mode), + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " - "1;"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"; - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " - "__afl_fuzz_alt_ptr)"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " - "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " - "? 0 : *__afl_fuzz_len)"; + ck_free(ptr2); + ck_free(ptr3); - if (compiler_mode != GCC && compiler_mode != CLANG) { + if ((isatty(2) && !be_quiet) || aflcc->debug) { - cc_params[cc_par_cnt++] = - "-D__AFL_LOOP(_A)=" - "({ static volatile const char *_B __attribute__((used,unused)); " - " _B = (const char*)\"" PERSIST_SIG - "\"; " - "extern int __afl_connected;" -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " -#else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " -#endif /* ^__APPLE__ */ - // if afl is connected, we run _A times, else once. - "_L(__afl_connected ? _A : 1); })"; - - cc_params[cc_par_cnt++] = - "-D__AFL_INIT()=" - "do { static volatile const char *_A __attribute__((used,unused)); " - " _A = (const char*)\"" DEFER_SIG - "\"; " -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"___afl_manual_init\"); " -#else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " -#endif /* ^__APPLE__ */ - "_I(); } while (0)"; + SAYF(cCYA + "afl-cc" VERSION cRST + " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", + compiler_mode_2str(aflcc->compiler_mode), ptr1); } - if (x_set) { - - cc_params[cc_par_cnt++] = "-x"; - cc_params[cc_par_cnt++] = "none"; - - } + ck_free(ptr1); - // prevent unnecessary build errors - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) { + if (!be_quiet && + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG)) { - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + WARNF( + "You are using outdated instrumentation, install LLVM and/or " + "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " + "instead!"); } - if (preprocessor_only || have_c || !non_dash) { +} - /* In the preprocessor_only case (-E), we are not actually compiling at - all but requesting the compiler to output preprocessed sources only. - We must not add the runtime in this case because the compiler will - simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ - cc_params[cc_par_cnt] = NULL; - return; +void add_real_argv0(aflcc_state_t *aflcc) { - } + static u8 llvm_fullpath[PATH_MAX]; -#ifndef __ANDROID__ + if (aflcc->plusplus_mode) { - if (compiler_mode != GCC && compiler_mode != CLANG) { + u8 *alt_cxx = getenv("AFL_CXX"); - switch (bit_mode) { + if (!alt_cxx) { - case 0: - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt.o", obj_path); - if (lto_mode) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); - break; + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - case 32: - if (!shared_linking && !partial_linking) { + alt_cxx = "g++"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cxx = "clang++"; - if (lto_mode) { + } else { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); + alt_cxx = llvm_fullpath; - } + } - break; + } - case 64: - if (!shared_linking && !partial_linking) { + aflcc->cc_params[0] = alt_cxx; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + } else { - } + u8 *alt_cc = getenv("AFL_CC"); - if (lto_mode) { + if (!alt_cc) { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - } + alt_cc = "gcc"; - break; + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cc = "clang"; - #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); - #endif + } else { - #if defined(__APPLE__) - if (shared_linking || partial_linking) { + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); + alt_cc = llvm_fullpath; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___afl_area_ptr"; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___sanitizer_cov_trace_pc_guard_init"; + } } - #endif + aflcc->cc_params[0] = alt_cc; } - #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - cc_params[cc_par_cnt++] = "-lrt"; - #endif - -#endif - - cc_params[cc_par_cnt] = NULL; - } -/* Main entry point */ +/* Macro defs for the preprocessor */ -int main(int argc, char **argv, char **envp) { +void add_defs_common(aflcc_state_t *aflcc) { - int i; - char *callname = argv[0], *ptr = NULL; + insert_param(aflcc, "-D__AFL_COMPILER=1"); + insert_param(aflcc, "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"); - if (getenv("AFL_DEBUG")) { +} - debug = 1; - if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); +/* See instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives */ +void add_defs_selective_instr(aflcc_state_t *aflcc) { - } else if (getenv("AFL_QUIET")) + if (aflcc->plusplus_mode) { - be_quiet = 1; + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "extern \"C\" void __afl_coverage_discard();" + "extern \"C\" void __afl_coverage_skip();" + "extern \"C\" void __afl_coverage_on();" + "extern \"C\" void __afl_coverage_off();"); - if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || - getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || - getenv("AFL_LLVM_BLOCKLIST")) { + } else { - have_instr_env = 1; + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "void __afl_coverage_discard();" + "void __afl_coverage_skip();" + "void __afl_coverage_on();" + "void __afl_coverage_off();"); } - if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { + insert_param( + aflcc, + "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " + "1;"); + insert_param(aflcc, "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"); + insert_param(aflcc, "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"); + insert_param(aflcc, "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"); + insert_param(aflcc, "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"); - passthrough = 1; - if (!debug) { be_quiet = 1; } +} - } +/* As documented in instrumentation/README.persistent_mode.md, deferred + forkserver initialization and persistent mode are not available in afl-gcc + and afl-clang. */ +void add_defs_persistent_mode(aflcc_state_t *aflcc) { - if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1; - argvnull = (u8 *)argv[0]; - check_environment_vars(envp); + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; - if ((ptr = find_object("as", argv[0])) != NULL) { + insert_param(aflcc, "-D__AFL_HAVE_MANUAL_CONTROL=1"); - have_gcc = 1; - ck_free(ptr); + /* When the user tries to use persistent or deferred forkserver modes by + appending a single line to the program, we want to reliably inject a + signature into the binary (to be picked up by afl-fuzz) and we want + to call a function from the runtime .o file. This is unnecessarily + painful for three reasons: - } + 1) We need to convince the compiler not to optimize out the signature. + This is done with __attribute__((used)). -#if (LLVM_MAJOR >= 3) + 2) We need to convince the linker, when called with -Wl,--gc-sections, + not to do the same. This is done by forcing an assignment to a + 'volatile' pointer. - if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) { + 3) We need to declare __afl_persistent_loop() in the global namespace, + but doing this within a method in a class is hard - :: and extern "C" + are forbidden and __attribute__((alias(...))) doesn't work. Hence the + __asm__ aliasing trick. - have_lto = 1; - ck_free(ptr); + */ - } + insert_param(aflcc, + "-D__AFL_FUZZ_INIT()=" + "int __afl_sharedmem_fuzzing = 1;" + "extern unsigned int *__afl_fuzz_len;" + "extern unsigned char *__afl_fuzz_ptr;" + "unsigned char __afl_fuzz_alt[1048576];" + "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"); - if ((ptr = find_object("cmplog-routines-pass.so", argv[0])) != NULL) { + insert_param(aflcc, + "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " + "__afl_fuzz_alt_ptr)"); - have_llvm = 1; - ck_free(ptr); + insert_param( + aflcc, + "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " + "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " + "? 0 : *__afl_fuzz_len)"); + + insert_param( + aflcc, + "-D__AFL_LOOP(_A)=" + "({ static volatile const char *_B __attribute__((used,unused)); " + " _B = (const char*)\"" PERSIST_SIG + "\"; " + "extern int __afl_connected;" +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " +#else + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " +#endif /* ^__APPLE__ */ + // if afl is connected, we run _A times, else once. + "_L(__afl_connected ? _A : 1); })"); + + insert_param( + aflcc, + "-D__AFL_INIT()=" + "do { static volatile const char *_A __attribute__((used,unused)); " + " _A = (const char*)\"" DEFER_SIG + "\"; " +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"___afl_manual_init\"); " +#else + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " +#endif /* ^__APPLE__ */ + "_I(); } while (0)"); - } +} -#endif +/* Control _FORTIFY_SOURCE */ +void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { -#ifdef __ANDROID__ - have_llvm = 1; -#endif + switch (action) { - if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) { + case 1: + insert_param(aflcc, "-D_FORTIFY_SOURCE=1"); + break; - have_gcc_plugin = 1; - ck_free(ptr); + case 2: + insert_param(aflcc, "-D_FORTIFY_SOURCE=2"); + break; + + default: // OFF + insert_param(aflcc, "-U_FORTIFY_SOURCE"); + break; } -#if (LLVM_MAJOR >= 3) +} - if (strncmp(callname, "afl-clang-fast", 14) == 0) { +void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { - compiler_mode = LLVM; + insert_param(aflcc, "-includesanitizer/lsan_interface.h"); + insert_param( + aflcc, + "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " + "_exit(23); }"); + insert_param(aflcc, "-D__AFL_LSAN_OFF()=__lsan_disable();"); + insert_param(aflcc, "-D__AFL_LSAN_ON()=__lsan_enable();"); - } else if (strncmp(callname, "afl-clang-lto", 13) == 0 || +} - strncmp(callname, "afl-lto", 7) == 0) { +/* About fsanitize (including PCGUARD features) */ - compiler_mode = LTO; +/* For input "-fsanitize=...", it: - } else + 1. may have various OOB traps :) if ... doesn't contain ',' or + the input has bad syntax such as "-fsantiz=," + 2. strips any fuzzer* in ... and writes back (may result in "-fsanitize=") + 3. rets 1 if exactly "fuzzer" found, otherwise rets 0 +*/ +static u8 fsanitize_fuzzer_comma(char *string) { -#endif - if (strncmp(callname, "afl-gcc-fast", 12) == 0 || + u8 detect_single_fuzzer = 0; + + char *p, *ptr = string + strlen("-fsanitize="); + // ck_alloc will check alloc failure + char *new = ck_alloc(strlen(string) + 1); + char *tmp = ck_alloc(strlen(ptr) + 1); + u32 count = 0, len, ende = 0; - strncmp(callname, "afl-g++-fast", 12) == 0) { + strcpy(new, "-fsanitize="); + + do { + + p = strchr(ptr, ','); + if (!p) { - compiler_mode = GCC_PLUGIN; + p = ptr + strlen(ptr) + 1; + ende = 1; - } else if (strncmp(callname, "afl-gcc", 7) == 0 || + } - strncmp(callname, "afl-g++", 7) == 0) { + len = p - ptr; + if (len) { - compiler_mode = GCC; + strncpy(tmp, ptr, len); + tmp[len] = 0; + // fprintf(stderr, "Found: %s\n", tmp); + ptr += len + 1; + if (*tmp) { - } else if (strcmp(callname, "afl-clang") == 0 || + u32 copy = 1; + if (!strcmp(tmp, "fuzzer")) { - strcmp(callname, "afl-clang++") == 0) { + detect_single_fuzzer = 1; + copy = 0; - compiler_mode = CLANG; + } else if (!strncmp(tmp, "fuzzer", 6)) { - } + copy = 0; - if ((ptr = getenv("AFL_CC_COMPILER"))) { + } - if (compiler_mode) { + if (copy) { - if (!be_quiet) { + if (count) { strcat(new, ","); } + strcat(new, tmp); + ++count; - WARNF( - "\"AFL_CC_COMPILER\" is set but a specific compiler was already " - "selected by command line parameter or symlink, ignoring the " - "environment variable!"); + } } } else { - if (strncasecmp(ptr, "LTO", 3) == 0) { + ptr++; - compiler_mode = LTO; + } - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } while (!ende); - compiler_mode = LLVM; + strcpy(string, new); + // fprintf(stderr, "string: %s\n", string); + // fprintf(stderr, "new: %s\n", new); - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + ck_free(tmp); + ck_free(new); - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + return detect_single_fuzzer; - compiler_mode = GCC_PLUGIN; +} - } else if (strcasecmp(ptr, "GCC") == 0) { +param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { - compiler_mode = GCC; + param_st final_ = PARAM_MISS; - } else + if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && + strstr(cur_argv, "list=")) { + + if (scan) { + + aflcc->have_instr_list = 1; + final_ = PARAM_SCAN; + + } else { - FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); + final_ = PARAM_KEEP; // may be set to DROP next } } - if (strcmp(callname, "afl-clang") == 0 || - strcmp(callname, "afl-clang++") == 0) { + if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { - clang_mode = 1; - compiler_mode = CLANG; + if (scan) { - if (strcmp(callname, "afl-clang++") == 0) { plusplus_mode = 1; } + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; - } + } else { - for (i = 1; i < argc; i++) { + final_ = PARAM_DROP; - if (strncmp(argv[i], "--afl", 5) == 0) { + } - if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { + } else if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize=")) && - passthrough = 1; - argv[i] = "-g"; // we have to overwrite it, -g is always good - continue; + strchr(cur_argv, ',') && + !strstr(cur_argv, "=,")) { // avoid OOB errors - } + if (scan) { - if (compiler_mode && !be_quiet) { + u8 *cur_argv_ = ck_strdup(cur_argv); - WARNF( - "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " - "symlink compiler selection!"); + if (fsanitize_fuzzer_comma(cur_argv_)) { + + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; } - ptr = argv[i]; - ptr += 5; - while (*ptr == '-') - ptr++; + ck_free(cur_argv_); - if (strncasecmp(ptr, "LTO", 3) == 0) { + } else { - compiler_mode = LTO; + fsanitize_fuzzer_comma(cur_argv); + if (!cur_argv || strlen(cur_argv) <= strlen("-fsanitize=")) + final_ = PARAM_DROP; // this means it only has "fuzzer" previously. - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } - compiler_mode = LLVM; + } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", - } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || + strlen("-fsanitize=fuzzer-")) || + !strncmp(cur_argv, "-fsanitize-coverage", + strlen("-fsanitize-coverage"))) && + (strncmp(cur_argv, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur_argv, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { - strncasecmp(ptr, "PC-GUARD", 8) == 0) { + if (scan) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_PCGUARD; + final_ = PARAM_SCAN; - } else if (strcasecmp(ptr, "INSTRIM") == 0 || + } else { - strcasecmp(ptr, "CFG") == 0) { + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); + } - } else if (strcasecmp(ptr, "AFL") == 0 || + } - strcasecmp(ptr, "CLASSIC") == 0) { + if (!strcmp(cur_argv, "-fsanitize=address") || + !strcmp(cur_argv, "-fsanitize=memory")) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_CLASSIC; + if (scan) { - } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || + // "-fsanitize=undefined,address" may be un-treated, but it's OK. + aflcc->asan_set = 1; + final_ = PARAM_SCAN; - strcasecmp(ptr, "NATIVE") == 0 || - strcasecmp(ptr, "LLVM-NATIVE") == 0) { + } else { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_LLVMNATIVE; + // It's impossible that final_ is PARAM_DROP before, + // so no checks are needed here. + final_ = PARAM_KEEP; - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + } - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + } - compiler_mode = GCC_PLUGIN; + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - } else if (strcasecmp(ptr, "GCC") == 0) { + return final_; - compiler_mode = GCC; +} - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { +void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - compiler_mode = CLANG; + if (!aflcc->asan_set) { - } else + if (getenv("AFL_USE_ASAN")) { - FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); + if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); - } + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=address"); - if (strlen(callname) > 2 && - (strncmp(callname + strlen(callname) - 2, "++", 2) == 0 || - strstr(callname, "-g++") != NULL)) - plusplus_mode = 1; + } else if (getenv("AFL_USE_MSAN")) { - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); - if (instrument_mode == 0) - instrument_mode = INSTRUMENT_PCGUARD; - else if (instrument_mode != INSTRUMENT_PCGUARD) - FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=memory"); + + } } - if (have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { + if (getenv("AFL_USE_UBSAN")) { - WARNF( - "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " - "for file matching, only function matching!"); + insert_param(aflcc, "-fsanitize=undefined"); + insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); + insert_param(aflcc, "-fno-sanitize-recover=all"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || - getenv("INSTRIM_LIB")) { + if (getenv("AFL_USE_TSAN")) { - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " - "(default in afl-cc).\n"); + insert_param(aflcc, "-fsanitize=thread"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_CTX")) instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER")) instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - - if (getenv("AFL_LLVM_NGRAM_SIZE")) { + if (getenv("AFL_USE_LSAN")) { - instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; - ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " - "(%u)", - NGRAM_SIZE_MAX); + insert_param(aflcc, "-fsanitize=leak"); + add_defs_lsan_ctrl(aflcc); } - if (getenv("AFL_LLVM_CTX_K")) { + if (getenv("AFL_USE_CFISAN")) { - ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", - CTX_MAX_K); - if (ctx_k == 1) { + if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + insert_param(aflcc, "-fcf-protection=full"); } else { - instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; + if (!aflcc->lto_mode) { + + 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"); + + } + + insert_param(aflcc, "-fsanitize=cfi"); + insert_param(aflcc, "-fvisibility=hidden"); } } - if (getenv("AFL_LLVM_INSTRUMENT")) { +} - u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); +void add_native_pcguard(aflcc_state_t *aflcc) { - while (ptr2) { + /* If llvm-config doesn't figure out LLVM_MAJOR, just + go on anyway and let compiler complain if doesn't work. */ - if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || - strncasecmp(ptr2, "classic", strlen("classic")) == 0) { + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - if (instrument_mode == INSTRUMENT_LTO) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); +#endif - instrument_mode = INSTRUMENT_CLASSIC; - lto_mode = 1; + } else { - } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); +#endif - instrument_mode = INSTRUMENT_AFL; + } - } else { +} - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); +void add_optimized_pcguard(aflcc_state_t *aflcc) { - } +#if LLVM_MAJOR >= 13 + #if defined __ANDROID__ || ANDROID - } + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || - strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { + #else - if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) - instrument_mode = INSTRUMENT_PCGUARD; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + if (aflcc->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"); - if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || - strncasecmp(ptr2, "native", strlen("native")) == 0) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) - instrument_mode = INSTRUMENT_LLVMNATIVE; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } else { - } + /* Since LLVM_MAJOR >= 13 we use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0); - if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || - strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { + } - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + #endif // defined __ANDROID__ || ANDROID +#else // LLVM_MAJOR < 13 + #if LLVM_MAJOR >= 4 - instrument_mode = INSTRUMENT_LLVMNATIVE; - instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } else { + #else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - } + #endif +#endif - } +} - if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || - strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { +/* Linking behaviors */ - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); +param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, + u8 *skip_next, char **argv) { - } + if (aflcc->lto_mode && !strncmp(cur_argv, "-flto=thin", 10)) { - if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); - lto_mode = 1; - if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) - instrument_mode = INSTRUMENT_LTO; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } - } + param_st final_ = PARAM_MISS; - if (strcasecmp(ptr2, "gcc") == 0) { + if (!strcmp(cur_argv, "-shared") || !strcmp(cur_argv, "-dynamiclib")) { - if (!instrument_mode || instrument_mode == INSTRUMENT_GCC) - instrument_mode = INSTRUMENT_GCC; - else if (instrument_mode != INSTRUMENT_GCC) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = GCC; + if (scan) { - } + aflcc->shared_linking = 1; + final_ = PARAM_SCAN; - if (strcasecmp(ptr2, "clang") == 0) { + } else { - if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG) - instrument_mode = INSTRUMENT_CLANG; - else if (instrument_mode != INSTRUMENT_CLANG) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = CLANG; + final_ = PARAM_KEEP; - } + } - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || - strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || - strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { + } else if (!strcmp(cur_argv, "-Wl,-r") || !strcmp(cur_argv, "-Wl,-i") || - u8 *ptr3 = ptr2; - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + !strcmp(cur_argv, "-Wl,--relocatable") || + !strcmp(cur_argv, "-r") || !strcmp(cur_argv, "--relocatable")) { - if (!*ptr3) { + if (scan) { - if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) - FATAL( - "you must set the K-CTX K with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ctx-2"); + aflcc->partial_linking = 1; + final_ = PARAM_SCAN; - } + } else { - ctx_k = atoi(ptr3); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL( - "K-CTX instrumentation option must be between 1 and CTX_MAX_K " - "(%u)", - CTX_MAX_K); + final_ = PARAM_KEEP; - if (ctx_k == 1) { + } - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); + } else if (!strncmp(cur_argv, "-fuse-ld=", 9) || - } else { + !strncmp(cur_argv, "--ld-path=", 10)) { - instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); - u8 *ptr4 = alloc_printf("%u", ctx_k); - setenv("AFL_LLVM_CTX_K", ptr4, 1); + if (scan) { - } + final_ = PARAM_SCAN; - } + } else { - if (strcasecmp(ptr2, "ctx") == 0) { + if (aflcc->lto_mode) + final_ = PARAM_DROP; + else + final_ = PARAM_KEEP; - instrument_opt_mode |= INSTRUMENT_OPT_CTX; - setenv("AFL_LLVM_CTX", "1", 1); + } - } + } else if (!strcmp(cur_argv, "-Wl,-z,defs") || - if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { + !strcmp(cur_argv, "-Wl,--no-undefined") || + !strcmp(cur_argv, "--no-undefined") || + strstr(cur_argv, "afl-compiler-rt") || + strstr(cur_argv, "afl-llvm-rt")) { - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); + if (scan) { - } + final_ = PARAM_SCAN; - if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { + } else { - u8 *ptr3 = ptr2 + strlen("ngram"); - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + final_ = PARAM_DROP; - if (!*ptr3) { + } - if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) - FATAL( - "you must set the NGRAM size with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ngram-2"); + } else if (!strcmp(cur_argv, "-z") || !strcmp(cur_argv, "-Wl,-z")) { - } + u8 *param = *(argv + 1); + if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { - ngram_size = atoi(ptr3); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation option must be between 2 and " - "NGRAM_SIZE_MAX (%u)", - NGRAM_SIZE_MAX); - instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); - u8 *ptr4 = alloc_printf("%u", ngram_size); - setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); + *skip_next = 1; - } + if (scan) { - ptr2 = strtok(NULL, ":,;"); + final_ = PARAM_SCAN; - } + } else { - } + final_ = PARAM_DROP; - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { + } - FATAL("you cannot set CTX and CALLER together"); + } } - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - FATAL("you cannot set CTX and K-CTX together"); + return final_; - } +} - if ((instrument_opt_mode & INSTRUMENT_OPT_CALLER) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { +void add_lto_linker(aflcc_state_t *aflcc) { - FATAL("you cannot set CALLER and K-CTX together"); + unsetenv("AFL_LD"); + unsetenv("AFL_LD_CALLER"); - } + u8 *ld_path = NULL; + if (getenv("AFL_REAL_LD")) { - if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT && - (compiler_mode == LLVM || compiler_mode == UNSET)) { + ld_path = strdup(getenv("AFL_REAL_LD")); - instrument_mode = INSTRUMENT_CLASSIC; - compiler_mode = LLVM; + } else { + + ld_path = strdup(AFL_REAL_LD); } - if (!compiler_mode) { + if (!ld_path || !*ld_path) { - // lto is not a default because outside of afl-cc RANLIB and AR have to - // be set to LLVM versions so this would work - if (have_llvm) - compiler_mode = LLVM; - else if (have_gcc_plugin) - compiler_mode = GCC_PLUGIN; - else if (have_gcc) -#ifdef __APPLE__ - // on OSX clang masquerades as GCC - compiler_mode = CLANG; -#else - compiler_mode = GCC; -#endif - else if (have_lto) - compiler_mode = LTO; - else - FATAL("no compiler mode available"); + if (ld_path) { - } + // Freeing empty string + free(ld_path); - /* if our PCGUARD implementation is not available then silently switch to - native LLVM PCGUARD */ - if (compiler_mode == CLANG && - (instrument_mode == INSTRUMENT_DEFAULT || - instrument_mode == INSTRUMENT_PCGUARD) && - find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) { + } - instrument_mode = INSTRUMENT_LLVMNATIVE; + ld_path = strdup("ld.lld"); } - if (compiler_mode == GCC) { - - if (clang_mode) { - - instrument_mode = INSTRUMENT_CLANG; + if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 + insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); +#else + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); +#endif + free(ld_path); - } else { +} - instrument_mode = INSTRUMENT_GCC; +void add_lto_passes(aflcc_state_t *aflcc) { + +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 + // The NewPM implementation only works fully since LLVM 15. + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", + 0); +#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#else + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#endif + + insert_param(aflcc, "-Wl,--allow-multiple-definition"); + insert_param(aflcc, aflcc->lto_flag); + +} + +static void add_aflpplib(aflcc_state_t *aflcc) { + + if (!aflcc->need_aflpplib) return; + + u8 *afllib = find_object(aflcc, "libAFLDriver.a"); + + if (!be_quiet) { + + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + + } + + if (!afllib) { + + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); } + } else { + + insert_param(aflcc, afllib); + +#ifdef __APPLE__ + insert_param(aflcc, "-Wl,-undefined"); + insert_param(aflcc, "dynamic_lookup"); +#endif + + } + +} + +void add_runtime(aflcc_state_t *aflcc) { + + if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { + + /* In the preprocessor_only case (-E), we are not actually compiling at + all but requesting the compiler to output preprocessed sources only. + We must not add the runtime in this case because the compiler will + simply output its binary content back on stdout, breaking any build + systems that rely on a separate source preprocessing step. */ + return; + + } + + if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC && + !getenv("AFL_LLVM_NO_RPATH")) { + + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + const char *libdir = LLVM_LIBDIR; + if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { + + u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); + insert_param(aflcc, libdir_opt); + + } + + } + +#ifndef __ANDROID__ + + #define M32_ERR_MSG "-m32 is not supported by your compiler" + #define M64_ERR_MSG "-m64 is not supported by your compiler" + + if (aflcc->compiler_mode != GCC && aflcc->compiler_mode != CLANG) { + + switch (aflcc->bit_mode) { + + case 0: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt.o", 0, 0); + if (aflcc->lto_mode) insert_object(aflcc, "afl-llvm-rt-lto.o", 0, 0); + break; + + case 32: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-32.o", 0, M32_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-32.o", 0, M32_ERR_MSG); + break; + + case 64: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-64.o", 0, M64_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-64.o", 0, M64_ERR_MSG); + break; + + } + + #if !defined(__APPLE__) && !defined(__sun) + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); + #endif + + #if defined(__APPLE__) + if (aflcc->shared_linking || aflcc->partial_linking) { + + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___afl_area_ptr"); + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___sanitizer_cov_trace_pc_guard_init"); + + } + + #endif + + } + +#endif + + add_aflpplib(aflcc); + +#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ + insert_param(aflcc, "-Wl,-lrt"); +#endif + +} + +/* Misc */ + +void add_assembler(aflcc_state_t *aflcc) { + + u8 *afl_as = find_object(aflcc, "as"); + + if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); + + u8 *slash = strrchr(afl_as, '/'); + if (slash) *slash = 0; + + insert_param(aflcc, "-B"); + insert_param(aflcc, afl_as); + + if (aflcc->compiler_mode == CLANG) insert_param(aflcc, "-no-integrated-as"); + +} + +void add_gcc_plugin(aflcc_state_t *aflcc) { + + if (aflcc->cmplog_mode) { + + insert_object(aflcc, "afl-gcc-cmplog-pass.so", "-fplugin=%s", 0); + insert_object(aflcc, "afl-gcc-cmptrs-pass.so", "-fplugin=%s", 0); + + } + + insert_object(aflcc, "afl-gcc-pass.so", "-fplugin=%s", 0); + + insert_param(aflcc, "-fno-if-conversion"); + insert_param(aflcc, "-fno-if-conversion2"); + +} + +void add_misc_params(aflcc_state_t *aflcc) { + + if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || + aflcc->lto_mode) { + + insert_param(aflcc, "-fno-builtin-strcmp"); + insert_param(aflcc, "-fno-builtin-strncmp"); + insert_param(aflcc, "-fno-builtin-strcasecmp"); + insert_param(aflcc, "-fno-builtin-strncasecmp"); + insert_param(aflcc, "-fno-builtin-memcmp"); + insert_param(aflcc, "-fno-builtin-bcmp"); + insert_param(aflcc, "-fno-builtin-strstr"); + insert_param(aflcc, "-fno-builtin-strcasestr"); + + } + + if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } + + if (getenv("AFL_HARDEN")) { + + insert_param(aflcc, "-fstack-protector-all"); + + if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); + + } + + if (!getenv("AFL_DONT_OPTIMIZE")) { + + insert_param(aflcc, "-g"); + if (!aflcc->have_o) insert_param(aflcc, "-O3"); + if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); + // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') + // insert_param(aflcc, aflcc->march_opt); + } - if (compiler_mode == CLANG) { + if (aflcc->x_set) { - instrument_mode = INSTRUMENT_CLANG; - setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + insert_param(aflcc, "-x"); + insert_param(aflcc, "none"); } +} + +param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { + + param_st final_ = PARAM_MISS; + +// MACRO START +#define SCAN_KEEP(dst, src) \ + do { \ + \ + if (scan) { \ + \ + dst = src; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } while (0) + + // MACRO END + + if (!strncasecmp(cur_argv, "-fpic", 5)) { + + SCAN_KEEP(aflcc->have_pic, 1); + + } else if (cur_argv[0] != '-') { + + SCAN_KEEP(aflcc->non_dash, 1); + + } else if (!strcmp(cur_argv, "-m32") || + + !strcmp(cur_argv, "armv7a-linux-androideabi")) { + + SCAN_KEEP(aflcc->bit_mode, 32); + + } else if (!strcmp(cur_argv, "-m64")) { + + SCAN_KEEP(aflcc->bit_mode, 64); + + } else if (strstr(cur_argv, "FORTIFY_SOURCE")) { + + SCAN_KEEP(aflcc->fortify_set, 1); + + } else if (!strcmp(cur_argv, "-x")) { + + SCAN_KEEP(aflcc->x_set, 1); + + } else if (!strcmp(cur_argv, "-E")) { + + SCAN_KEEP(aflcc->preprocessor_only, 1); + + } else if (!strcmp(cur_argv, "--target=wasm32-wasi")) { + + SCAN_KEEP(aflcc->passthrough, 1); + + } else if (!strcmp(cur_argv, "-c")) { + + SCAN_KEEP(aflcc->have_c, 1); + + } else if (!strncmp(cur_argv, "-O", 2)) { + + SCAN_KEEP(aflcc->have_o, 1); + + } else if (!strncmp(cur_argv, "-funroll-loop", 13)) { + + SCAN_KEEP(aflcc->have_unroll, 1); + + } else if (!strncmp(cur_argv, "--afl", 5)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-fno-unroll", 11)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strcmp(cur_argv, "-pipe") && aflcc->compiler_mode == GCC_PLUGIN) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-stdlib=", 8) && + + (aflcc->compiler_mode == GCC || + aflcc->compiler_mode == GCC_PLUGIN)) { + + if (scan) { + + final_ = PARAM_SCAN; + + } else { + + if (!be_quiet) WARNF("Found '%s' - stripping!", cur_argv); + final_ = PARAM_DROP; + + } + + } + +#undef SCAN_KEEP + + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); + + return final_; + +} + +static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { + if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { printf("afl-cc" VERSION @@ -2168,16 +2433,18 @@ int main(int argc, char **argv, char **envp) { " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - have_llvm ? "AVAILABLE" : "unavailable!", - compiler_mode == LLVM ? " [SELECTED]" : "", - have_llvm ? "AVAILABLE" : "unavailable!", - have_llvm ? "AVAILABLE" : "unavailable!", - have_lto ? "AVAILABLE" : "unavailable!", - compiler_mode == LTO ? " [SELECTED]" : "", - have_gcc_plugin ? "AVAILABLE" : "unavailable!", - compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", - have_gcc ? "AVAILABLE" : "unavailable!", - (compiler_mode == GCC || compiler_mode == CLANG) ? " [SELECTED]" : ""); + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LLVM ? " [SELECTED]" : "", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_lto ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LTO ? " [SELECTED]" : "", + aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", + aflcc->have_gcc ? "AVAILABLE" : "unavailable!", + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) + ? " [SELECTED]" + : ""); SAYF( "Modes:\n" @@ -2266,7 +2533,7 @@ int main(int argc, char **argv, char **envp) { " AFL_USE_TSAN: activate thread sanitizer\n" " AFL_USE_LSAN: activate leak-checker sanitizer\n"); - if (have_gcc_plugin) + if (aflcc->have_gcc_plugin) SAYF( "\nGCC Plugin-specific environment variables:\n" " AFL_GCC_CMPLOG: log operands of comparisons (RedQueen mutator)\n" @@ -2282,7 +2549,7 @@ int main(int argc, char **argv, char **envp) { #define COUNTER_BEHAVIOUR \ " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" #endif - if (have_llvm) + if (aflcc->have_llvm) SAYF( "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " "variables:\n" @@ -2310,7 +2577,7 @@ int main(int argc, char **argv, char **envp) { "instrument allow/\n" " deny listing (selective instrumentation)\n"); - if (have_llvm) + if (aflcc->have_llvm) SAYF( " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " "mutator)\n" @@ -2329,7 +2596,7 @@ int main(int argc, char **argv, char **envp) { "locations\n"); #ifdef AFL_CLANG_FLTO - if (have_lto) + if (aflcc->have_lto) SAYF( "\nLTO/afl-clang-lto specific environment variables:\n" " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), " @@ -2365,9 +2632,9 @@ int main(int argc, char **argv, char **envp) { "targets.\n\n"); #if (LLVM_MAJOR >= 3) - if (have_lto) + if (aflcc->have_lto) SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO); - if (have_llvm) + if (aflcc->have_llvm) SAYF("afl-cc LLVM version %d using the binary path \"%s\".\n", LLVM_MAJOR, LLVM_BINDIR); #endif @@ -2406,205 +2673,350 @@ int main(int argc, char **argv, char **envp) { } - if (compiler_mode == LTO) { - - if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO || - instrument_mode == INSTRUMENT_CFG || - instrument_mode == INSTRUMENT_PCGUARD) { +} - lto_mode = 1; - // force CFG - // if (!instrument_mode) { +static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, + char **argv) { - instrument_mode = INSTRUMENT_PCGUARD; - // ptr = instrument_mode_string[instrument_mode]; - // } + limit_params(aflcc, argc); - } else if (instrument_mode == INSTRUMENT_CLASSIC) { + // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); - lto_mode = 1; + /* Process the argument list. */ - } else { + u8 skip_next = 0; + while (--argc) { - if (!be_quiet) { + u8 *cur = *(++argv); - WARNF("afl-clang-lto called with mode %s, using that mode instead", - instrument_mode_string[instrument_mode]); + if (skip_next > 0) { - } + skip_next--; + continue; } - } + if (PARAM_MISS != parse_misc_params(aflcc, cur, scan)) continue; - if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) { + if (PARAM_MISS != parse_fsanitize(aflcc, cur, scan)) continue; -#if LLVM_MAJOR >= 7 - #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (have_instr_env) { + if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv)) + continue; - instrument_mode = INSTRUMENT_AFL; - if (!be_quiet) { + if (*cur == '@') { - WARNF( - "Switching to classic instrumentation because " - "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); + // response file support. + // 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. + // We do *not* support quotes in the rsp files to cope with spaces in + // filenames etc! If you need that then send a patch! + u8 *filename = cur + 1; + if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } + FILE *f = fopen(filename, "r"); + struct stat st; + + // Check not found or empty? let the compiler complain if so. + if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + + if (!scan) insert_param(aflcc, cur); + continue; } - } else + u8 *tmpbuf = malloc(st.st_size + 2), *ptr; + char **args = malloc(sizeof(char *) * (st.st_size >> 1)); + int count = 1, cont = 0, cont_act = 0; - #endif - instrument_mode = INSTRUMENT_PCGUARD; + while (fgets(tmpbuf, st.st_size + 1, f)) { -#else - instrument_mode = INSTRUMENT_AFL; -#endif + ptr = tmpbuf; + // fprintf(stderr, "1: %s\n", ptr); + // no leading whitespace + while (isspace(*ptr)) { - } + ++ptr; + cont_act = 0; - if (instrument_opt_mode && compiler_mode != LLVM) - FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); + } - if (!instrument_opt_mode) { + // no comments, no empty lines + if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } + // remove LF + if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } + // remove CR + if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } + // handle \ at end of line + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { - if (lto_mode && instrument_mode == INSTRUMENT_CFG) - instrument_mode = INSTRUMENT_PCGUARD; - ptr = instrument_mode_string[instrument_mode]; + cont = 1; + ptr[strlen(ptr) - 1] = 0; - } else { + } - char *ptr2 = alloc_printf(" + NGRAM-%u", ngram_size); - char *ptr3 = alloc_printf(" + K-CTX-%u", ctx_k); + // fprintf(stderr, "2: %s\n", ptr); - ptr = alloc_printf( - "%s%s%s%s%s", instrument_mode_string[instrument_mode], - (instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", - (instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", - (instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); + // remove whitespace at end + while (*ptr && isspace(ptr[strlen(ptr) - 1])) { - ck_free(ptr2); - ck_free(ptr3); + ptr[strlen(ptr) - 1] = 0; + cont = 0; - } + } -#ifndef AFL_CLANG_FLTO - if (lto_mode) - FATAL( - "instrumentation mode LTO specified but LLVM support not available " - "(requires LLVM 11 or higher)"); -#endif + // fprintf(stderr, "3: %s\n", ptr); + if (*ptr) { - if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV && - instrument_mode != INSTRUMENT_CLASSIC) - FATAL( - "CALLER, CTX and NGRAM instrumentation options can only be used with " - "the LLVM CLASSIC instrumentation mode."); + do { - if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) - FATAL( - "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " - "together"); + u8 *value = ptr; + while (*ptr && !isspace(*ptr)) { -#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) { + ++ptr; - FATAL( - "Instrumentation type PCGUARD does not support " - "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); + } - } + while (*ptr && isspace(*ptr)) { -#endif + *ptr++ = 0; - u8 *ptr2; + } - if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') - FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); + if (cont_act) { - if ((isatty(2) && !be_quiet) || debug) { + u32 len = strlen(args[count - 1]) + strlen(value) + 1; + u8 *tmp = malloc(len); + snprintf(tmp, len, "%s%s", args[count - 1], value); + free(args[count - 1]); + args[count - 1] = tmp; + cont_act = 0; - SAYF(cCYA - "afl-cc" VERSION cRST - " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", - compiler_mode_string[compiler_mode], ptr); + } else { - } + args[count++] = strdup(value); - if (!be_quiet && (compiler_mode == GCC || compiler_mode == CLANG)) { + } - WARNF( - "You are using outdated instrumentation, install LLVM and/or " - "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " - "instead!"); + } while (*ptr); + + } + + if (cont) { + + cont_act = 1; + cont = 0; + + } + + } + + if (count) { process_params(aflcc, scan, count, args); } + + // we cannot free args[] unless we don't need + // to keep any reference in cc_params + if (scan) { + + if (count) do { + + free(args[--count]); + + } while (count); + + free(args); + + } + + free(tmpbuf); + + continue; + + } + + if (!scan) insert_param(aflcc, cur); } - if (debug) { +} - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < argc; i++) - SAYF(" '%s'", argv[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); +/* Copy argv to cc_params, making the necessary edits. */ + +static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, + char **envp) { + + 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 (getenv("AFL_LLVM_LAF_ALL")) { + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) { - setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); - setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); + add_assembler(aflcc); } - cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || - getenv("AFL_GCC_CMPLOG"); + if (aflcc->compiler_mode == GCC_PLUGIN) { add_gcc_plugin(aflcc); } -#if !defined(__ANDROID__) && !defined(ANDROID) - ptr = find_object("afl-compiler-rt.o", argv[0]); + if (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == LTO) { - if (!ptr) { + if (aflcc->lto_mode && aflcc->have_instr_env) { - FATAL( - "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " - "environment variable."); + load_llvm_pass(aflcc, "afl-llvm-lto-instrumentlist.so"); - } + } - if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); } + if (getenv("AFL_LLVM_DICT2FILE")) { - ck_free(ptr); -#endif + load_llvm_pass(aflcc, "afl-llvm-dict2file.so"); - edit_params(argc, argv, envp); + } - if (debug) { + // laf + if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < (s32)cc_par_cnt; i++) - SAYF(" '%s'", cc_params[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); + 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 && !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"); + + } + + } + + if (aflcc->cmplog_mode) { + + load_llvm_pass(aflcc, "cmplog-instructions-pass.so"); + load_llvm_pass(aflcc, "cmplog-routines-pass.so"); + + } + + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_SQL") || + getenv("AFL_LLVM_INJECTIONS_LDAP") || + getenv("AFL_LLVM_INJECTIONS_XSS")) { + + load_llvm_pass(aflcc, "injection-pass.so"); + + } + + // insert_param(aflcc, "-Qunused-arguments"); } - if (passthrough) { + /* Inspect the command line parameters. */ + + process_params(aflcc, 0, argc, argv); + + add_sanitizers(aflcc, envp); + + add_misc_params(aflcc); + + add_defs_common(aflcc); + add_defs_selective_instr(aflcc); + add_defs_persistent_mode(aflcc); + + add_runtime(aflcc); + + insert_param(aflcc, NULL); + +} + +/* Main entry point */ + +int main(int argc, char **argv, char **envp) { + + aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); + aflcc_state_init(aflcc, (u8 *)argv[0]); + + check_environment_vars(envp); + + find_built_deps(aflcc); + + compiler_mode_by_callname(aflcc); + compiler_mode_by_environ(aflcc); + compiler_mode_by_cmdline(aflcc, argc, argv); + + instrument_mode_by_environ(aflcc); + + mode_final_checkout(aflcc, argc, argv); + + process_params(aflcc, 1, argc, argv); + + maybe_usage(aflcc, argc, argv); + + mode_notification(aflcc); + + if (aflcc->debug) debugf_args(argc, argv); + + edit_params(aflcc, argc, argv, envp); + + if (aflcc->debug) + debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); + + if (aflcc->passthrough) { - argv[0] = cc_params[0]; - execvp(cc_params[0], (char **)argv); + argv[0] = aflcc->cc_params[0]; + execvp(aflcc->cc_params[0], (char **)argv); } else { - execvp(cc_params[0], (char **)cc_params); + execvp(aflcc->cc_params[0], (char **)aflcc->cc_params); } - FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); + FATAL("Oops, failed to execute '%s' - check your PATH", aflcc->cc_params[0]); return 0; -- cgit 1.4.1 From 4e9c6050d038c852db4f1a22fad2e8c678c9f053 Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 11 Jan 2024 18:44:40 +0800 Subject: Fix broken LTO mode and response file support (#1948) --- src/afl-cc.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 08348d2c..5ee19e42 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2059,7 +2059,6 @@ void add_lto_passes(aflcc_state_t *aflcc) { #endif insert_param(aflcc, "-Wl,--allow-multiple-definition"); - insert_param(aflcc, aflcc->lto_flag); } @@ -2295,10 +2294,6 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_pic, 1); - } else if (cur_argv[0] != '-') { - - SCAN_KEEP(aflcc->non_dash, 1); - } else if (!strcmp(cur_argv, "-m32") || !strcmp(cur_argv, "armv7a-linux-androideabi")) { @@ -2374,6 +2369,14 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } + } else if (cur_argv[0] != '-') { + + /* It's a weak, loose pattern, with very different purpose + than others. We handle it at last, cautiously and robustly. */ + + if (scan && cur_argv[0] != '@') // response file support + aflcc->non_dash = 1; + } #undef SCAN_KEEP @@ -2912,10 +2915,16 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, // use. insert_param(aflcc, "-flegacy-pass-manager"); // #endif - if (aflcc->lto_mode && !aflcc->have_c) { + if (aflcc->lto_mode) { + + insert_param(aflcc, aflcc->lto_flag); + + if (!aflcc->have_c) { - add_lto_linker(aflcc); - add_lto_passes(aflcc); + add_lto_linker(aflcc); + add_lto_passes(aflcc); + + } } else { -- cgit 1.4.1 From 9d3c25ac8103d79217f89d79dcc7dc20873222f4 Mon Sep 17 00:00:00 2001 From: Nils Bars Date: Thu, 11 Jan 2024 11:45:26 +0100 Subject: Strip `-Wl,-no-undefined` during compilation (#1952) Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`. Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix). --- src/afl-cc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5ee19e42..f39dfdcc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1962,8 +1962,8 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } } else if (!strcmp(cur_argv, "-Wl,-z,defs") || - !strcmp(cur_argv, "-Wl,--no-undefined") || + !strcmp(cur_argv, "-Wl,-no-undefined") || !strcmp(cur_argv, "--no-undefined") || strstr(cur_argv, "afl-compiler-rt") || strstr(cur_argv, "afl-llvm-rt")) { @@ -3030,4 +3030,3 @@ int main(int argc, char **argv, char **envp) { return 0; } - -- cgit 1.4.1 From 46ef6a54e1395b3b03923848967e2b2eb7f37022 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 12 Jan 2024 15:43:09 +0100 Subject: code format --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index f39dfdcc..41cdc13d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1962,6 +1962,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } } else if (!strcmp(cur_argv, "-Wl,-z,defs") || + !strcmp(cur_argv, "-Wl,--no-undefined") || !strcmp(cur_argv, "-Wl,-no-undefined") || !strcmp(cur_argv, "--no-undefined") || @@ -3030,3 +3031,4 @@ int main(int argc, char **argv, char **envp) { return 0; } + -- cgit 1.4.1 From 8412b17d799ee011507fa0bde21f3cb34fafad6a Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:56:28 +0800 Subject: fix segv about skip_next, warn on unsupported cases of linking options (#1958) --- src/afl-cc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 41cdc13d..748fbdfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1982,7 +1982,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } else if (!strcmp(cur_argv, "-z") || !strcmp(cur_argv, "-Wl,-z")) { u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { + if (param && (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs"))) { *skip_next = 1; @@ -2000,6 +2000,64 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } + // Try to warn user for some unsupported cases + if (scan && final_ == PARAM_MISS) { + + u8 *ptr_ = NULL; + + if (!strcmp(cur_argv, "-Xlinker") && (ptr_ = *(argv + 1))) { + + if (!strcmp(ptr_, "defs")) { + + WARNF("'-Xlinker' 'defs' detected. This may result in a bad link."); + + } else if (strstr(ptr_, "-no-undefined")) { + + WARNF( + "'-Xlinker' '%s' detected. The latter option may be dropped and " + "result in a bad link.", + ptr_); + + } + + } else if (!strncmp(cur_argv, "-Wl,", 4) && + + (u8 *)strrchr(cur_argv, ',') != (cur_argv + 3)) { + + ptr_ = cur_argv + 4; + + if (strstr(ptr_, "-shared") || strstr(ptr_, "-dynamiclib")) { + + WARNF( + "'%s': multiple link options after '-Wl,' may break shared " + "linking.", + ptr_); + + } + + if (strstr(ptr_, "-r,") || strstr(ptr_, "-i,") || strstr(ptr_, ",-r") || + strstr(ptr_, ",-i") || strstr(ptr_, "--relocatable")) { + + WARNF( + "'%s': multiple link options after '-Wl,' may break partial " + "linking.", + ptr_); + + } + + if (strstr(ptr_, "defs") || strstr(ptr_, "no-undefined")) { + + WARNF( + "'%s': multiple link options after '-Wl,' may enable report " + "unresolved symbol references and result in a bad link.", + ptr_); + + } + + } + + } + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); return final_; -- cgit 1.4.1 From 136febaf6855ac1e04c8ea4ecbcb84eb42de2143 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 Jan 2024 09:17:25 +0100 Subject: ensure afl-cc only allows available compiler modes --- src/afl-cc.c | 140 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 36 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 748fbdfc..3377b42f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -167,7 +167,7 @@ typedef struct aflcc_state { u8 cmplog_mode; - u8 have_instr_env, have_gcc, have_llvm, have_gcc_plugin, have_lto, + u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, have_optimized_pcguard, have_instr_list; u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, @@ -504,13 +504,20 @@ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; +#if defined(__x86_64__) if ((ptr = find_object(aflcc, "as")) != NULL) { + #ifndef __APPLE__ + // on OSX clang masquerades as GCC aflcc->have_gcc = 1; + #endif + aflcc->have_clang = 1; ck_free(ptr); } +#endif + if ((ptr = find_object(aflcc, "SanitizerCoveragePCGUARD.so")) != NULL) { aflcc->have_optimized_pcguard = 1; @@ -604,12 +611,18 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; +#if defined(__x86_64__) + } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || strncmp(aflcc->callname, "afl-g++", 7) == 0) { aflcc->compiler_mode = GCC; +#endif + +#if defined(__x86_64__) + } else if (strcmp(aflcc->callname, "afl-clang") == 0 || strcmp(aflcc->callname, "afl-clang++") == 0) { @@ -618,6 +631,8 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { } +#endif + } void compiler_mode_by_environ(aflcc_state_t *aflcc) { @@ -660,14 +675,22 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; +#if defined(__x86_64__) + } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; +#endif + +#if defined(__x86_64__) + } else if (strcasecmp(ptr, "CLANG") == 0) { aflcc->compiler_mode = CLANG; +#endif + } else FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); @@ -751,14 +774,22 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode = GCC_PLUGIN; +#if defined(__x86_64__) + } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; +#endif + +#if defined(__x86_64__) + } else if (strncasecmp(ptr, "CLANG", 5) == 0) { aflcc->compiler_mode = CLANG; +#endif + } else FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); @@ -929,6 +960,7 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +#if defined(__x86_64__) if (strcasecmp(ptr2, "gcc") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) @@ -943,6 +975,9 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +#endif + +#if defined(__x86_64__) if (strcasecmp(ptr2, "clang") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) @@ -957,6 +992,8 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +#endif + if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { @@ -1130,12 +1167,9 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { else if (aflcc->have_gcc_plugin) aflcc->compiler_mode = GCC_PLUGIN; else if (aflcc->have_gcc) -#ifdef __APPLE__ - // on OSX clang masquerades as GCC - aflcc->compiler_mode = CLANG; -#else aflcc->compiler_mode = GCC; -#endif + else if (aflcc->have_clang) + aflcc->compiler_mode = CLANG; else if (aflcc->have_lto) aflcc->compiler_mode = LTO; else @@ -1143,6 +1177,38 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } + switch (aflcc->compiler_mode) { + + case GCC: + if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + break; + case CLANG: + if (!aflcc->have_clang) + FATAL("afl-clang not available on your platform!"); + break; + case LLVM: + if (!aflcc->have_llvm) + FATAL( + "LLVM mode is not available, please install LLVM 13+ and recompile " + "AFL++"); + break; + case GCC_PLUGIN: + if (!aflcc->have_gcc_plugin) + FATAL( + "GCC_PLUGIN mode is not available, install gcc plugin support and " + "recompile AFL++"); + break; + case LTO: + if (!aflcc->have_lto) + FATAL( + "LTO mode is not available, please install LLVM 13+ and lld of the " + "same version and recompile AFL++"); + break; + default: + FATAL("no compiler mode available"); + + } + if (aflcc->compiler_mode == GCC) { aflcc->instrument_mode = INSTRUMENT_GCC; } if (aflcc->compiler_mode == CLANG) { @@ -1217,7 +1283,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_PCGUARD; #else - aflcc->instrument_mode = INSTRUMENT_AFL; + aflcc->instrument_mode = INSTRUMENT_AFL; #endif } @@ -1491,8 +1557,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ // if afl is connected, we run _A times, else once. "_L(__afl_connected ? _A : 1); })"); @@ -1507,8 +1573,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "void _I(void) __asm__(\"___afl_manual_init\"); " #else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " #endif /* ^__APPLE__ */ "_I(); } while (0)"); @@ -1618,8 +1684,6 @@ static u8 fsanitize_fuzzer_comma(char *string) { } while (!ende); strcpy(string, new); - // fprintf(stderr, "string: %s\n", string); - // fprintf(stderr, "new: %s\n", new); ck_free(tmp); ck_free(new); @@ -1824,12 +1888,12 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); #endif } else { @@ -1838,11 +1902,11 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); #endif } @@ -1884,16 +1948,16 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { #else // LLVM_MAJOR < 13 #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); - aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif #endif @@ -2097,7 +2161,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); #else - insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); #endif free(ld_path); @@ -2110,11 +2174,11 @@ void add_lto_passes(aflcc_state_t *aflcc) { insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", 0); #elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #else - insert_param(aflcc, "-fno-experimental-new-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #endif insert_param(aflcc, "-Wl,--allow-multiple-definition"); @@ -2503,7 +2567,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode == LTO ? " [SELECTED]" : "", aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", - aflcc->have_gcc ? "AVAILABLE" : "unavailable!", + aflcc->have_gcc && aflcc->have_clang + ? "AVAILABLE" + : (aflcc->have_gcc + ? "GCC ONLY " + : (aflcc->have_clang ? "CLANG ONLY" : "unavailable!")), (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) ? " [SELECTED]" : ""); @@ -2708,7 +2776,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { SAYF("Compiled with shm_open support (adds -lrt when linking).\n"); #endif #else - SAYF("Compiled with shmat support.\n"); + SAYF("Compiled with shmat support.\n"); #endif SAYF("\n"); -- cgit 1.4.1 From e731a1c1ab48dbc9a70a9e5680f00aab307abfa1 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 18 Jan 2024 12:01:26 +0100 Subject: fix for arm64 --- src/afl-cc.c | 58 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 3377b42f..192c5423 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -629,10 +629,10 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = CLANG; - } - #endif + } + } void compiler_mode_by_environ(aflcc_state_t *aflcc) { @@ -1283,7 +1283,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_PCGUARD; #else - aflcc->instrument_mode = INSTRUMENT_AFL; + aflcc->instrument_mode = INSTRUMENT_AFL; #endif } @@ -1557,8 +1557,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " #else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " #endif /* ^__APPLE__ */ // if afl is connected, we run _A times, else once. "_L(__afl_connected ? _A : 1); })"); @@ -1573,8 +1573,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "__attribute__((visibility(\"default\"))) " "void _I(void) __asm__(\"___afl_manual_init\"); " #else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " #endif /* ^__APPLE__ */ "_I(); } while (0)"); @@ -1888,12 +1888,12 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); #endif } else { @@ -1902,11 +1902,11 @@ void add_native_pcguard(aflcc_state_t *aflcc) { FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); #endif } @@ -1948,16 +1948,16 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { #else // LLVM_MAJOR < 13 #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); - aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); #endif #endif @@ -2161,7 +2161,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); #else - insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); #endif free(ld_path); @@ -2174,11 +2174,11 @@ void add_lto_passes(aflcc_state_t *aflcc) { insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", 0); #elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #else - insert_param(aflcc, "-fno-experimental-new-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); #endif insert_param(aflcc, "-Wl,--allow-multiple-definition"); @@ -2776,7 +2776,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { SAYF("Compiled with shm_open support (adds -lrt when linking).\n"); #endif #else - SAYF("Compiled with shmat support.\n"); + SAYF("Compiled with shmat support.\n"); #endif SAYF("\n"); -- cgit 1.4.1 From 0c054f520eda67b7bb15f95ca58c028e9b68131f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 18 Jan 2024 16:17:48 +0100 Subject: push to stable (#1960) * Output afl-clang-fast stuffs only if necessary (#1912) * afl-cc header * afl-cc common declarations - Add afl-cc-state.c - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c - Use debugf_args in main - Modify execvp stuffs to fit new aflcc struct * afl-cc show usage * afl-cc mode selecting 1. compiler_mode by callname in argv[0] 2. compiler_mode by env "AFL_CC_COMPILER" 3. compiler_mode/instrument_mode by command line options "--afl-..." 4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT" 5. final checking steps 6. print "... - mode: %s-%s\n" 7. determine real argv[0] according to compiler_mode * afl-cc macro defs * afl-cc linking behaviors * afl-cc fsanitize behaviors * afl-cc misc * afl-cc body update * afl-cc all-in-one formated with custom-format.py * nits --------- Co-authored-by: vanhauser-thc * changelog * update grammar mutator * lto llvm 12+ * docs(custom_mutators): fix missing ':' (#1953) * Fix broken LTO mode and response file support (#1948) * Strip `-Wl,-no-undefined` during compilation (#1952) Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`. Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix). * Remove dead code in write_to_testcase (#1955) The custom_mutators_count check in if case is duplicate with if condition. The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed. Signed-off-by: Xeonacid * update qemuafl * WIP: Add ability to generate drcov trace using QEMU backend (#1956) * Document new drcov QEMU plugin * Add link to lightkeeper for QEMU drcov file loading --------- Co-authored-by: Jean-Romain Garnier * code format * changelog * sleep on uid != 0 afl-system-config * fix segv about skip_next, warn on unsupported cases of linking options (#1958) * todos * ensure afl-cc only allows available compiler modes * update grammar mutator * disable aslr on apple * fix for arm64 --------- Signed-off-by: Xeonacid Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com> Co-authored-by: Xeonacid Co-authored-by: Nils Bars Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com> Co-authored-by: Jean-Romain Garnier --- GNUmakefile.llvm | 6 +- afl-persistent-config | 8 + afl-system-config | 1 + docs/Changelog.md | 12 +- docs/custom_mutators.md | 2 +- include/envs.h | 319 +--- qemu_mode/QEMUAFL_VERSION | 2 +- qemu_mode/README.md | 33 +- qemu_mode/build_qemu_support.sh | 4 +- qemu_mode/qemuafl | 2 +- src/afl-cc.c | 3378 +++++++++++++++++++++++---------------- src/afl-fuzz-run.c | 41 +- src/afl-fuzz.c | 4 + 13 files changed, 2118 insertions(+), 1694 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index c704d772..7437130d 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -51,7 +51,7 @@ LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9] LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 ) LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 ) -LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[1-9]' && echo 1 || echo 0 ) +LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 ) LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) LLVM_STDCXX = gnu++11 @@ -95,12 +95,12 @@ ifeq "$(LLVM_NEWER_API)" "1" endif ifeq "$(LLVM_HAVE_LTO)" "1" - $(info [+] llvm_mode detected llvm 11+, enabling afl-lto LTO implementation) + $(info [+] llvm_mode detected llvm 12+, enabling afl-lto LTO implementation) LLVM_LTO = 1 endif ifeq "$(LLVM_LTO)" "0" - $(info [+] llvm_mode detected llvm < 11, afl-lto LTO will not be build.) + $(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.) endif ifeq "$(LLVM_APPLE_XCODE)" "1" diff --git a/afl-persistent-config b/afl-persistent-config index d78db286..26be9d9f 100755 --- a/afl-persistent-config +++ b/afl-persistent-config @@ -38,6 +38,7 @@ fi echo PLATFORM=`uname -s` +ARCH=`uname -m` # check that we're on Mac if [[ "$PLATFORM" = "Darwin" ]] ; then @@ -87,6 +88,13 @@ if [[ "$PLATFORM" = "Darwin" ]] ; then EOF + if [[ "$ARCH" = "x86_64" ]]; then + echo "Disabling ASLR system wide" + nvram boot-args="no_aslr=1" + else + echo NOTICE: on ARM64 we do not know currently how to disable system wide ASLR, please report if you know how. + fi + echo echo "Reboot and enjoy your fuzzing" exit 0 diff --git a/afl-system-config b/afl-system-config index c633e4e8..7e2cb688 100755 --- a/afl-system-config +++ b/afl-system-config @@ -25,6 +25,7 @@ echo "WARNING: this reduces the security of the system!" echo if [ '!' "$EUID" = 0 ] && [ '!' `id -u` = 0 ] ; then echo "Warning: you need to be root to run this!" + sleep 1 # we do not exit as other mechanisms exist that allows to do this than # being root. let the errors speak for themselves. fi diff --git a/docs/Changelog.md b/docs/Changelog.md index adc81d64..c681c4e1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,15 +9,23 @@ explore is slightly better now. - fixed minor issues in the mutation engine, thanks to @futhewo for reporting! + - afl-cc: + - large rewrite by @SonicStark which fixes a few corner cases, thanks! + - LTO mode now requires llvm 12+ - instrumentation: - LLVM 18 support, thanks to @devnexen! - Injection (SQL, LDAP, XSS) feature now available, see `instrumentation/README.injections.md` how to activate/use/expand. - compcov/LAF-intel: - floating point splitting bug fix by @hexcoder - - due a bug in LLVM 17 integer splitting is disabled! + - due a bug in LLVM 17 integer splitting is disabled there! - when splitting floats was selected, integers were always split as well, - fixed to require AFL_LLVM_LAF_SPLIT_COMPARES as it should + fixed to require AFL_LLVM_LAF_SPLIT_COMPARES or _ALL as it should + - qemu_mode: + - plugins are now activated by default and a new module is included that + produces drcov compatible traces for lighthouse/lightkeeper/... + thanks to @JRomainG to submitting! + - updated the custom grammar mutator ### Version ++4.09c (release) diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index ce0a42dc..73e3c802 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -73,7 +73,7 @@ def init(seed): def fuzz_count(buf): return cnt -def splice_optout() +def splice_optout(): pass def fuzz(buf, add_buf, max_size): diff --git a/include/envs.h b/include/envs.h index aa5c658e..0f645d23 100644 --- a/include/envs.h +++ b/include/envs.h @@ -16,255 +16,104 @@ static char *afl_environment_deprecated[] = { static 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_CC_COMPILER", - "AFL_CMIN_ALLOW_ANY", - "AFL_CMIN_CRASHES_ONLY", - "AFL_CMPLOG_ONLY_NEW", - "AFL_CODE_END", - "AFL_CODE_START", - "AFL_COMPCOV_BINNAME", - "AFL_COMPCOV_LEVEL", - "AFL_CRASH_EXITCODE", - "AFL_CRASHING_SEEDS_AS_NEW_CRASH", - "AFL_CUSTOM_MUTATOR_LIBRARY", - "AFL_CUSTOM_MUTATOR_ONLY", - "AFL_CUSTOM_INFO_PROGRAM", - "AFL_CUSTOM_INFO_PROGRAM_ARGV", - "AFL_CUSTOM_INFO_PROGRAM_INPUT", - "AFL_CUSTOM_INFO_OUT", - "AFL_CXX", - "AFL_CYCLE_SCHEDULES", - "AFL_DEBUG", - "AFL_DEBUG_CHILD", - "AFL_DEBUG_GDB", - "AFL_DEBUG_UNICORN", - "AFL_DISABLE_TRIM", - "AFL_DISABLE_LLVM_INSTRUMENTATION", - "AFL_DONT_OPTIMIZE", - "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", - "AFL_DUMB_FORKSRV", - "AFL_EARLY_FORKSERVER", - "AFL_ENTRYPOINT", - "AFL_EXIT_WHEN_DONE", - "AFL_EXIT_ON_TIME", - "AFL_EXIT_ON_SEED_ISSUES", - "AFL_FAST_CAL", - "AFL_FINAL_SYNC", - "AFL_FORCE_UI", - "AFL_FRIDA_DEBUG_MAPS", - "AFL_FRIDA_DRIVER_NO_HOOK", - "AFL_FRIDA_EXCLUDE_RANGES", - "AFL_FRIDA_INST_CACHE_SIZE", - "AFL_FRIDA_INST_COVERAGE_ABSOLUTE", - "AFL_FRIDA_INST_COVERAGE_FILE", - "AFL_FRIDA_INST_DEBUG_FILE", - "AFL_FRIDA_INST_INSN", - "AFL_FRIDA_INST_JIT", - "AFL_FRIDA_INST_NO_CACHE", - "AFL_FRIDA_INST_NO_DYNAMIC_LOAD", - "AFL_FRIDA_INST_NO_OPTIMIZE", - "AFL_FRIDA_INST_NO_PREFETCH", - "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", + "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_CC_COMPILER", + "AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW", + "AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME", + "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE", + "AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY", + "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM", + "AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT", + "AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", + "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM", + "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE", + "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV", + "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", + "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", + "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", + "AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES", + "AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE", + "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", + "AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE", + "AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE", + "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", "AFL_FRIDA_INST_NO_SUPPRESS" "AFL_FRIDA_INST_RANGES", - "AFL_FRIDA_INST_REGS_FILE", - "AFL_FRIDA_INST_SEED", - "AFL_FRIDA_INST_TRACE", - "AFL_FRIDA_INST_TRACE_UNIQUE", - "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE", - "AFL_FRIDA_JS_SCRIPT", - "AFL_FRIDA_OUTPUT_STDOUT", - "AFL_FRIDA_OUTPUT_STDERR", - "AFL_FRIDA_PERSISTENT_ADDR", - "AFL_FRIDA_PERSISTENT_CNT", - "AFL_FRIDA_PERSISTENT_DEBUG", - "AFL_FRIDA_PERSISTENT_HOOK", - "AFL_FRIDA_PERSISTENT_RET", - "AFL_FRIDA_STALKER_ADJACENT_BLOCKS", - "AFL_FRIDA_STALKER_IC_ENTRIES", - "AFL_FRIDA_STALKER_NO_BACKPATCH", - "AFL_FRIDA_STATS_FILE", - "AFL_FRIDA_STATS_INTERVAL", - "AFL_FRIDA_TRACEABLE", + "AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE", + "AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE", + "AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR", + "AFL_FRIDA_PERSISTENT_ADDR", "AFL_FRIDA_PERSISTENT_CNT", + "AFL_FRIDA_PERSISTENT_DEBUG", "AFL_FRIDA_PERSISTENT_HOOK", + "AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS", + "AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH", + "AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE", "AFL_FRIDA_VERBOSE", "AFL_FUZZER_ARGS", // oss-fuzz - "AFL_FUZZER_STATS_UPDATE_INTERVAL", - "AFL_GDB", - "AFL_GCC_ALLOWLIST", - "AFL_GCC_DENYLIST", - "AFL_GCC_BLOCKLIST", - "AFL_GCC_INSTRUMENT_FILE", - "AFL_GCC_OUT_OF_LINE", - "AFL_GCC_SKIP_NEVERZERO", - "AFL_GCJ", - "AFL_HANG_TMOUT", - "AFL_FORKSRV_INIT_TMOUT", - "AFL_HARDEN", - "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", - "AFL_IGNORE_PROBLEMS", - "AFL_IGNORE_PROBLEMS_COVERAGE", - "AFL_IGNORE_SEED_PROBLEMS", - "AFL_IGNORE_TIMEOUTS", - "AFL_IGNORE_UNKNOWN_ENVS", - "AFL_IMPORT_FIRST", - "AFL_INPUT_LEN_MIN", - "AFL_INPUT_LEN_MAX", - "AFL_INST_LIBS", - "AFL_INST_RATIO", - "AFL_KEEP_TIMEOUTS", - "AFL_KILL_SIGNAL", - "AFL_FORK_SERVER_KILL_SIGNAL", - "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_ALLOWLIST", - "AFL_LLVM_DENYLIST", - "AFL_LLVM_BLOCKLIST", - "AFL_CMPLOG", - "AFL_LLVM_CMPLOG", - "AFL_GCC_CMPLOG", - "AFL_LLVM_INSTRIM", - "AFL_LLVM_CALLER", - "AFL_LLVM_CTX", - "AFL_LLVM_CTX_K", - "AFL_LLVM_DICT2FILE", - "AFL_LLVM_DICT2FILE_NO_MAIN", - "AFL_LLVM_DOCUMENT_IDS", - "AFL_LLVM_INSTRIM_LOOPHEAD", - "AFL_LLVM_INSTRUMENT", - "AFL_LLVM_LTO_AUTODICTIONARY", - "AFL_LLVM_AUTODICTIONARY", + "AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST", + "AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE", + "AFL_GCC_OUT_OF_LINE", "AFL_GCC_SKIP_NEVERZERO", "AFL_GCJ", + "AFL_HANG_TMOUT", "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN", + "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IGNORE_PROBLEMS", + "AFL_IGNORE_PROBLEMS_COVERAGE", "AFL_IGNORE_SEED_PROBLEMS", + "AFL_IGNORE_TIMEOUTS", "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", + "AFL_INPUT_LEN_MIN", "AFL_INPUT_LEN_MAX", "AFL_INST_LIBS", "AFL_INST_RATIO", + "AFL_KEEP_TIMEOUTS", "AFL_KILL_SIGNAL", "AFL_FORK_SERVER_KILL_SIGNAL", + "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_ALLOWLIST", + "AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", "AFL_CMPLOG", "AFL_LLVM_CMPLOG", + "AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX", + "AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", "AFL_LLVM_DICT2FILE_NO_MAIN", + "AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRUMENT", + "AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY", "AFL_LLVM_SKIPSINGLEBLOCK", // Marker: ADD_TO_INJECTIONS - "AFL_LLVM_INJECTIONS_ALL", - "AFL_LLVM_INJECTIONS_SQL", - "AFL_LLVM_INJECTIONS_LDAP", - "AFL_LLVM_INJECTIONS_XSS", - "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_NO_RPATH", - "AFL_LLVM_NOT_ZERO", - "AFL_LLVM_INSTRUMENT_FILE", - "AFL_LLVM_THREADSAFE_INST", - "AFL_LLVM_SKIP_NEVERZERO", - "AFL_NO_AFFINITY", - "AFL_TRY_AFFINITY", - "AFL_LLVM_LTO_DONTWRITEID", + "AFL_LLVM_INJECTIONS_ALL", "AFL_LLVM_INJECTIONS_SQL", + "AFL_LLVM_INJECTIONS_LDAP", "AFL_LLVM_INJECTIONS_XSS", + "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_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE", + "AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", + "AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT" "AFL_LLVM_LTO_STARTID", - "AFL_FUZZER_LOOPCOUNT", - "AFL_NO_ARITH", - "AFL_NO_AUTODICT", - "AFL_NO_BUILTIN", + "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN", #if defined USE_COLOR && !defined ALWAYS_COLORED - "AFL_NO_COLOR", - "AFL_NO_COLOUR", + "AFL_NO_COLOR", "AFL_NO_COLOUR", #endif "AFL_NO_CPU_RED", "AFL_NO_CFG_FUZZING", // afl.rs rust crate option - "AFL_NO_CRASH_README", - "AFL_NO_FORKSRV", - "AFL_NO_UI", - "AFL_NO_PYTHON", - "AFL_NO_STARTUP_CALIBRATION", - "AFL_NO_WARN_INSTABILITY", - "AFL_UNTRACER_FILE", - "AFL_LLVM_USE_TRACE_PC", - "AFL_MAP_SIZE", - "AFL_MAPSIZE", + "AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", + "AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY", + "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_MAX_DET_EXTRAS", "AFL_NO_X86", // not really an env but we dont want to warn on it - "AFL_NOOPT", - "AFL_NYX_AUX_SIZE", - "AFL_NYX_DISABLE_SNAPSHOT_MODE", - "AFL_NYX_LOG", - "AFL_NYX_REUSE_SNAPSHOT", - "AFL_PASSTHROUGH", - "AFL_PATH", - "AFL_PERFORMANCE_FILE", - "AFL_PERSISTENT_RECORD", - "AFL_POST_PROCESS_KEEP_ORIGINAL", - "AFL_PRELOAD", - "AFL_TARGET_ENV", - "AFL_PYTHON_MODULE", - "AFL_QEMU_CUSTOM_BIN", - "AFL_QEMU_COMPCOV", - "AFL_QEMU_COMPCOV_DEBUG", - "AFL_QEMU_DEBUG_MAPS", - "AFL_QEMU_DISABLE_CACHE", - "AFL_QEMU_DRIVER_NO_HOOK", - "AFL_QEMU_FORCE_DFL", - "AFL_QEMU_PERSISTENT_ADDR", - "AFL_QEMU_PERSISTENT_CNT", - "AFL_QEMU_PERSISTENT_GPR", - "AFL_QEMU_PERSISTENT_HOOK", - "AFL_QEMU_PERSISTENT_MEM", - "AFL_QEMU_PERSISTENT_RET", - "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", - "AFL_QEMU_PERSISTENT_EXITS", - "AFL_QEMU_INST_RANGES", - "AFL_QEMU_EXCLUDE_RANGES", - "AFL_QEMU_SNAPSHOT", - "AFL_QEMU_TRACK_UNSTABLE", - "AFL_QUIET", - "AFL_RANDOM_ALLOC_CANARY", - "AFL_REAL_PATH", - "AFL_SHUFFLE_QUEUE", - "AFL_SKIP_BIN_CHECK", - "AFL_SKIP_CPUFREQ", - "AFL_SKIP_CRASHES", - "AFL_SKIP_OSSFUZZ", - "AFL_STATSD", - "AFL_STATSD_HOST", - "AFL_STATSD_PORT", - "AFL_STATSD_TAGS_FLAVOR", - "AFL_SYNC_TIME", - "AFL_TESTCACHE_SIZE", - "AFL_TESTCACHE_ENTRIES", - "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_TSAN", - "AFL_USE_CFISAN", - "AFL_USE_LSAN", - "AFL_WINE_PATH", - "AFL_NO_SNAPSHOT", - "AFL_EXPAND_HAVOC_NOW", - "AFL_USE_FASAN", - "AFL_USE_QASAN", - "AFL_PRINT_FILENAMES", - "AFL_PIZZA_MODE", - NULL + "AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE", + "AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT", "AFL_PASSTHROUGH", "AFL_PATH", + "AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD", + "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV", + "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV", + "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE", + "AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL", "AFL_QEMU_PERSISTENT_ADDR", + "AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR", + "AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_MEM", + "AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", + "AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_INST_RANGES", + "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_TRACK_UNSTABLE", + "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH", + "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", + "AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", + "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", + "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "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_TSAN", + "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", + "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN", + "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL }; diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 44ea5345..b4e764b7 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -a1321713c7 +e63c9af193 diff --git a/qemu_mode/README.md b/qemu_mode/README.md index 92038737..b78eb297 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -193,12 +193,39 @@ Comparative measurements of execution speed or instrumentation coverage will be fairly meaningless if the optimization levels or instrumentation scopes don't match. -## 12) Other features +## 12) Coverage information + +Coverage information about a run of a target binary can be obtained using a +dedicated QEMU user mode plugin enabled at runtime: the `drcov.c` plugin +collects coverage information from the target binary and writes it in the Drcov +format. This file can then be loaded using tools such as +[lighthouse](https://github.com/gaasedelen/lighthouse), +[lightkeeper](https://github.com/WorksButNotTested/lightkeeper) or +[Cartographer](https://github.com/nccgroup/Cartographer). + +To compile the QEMU TCG plugins, run the following command from the `qemuafl` +directory: + +``` +make plugins +``` + +Plugins can be loaded using either the `QEMU_PLUGIN` environment variable or +using the `-plugin` option. For example: + +``` +afl-qemu-trace -plugin qemuafl/build/contrib/plugins/libdrcov.so,arg=filename=/tmp/target.drcov.trace +``` + +This would execute the target binary with the provided arguments and, once done, +would write coverage information at `/tmp/target.drcov.trace`. + +## 13) Other features With `AFL_QEMU_FORCE_DFL`, you force QEMU to ignore the registered signal handlers of the target. -## 13) Gotchas, feedback, bugs +## 14) Gotchas, feedback, bugs If you need to fix up checksums or do other cleanups on mutated test cases, see `afl_custom_post_process` in custom_mutators/examples/example.c for a viable @@ -217,7 +244,7 @@ program may be utilizing. In particular, it does not appear to have full support for AVX2/FMA3. Using binaries for older CPUs or recompiling them with `-march=core2`, can help. -## 14) Alternatives: static rewriting +## 15) Alternatives: static rewriting Statically rewriting binaries just once, instead of attempting to translate them at run time, can be a faster alternative. That said, static rewriting is fraught diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index f59cba78..3f8a88f2 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -132,7 +132,10 @@ echo "Building for CPU target $CPU_TARGET" # --enable-pie seems to give a couple of exec's a second performance # improvement, much to my surprise. Not sure how universal this is.. +# --enable-plugins allows loading TCG plugins at runtime, for example to obtain +# coverage information, and does not seem to negatively impact performance QEMU_CONF_FLAGS=" \ + --enable-plugins \ --audio-drv-list= \ --disable-blobs \ --disable-bochs \ @@ -162,7 +165,6 @@ QEMU_CONF_FLAGS=" \ --disable-numa \ --disable-opengl \ --disable-parallels \ - --disable-plugins \ --disable-qcow1 \ --disable-qed \ --disable-rbd \ diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index b0abbe2e..e63c9af1 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit b0abbe2e74ed74ff6ff25b5ea3110d27ba978001 +Subproject commit e63c9af1937c13163cd1bc8bc276101441cbe70a diff --git a/src/afl-cc.c b/src/afl-cc.c index 54c733c9..192c5423 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -47,23 +47,22 @@ #define LLVM_MINOR 0 #endif -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, ctx_k, lto_mode; -static u8 compiler_mode, plusplus_mode, have_instr_env = 0, need_aflpplib = 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 int passthrough; -// static u8 *march_opt = CFLAGS_OPT; - -enum { +#ifndef MAX_PARAMS_NUM + #define MAX_PARAMS_NUM 2048 +#endif + +/* Global declarations */ + +typedef enum { + + PARAM_MISS, // not matched + PARAM_SCAN, // scan only + PARAM_KEEP, // kept as-is + PARAM_DROP, // ignored + +} param_st; + +typedef enum { INSTRUMENT_DEFAULT = 0, INSTRUMENT_CLASSIC = 1, @@ -80,7 +79,20 @@ enum { INSTRUMENT_OPT_CTX_K = 64, INSTRUMENT_OPT_CODECOV = 128, -}; +} instrument_mode_id; + +typedef enum { + + UNSET = 0, + LTO = 1, + LLVM = 2, + GCC_PLUGIN = 3, + GCC = 4, + CLANG = 5 + +} compiler_mode_id; + +static u8 cwd[4096]; char instrument_mode_string[18][18] = { @@ -105,17 +117,6 @@ char instrument_mode_string[18][18] = { }; -enum { - - UNSET = 0, - LTO = 1, - LLVM = 2, - GCC_PLUGIN = 3, - GCC = 4, - CLANG = 5 - -}; - char compiler_mode_string[7][12] = { "AUTOSELECT", "LLVM-LTO", "LLVM", "GCC_PLUGIN", @@ -123,6 +124,18 @@ char compiler_mode_string[7][12] = { }; +u8 *instrument_mode_2str(instrument_mode_id i) { + + return instrument_mode_string[i]; + +} + +u8 *compiler_mode_2str(compiler_mode_id i) { + + return compiler_mode_string[i]; + +} + u8 *getthecwd() { if (getcwd(cwd, sizeof(cwd)) == NULL) { @@ -136,26 +149,228 @@ u8 *getthecwd() { } -/* Try to find a specific runtime we need, returns NULL on fail. */ +typedef struct aflcc_state { + + u8 **cc_params; /* Parameters passed to the real CC */ + u32 cc_par_cnt; /* Param count, including argv0 */ + + u8 *argv0; /* Original argv0 (by strdup) */ + u8 *callname; /* Executable file argv0 indicated */ + + u8 debug; + + u8 compiler_mode, plusplus_mode, lto_mode; + + u8 *lto_flag; + + u8 instrument_mode, instrument_opt_mode, ngram_size, ctx_k; + + u8 cmplog_mode; + + u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, + have_optimized_pcguard, have_instr_list; + + u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, + have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + + // u8 *march_opt; + u8 need_aflpplib; + int passthrough; + + u8 use_stdin; /* dummy */ + u8 *argvnull; /* dummy */ + +} aflcc_state_t; + +void aflcc_state_init(aflcc_state_t *, u8 *argv0); + +/* Try to find a specific runtime we need, the path to obj would be + allocated and returned. Otherwise it returns NULL on fail. */ +u8 *find_object(aflcc_state_t *, u8 *obj); + +void find_built_deps(aflcc_state_t *); + +static inline void limit_params(aflcc_state_t *aflcc, u32 add) { + + if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); + +} + +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { + + aflcc->cc_params[aflcc->cc_par_cnt++] = param; + +} + +static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, + u8 *msg) { + + u8 *_obj_path = find_object(aflcc, obj); + if (!_obj_path) { + + if (msg) + FATAL("%s", msg); + else + FATAL("Unable to find '%s'", obj); + + } else { + + if (fmt) { + + u8 *_obj_path_fmt = alloc_printf(fmt, _obj_path); + ck_free(_obj_path); + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path_fmt; + + } else { + + aflcc->cc_params[aflcc->cc_par_cnt++] = _obj_path; + + } + + } + +} + +static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { + +#if LLVM_MAJOR >= 11 /* use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, pass, "-fpass-plugin=%s", 0); +#else + insert_param(aflcc, "-Xclang"); + insert_param(aflcc, "-load"); + insert_param(aflcc, "-Xclang"); + insert_object(aflcc, pass, 0, 0); +#endif + +} + +static inline void debugf_args(int argc, char **argv) { + + DEBUGF("cd '%s';", getthecwd()); + for (int i = 0; i < argc; i++) + SAYF(" '%s'", argv[i]); + SAYF("\n"); + fflush(stdout); + fflush(stderr); + +} + +void compiler_mode_by_callname(aflcc_state_t *); +void compiler_mode_by_environ(aflcc_state_t *); +void compiler_mode_by_cmdline(aflcc_state_t *, int argc, char **argv); +void instrument_mode_by_environ(aflcc_state_t *); +void mode_final_checkout(aflcc_state_t *, int argc, char **argv); +void mode_notification(aflcc_state_t *); + +void add_real_argv0(aflcc_state_t *); + +void add_defs_common(aflcc_state_t *); +void add_defs_selective_instr(aflcc_state_t *); +void add_defs_persistent_mode(aflcc_state_t *); +void add_defs_fortify(aflcc_state_t *, u8); +void add_defs_lsan_ctrl(aflcc_state_t *); + +param_st parse_fsanitize(aflcc_state_t *, u8 *, u8); +void add_sanitizers(aflcc_state_t *, char **envp); +void add_optimized_pcguard(aflcc_state_t *); +void add_native_pcguard(aflcc_state_t *); + +void add_assembler(aflcc_state_t *); +void add_gcc_plugin(aflcc_state_t *); + +param_st parse_misc_params(aflcc_state_t *, u8 *, u8); +void add_misc_params(aflcc_state_t *); + +param_st parse_linking_params(aflcc_state_t *, u8 *, u8, u8 *skip_next, + char **argv); + +void add_lto_linker(aflcc_state_t *); +void add_lto_passes(aflcc_state_t *); +void add_runtime(aflcc_state_t *); + +/* Working state */ + +void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { + + // Default NULL/0 is a good start + memset(aflcc, 0, sizeof(aflcc_state_t)); + + aflcc->cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + aflcc->cc_par_cnt = 1; + + aflcc->lto_flag = AFL_CLANG_FLTO; + + // aflcc->march_opt = CFLAGS_OPT; + + /* callname & if C++ mode */ + + aflcc->argv0 = ck_strdup(argv0); + + char *cname = NULL; + + if ((cname = strrchr(aflcc->argv0, '/')) != NULL) { + + cname++; + + } else { + + cname = aflcc->argv0; + + } + + aflcc->callname = cname; + + if (strlen(cname) > 2 && (strncmp(cname + strlen(cname) - 2, "++", 2) == 0 || + strstr(cname, "-g++") != NULL)) { + + aflcc->plusplus_mode = 1; + + } + + /* debug */ + + if (getenv("AFL_DEBUG")) { + + aflcc->debug = 1; + if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); + + } else if (getenv("AFL_QUIET")) { + + be_quiet = 1; + + } + + if ((getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) && (!aflcc->debug)) { + + be_quiet = 1; + + } + +} /* 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 + 1. firstly we check the $AFL_PATH environment variable location if set + 2. 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 + 3. if 2. 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 + 4. we look into the AFL_PATH define (usually /usr/local/lib/afl) + 5. we finally try the current directory if all these attempts fail - we return NULL and the caller has to decide - what to do. + what to do. Otherwise the path to obj would be allocated and returned. */ -static u8 *find_object(u8 *obj, u8 *argv0) { +u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { + + u8 *argv0 = aflcc->argv0; u8 *afl_path = getenv("AFL_PATH"); u8 *slash = NULL, *tmp; @@ -164,14 +379,9 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", afl_path, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { - - obj_path = afl_path; - return tmp; + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); @@ -190,11 +400,11 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - obj_path = dir; + ck_free(dir); return tmp; } @@ -202,12 +412,10 @@ static u8 *find_object(u8 *obj, u8 *argv0) { ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", dir, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); if (!access(tmp, R_OK)) { - u8 *dir2 = alloc_printf("%s/../lib/afl", dir); - obj_path = dir2; ck_free(dir); return tmp; @@ -247,26 +455,16 @@ static u8 *find_object(u8 *obj, u8 *argv0) { *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; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj); - if (debug) DEBUGF("Trying %s\n", tmp); - - if (!access(tmp, R_OK)) { + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - u8 *dir = alloc_printf("%s/../lib/afl/", exepath); - obj_path = dir; - return tmp; + if (!access(tmp, R_OK)) { return tmp; } - } + ck_free(tmp); } @@ -283,1843 +481,2036 @@ static u8 *find_object(u8 *obj, u8 *argv0) { tmp = alloc_printf("%s/%s", AFL_PATH, obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = AFL_PATH; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - tmp = alloc_printf("./%s", obj); - if (debug) DEBUGF("Trying %s\n", tmp); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); - if (!access(tmp, R_OK)) { - - obj_path = "."; - return tmp; - - } + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); - if (debug) DEBUGF("Trying ... giving up\n"); + if (aflcc->debug) DEBUGF("Trying ... giving up\n"); return NULL; } -void parse_fsanitize(char *string) { +void find_built_deps(aflcc_state_t *aflcc) { - char *p, *ptr = string + strlen("-fsanitize="); - char *new = malloc(strlen(string) + 1); - char *tmp = malloc(strlen(ptr) + 1); - u32 count = 0, len, ende = 0; + char *ptr = NULL; - if (!new || !tmp) { FATAL("could not acquire memory"); } - strcpy(new, "-fsanitize="); +#if defined(__x86_64__) + if ((ptr = find_object(aflcc, "as")) != NULL) { - do { + #ifndef __APPLE__ + // on OSX clang masquerades as GCC + aflcc->have_gcc = 1; + #endif + aflcc->have_clang = 1; + ck_free(ptr); - p = strchr(ptr, ','); - if (!p) { + } - p = ptr + strlen(ptr) + 1; - ende = 1; +#endif - } + if ((ptr = find_object(aflcc, "SanitizerCoveragePCGUARD.so")) != NULL) { - len = p - ptr; - if (len) { + aflcc->have_optimized_pcguard = 1; + ck_free(ptr); - strncpy(tmp, ptr, len); - tmp[len] = 0; - // fprintf(stderr, "Found: %s\n", tmp); - ptr += len + 1; - if (*tmp) { + } - u32 copy = 1; - if (!strcmp(tmp, "fuzzer")) { +#if (LLVM_MAJOR >= 3) - need_aflpplib = 1; - copy = 0; + if ((ptr = find_object(aflcc, "SanitizerCoverageLTO.so")) != NULL) { - } else if (!strncmp(tmp, "fuzzer", 6)) { + aflcc->have_lto = 1; + ck_free(ptr); - copy = 0; + } - } + if ((ptr = find_object(aflcc, "cmplog-routines-pass.so")) != NULL) { - if (copy) { + aflcc->have_llvm = 1; + ck_free(ptr); - if (count) { strcat(new, ","); } - strcat(new, tmp); - ++count; + } - } +#endif - } +#ifdef __ANDROID__ + aflcc->have_llvm = 1; +#endif - } else { + if ((ptr = find_object(aflcc, "afl-gcc-pass.so")) != NULL) { - ptr++; /*fprintf(stderr, "NO!\n"); */ + aflcc->have_gcc_plugin = 1; + ck_free(ptr); - } + } - } while (!ende); +#if !defined(__ANDROID__) && !defined(ANDROID) + ptr = find_object(aflcc, "afl-compiler-rt.o"); - strcpy(string, new); - // fprintf(stderr, "string: %s\n", string); - // fprintf(stderr, "new: %s\n", new); + if (!ptr) { -} + FATAL( + "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " + "environment variable."); -static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - shared_linking = 0, preprocessor_only = 0, have_unroll = 0, - have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0, - non_dash = 0; + } -#ifndef MAX_PARAMS_NUM - #define MAX_PARAMS_NUM 2048 + if (aflcc->debug) { DEBUGF("rt=%s\n", ptr); } + + ck_free(ptr); #endif -static void process_params(u32 argc, char **argv) { +} - if (cc_par_cnt + argc >= MAX_PARAMS_NUM) { +/* compiler_mode & instrument_mode selecting */ - FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); +void compiler_mode_by_callname(aflcc_state_t *aflcc) { - } + if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { - // reset - have_instr_list = 0; - have_c = 0; + /* afl-clang-fast is always created there by makefile + just like afl-clang, burdened with special purposes: + - If llvm-config is not available (i.e. LLVM_MAJOR is 0), + or too old, it falls back to LLVM-NATIVE mode and let + the actual compiler complain if doesn't work. + - Otherwise try default llvm instruments except LTO. + */ +#if (LLVM_MAJOR >= 3) + aflcc->compiler_mode = LLVM; +#else + aflcc->compiler_mode = CLANG; +#endif - if (lto_mode && argc > 1) { + } else - u32 idx; - for (idx = 1; idx < argc; idx++) { +#if (LLVM_MAJOR >= 3) - if (!strncasecmp(argv[idx], "-fpic", 5)) { have_pic = 1; } + if (strncmp(aflcc->callname, "afl-clang-lto", 13) == 0 || - } + strncmp(aflcc->callname, "afl-lto", 7) == 0) { - } + aflcc->compiler_mode = LTO; - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); + } else - /* Process the argument list. */ +#endif - u8 skip_next = 0; - while (--argc) { + if (strncmp(aflcc->callname, "afl-gcc-fast", 12) == 0 || - u8 *cur = *(++argv); + strncmp(aflcc->callname, "afl-g++-fast", 12) == 0) { - if (skip_next) { + aflcc->compiler_mode = GCC_PLUGIN; - skip_next = 0; - continue; +#if defined(__x86_64__) - } + } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || - if (cur[0] != '-') { non_dash = 1; } - if (!strncmp(cur, "--afl", 5)) continue; + strncmp(aflcc->callname, "afl-g++", 7) == 0) { - if (lto_mode && !strncmp(cur, "-flto=thin", 10)) { + aflcc->compiler_mode = GCC; - FATAL( - "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " - "use afl-clang-fast!"); +#endif - } +#if defined(__x86_64__) - if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; - if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - if (!strncmp(cur, "-fno-unroll", 11)) continue; - if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue; - if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") || - !strcmp(cur, "--no-undefined")) { + } else if (strcmp(aflcc->callname, "afl-clang") == 0 || - continue; + strcmp(aflcc->callname, "afl-clang++") == 0) { - } + aflcc->compiler_mode = CLANG; + +#endif - if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; } + } - if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { +} - u8 *param = *(argv + 1); - if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { +void compiler_mode_by_environ(aflcc_state_t *aflcc) { - skip_next = 1; - continue; + if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { - } + aflcc->passthrough = 1; - } + } - if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && - !strncmp(cur, "-stdlib=", 8)) { + char *ptr = getenv("AFL_CC_COMPILER"); - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + if (!ptr) { return; } - } + if (aflcc->compiler_mode) { - if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) { + if (!be_quiet) { - have_instr_list = 1; + WARNF( + "\"AFL_CC_COMPILER\" is set but a specific compiler was already " + "selected by command line parameter or symlink, ignoring the " + "environment variable!"); } - if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) && - strchr(cur, ',')) { + } else { - parse_fsanitize(cur); - if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; } + if (strncasecmp(ptr, "LTO", 3) == 0) { - } else if ((!strncmp(cur, "-fsanitize=fuzzer-", + aflcc->compiler_mode = LTO; - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - instrument_mode != INSTRUMENT_LLVMNATIVE)) { + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } - continue; + aflcc->compiler_mode = LLVM; - } + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) { + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - u8 *afllib = find_object("libAFLDriver.a", argv[0]); + aflcc->compiler_mode = GCC_PLUGIN; - if (!be_quiet) { +#if defined(__x86_64__) - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + } else if (strcasecmp(ptr, "GCC") == 0) { - } + aflcc->compiler_mode = GCC; - if (!afllib) { +#endif - if (!be_quiet) { +#if defined(__x86_64__) - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); + } else if (strcasecmp(ptr, "CLANG") == 0) { - } + aflcc->compiler_mode = CLANG; - } else { - - cc_params[cc_par_cnt++] = afllib; - -#ifdef __APPLE__ - cc_params[cc_par_cnt++] = "-undefined"; - cc_params[cc_par_cnt++] = "dynamic_lookup"; #endif - } + } else - if (need_aflpplib) { + FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); - need_aflpplib = 0; + } - } else { +} - continue; +// If it can be inferred, instrument_mode would also be set +void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { - } + char *ptr = NULL; - } + for (int i = 1; i < argc; i++) { - if (!strcmp(cur, "-m32")) bit_mode = 32; - if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32; - if (!strcmp(cur, "-m64")) bit_mode = 64; + if (strncmp(argv[i], "--afl", 5) == 0) { - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) - asan_set = 1; + if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + aflcc->passthrough = 1; + argv[i] = "-g"; // we have to overwrite it, -g is always good + continue; - if (!strcmp(cur, "-x")) x_set = 1; - if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; - if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; - if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1; - if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; - if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; - if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-r")) partial_linking = 1; - if (!strcmp(cur, "--relocatable")) partial_linking = 1; - if (!strcmp(cur, "-c")) have_c = 1; + } - if (!strncmp(cur, "-O", 2)) have_o = 1; - if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1; + if (aflcc->compiler_mode && !be_quiet) { - if (*cur == '@') { + WARNF( + "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " + "symlink compiler selection!"); - // response file support. - // 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. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! - u8 *filename = cur + 1; - if (debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; + } - // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + ptr = argv[i]; + ptr += 5; + while (*ptr == '-') + ptr++; - cc_params[cc_par_cnt++] = cur; - continue; + if (strncasecmp(ptr, "LTO", 3) == 0) { - } + aflcc->compiler_mode = LTO; - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + } else if (strncasecmp(ptr, "LLVM", 4) == 0) { - while (fgets(tmpbuf, st.st_size + 1, f)) { + aflcc->compiler_mode = LLVM; - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || - ++ptr; - cont_act = 0; + strncasecmp(ptr, "PC-GUARD", 8) == 0) { - } + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + } else if (strcasecmp(ptr, "INSTRIM") == 0 || - cont = 1; - ptr[strlen(ptr) - 1] = 0; + strcasecmp(ptr, "CFG") == 0) { - } + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); - // fprintf(stderr, "2: %s\n", ptr); + } else if (strcasecmp(ptr, "AFL") == 0 || - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + strcasecmp(ptr, "CLASSIC") == 0) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_CLASSIC; - } + } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + strcasecmp(ptr, "NATIVE") == 0 || + strcasecmp(ptr, "LLVM-NATIVE") == 0) { - do { + aflcc->compiler_mode = LLVM; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || - ++ptr; + strncasecmp(ptr, "GCC-P", 5) == 0 || + strncasecmp(ptr, "GCCP", 4) == 0) { - } + aflcc->compiler_mode = GCC_PLUGIN; - while (*ptr && isspace(*ptr)) { +#if defined(__x86_64__) - *ptr++ = 0; + } else if (strcasecmp(ptr, "GCC") == 0) { - } + aflcc->compiler_mode = GCC; - if (cont_act) { +#endif - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; +#if defined(__x86_64__) - } else { + } else if (strncasecmp(ptr, "CLANG", 5) == 0) { - args[count++] = strdup(value); + aflcc->compiler_mode = CLANG; - } +#endif - } while (*ptr); + } else - } + FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); - if (cont) { + } - cont_act = 1; - cont = 0; + } - } +} - } +static void instrument_mode_old_environ(aflcc_state_t *aflcc) { - if (count) { process_params(count, args); } + if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || + getenv("INSTRIM_LIB")) { - // we cannot free args[] - free(tmpbuf); + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " + "(default in afl-cc).\n"); - continue; + } - } + if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || + getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { - cc_params[cc_par_cnt++] = cur; + if (aflcc->instrument_mode == 0) + aflcc->instrument_mode = INSTRUMENT_PCGUARD; + else if (aflcc->instrument_mode != INSTRUMENT_PCGUARD) + FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); } -} - -/* Copy argv to cc_params, making the necessary edits. */ + if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + if (getenv("AFL_LLVM_CALLER")) + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; -static void edit_params(u32 argc, char **argv, char **envp) { + if (getenv("AFL_LLVM_NGRAM_SIZE")) { - cc_params = ck_alloc(MAX_PARAMS_NUM * sizeof(u8 *)); + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; + aflcc->ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) + FATAL( + "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " + "(%u)", + NGRAM_SIZE_MAX); - for (u32 c = 1; c < argc; ++c) { + } - if (!strcmp(argv[c], "-c")) have_c = 1; - if (!strncmp(argv[c], "-fsanitize-coverage-", 20) && - strstr(argv[c], "list=")) { + if (getenv("AFL_LLVM_CTX_K")) { - have_instr_list = 1; + aflcc->ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", + CTX_MAX_K); + if (aflcc->ctx_k == 1) { - } + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - } + } else { - if (lto_mode) { + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; - if (lto_flag[0] != '-') - FATAL( - "Using afl-clang-lto is not possible because Makefile magic did not " - "identify the correct -flto flag"); - else - compiler_mode = LTO; + } } - if (plusplus_mode) { +} - u8 *alt_cxx = getenv("AFL_CXX"); +// compiler_mode would also be set if depended by the instrument_mode +static void instrument_mode_new_environ(aflcc_state_t *aflcc) { - if (!alt_cxx) { + if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } - if (compiler_mode >= GCC_PLUGIN) { + u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); - if (compiler_mode == GCC) { + while (ptr2) { - alt_cxx = clang_mode ? "clang++" : "g++"; + if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || + strncasecmp(ptr2, "classic", strlen("classic")) == 0) { - } else if (compiler_mode == CLANG) { + if (aflcc->instrument_mode == INSTRUMENT_LTO) { - alt_cxx = "clang++"; + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->lto_mode = 1; - } else { + } else if (!aflcc->instrument_mode || - alt_cxx = "g++"; + aflcc->instrument_mode == INSTRUMENT_AFL) { - } + aflcc->instrument_mode = INSTRUMENT_AFL; } else { - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); - alt_cxx = llvm_fullpath; + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } } - cc_params[0] = alt_cxx; + if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || + strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { - } else { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) - u8 *alt_cc = getenv("AFL_CC"); + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - if (!alt_cc) { + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); + + } - if (compiler_mode >= GCC_PLUGIN) { + if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || + strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || + strncasecmp(ptr2, "native", strlen("native")) == 0) { - if (compiler_mode == GCC) { + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) - alt_cc = clang_mode ? "clang" : "gcc"; + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } else if (compiler_mode == CLANG) { + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - alt_cc = "clang"; + } - } else { + if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || + strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { - alt_cc = "gcc"; + if (!aflcc->instrument_mode || + aflcc->instrument_mode == INSTRUMENT_LLVMNATIVE) { - } + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; } else { - if (USE_BINDIR) - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", - LLVM_BINDIR); - else - snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s", CLANG_BIN); - alt_cc = llvm_fullpath; + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } } - cc_params[0] = alt_cc; + if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || + strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { - } + FATAL( + "InsTrim instrumentation was removed. Use a modern LLVM and " + "PCGUARD (default in afl-cc).\n"); + + } - if (compiler_mode == GCC || compiler_mode == CLANG) { + if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { - cc_params[cc_par_cnt++] = "-B"; - cc_params[cc_par_cnt++] = obj_path; + aflcc->lto_mode = 1; + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_LTO) - if (clang_mode || compiler_mode == CLANG) { + aflcc->instrument_mode = INSTRUMENT_LTO; - cc_params[cc_par_cnt++] = "-no-integrated-as"; + else + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); } - } +#if defined(__x86_64__) + if (strcasecmp(ptr2, "gcc") == 0) { - if (compiler_mode == GCC_PLUGIN) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) - char *fplugin_arg; + aflcc->instrument_mode = INSTRUMENT_GCC; - if (cmplog_mode) { + else if (aflcc->instrument_mode != INSTRUMENT_GCC) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmplog-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - fplugin_arg = - alloc_printf("-fplugin=%s/afl-gcc-cmptrs-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; + aflcc->compiler_mode = GCC; } - fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path); - cc_params[cc_par_cnt++] = fplugin_arg; - cc_params[cc_par_cnt++] = "-fno-if-conversion"; - cc_params[cc_par_cnt++] = "-fno-if-conversion2"; +#endif - } +#if defined(__x86_64__) + if (strcasecmp(ptr2, "clang") == 0) { - if (compiler_mode == LLVM || compiler_mode == LTO) { + if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + aflcc->instrument_mode = INSTRUMENT_CLANG; - if (lto_mode && have_instr_env) { + else if (aflcc->instrument_mode != INSTRUMENT_CLANG) + FATAL("main instrumentation mode already set with %s", + instrument_mode_2str(aflcc->instrument_mode)); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path); -#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/afl-llvm-lto-instrumentlist.so", obj_path); -#endif + aflcc->compiler_mode = CLANG; } - if (getenv("AFL_LLVM_DICT2FILE")) { - -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path); -#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/afl-llvm-dict2file.so", obj_path); #endif - } + if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || + strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || + strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { - // laf - if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { + u8 *ptr3 = ptr2; + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) + ptr3++; -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#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/split-switches-pass.so", obj_path); -#endif + if (!*ptr3) { - } + if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) + FATAL( + "you must set the K-CTX K with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ctx-2"); - if (getenv("LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path); -#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/compare-transform-pass.so", obj_path); -#endif + aflcc->ctx_k = atoi(ptr3); + if (aflcc->ctx_k < 1 || aflcc->ctx_k > CTX_MAX_K) + FATAL( + "K-CTX instrumentation option must be between 1 and CTX_MAX_K " + "(%u)", + CTX_MAX_K); - } + if (aflcc->ctx_k == 1) { - if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || - getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) { + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); + unsetenv("AFL_LLVM_CTX_K"); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path); -#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/split-compares-pass.so", obj_path); -#endif + } else { - } + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); + u8 *ptr4 = alloc_printf("%u", aflcc->ctx_k); + setenv("AFL_LLVM_CTX_K", ptr4, 1); - // /laf + } - unsetenv("AFL_LD"); - unsetenv("AFL_LD_CALLER"); + } - if (cmplog_mode) { + if (strcasecmp(ptr2, "ctx") == 0) { - cc_params[cc_par_cnt++] = "-fno-inline"; + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; + setenv("AFL_LLVM_CTX", "1", 1); -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path); -#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/cmplog-switches-pass.so", obj_path); + } - // reuse split switches from laf - 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/split-switches-pass.so", obj_path); -#endif + if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { + + aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + setenv("AFL_LLVM_CALLER", "1", 1); } - // #if LLVM_MAJOR >= 13 - // // Use the old pass manager in LLVM 14 which the AFL++ passes still - // use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; - // #endif + if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { - if (lto_mode && !have_c) { + u8 *ptr3 = ptr2 + strlen("ngram"); + while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) { - u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { + ptr3++; - ld_path = strdup(getenv("AFL_REAL_LD")); + } - } else { + if (!*ptr3) { - ld_path = strdup(AFL_REAL_LD); + if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) + FATAL( + "you must set the NGRAM size with (e.g. for value 2) " + "AFL_LLVM_INSTRUMENT=ngram-2"); } - if (!ld_path || !*ld_path) { + aflcc->ngram_size = atoi(ptr3); - if (ld_path) { + if (aflcc->ngram_size < 2 || aflcc->ngram_size > NGRAM_SIZE_MAX) { - // Freeing empty string - free(ld_path); + FATAL( + "NGRAM instrumentation option must be between 2 and " + "NGRAM_SIZE_MAX (%u)", + NGRAM_SIZE_MAX); - } + } - ld_path = strdup("ld.lld"); + aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); + u8 *ptr4 = alloc_printf("%u", aflcc->ngram_size); + setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); - } + } - if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 - cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path); -#else - cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path); -#endif - free(ld_path); + ptr2 = strtok(NULL, ":,;"); -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 - // The NewPM implementation only works fully since LLVM 15. - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,--load-pass-plugin=%s/SanitizerCoverageLTO.so", obj_path); -#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#else - cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager"; - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path); -#endif - - cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition"; - cc_params[cc_par_cnt++] = lto_flag; - - } else { - - if (instrument_mode == INSTRUMENT_PCGUARD) { - -#if LLVM_MAJOR >= 13 - #if defined __ANDROID__ || ANDROID - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - 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"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - - } else { - - #if LLVM_MAJOR >= 13 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path); - #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); - #endif - - } - - #endif -#else - #if LLVM_MAJOR >= 4 - if (!be_quiet) - SAYF( - "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " - "enhanced version.\n"); - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - instrument_mode = INSTRUMENT_LLVMNATIVE; - #else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - #endif -#endif - - } else if (instrument_mode == INSTRUMENT_LLVMNATIVE) { - -#if LLVM_MAJOR >= 4 - if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - - #if LLVM_MAJOR >= 6 - cc_params[cc_par_cnt++] = - "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"; - #else - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); - #endif + } - } else { +} - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; +void instrument_mode_by_environ(aflcc_state_t *aflcc) { - } + if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || + getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") || + getenv("AFL_LLVM_BLOCKLIST")) { -#else - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#endif + aflcc->have_instr_env = 1; - } else { + } -#if LLVM_MAJOR >= 11 /* use new pass manager */ - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); -#else + if (aflcc->have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { - 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-pass.so", obj_path); -#endif + WARNF( + "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " + "for file matching, only function matching!"); - } + } - } + instrument_mode_old_environ(aflcc); + instrument_mode_new_environ(aflcc); - if (cmplog_mode) { +} -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = alloc_printf( - "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path); -#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/cmplog-instructions-pass.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/cmplog-routines-pass.so", obj_path); -#endif +static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { - } + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { - if (getenv("AFL_LLVM_INJECTIONS_ALL") || - getenv("AFL_LLVM_INJECTIONS_SQL") || - getenv("AFL_LLVM_INJECTIONS_LDAP") || - getenv("AFL_LLVM_INJECTIONS_XSS")) { + FATAL("you cannot set CTX and CALLER together"); -#if LLVM_MAJOR >= 11 - #if LLVM_MAJOR < 16 - cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; - #endif - cc_params[cc_par_cnt++] = - alloc_printf("-fpass-plugin=%s/injection-pass.so", obj_path); -#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/injection-pass.so", obj_path); -#endif + } - } + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { - // cc_params[cc_par_cnt++] = "-Qunused-arguments"; + FATAL("you cannot set CTX and K-CTX together"); } - /* Inspect the command line parameters. */ + if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { - process_params(argc, argv); + FATAL("you cannot set CALLER and K-CTX together"); - if (!have_pic) { + } - cc_params[cc_par_cnt++] = "-fPIC"; - have_pic = 1; + if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM) + FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); - } + if (aflcc->instrument_opt_mode && + aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV && + aflcc->instrument_mode != INSTRUMENT_CLASSIC) + FATAL( + "CALLER, CTX and NGRAM instrumentation options can only be used with " + "the LLVM CLASSIC instrumentation mode."); - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC && - !getenv("AFL_LLVM_NO_RPATH")) { +} - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - const char *libdir = LLVM_LIBDIR; - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { +void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { - u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); - cc_params[cc_par_cnt++] = libdir_opt; + if (aflcc->instrument_opt_mode && + aflcc->instrument_mode == INSTRUMENT_DEFAULT && + (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == UNSET)) { - } + aflcc->instrument_mode = INSTRUMENT_CLASSIC; + aflcc->compiler_mode = LLVM; } - if (getenv("AFL_HARDEN")) { - - cc_params[cc_par_cnt++] = "-fstack-protector-all"; + if (!aflcc->compiler_mode) { - if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; + // lto is not a default because outside of afl-cc RANLIB and AR have to + // be set to LLVM versions so this would work + if (aflcc->have_llvm) + aflcc->compiler_mode = LLVM; + else if (aflcc->have_gcc_plugin) + aflcc->compiler_mode = GCC_PLUGIN; + else if (aflcc->have_gcc) + aflcc->compiler_mode = GCC; + else if (aflcc->have_clang) + aflcc->compiler_mode = CLANG; + else if (aflcc->have_lto) + aflcc->compiler_mode = LTO; + else + FATAL("no compiler mode available"); } - if (!asan_set) { + switch (aflcc->compiler_mode) { - if (getenv("AFL_USE_ASAN")) { + case GCC: + if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + break; + case CLANG: + if (!aflcc->have_clang) + FATAL("afl-clang not available on your platform!"); + break; + case LLVM: + if (!aflcc->have_llvm) + FATAL( + "LLVM mode is not available, please install LLVM 13+ and recompile " + "AFL++"); + break; + case GCC_PLUGIN: + if (!aflcc->have_gcc_plugin) + FATAL( + "GCC_PLUGIN mode is not available, install gcc plugin support and " + "recompile AFL++"); + break; + case LTO: + if (!aflcc->have_lto) + FATAL( + "LTO mode is not available, please install LLVM 13+ and lld of the " + "same version and recompile AFL++"); + break; + default: + FATAL("no compiler mode available"); - if (getenv("AFL_USE_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) { aflcc->instrument_mode = INSTRUMENT_GCC; } - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=address"; + if (aflcc->compiler_mode == CLANG) { - } else if (getenv("AFL_USE_MSAN")) { + /* if our PCGUARD implementation is not available then silently switch to + native LLVM PCGUARD. Or classic asm instrument is explicitly preferred. */ + if (!aflcc->have_optimized_pcguard && + (aflcc->instrument_mode == INSTRUMENT_DEFAULT || + aflcc->instrument_mode == INSTRUMENT_PCGUARD)) { - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + } else { - cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; - cc_params[cc_par_cnt++] = "-fsanitize=memory"; + aflcc->instrument_mode = INSTRUMENT_CLANG; + setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as } } - if (getenv("AFL_USE_UBSAN")) { + if (aflcc->compiler_mode == LTO) { - cc_params[cc_par_cnt++] = "-fsanitize=undefined"; - cc_params[cc_par_cnt++] = "-fsanitize-undefined-trap-on-error"; - cc_params[cc_par_cnt++] = "-fno-sanitize-recover=all"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + if (aflcc->instrument_mode == 0 || + aflcc->instrument_mode == INSTRUMENT_LTO || + aflcc->instrument_mode == INSTRUMENT_CFG || + aflcc->instrument_mode == INSTRUMENT_PCGUARD) { - } + aflcc->lto_mode = 1; + // force CFG + // if (!aflcc->instrument_mode) { - if (getenv("AFL_USE_TSAN")) { + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - cc_params[cc_par_cnt++] = "-fsanitize=thread"; - cc_params[cc_par_cnt++] = "-fno-omit-frame-pointer"; + // } - } + } else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) { - if (getenv("AFL_USE_LSAN")) { + aflcc->lto_mode = 1; - cc_params[cc_par_cnt++] = "-fsanitize=leak"; - cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h"; - cc_params[cc_par_cnt++] = - "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " - "_exit(23); }"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_OFF()=__lsan_disable();"; - cc_params[cc_par_cnt++] = "-D__AFL_LSAN_ON()=__lsan_enable();"; + } else { - } + if (!be_quiet) { - if (getenv("AFL_USE_CFISAN")) { + WARNF("afl-clang-lto called with mode %s, using that mode instead", + instrument_mode_2str(aflcc->instrument_mode)); - if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) { + } - cc_params[cc_par_cnt++] = "-fcf-protection=full"; + } - } else { + } - if (!lto_mode) { + if (aflcc->instrument_mode == 0 && aflcc->compiler_mode < GCC_PLUGIN) { - uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) - if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) cc_params[cc_par_cnt++] = "-flto"; +#if LLVM_MAJOR >= 7 + #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) + if (aflcc->have_instr_env) { - } + aflcc->instrument_mode = INSTRUMENT_AFL; + if (!be_quiet) { - cc_params[cc_par_cnt++] = "-fsanitize=cfi"; - cc_params[cc_par_cnt++] = "-fvisibility=hidden"; + WARNF( + "Switching to classic instrumentation because " + "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); - } + } - } + } else - if (!getenv("AFL_DONT_OPTIMIZE")) { + #endif + aflcc->instrument_mode = INSTRUMENT_PCGUARD; - cc_params[cc_par_cnt++] = "-g"; - if (!have_o) cc_params[cc_par_cnt++] = "-O3"; - if (!have_unroll) cc_params[cc_par_cnt++] = "-funroll-loops"; - // if (strlen(march_opt) > 1 && march_opt[0] == '-') - // cc_params[cc_par_cnt++] = march_opt; +#else + aflcc->instrument_mode = INSTRUMENT_AFL; +#endif } - if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || - getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") || - lto_mode) { + if (!aflcc->instrument_opt_mode && aflcc->lto_mode && + aflcc->instrument_mode == INSTRUMENT_CFG) { - cc_params[cc_par_cnt++] = "-fno-builtin-strcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-bcmp"; - cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; - cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; + aflcc->instrument_mode = INSTRUMENT_PCGUARD; } -#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; +#ifndef AFL_CLANG_FLTO + if (aflcc->lto_mode) + FATAL( + "instrumentation mode LTO specified but LLVM support not available " + "(requires LLVM 11 or higher)"); #endif - cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; - cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; + if (aflcc->lto_mode) { - /* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ - if (compiler_mode != GCC && compiler_mode != CLANG) { + if (aflcc->lto_flag[0] != '-') + FATAL( + "Using afl-clang-lto is not possible because Makefile magic did not " + "identify the correct -flto flag"); + else + aflcc->compiler_mode = LTO; - cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1"; + } - /* When the user tries to use persistent or deferred forkserver modes by - appending a single line to the program, we want to reliably inject a - signature into the binary (to be picked up by afl-fuzz) and we want - to call a function from the runtime .o file. This is unnecessarily - painful for three reasons: + if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) + FATAL( + "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " + "together"); - 1) We need to convince the compiler not to optimize out the signature. - This is done with __attribute__((used)). +#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - 2) We need to convince the linker, when called with -Wl,--gc-sections, - not to do the same. This is done by forcing an assignment to a - 'volatile' pointer. + if (aflcc->instrument_mode == INSTRUMENT_PCGUARD && aflcc->have_instr_env) { - 3) We need to declare __afl_persistent_loop() in the global namespace, - but doing this within a method in a class is hard - :: and extern "C" - are forbidden and __attribute__((alias(...))) doesn't work. Hence the - __asm__ aliasing trick. + FATAL( + "Instrumentation type PCGUARD does not support " + "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); - */ + } - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_INIT()=" - "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" - "unsigned char __afl_fuzz_alt[1048576];" - "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"; +#endif - } + instrument_opt_mode_exclude(aflcc); - if (plusplus_mode) { + u8 *ptr2; - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "extern \"C\" void __afl_coverage_discard();" - "extern \"C\" void __afl_coverage_skip();" - "extern \"C\" void __afl_coverage_on();" - "extern \"C\" void __afl_coverage_off();"; + if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') + FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); - } else { + if (getenv("AFL_LLVM_LAF_ALL")) { - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" - "void __afl_coverage_discard();" - "void __afl_coverage_skip();" - "void __afl_coverage_on();" - "void __afl_coverage_off();"; + setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); + setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); } - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " - "1;"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"; - cc_params[cc_par_cnt++] = - "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"; - cc_params[cc_par_cnt++] = "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " - "__afl_fuzz_alt_ptr)"; - cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " - "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " - "? 0 : *__afl_fuzz_len)"; + aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || + getenv("AFL_GCC_CMPLOG"); - if (compiler_mode != GCC && compiler_mode != CLANG) { +} - cc_params[cc_par_cnt++] = - "-D__AFL_LOOP(_A)=" - "({ static volatile const char *_B __attribute__((used,unused)); " - " _B = (const char*)\"" PERSIST_SIG - "\"; " - "extern int __afl_connected;" -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " -#else - "__attribute__((visibility(\"default\"))) " - "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " -#endif /* ^__APPLE__ */ - // if afl is connected, we run _A times, else once. - "_L(__afl_connected ? _A : 1); })"; - - cc_params[cc_par_cnt++] = - "-D__AFL_INIT()=" - "do { static volatile const char *_A __attribute__((used,unused)); " - " _A = (const char*)\"" DEFER_SIG - "\"; " -#ifdef __APPLE__ - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"___afl_manual_init\"); " -#else - "__attribute__((visibility(\"default\"))) " - "void _I(void) __asm__(\"__afl_manual_init\"); " -#endif /* ^__APPLE__ */ - "_I(); } while (0)"; +void mode_notification(aflcc_state_t *aflcc) { - } + char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); + char *ptr3 = alloc_printf(" + K-CTX-%u", aflcc->ctx_k); + + char *ptr1 = alloc_printf( + "%s%s%s%s%s", instrument_mode_2str(aflcc->instrument_mode), + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); - if (x_set) { + ck_free(ptr2); + ck_free(ptr3); - cc_params[cc_par_cnt++] = "-x"; - cc_params[cc_par_cnt++] = "none"; + if ((isatty(2) && !be_quiet) || aflcc->debug) { + + SAYF(cCYA + "afl-cc" VERSION cRST + " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", + compiler_mode_2str(aflcc->compiler_mode), ptr1); } - // prevent unnecessary build errors - if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) { + ck_free(ptr1); + + if (!be_quiet && + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG)) { - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + WARNF( + "You are using outdated instrumentation, install LLVM and/or " + "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " + "instead!"); } - if (preprocessor_only || have_c || !non_dash) { +} - /* In the preprocessor_only case (-E), we are not actually compiling at - all but requesting the compiler to output preprocessed sources only. - We must not add the runtime in this case because the compiler will - simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ - cc_params[cc_par_cnt] = NULL; - return; +void add_real_argv0(aflcc_state_t *aflcc) { - } + static u8 llvm_fullpath[PATH_MAX]; -#ifndef __ANDROID__ + if (aflcc->plusplus_mode) { - if (compiler_mode != GCC && compiler_mode != CLANG) { + u8 *alt_cxx = getenv("AFL_CXX"); - switch (bit_mode) { + if (!alt_cxx) { - case 0: - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt.o", obj_path); - if (lto_mode) - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); - break; + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - case 32: - if (!shared_linking && !partial_linking) { + alt_cxx = "g++"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cxx = "clang++"; - if (lto_mode) { + } else { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-32.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m32 is not supported by your compiler"); + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANGPP_BIN); + alt_cxx = llvm_fullpath; - } + } - break; + } - case 64: - if (!shared_linking && !partial_linking) { + aflcc->cc_params[0] = alt_cxx; - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-compiler-rt-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + } else { - } + u8 *alt_cc = getenv("AFL_CC"); - if (lto_mode) { + if (!alt_cc) { - cc_params[cc_par_cnt++] = - alloc_printf("%s/afl-llvm-rt-lto-64.o", obj_path); - if (access(cc_params[cc_par_cnt - 1], R_OK)) - FATAL("-m64 is not supported by your compiler"); + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { - } + alt_cc = "gcc"; - break; + } else if (aflcc->compiler_mode == CLANG) { - } + alt_cc = "clang"; - #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking && !partial_linking) - cc_params[cc_par_cnt++] = - alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); - #endif + } else { - #if defined(__APPLE__) - if (shared_linking || partial_linking) { + if (USE_BINDIR) + snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", + LLVM_BINDIR); + else + snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); + alt_cc = llvm_fullpath; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___afl_area_ptr"; - cc_params[cc_par_cnt++] = "-Wl,-U"; - cc_params[cc_par_cnt++] = "-Wl,___sanitizer_cov_trace_pc_guard_init"; + } } - #endif + aflcc->cc_params[0] = alt_cc; } - #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - cc_params[cc_par_cnt++] = "-lrt"; - #endif +} -#endif +/* Macro defs for the preprocessor */ - cc_params[cc_par_cnt] = NULL; +void add_defs_common(aflcc_state_t *aflcc) { + + insert_param(aflcc, "-D__AFL_COMPILER=1"); + insert_param(aflcc, "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"); } -/* Main entry point */ +/* See instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives */ +void add_defs_selective_instr(aflcc_state_t *aflcc) { -int main(int argc, char **argv, char **envp) { + if (aflcc->plusplus_mode) { - int i; - char *callname = argv[0], *ptr = NULL; + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "extern \"C\" void __afl_coverage_discard();" + "extern \"C\" void __afl_coverage_skip();" + "extern \"C\" void __afl_coverage_on();" + "extern \"C\" void __afl_coverage_off();"); - if (getenv("AFL_DEBUG")) { + } else { - debug = 1; - if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG"); + insert_param(aflcc, + "-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;" + "void __afl_coverage_discard();" + "void __afl_coverage_skip();" + "void __afl_coverage_on();" + "void __afl_coverage_off();"); - } else if (getenv("AFL_QUIET")) + } - be_quiet = 1; + insert_param( + aflcc, + "-D__AFL_COVERAGE_START_OFF()=int __afl_selective_coverage_start_off = " + "1;"); + insert_param(aflcc, "-D__AFL_COVERAGE_ON()=__afl_coverage_on()"); + insert_param(aflcc, "-D__AFL_COVERAGE_OFF()=__afl_coverage_off()"); + insert_param(aflcc, "-D__AFL_COVERAGE_DISCARD()=__afl_coverage_discard()"); + insert_param(aflcc, "-D__AFL_COVERAGE_SKIP()=__afl_coverage_skip()"); - 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; +/* As documented in instrumentation/README.persistent_mode.md, deferred + forkserver initialization and persistent mode are not available in afl-gcc + and afl-clang. */ +void add_defs_persistent_mode(aflcc_state_t *aflcc) { - } + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; - if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { + insert_param(aflcc, "-D__AFL_HAVE_MANUAL_CONTROL=1"); - passthrough = 1; - if (!debug) { be_quiet = 1; } + /* When the user tries to use persistent or deferred forkserver modes by + appending a single line to the program, we want to reliably inject a + signature into the binary (to be picked up by afl-fuzz) and we want + to call a function from the runtime .o file. This is unnecessarily + painful for three reasons: - } + 1) We need to convince the compiler not to optimize out the signature. + This is done with __attribute__((used)). - if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1; - argvnull = (u8 *)argv[0]; - check_environment_vars(envp); + 2) We need to convince the linker, when called with -Wl,--gc-sections, + not to do the same. This is done by forcing an assignment to a + 'volatile' pointer. - if ((ptr = find_object("as", argv[0])) != NULL) { + 3) We need to declare __afl_persistent_loop() in the global namespace, + but doing this within a method in a class is hard - :: and extern "C" + are forbidden and __attribute__((alias(...))) doesn't work. Hence the + __asm__ aliasing trick. - have_gcc = 1; - ck_free(ptr); + */ - } + insert_param(aflcc, + "-D__AFL_FUZZ_INIT()=" + "int __afl_sharedmem_fuzzing = 1;" + "extern unsigned int *__afl_fuzz_len;" + "extern unsigned char *__afl_fuzz_ptr;" + "unsigned char __afl_fuzz_alt[1048576];" + "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"); -#if (LLVM_MAJOR >= 3) + insert_param(aflcc, + "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " + "__afl_fuzz_alt_ptr)"); - if ((ptr = find_object("SanitizerCoverageLTO.so", argv[0])) != NULL) { + insert_param( + aflcc, + "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : " + "(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff " + "? 0 : *__afl_fuzz_len)"); + + insert_param( + aflcc, + "-D__AFL_LOOP(_A)=" + "({ static volatile const char *_B __attribute__((used,unused)); " + " _B = (const char*)\"" PERSIST_SIG + "\"; " + "extern int __afl_connected;" +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " +#else + "__attribute__((visibility(\"default\"))) " + "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); " +#endif /* ^__APPLE__ */ + // if afl is connected, we run _A times, else once. + "_L(__afl_connected ? _A : 1); })"); + + insert_param( + aflcc, + "-D__AFL_INIT()=" + "do { static volatile const char *_A __attribute__((used,unused)); " + " _A = (const char*)\"" DEFER_SIG + "\"; " +#ifdef __APPLE__ + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"___afl_manual_init\"); " +#else + "__attribute__((visibility(\"default\"))) " + "void _I(void) __asm__(\"__afl_manual_init\"); " +#endif /* ^__APPLE__ */ + "_I(); } while (0)"); - have_lto = 1; - ck_free(ptr); +} - } +/* Control _FORTIFY_SOURCE */ +void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { - if ((ptr = find_object("cmplog-routines-pass.so", argv[0])) != NULL) { + switch (action) { - have_llvm = 1; - ck_free(ptr); + case 1: + insert_param(aflcc, "-D_FORTIFY_SOURCE=1"); + break; - } + case 2: + insert_param(aflcc, "-D_FORTIFY_SOURCE=2"); + break; -#endif + default: // OFF + insert_param(aflcc, "-U_FORTIFY_SOURCE"); + break; -#ifdef __ANDROID__ - have_llvm = 1; -#endif + } - if ((ptr = find_object("afl-gcc-pass.so", argv[0])) != NULL) { +} - have_gcc_plugin = 1; - ck_free(ptr); +void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { - } + insert_param(aflcc, "-includesanitizer/lsan_interface.h"); + insert_param( + aflcc, + "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) " + "_exit(23); }"); + insert_param(aflcc, "-D__AFL_LSAN_OFF()=__lsan_disable();"); + insert_param(aflcc, "-D__AFL_LSAN_ON()=__lsan_enable();"); -#if (LLVM_MAJOR >= 3) +} - if (strncmp(callname, "afl-clang-fast", 14) == 0) { +/* About fsanitize (including PCGUARD features) */ - compiler_mode = LLVM; +/* For input "-fsanitize=...", it: - } else if (strncmp(callname, "afl-clang-lto", 13) == 0 || + 1. may have various OOB traps :) if ... doesn't contain ',' or + the input has bad syntax such as "-fsantiz=," + 2. strips any fuzzer* in ... and writes back (may result in "-fsanitize=") + 3. rets 1 if exactly "fuzzer" found, otherwise rets 0 +*/ +static u8 fsanitize_fuzzer_comma(char *string) { - strncmp(callname, "afl-lto", 7) == 0) { + u8 detect_single_fuzzer = 0; - compiler_mode = LTO; + char *p, *ptr = string + strlen("-fsanitize="); + // ck_alloc will check alloc failure + char *new = ck_alloc(strlen(string) + 1); + char *tmp = ck_alloc(strlen(ptr) + 1); + u32 count = 0, len, ende = 0; - } else + strcpy(new, "-fsanitize="); -#endif - if (strncmp(callname, "afl-gcc-fast", 12) == 0 || + do { - strncmp(callname, "afl-g++-fast", 12) == 0) { + p = strchr(ptr, ','); + if (!p) { - compiler_mode = GCC_PLUGIN; + p = ptr + strlen(ptr) + 1; + ende = 1; - } else if (strncmp(callname, "afl-gcc", 7) == 0 || + } - strncmp(callname, "afl-g++", 7) == 0) { + len = p - ptr; + if (len) { - compiler_mode = GCC; + strncpy(tmp, ptr, len); + tmp[len] = 0; + // fprintf(stderr, "Found: %s\n", tmp); + ptr += len + 1; + if (*tmp) { - } else if (strcmp(callname, "afl-clang") == 0 || + u32 copy = 1; + if (!strcmp(tmp, "fuzzer")) { - strcmp(callname, "afl-clang++") == 0) { + detect_single_fuzzer = 1; + copy = 0; - compiler_mode = CLANG; + } else if (!strncmp(tmp, "fuzzer", 6)) { - } + copy = 0; - if ((ptr = getenv("AFL_CC_COMPILER"))) { + } - if (compiler_mode) { + if (copy) { - if (!be_quiet) { + if (count) { strcat(new, ","); } + strcat(new, tmp); + ++count; - WARNF( - "\"AFL_CC_COMPILER\" is set but a specific compiler was already " - "selected by command line parameter or symlink, ignoring the " - "environment variable!"); + } } } else { - if (strncasecmp(ptr, "LTO", 3) == 0) { + ptr++; - compiler_mode = LTO; + } - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } while (!ende); - compiler_mode = LLVM; + strcpy(string, new); - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + ck_free(tmp); + ck_free(new); - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + return detect_single_fuzzer; - compiler_mode = GCC_PLUGIN; +} - } else if (strcasecmp(ptr, "GCC") == 0) { +param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { - compiler_mode = GCC; + param_st final_ = PARAM_MISS; - } else + if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && + strstr(cur_argv, "list=")) { + + if (scan) { + + aflcc->have_instr_list = 1; + final_ = PARAM_SCAN; + + } else { - FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); + final_ = PARAM_KEEP; // may be set to DROP next } } - if (strcmp(callname, "afl-clang") == 0 || - strcmp(callname, "afl-clang++") == 0) { + if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { - clang_mode = 1; - compiler_mode = CLANG; + if (scan) { - if (strcmp(callname, "afl-clang++") == 0) { plusplus_mode = 1; } + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; - } + } else { - for (i = 1; i < argc; i++) { + final_ = PARAM_DROP; - if (strncmp(argv[i], "--afl", 5) == 0) { + } - if (!strcmp(argv[i], "--afl_noopt") || !strcmp(argv[i], "--afl-noopt")) { + } else if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize=")) && - passthrough = 1; - argv[i] = "-g"; // we have to overwrite it, -g is always good - continue; + strchr(cur_argv, ',') && + !strstr(cur_argv, "=,")) { // avoid OOB errors - } + if (scan) { - if (compiler_mode && !be_quiet) { + u8 *cur_argv_ = ck_strdup(cur_argv); - WARNF( - "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " - "symlink compiler selection!"); + if (fsanitize_fuzzer_comma(cur_argv_)) { + + aflcc->need_aflpplib = 1; + final_ = PARAM_SCAN; } - ptr = argv[i]; - ptr += 5; - while (*ptr == '-') - ptr++; + ck_free(cur_argv_); - if (strncasecmp(ptr, "LTO", 3) == 0) { + } else { - compiler_mode = LTO; + fsanitize_fuzzer_comma(cur_argv); + if (!cur_argv || strlen(cur_argv) <= strlen("-fsanitize=")) + final_ = PARAM_DROP; // this means it only has "fuzzer" previously. - } else if (strncasecmp(ptr, "LLVM", 4) == 0) { + } - compiler_mode = LLVM; + } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", - } else if (strncasecmp(ptr, "PCGUARD", 7) == 0 || + strlen("-fsanitize=fuzzer-")) || + !strncmp(cur_argv, "-fsanitize-coverage", + strlen("-fsanitize-coverage"))) && + (strncmp(cur_argv, "sanitize-coverage-allow", + strlen("sanitize-coverage-allow")) && + strncmp(cur_argv, "sanitize-coverage-deny", + strlen("sanitize-coverage-deny")) && + aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { - strncasecmp(ptr, "PC-GUARD", 8) == 0) { + if (scan) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_PCGUARD; + final_ = PARAM_SCAN; - } else if (strcasecmp(ptr, "INSTRIM") == 0 || + } else { - strcasecmp(ptr, "CFG") == 0) { + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); + } - } else if (strcasecmp(ptr, "AFL") == 0 || + } - strcasecmp(ptr, "CLASSIC") == 0) { + if (!strcmp(cur_argv, "-fsanitize=address") || + !strcmp(cur_argv, "-fsanitize=memory")) { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_CLASSIC; + if (scan) { - } else if (strcasecmp(ptr, "LLVMNATIVE") == 0 || + // "-fsanitize=undefined,address" may be un-treated, but it's OK. + aflcc->asan_set = 1; + final_ = PARAM_SCAN; - strcasecmp(ptr, "NATIVE") == 0 || - strcasecmp(ptr, "LLVM-NATIVE") == 0) { + } else { - compiler_mode = LLVM; - instrument_mode = INSTRUMENT_LLVMNATIVE; + // It's impossible that final_ is PARAM_DROP before, + // so no checks are needed here. + final_ = PARAM_KEEP; - } else if (strncasecmp(ptr, "GCC_P", 5) == 0 || + } - strncasecmp(ptr, "GCC-P", 5) == 0 || - strncasecmp(ptr, "GCCP", 4) == 0) { + } - compiler_mode = GCC_PLUGIN; + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - } else if (strcasecmp(ptr, "GCC") == 0) { + return final_; - compiler_mode = GCC; +} - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { +void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - compiler_mode = CLANG; + if (!aflcc->asan_set) { - } else + if (getenv("AFL_USE_ASAN")) { - FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); + if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); - } + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=address"); - if (strlen(callname) > 2 && - (strncmp(callname + strlen(callname) - 2, "++", 2) == 0 || - strstr(callname, "-g++") != NULL)) - plusplus_mode = 1; + } else if (getenv("AFL_USE_MSAN")) { - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); - if (instrument_mode == 0) - instrument_mode = INSTRUMENT_PCGUARD; - else if (instrument_mode != INSTRUMENT_PCGUARD) - FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=memory"); + + } } - if (have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { + if (getenv("AFL_USE_UBSAN")) { - WARNF( - "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " - "for file matching, only function matching!"); + insert_param(aflcc, "-fsanitize=undefined"); + insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); + insert_param(aflcc, "-fno-sanitize-recover=all"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || - getenv("INSTRIM_LIB")) { + if (getenv("AFL_USE_TSAN")) { - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and PCGUARD " - "(default in afl-cc).\n"); + insert_param(aflcc, "-fsanitize=thread"); + insert_param(aflcc, "-fno-omit-frame-pointer"); } - if (getenv("AFL_LLVM_CTX")) instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER")) instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - - if (getenv("AFL_LLVM_NGRAM_SIZE")) { + if (getenv("AFL_USE_LSAN")) { - instrument_opt_mode |= INSTRUMENT_OPT_NGRAM; - ngram_size = atoi(getenv("AFL_LLVM_NGRAM_SIZE")); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation mode must be between 2 and NGRAM_SIZE_MAX " - "(%u)", - NGRAM_SIZE_MAX); + insert_param(aflcc, "-fsanitize=leak"); + add_defs_lsan_ctrl(aflcc); } - if (getenv("AFL_LLVM_CTX_K")) { + if (getenv("AFL_USE_CFISAN")) { - ctx_k = atoi(getenv("AFL_LLVM_CTX_K")); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL("K-CTX instrumentation mode must be between 1 and CTX_MAX_K (%u)", - CTX_MAX_K); - if (ctx_k == 1) { + if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; + insert_param(aflcc, "-fcf-protection=full"); } else { - instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; + if (!aflcc->lto_mode) { + + 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"); + + } + + insert_param(aflcc, "-fsanitize=cfi"); + insert_param(aflcc, "-fvisibility=hidden"); } } - if (getenv("AFL_LLVM_INSTRUMENT")) { +} - u8 *ptr2 = strtok(getenv("AFL_LLVM_INSTRUMENT"), ":,;"); +void add_native_pcguard(aflcc_state_t *aflcc) { - while (ptr2) { + /* If llvm-config doesn't figure out LLVM_MAJOR, just + go on anyway and let compiler complain if doesn't work. */ - if (strncasecmp(ptr2, "afl", strlen("afl")) == 0 || - strncasecmp(ptr2, "classic", strlen("classic")) == 0) { + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - if (instrument_mode == INSTRUMENT_LTO) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, + "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); +#endif - instrument_mode = INSTRUMENT_CLASSIC; - lto_mode = 1; + } else { - } else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) { +#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); +#else + #if LLVM_MAJOR == 0 + WARNF( + "pcguard instrumentation requires LLVM 4.0.1+" + " otherwise the compiler will fail"); + #endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); +#endif - instrument_mode = INSTRUMENT_AFL; + } - } else { +} - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); +void add_optimized_pcguard(aflcc_state_t *aflcc) { - } +#if LLVM_MAJOR >= 13 + #if defined __ANDROID__ || ANDROID - } + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 || - strncasecmp(ptr2, "pcguard", strlen("pcguard")) == 0) { + #else - if (!instrument_mode || instrument_mode == INSTRUMENT_PCGUARD) - instrument_mode = INSTRUMENT_PCGUARD; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + if (aflcc->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"); - if (strncasecmp(ptr2, "llvmnative", strlen("llvmnative")) == 0 || - strncasecmp(ptr2, "llvm-native", strlen("llvm-native")) == 0 || - strncasecmp(ptr2, "native", strlen("native")) == 0) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) - instrument_mode = INSTRUMENT_LLVMNATIVE; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } else { - } + /* Since LLVM_MAJOR >= 13 we use new pass manager */ + #if LLVM_MAJOR < 16 + insert_param(aflcc, "-fexperimental-new-pass-manager"); + #endif + insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0); - if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 || - strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) { + } - if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) { + #endif // defined __ANDROID__ || ANDROID +#else // LLVM_MAJOR < 13 + #if LLVM_MAJOR >= 4 - instrument_mode = INSTRUMENT_LLVMNATIVE; - instrument_opt_mode |= INSTRUMENT_OPT_CODECOV; + if (!be_quiet) + SAYF( + "Using unoptimized trace-pc-guard, upgrade to LLVM 13+ for " + "enhanced version.\n"); + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); + aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; - } else { + #else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + FATAL("pcguard instrumentation requires LLVM 4.0.1+"); - } + #endif +#endif - } +} - if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 || - strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) { +/* Linking behaviors */ - FATAL( - "InsTrim instrumentation was removed. Use a modern LLVM and " - "PCGUARD (default in afl-cc).\n"); +param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, + u8 *skip_next, char **argv) { - } + if (aflcc->lto_mode && !strncmp(cur_argv, "-flto=thin", 10)) { - if (strncasecmp(ptr2, "lto", strlen("lto")) == 0) { + FATAL( + "afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or " + "use afl-clang-fast!"); - lto_mode = 1; - if (!instrument_mode || instrument_mode == INSTRUMENT_LTO) - instrument_mode = INSTRUMENT_LTO; - else - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); + } - } + param_st final_ = PARAM_MISS; - if (strcasecmp(ptr2, "gcc") == 0) { + if (!strcmp(cur_argv, "-shared") || !strcmp(cur_argv, "-dynamiclib")) { - if (!instrument_mode || instrument_mode == INSTRUMENT_GCC) - instrument_mode = INSTRUMENT_GCC; - else if (instrument_mode != INSTRUMENT_GCC) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = GCC; + if (scan) { - } + aflcc->shared_linking = 1; + final_ = PARAM_SCAN; - if (strcasecmp(ptr2, "clang") == 0) { + } else { - if (!instrument_mode || instrument_mode == INSTRUMENT_CLANG) - instrument_mode = INSTRUMENT_CLANG; - else if (instrument_mode != INSTRUMENT_CLANG) - FATAL("main instrumentation mode already set with %s", - instrument_mode_string[instrument_mode]); - compiler_mode = CLANG; + final_ = PARAM_KEEP; - } + } - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || - strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || - strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { + } else if (!strcmp(cur_argv, "-Wl,-r") || !strcmp(cur_argv, "-Wl,-i") || - u8 *ptr3 = ptr2; - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + !strcmp(cur_argv, "-Wl,--relocatable") || + !strcmp(cur_argv, "-r") || !strcmp(cur_argv, "--relocatable")) { - if (!*ptr3) { + if (scan) { - if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) - FATAL( - "you must set the K-CTX K with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ctx-2"); + aflcc->partial_linking = 1; + final_ = PARAM_SCAN; - } + } else { - ctx_k = atoi(ptr3); - if (ctx_k < 1 || ctx_k > CTX_MAX_K) - FATAL( - "K-CTX instrumentation option must be between 1 and CTX_MAX_K " - "(%u)", - CTX_MAX_K); + final_ = PARAM_KEEP; - if (ctx_k == 1) { + } - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); - unsetenv("AFL_LLVM_CTX_K"); + } else if (!strncmp(cur_argv, "-fuse-ld=", 9) || - } else { + !strncmp(cur_argv, "--ld-path=", 10)) { - instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); - u8 *ptr4 = alloc_printf("%u", ctx_k); - setenv("AFL_LLVM_CTX_K", ptr4, 1); + if (scan) { - } + final_ = PARAM_SCAN; - } + } else { - if (strcasecmp(ptr2, "ctx") == 0) { + if (aflcc->lto_mode) + final_ = PARAM_DROP; + else + final_ = PARAM_KEEP; - instrument_opt_mode |= INSTRUMENT_OPT_CTX; - setenv("AFL_LLVM_CTX", "1", 1); + } - } + } else if (!strcmp(cur_argv, "-Wl,-z,defs") || - if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { + !strcmp(cur_argv, "-Wl,--no-undefined") || + !strcmp(cur_argv, "-Wl,-no-undefined") || + !strcmp(cur_argv, "--no-undefined") || + strstr(cur_argv, "afl-compiler-rt") || + strstr(cur_argv, "afl-llvm-rt")) { - instrument_opt_mode |= INSTRUMENT_OPT_CALLER; - setenv("AFL_LLVM_CALLER", "1", 1); + if (scan) { - } + final_ = PARAM_SCAN; - if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { + } else { - u8 *ptr3 = ptr2 + strlen("ngram"); - while (*ptr3 && (*ptr3 < '0' || *ptr3 > '9')) - ptr3++; + final_ = PARAM_DROP; - if (!*ptr3) { + } - if ((ptr3 = getenv("AFL_LLVM_NGRAM_SIZE")) == NULL) - FATAL( - "you must set the NGRAM size with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ngram-2"); + } else if (!strcmp(cur_argv, "-z") || !strcmp(cur_argv, "-Wl,-z")) { - } + u8 *param = *(argv + 1); + if (param && (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs"))) { - ngram_size = atoi(ptr3); - if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX) - FATAL( - "NGRAM instrumentation option must be between 2 and " - "NGRAM_SIZE_MAX (%u)", - NGRAM_SIZE_MAX); - instrument_opt_mode |= (INSTRUMENT_OPT_NGRAM); - u8 *ptr4 = alloc_printf("%u", ngram_size); - setenv("AFL_LLVM_NGRAM_SIZE", ptr4, 1); + *skip_next = 1; - } + if (scan) { - ptr2 = strtok(NULL, ":,;"); + final_ = PARAM_SCAN; - } + } else { - } + final_ = PARAM_DROP; - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { + } - FATAL("you cannot set CTX and CALLER together"); + } } - if ((instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { + // Try to warn user for some unsupported cases + if (scan && final_ == PARAM_MISS) { - FATAL("you cannot set CTX and K-CTX together"); + u8 *ptr_ = NULL; - } + if (!strcmp(cur_argv, "-Xlinker") && (ptr_ = *(argv + 1))) { - if ((instrument_opt_mode & INSTRUMENT_OPT_CALLER) && - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K)) { + if (!strcmp(ptr_, "defs")) { - FATAL("you cannot set CALLER and K-CTX together"); + WARNF("'-Xlinker' 'defs' detected. This may result in a bad link."); - } + } else if (strstr(ptr_, "-no-undefined")) { - if (instrument_opt_mode && instrument_mode == INSTRUMENT_DEFAULT && - (compiler_mode == LLVM || compiler_mode == UNSET)) { + WARNF( + "'-Xlinker' '%s' detected. The latter option may be dropped and " + "result in a bad link.", + ptr_); - instrument_mode = INSTRUMENT_CLASSIC; - compiler_mode = LLVM; + } - } + } else if (!strncmp(cur_argv, "-Wl,", 4) && - if (!compiler_mode) { + (u8 *)strrchr(cur_argv, ',') != (cur_argv + 3)) { - // lto is not a default because outside of afl-cc RANLIB and AR have to - // be set to LLVM versions so this would work - if (have_llvm) - compiler_mode = LLVM; - else if (have_gcc_plugin) - compiler_mode = GCC_PLUGIN; - else if (have_gcc) -#ifdef __APPLE__ - // on OSX clang masquerades as GCC - compiler_mode = CLANG; -#else - compiler_mode = GCC; -#endif - else if (have_lto) - compiler_mode = LTO; - else - FATAL("no compiler mode available"); + ptr_ = cur_argv + 4; - } + if (strstr(ptr_, "-shared") || strstr(ptr_, "-dynamiclib")) { - /* if our PCGUARD implementation is not available then silently switch to - native LLVM PCGUARD */ - if (compiler_mode == CLANG && - (instrument_mode == INSTRUMENT_DEFAULT || - instrument_mode == INSTRUMENT_PCGUARD) && - find_object("SanitizerCoveragePCGUARD.so", argv[0]) == NULL) { + WARNF( + "'%s': multiple link options after '-Wl,' may break shared " + "linking.", + ptr_); - instrument_mode = INSTRUMENT_LLVMNATIVE; + } - } + if (strstr(ptr_, "-r,") || strstr(ptr_, "-i,") || strstr(ptr_, ",-r") || + strstr(ptr_, ",-i") || strstr(ptr_, "--relocatable")) { - if (compiler_mode == GCC) { + WARNF( + "'%s': multiple link options after '-Wl,' may break partial " + "linking.", + ptr_); - if (clang_mode) { + } - instrument_mode = INSTRUMENT_CLANG; + if (strstr(ptr_, "defs") || strstr(ptr_, "no-undefined")) { - } else { + WARNF( + "'%s': multiple link options after '-Wl,' may enable report " + "unresolved symbol references and result in a bad link.", + ptr_); - instrument_mode = INSTRUMENT_GCC; + } } } - if (compiler_mode == CLANG) { + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - instrument_mode = INSTRUMENT_CLANG; - setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as + return final_; - } +} + +void add_lto_linker(aflcc_state_t *aflcc) { + + unsetenv("AFL_LD"); + unsetenv("AFL_LD_CALLER"); + + u8 *ld_path = NULL; + if (getenv("AFL_REAL_LD")) { + + ld_path = strdup(getenv("AFL_REAL_LD")); + + } else { + + ld_path = strdup(AFL_REAL_LD); + + } + + if (!ld_path || !*ld_path) { + + if (ld_path) { + + // Freeing empty string + free(ld_path); + + } + + ld_path = strdup("ld.lld"); + + } + + if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 + insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); +#else + insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); +#endif + free(ld_path); + +} + +void add_lto_passes(aflcc_state_t *aflcc) { + +#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 + // The NewPM implementation only works fully since LLVM 15. + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", + 0); +#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 + insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#else + insert_param(aflcc, "-fno-experimental-new-pass-manager"); + insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); +#endif + + insert_param(aflcc, "-Wl,--allow-multiple-definition"); + +} + +static void add_aflpplib(aflcc_state_t *aflcc) { + + if (!aflcc->need_aflpplib) return; + + u8 *afllib = find_object(aflcc, "libAFLDriver.a"); + + if (!be_quiet) { + + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + + } + + if (!afllib) { + + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); + + } + + } else { + + insert_param(aflcc, afllib); + +#ifdef __APPLE__ + insert_param(aflcc, "-Wl,-undefined"); + insert_param(aflcc, "dynamic_lookup"); +#endif + + } + +} + +void add_runtime(aflcc_state_t *aflcc) { + + if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { + + /* In the preprocessor_only case (-E), we are not actually compiling at + all but requesting the compiler to output preprocessed sources only. + We must not add the runtime in this case because the compiler will + simply output its binary content back on stdout, breaking any build + systems that rely on a separate source preprocessing step. */ + return; + + } + + if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC && + !getenv("AFL_LLVM_NO_RPATH")) { + + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + const char *libdir = LLVM_LIBDIR; + if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && + strncmp(libdir, "/lib", 4)) { + + u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); + insert_param(aflcc, libdir_opt); + + } + + } + +#ifndef __ANDROID__ + + #define M32_ERR_MSG "-m32 is not supported by your compiler" + #define M64_ERR_MSG "-m64 is not supported by your compiler" + + if (aflcc->compiler_mode != GCC && aflcc->compiler_mode != CLANG) { + + switch (aflcc->bit_mode) { + + case 0: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt.o", 0, 0); + if (aflcc->lto_mode) insert_object(aflcc, "afl-llvm-rt-lto.o", 0, 0); + break; + + case 32: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-32.o", 0, M32_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-32.o", 0, M32_ERR_MSG); + break; + + case 64: + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "afl-compiler-rt-64.o", 0, M64_ERR_MSG); + if (aflcc->lto_mode) + insert_object(aflcc, "afl-llvm-rt-lto-64.o", 0, M64_ERR_MSG); + break; + + } + + #if !defined(__APPLE__) && !defined(__sun) + if (!aflcc->shared_linking && !aflcc->partial_linking) + insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); + #endif + + #if defined(__APPLE__) + if (aflcc->shared_linking || aflcc->partial_linking) { + + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___afl_area_ptr"); + insert_param(aflcc, "-Wl,-U"); + insert_param(aflcc, "-Wl,___sanitizer_cov_trace_pc_guard_init"); + + } + + #endif + + } + +#endif + + add_aflpplib(aflcc); + +#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ + insert_param(aflcc, "-Wl,-lrt"); +#endif + +} + +/* Misc */ + +void add_assembler(aflcc_state_t *aflcc) { + + u8 *afl_as = find_object(aflcc, "as"); + + if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); + + u8 *slash = strrchr(afl_as, '/'); + if (slash) *slash = 0; + + insert_param(aflcc, "-B"); + insert_param(aflcc, afl_as); + + if (aflcc->compiler_mode == CLANG) insert_param(aflcc, "-no-integrated-as"); + +} + +void add_gcc_plugin(aflcc_state_t *aflcc) { + + if (aflcc->cmplog_mode) { + + insert_object(aflcc, "afl-gcc-cmplog-pass.so", "-fplugin=%s", 0); + insert_object(aflcc, "afl-gcc-cmptrs-pass.so", "-fplugin=%s", 0); + + } + + insert_object(aflcc, "afl-gcc-pass.so", "-fplugin=%s", 0); + + insert_param(aflcc, "-fno-if-conversion"); + insert_param(aflcc, "-fno-if-conversion2"); + +} + +void add_misc_params(aflcc_state_t *aflcc) { + + if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || + aflcc->lto_mode) { + + insert_param(aflcc, "-fno-builtin-strcmp"); + insert_param(aflcc, "-fno-builtin-strncmp"); + insert_param(aflcc, "-fno-builtin-strcasecmp"); + insert_param(aflcc, "-fno-builtin-strncasecmp"); + insert_param(aflcc, "-fno-builtin-memcmp"); + insert_param(aflcc, "-fno-builtin-bcmp"); + insert_param(aflcc, "-fno-builtin-strstr"); + insert_param(aflcc, "-fno-builtin-strcasestr"); + + } + + if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } + + if (getenv("AFL_HARDEN")) { + + insert_param(aflcc, "-fstack-protector-all"); + + if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); + + } + + if (!getenv("AFL_DONT_OPTIMIZE")) { + + insert_param(aflcc, "-g"); + if (!aflcc->have_o) insert_param(aflcc, "-O3"); + if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); + // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') + // insert_param(aflcc, aflcc->march_opt); + + } + + if (aflcc->x_set) { + + insert_param(aflcc, "-x"); + insert_param(aflcc, "none"); + + } + +} + +param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { + + param_st final_ = PARAM_MISS; + +// MACRO START +#define SCAN_KEEP(dst, src) \ + do { \ + \ + if (scan) { \ + \ + dst = src; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } while (0) + + // MACRO END + + if (!strncasecmp(cur_argv, "-fpic", 5)) { + + SCAN_KEEP(aflcc->have_pic, 1); + + } else if (!strcmp(cur_argv, "-m32") || + + !strcmp(cur_argv, "armv7a-linux-androideabi")) { + + SCAN_KEEP(aflcc->bit_mode, 32); + + } else if (!strcmp(cur_argv, "-m64")) { + + SCAN_KEEP(aflcc->bit_mode, 64); + + } else if (strstr(cur_argv, "FORTIFY_SOURCE")) { + + SCAN_KEEP(aflcc->fortify_set, 1); + + } else if (!strcmp(cur_argv, "-x")) { + + SCAN_KEEP(aflcc->x_set, 1); + + } else if (!strcmp(cur_argv, "-E")) { + + SCAN_KEEP(aflcc->preprocessor_only, 1); + + } else if (!strcmp(cur_argv, "--target=wasm32-wasi")) { + + SCAN_KEEP(aflcc->passthrough, 1); + + } else if (!strcmp(cur_argv, "-c")) { + + SCAN_KEEP(aflcc->have_c, 1); + + } else if (!strncmp(cur_argv, "-O", 2)) { + + SCAN_KEEP(aflcc->have_o, 1); + + } else if (!strncmp(cur_argv, "-funroll-loop", 13)) { + + SCAN_KEEP(aflcc->have_unroll, 1); + + } else if (!strncmp(cur_argv, "--afl", 5)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-fno-unroll", 11)) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strcmp(cur_argv, "-pipe") && aflcc->compiler_mode == GCC_PLUGIN) { + + if (scan) + final_ = PARAM_SCAN; + else + final_ = PARAM_DROP; + + } else if (!strncmp(cur_argv, "-stdlib=", 8) && + + (aflcc->compiler_mode == GCC || + aflcc->compiler_mode == GCC_PLUGIN)) { + + if (scan) { + + final_ = PARAM_SCAN; + + } else { + + if (!be_quiet) WARNF("Found '%s' - stripping!", cur_argv); + final_ = PARAM_DROP; + + } + + } else if (cur_argv[0] != '-') { + + /* It's a weak, loose pattern, with very different purpose + than others. We handle it at last, cautiously and robustly. */ + + if (scan && cur_argv[0] != '@') // response file support + aflcc->non_dash = 1; + + } + +#undef SCAN_KEEP + + if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); + + return final_; + +} + +static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { @@ -2168,16 +2559,22 @@ int main(int argc, char **argv, char **envp) { " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - have_llvm ? "AVAILABLE" : "unavailable!", - compiler_mode == LLVM ? " [SELECTED]" : "", - have_llvm ? "AVAILABLE" : "unavailable!", - have_llvm ? "AVAILABLE" : "unavailable!", - have_lto ? "AVAILABLE" : "unavailable!", - compiler_mode == LTO ? " [SELECTED]" : "", - have_gcc_plugin ? "AVAILABLE" : "unavailable!", - compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", - have_gcc ? "AVAILABLE" : "unavailable!", - (compiler_mode == GCC || compiler_mode == CLANG) ? " [SELECTED]" : ""); + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LLVM ? " [SELECTED]" : "", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_lto ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == LTO ? " [SELECTED]" : "", + aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", + aflcc->compiler_mode == GCC_PLUGIN ? " [SELECTED]" : "", + aflcc->have_gcc && aflcc->have_clang + ? "AVAILABLE" + : (aflcc->have_gcc + ? "GCC ONLY " + : (aflcc->have_clang ? "CLANG ONLY" : "unavailable!")), + (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) + ? " [SELECTED]" + : ""); SAYF( "Modes:\n" @@ -2266,7 +2663,7 @@ int main(int argc, char **argv, char **envp) { " AFL_USE_TSAN: activate thread sanitizer\n" " AFL_USE_LSAN: activate leak-checker sanitizer\n"); - if (have_gcc_plugin) + if (aflcc->have_gcc_plugin) SAYF( "\nGCC Plugin-specific environment variables:\n" " AFL_GCC_CMPLOG: log operands of comparisons (RedQueen mutator)\n" @@ -2282,7 +2679,7 @@ int main(int argc, char **argv, char **envp) { #define COUNTER_BEHAVIOUR \ " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" #endif - if (have_llvm) + if (aflcc->have_llvm) SAYF( "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " "variables:\n" @@ -2310,7 +2707,7 @@ int main(int argc, char **argv, char **envp) { "instrument allow/\n" " deny listing (selective instrumentation)\n"); - if (have_llvm) + if (aflcc->have_llvm) SAYF( " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " "mutator)\n" @@ -2329,7 +2726,7 @@ int main(int argc, char **argv, char **envp) { "locations\n"); #ifdef AFL_CLANG_FLTO - if (have_lto) + if (aflcc->have_lto) SAYF( "\nLTO/afl-clang-lto specific environment variables:\n" " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), " @@ -2365,9 +2762,9 @@ int main(int argc, char **argv, char **envp) { "targets.\n\n"); #if (LLVM_MAJOR >= 3) - if (have_lto) + if (aflcc->have_lto) SAYF("afl-cc LTO with ld=%s %s\n", AFL_REAL_LD, AFL_CLANG_FLTO); - if (have_llvm) + if (aflcc->have_llvm) SAYF("afl-cc LLVM version %d using the binary path \"%s\".\n", LLVM_MAJOR, LLVM_BINDIR); #endif @@ -2406,205 +2803,356 @@ int main(int argc, char **argv, char **envp) { } - if (compiler_mode == LTO) { +} - if (instrument_mode == 0 || instrument_mode == INSTRUMENT_LTO || - instrument_mode == INSTRUMENT_CFG || - instrument_mode == INSTRUMENT_PCGUARD) { +static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, + char **argv) { - lto_mode = 1; - // force CFG - // if (!instrument_mode) { + limit_params(aflcc, argc); - instrument_mode = INSTRUMENT_PCGUARD; - // ptr = instrument_mode_string[instrument_mode]; - // } - - } else if (instrument_mode == INSTRUMENT_CLASSIC) { + // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); - lto_mode = 1; + /* Process the argument list. */ - } else { + u8 skip_next = 0; + while (--argc) { - if (!be_quiet) { + u8 *cur = *(++argv); - WARNF("afl-clang-lto called with mode %s, using that mode instead", - instrument_mode_string[instrument_mode]); + if (skip_next > 0) { - } + skip_next--; + continue; } - } + if (PARAM_MISS != parse_misc_params(aflcc, cur, scan)) continue; - if (instrument_mode == 0 && compiler_mode < GCC_PLUGIN) { + if (PARAM_MISS != parse_fsanitize(aflcc, cur, scan)) continue; -#if LLVM_MAJOR >= 7 - #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (have_instr_env) { + if (PARAM_MISS != parse_linking_params(aflcc, cur, scan, &skip_next, argv)) + continue; - instrument_mode = INSTRUMENT_AFL; - if (!be_quiet) { + if (*cur == '@') { - WARNF( - "Switching to classic instrumentation because " - "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); + // response file support. + // 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. + // We do *not* support quotes in the rsp files to cope with spaces in + // filenames etc! If you need that then send a patch! + u8 *filename = cur + 1; + if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } + FILE *f = fopen(filename, "r"); + struct stat st; + + // Check not found or empty? let the compiler complain if so. + if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + + if (!scan) insert_param(aflcc, cur); + continue; } - } else + u8 *tmpbuf = malloc(st.st_size + 2), *ptr; + char **args = malloc(sizeof(char *) * (st.st_size >> 1)); + int count = 1, cont = 0, cont_act = 0; - #endif - instrument_mode = INSTRUMENT_PCGUARD; + while (fgets(tmpbuf, st.st_size + 1, f)) { -#else - instrument_mode = INSTRUMENT_AFL; -#endif + ptr = tmpbuf; + // fprintf(stderr, "1: %s\n", ptr); + // no leading whitespace + while (isspace(*ptr)) { - } + ++ptr; + cont_act = 0; - if (instrument_opt_mode && compiler_mode != LLVM) - FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); + } - if (!instrument_opt_mode) { + // no comments, no empty lines + if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } + // remove LF + if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } + // remove CR + if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } + // handle \ at end of line + if (*ptr && ptr[strlen(ptr) - 1] == '\\') { - if (lto_mode && instrument_mode == INSTRUMENT_CFG) - instrument_mode = INSTRUMENT_PCGUARD; - ptr = instrument_mode_string[instrument_mode]; + cont = 1; + ptr[strlen(ptr) - 1] = 0; - } else { + } - char *ptr2 = alloc_printf(" + NGRAM-%u", ngram_size); - char *ptr3 = alloc_printf(" + K-CTX-%u", ctx_k); + // fprintf(stderr, "2: %s\n", ptr); - ptr = alloc_printf( - "%s%s%s%s%s", instrument_mode_string[instrument_mode], - (instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", - (instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", - (instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", - (instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); + // remove whitespace at end + while (*ptr && isspace(ptr[strlen(ptr) - 1])) { - ck_free(ptr2); - ck_free(ptr3); + ptr[strlen(ptr) - 1] = 0; + cont = 0; - } + } -#ifndef AFL_CLANG_FLTO - if (lto_mode) - FATAL( - "instrumentation mode LTO specified but LLVM support not available " - "(requires LLVM 11 or higher)"); -#endif + // fprintf(stderr, "3: %s\n", ptr); + if (*ptr) { - if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV && - instrument_mode != INSTRUMENT_CLASSIC) - FATAL( - "CALLER, CTX and NGRAM instrumentation options can only be used with " - "the LLVM CLASSIC instrumentation mode."); + do { - if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) - FATAL( - "AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set " - "together"); + u8 *value = ptr; + while (*ptr && !isspace(*ptr)) { -#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1) - if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) { + ++ptr; - FATAL( - "Instrumentation type PCGUARD does not support " - "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead."); + } - } + while (*ptr && isspace(*ptr)) { -#endif + *ptr++ = 0; - u8 *ptr2; + } - if ((ptr2 = getenv("AFL_LLVM_DICT2FILE")) != NULL && *ptr2 != '/') - FATAL("AFL_LLVM_DICT2FILE must be set to an absolute file path"); + if (cont_act) { - if ((isatty(2) && !be_quiet) || debug) { + u32 len = strlen(args[count - 1]) + strlen(value) + 1; + u8 *tmp = malloc(len); + snprintf(tmp, len, "%s%s", args[count - 1], value); + free(args[count - 1]); + args[count - 1] = tmp; + cont_act = 0; - SAYF(cCYA - "afl-cc" VERSION cRST - " by Michal Zalewski, Laszlo Szekeres, Marc Heuse - mode: %s-%s\n", - compiler_mode_string[compiler_mode], ptr); + } else { - } + args[count++] = strdup(value); - if (!be_quiet && (compiler_mode == GCC || compiler_mode == CLANG)) { + } - WARNF( - "You are using outdated instrumentation, install LLVM and/or " - "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " - "instead!"); + } while (*ptr); + + } + + if (cont) { + + cont_act = 1; + cont = 0; + + } + + } + + if (count) { process_params(aflcc, scan, count, args); } + + // we cannot free args[] unless we don't need + // to keep any reference in cc_params + if (scan) { + + if (count) do { + + free(args[--count]); + + } while (count); + + free(args); + + } + + free(tmpbuf); + + continue; + + } + + if (!scan) insert_param(aflcc, cur); } - if (debug) { +} - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < argc; i++) - SAYF(" '%s'", argv[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); +/* Copy argv to cc_params, making the necessary edits. */ + +static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, + char **envp) { + + 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 (getenv("AFL_LLVM_LAF_ALL")) { + if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) { - setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); - setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); - setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); + add_assembler(aflcc); } - cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || - getenv("AFL_GCC_CMPLOG"); + if (aflcc->compiler_mode == GCC_PLUGIN) { add_gcc_plugin(aflcc); } -#if !defined(__ANDROID__) && !defined(ANDROID) - ptr = find_object("afl-compiler-rt.o", argv[0]); + if (aflcc->compiler_mode == LLVM || aflcc->compiler_mode == LTO) { - if (!ptr) { + if (aflcc->lto_mode && aflcc->have_instr_env) { - FATAL( - "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH " - "environment variable."); + load_llvm_pass(aflcc, "afl-llvm-lto-instrumentlist.so"); - } + } - if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); } + if (getenv("AFL_LLVM_DICT2FILE")) { - ck_free(ptr); -#endif + load_llvm_pass(aflcc, "afl-llvm-dict2file.so"); - edit_params(argc, argv, envp); + } - if (debug) { + // laf + if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) { - DEBUGF("cd '%s';", getthecwd()); - for (i = 0; i < (s32)cc_par_cnt; i++) - SAYF(" '%s'", cc_params[i]); - SAYF("\n"); - fflush(stdout); - fflush(stderr); + 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"); + + } + + } + + if (aflcc->cmplog_mode) { + + load_llvm_pass(aflcc, "cmplog-instructions-pass.so"); + load_llvm_pass(aflcc, "cmplog-routines-pass.so"); + + } + + if (getenv("AFL_LLVM_INJECTIONS_ALL") || + getenv("AFL_LLVM_INJECTIONS_SQL") || + getenv("AFL_LLVM_INJECTIONS_LDAP") || + getenv("AFL_LLVM_INJECTIONS_XSS")) { + + load_llvm_pass(aflcc, "injection-pass.so"); + + } + + // insert_param(aflcc, "-Qunused-arguments"); } - if (passthrough) { + /* Inspect the command line parameters. */ + + process_params(aflcc, 0, argc, argv); + + add_sanitizers(aflcc, envp); + + add_misc_params(aflcc); + + add_defs_common(aflcc); + add_defs_selective_instr(aflcc); + add_defs_persistent_mode(aflcc); + + add_runtime(aflcc); + + insert_param(aflcc, NULL); + +} + +/* Main entry point */ + +int main(int argc, char **argv, char **envp) { + + aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); + aflcc_state_init(aflcc, (u8 *)argv[0]); + + check_environment_vars(envp); + + find_built_deps(aflcc); + + compiler_mode_by_callname(aflcc); + compiler_mode_by_environ(aflcc); + compiler_mode_by_cmdline(aflcc, argc, argv); + + instrument_mode_by_environ(aflcc); + + mode_final_checkout(aflcc, argc, argv); + + process_params(aflcc, 1, argc, argv); + + maybe_usage(aflcc, argc, argv); + + mode_notification(aflcc); + + if (aflcc->debug) debugf_args(argc, argv); + + edit_params(aflcc, argc, argv, envp); + + if (aflcc->debug) + debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); + + if (aflcc->passthrough) { - argv[0] = cc_params[0]; - execvp(cc_params[0], (char **)argv); + argv[0] = aflcc->cc_params[0]; + execvp(aflcc->cc_params[0], (char **)argv); } else { - execvp(cc_params[0], (char **)cc_params); + execvp(aflcc->cc_params[0], (char **)aflcc->cc_params); } - FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]); + FATAL("Oops, failed to execute '%s' - check your PATH", aflcc->cc_params[0]); return 0; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 34a5ff81..1ee8ebe7 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -169,20 +169,16 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz_send) { + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - el->afl_custom_fuzz_send(el->data, *mem, new_size); - sent = 1; + if (el->afl_custom_fuzz_send) { - } + el->afl_custom_fuzz_send(el->data, *mem, new_size); + sent = 1; - }); + } - } + }); if (likely(!sent)) { @@ -203,7 +199,7 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - } else { + } else { /* !afl->custom_mutators_count */ if (unlikely(len < afl->min_length && !fix)) { @@ -215,27 +211,8 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { } - if (unlikely(afl->custom_mutators_count)) { - - LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { - - if (el->afl_custom_fuzz_send) { - - el->afl_custom_fuzz_send(el->data, *mem, len); - sent = 1; - - } - - }); - - } - - if (likely(!sent)) { - - /* boring uncustom. */ - afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len); - - } + /* boring uncustom. */ + afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 17949fd7..2d5787e8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1812,6 +1812,10 @@ int main(int argc, char **argv_orig, char **envp) { check_cpu_governor(afl); #endif + #ifdef __APPLE__ + setenv("DYLD_NO_PIE", "1", 0); + #endif + if (getenv("LD_PRELOAD")) { WARNF( -- cgit 1.4.1 From 660b697ed9d1d14987ffba4bf80ad4cbe6f29f95 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Jan 2024 10:28:39 +0100 Subject: typos --- src/afl-cc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 192c5423..cda964df 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1180,11 +1180,11 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { switch (aflcc->compiler_mode) { case GCC: - if (!aflcc->have_gcc) FATAL("afl-gcc not available on your platform!"); + if (!aflcc->have_gcc) FATAL("afl-gcc is not available on your platform!"); break; case CLANG: if (!aflcc->have_clang) - FATAL("afl-clang not available on your platform!"); + FATAL("afl-clang is not available on your platform!"); break; case LLVM: if (!aflcc->have_llvm) @@ -2538,11 +2538,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" " [LLVM] LLVM: %s%s\n" - " PCGUARD %s yes yes module yes yes " + " PCGUARD %s yes yes module yes yes " "yes\n" - " NATIVE AVAILABLE no yes no no " + " NATIVE AVAILABLE no yes no no " "part. yes\n" - " CLASSIC %s no yes module yes yes " + " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" " - CALLER\n" -- cgit 1.4.1 From ab0823cd3bd0bf59e6fd1b29484e1529d055776b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Jan 2024 15:51:57 +0100 Subject: apple fixes --- src/afl-cc.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index cda964df..5cbd964e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -611,26 +611,18 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strncmp(aflcc->callname, "afl-gcc", 7) == 0 || strncmp(aflcc->callname, "afl-g++", 7) == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strcmp(aflcc->callname, "afl-clang") == 0 || strcmp(aflcc->callname, "afl-clang++") == 0) { aflcc->compiler_mode = CLANG; -#endif - } } @@ -675,22 +667,14 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "CLANG") == 0) { aflcc->compiler_mode = CLANG; -#endif - } else FATAL("Unknown AFL_CC_COMPILER mode: %s\n", ptr); @@ -774,22 +758,14 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->compiler_mode = GCC_PLUGIN; -#if defined(__x86_64__) - } else if (strcasecmp(ptr, "GCC") == 0) { aflcc->compiler_mode = GCC; -#endif - -#if defined(__x86_64__) - } else if (strncasecmp(ptr, "CLANG", 5) == 0) { aflcc->compiler_mode = CLANG; -#endif - } else FATAL("Unknown --afl-... compiler mode: %s\n", argv[i]); @@ -960,7 +936,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#if defined(__x86_64__) if (strcasecmp(ptr2, "gcc") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_GCC) @@ -975,9 +950,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#endif - -#if defined(__x86_64__) if (strcasecmp(ptr2, "clang") == 0) { if (!aflcc->instrument_mode || aflcc->instrument_mode == INSTRUMENT_CLANG) @@ -992,8 +964,6 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } -#endif - if (strncasecmp(ptr2, "ctx-", strlen("ctx-")) == 0 || strncasecmp(ptr2, "kctx-", strlen("c-ctx-")) == 0 || strncasecmp(ptr2, "k-ctx-", strlen("k-ctx-")) == 0) { -- cgit 1.4.1 From d5812786f30f03ad162643a0e21c945f8ffd14d3 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 24 Jan 2024 17:54:57 +0100 Subject: gcc asan workaround (#1966) --- src/afl-cc.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 138 insertions(+), 38 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5cbd964e..ec25bf9d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -170,8 +170,10 @@ typedef struct aflcc_state { u8 have_instr_env, have_gcc, have_clang, have_llvm, have_gcc_plugin, have_lto, have_optimized_pcguard, have_instr_list; - u8 fortify_set, asan_set, x_set, bit_mode, preprocessor_only, have_unroll, - have_o, have_pic, have_c, shared_linking, partial_linking, non_dash; + u8 fortify_set, x_set, bit_mode, preprocessor_only, have_unroll, have_o, + have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp, + have_flto, have_hidden, have_fortify, have_fcf, have_staticasan, + have_asan, have_msan, have_ubsan, have_lsan, have_tsan, have_cfisan; // u8 *march_opt; u8 need_aflpplib; @@ -1553,6 +1555,8 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { /* Control _FORTIFY_SOURCE */ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { + if (aflcc->have_fortify) { return; } + switch (action) { case 1: @@ -1666,6 +1670,42 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; + if (strstr(cur_argv, "=address") || strstr(cur_argv, ",address")) { + + aflcc->have_asan = 1; + + } + + if (strstr(cur_argv, "=memory") || strstr(cur_argv, ",memory")) { + + aflcc->have_msan = 1; + + } + + if (strstr(cur_argv, "=undefined") || strstr(cur_argv, ",undefined")) { + + aflcc->have_ubsan = 1; + + } + + if (strstr(cur_argv, "=thread") || strstr(cur_argv, ",thread")) { + + aflcc->have_tsan = 1; + + } + + if (strstr(cur_argv, "=leak") || strstr(cur_argv, ",leak")) { + + aflcc->have_lsan = 1; + + } + + if (strstr(cur_argv, "=cfi") || strstr(cur_argv, ",cfi")) { + + aflcc->have_cfisan = 1; + + } + if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && strstr(cur_argv, "list=")) { @@ -1745,19 +1785,14 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - if (!strcmp(cur_argv, "-fsanitize=address") || - !strcmp(cur_argv, "-fsanitize=memory")) { + if (final_ == PARAM_MISS) { if (scan) { - // "-fsanitize=undefined,address" may be un-treated, but it's OK. - aflcc->asan_set = 1; final_ = PARAM_SCAN; } else { - // It's impossible that final_ is PARAM_DROP before, - // so no checks are needed here. final_ = PARAM_KEEP; } @@ -1772,74 +1807,113 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { void add_sanitizers(aflcc_state_t *aflcc, char **envp) { - if (!aflcc->asan_set) { + 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_USE_ASAN")) { + if (getenv("AFL_HARDEN")) + FATAL("ASAN and AFL_HARDEN are mutually exclusive"); - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (aflcc->compiler_mode == GCC_PLUGIN && !aflcc->have_staticasan) { - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + insert_param(aflcc, "-static-libasan"); - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=address"); + } - } else if (getenv("AFL_USE_MSAN")) { + add_defs_fortify(aflcc, 0); + if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); } + aflcc->have_asan = 1; - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + } else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) { - if (getenv("AFL_HARDEN")) - FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + if (getenv("AFL_USE_ASAN") || aflcc->have_asan) + FATAL("ASAN and MSAN are mutually exclusive"); - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=memory"); + if (getenv("AFL_HARDEN")) + FATAL("MSAN and AFL_HARDEN are mutually exclusive"); - } + add_defs_fortify(aflcc, 0); + insert_param(aflcc, "-fsanitize=memory"); + aflcc->have_msan = 1; } - if (getenv("AFL_USE_UBSAN")) { + 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; + + } - insert_param(aflcc, "-fsanitize=undefined"); - insert_param(aflcc, "-fsanitize-undefined-trap-on-error"); - insert_param(aflcc, "-fno-sanitize-recover=all"); - insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_ubsan = 1; } - if (getenv("AFL_USE_TSAN")) { + if (getenv("AFL_USE_TSAN") || aflcc->have_tsan) { + + if (!aflcc->have_fp) { + + insert_param(aflcc, "-fno-omit-frame-pointer"); + aflcc->have_fp = 1; + + } - insert_param(aflcc, "-fsanitize=thread"); - insert_param(aflcc, "-fno-omit-frame-pointer"); + if (!aflcc->have_tsan) { insert_param(aflcc, "-fsanitize=thread"); } + aflcc->have_tsan = 1; } - if (getenv("AFL_USE_LSAN")) { + 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")) { + if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { - insert_param(aflcc, "-fcf-protection=full"); + if (!aflcc->have_fcf) { insert_param(aflcc, "-fcf-protection=full"); } } else { - if (!aflcc->lto_mode) { + if (!aflcc->lto_mode && !aflcc->have_flto) { uint32_t i = 0, found = 0; - while (envp[i] != NULL && !found) + while (envp[i] != NULL && !found) { + if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - if (!found) insert_param(aflcc, "-flto"); + + } + + if (!found) { insert_param(aflcc, "-flto"); } + aflcc->have_flto = 1; } - insert_param(aflcc, "-fsanitize=cfi"); - insert_param(aflcc, "-fvisibility=hidden"); + 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; } @@ -2417,6 +2491,32 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_c, 1); + } else if (!strcmp(cur_argv, "-static-libasan")) { + + SCAN_KEEP(aflcc->have_staticasan, 1); + + } else if (!strcmp(cur_argv, "-fno-omit-frame-pointer")) { + + SCAN_KEEP(aflcc->have_fp, 1); + + } else if (!strcmp(cur_argv, "-fvisibility=hidden")) { + + SCAN_KEEP(aflcc->have_hidden, 1); + + } else if (!strcmp(cur_argv, "-flto") || !strcmp(cur_argv, "-flto=full")) { + + SCAN_KEEP(aflcc->have_flto, 1); + + } else if (!strncmp(cur_argv, "-D_FORTIFY_SOURCE", + + strlen("-D_FORTIFY_SOURCE"))) { + + SCAN_KEEP(aflcc->have_fortify, 1); + + } else if (!strncmp(cur_argv, "-fcf-protection", strlen("-fcf-protection"))) { + + SCAN_KEEP(aflcc->have_cfisan, 1); + } else if (!strncmp(cur_argv, "-O", 2)) { SCAN_KEEP(aflcc->have_o, 1); -- cgit 1.4.1 From 8746b3e310ba6200e9e62fd6fabbba36edaa3811 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Jan 2024 18:06:02 +0100 Subject: fix github merge fuckup --- src/afl-cc.c | 503 ++++------------------------------------------------------- 1 file changed, 27 insertions(+), 476 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index dee90946..ec25bf9d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -650,7 +650,7 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { "selected by command line parameter or symlink, ignoring the " "environment variable!"); - if (aflcc->compiler_mode) { + } } else { @@ -708,7 +708,7 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " "symlink compiler selection!"); - char *ptr = NULL; + } ptr = argv[i]; ptr += 5; @@ -831,8 +831,7 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX_K; - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + } } @@ -1005,26 +1004,21 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } - if ((ptr3 = getenv("AFL_LLVM_CTX_K")) == NULL) - FATAL( - "you must set the K-CTX K with (e.g. for value 2) " - "AFL_LLVM_INSTRUMENT=ctx-2"); + } if (strcasecmp(ptr2, "ctx") == 0) { aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; setenv("AFL_LLVM_CTX", "1", 1); - if (aflcc->ctx_k == 1) { + } if (strncasecmp(ptr2, "caller", strlen("caller")) == 0) { aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; setenv("AFL_LLVM_CALLER", "1", 1); - aflcc->instrument_opt_mode |= (INSTRUMENT_OPT_CTX_K); - u8 *ptr4 = alloc_printf("%u", aflcc->ctx_k); - setenv("AFL_LLVM_CTX_K", ptr4, 1); + } if (strncasecmp(ptr2, "ngram", strlen("ngram")) == 0) { @@ -1204,8 +1198,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_CLANG; setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as - aflcc->instrument_mode = INSTRUMENT_CLASSIC; - aflcc->compiler_mode = LLVM; + } } @@ -1265,7 +1258,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode = INSTRUMENT_AFL; #endif - if (!be_quiet) { + } if (!aflcc->instrument_opt_mode && aflcc->lto_mode && aflcc->instrument_mode == INSTRUMENT_CFG) { @@ -1290,7 +1283,7 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { else aflcc->compiler_mode = LTO; - } else + } if (getenv("AFL_LLVM_SKIP_NEVERZERO") && getenv("AFL_LLVM_NOT_ZERO")) FATAL( @@ -1364,18 +1357,10 @@ void mode_notification(aflcc_state_t *aflcc) { "gcc-plugin and use afl-clang-fast/afl-clang-lto/afl-gcc-fast " "instead!"); - char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); - char *ptr3 = alloc_printf(" + K-CTX-%u", aflcc->ctx_k); - - char *ptr1 = alloc_printf( - "%s%s%s%s%s", instrument_mode_2str(aflcc->instrument_mode), - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) ? " + CTX" : "", - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) ? " + CALLER" : "", - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_NGRAM) ? ptr2 : "", - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX_K) ? ptr3 : ""); - } +} + void add_real_argv0(aflcc_state_t *aflcc) { static u8 llvm_fullpath[PATH_MAX]; @@ -1434,7 +1419,7 @@ void add_real_argv0(aflcc_state_t *aflcc) { } - alt_cc = "clang"; + } aflcc->cc_params[0] = alt_cc; @@ -1586,9 +1571,7 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { insert_param(aflcc, "-U_FORTIFY_SOURCE"); break; - case 2: - insert_param(aflcc, "-D_FORTIFY_SOURCE=2"); - break; + } } @@ -1709,7 +1692,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { aflcc->have_tsan = 1; - } else { + } if (strstr(cur_argv, "=leak") || strstr(cur_argv, ",leak")) { @@ -1798,11 +1781,9 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } final_ = PARAM_DROP; - if (getenv("AFL_HARDEN")) - FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + } - add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=address"); + } if (final_ == PARAM_MISS) { @@ -1916,8 +1897,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { if (strncmp("-flto", envp[i++], 5) == 0) found = 1; - #endif -#endif + } if (!found) { insert_param(aflcc, "-flto"); } aflcc->have_flto = 1; @@ -1931,7 +1911,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { insert_param(aflcc, "-fvisibility=hidden"); aflcc->have_hidden = 1; - if (aflcc->lto_mode && !strncmp(cur_argv, "-flto=thin", 10)) { + } aflcc->have_cfisan = 1; @@ -2101,10 +2081,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, final_ = PARAM_SCAN; - WARNF( - "'%s': multiple link options after '-Wl,' may enable report " - "unresolved symbol references and result in a bad link.", - ptr_); + } else { final_ = PARAM_DROP; @@ -2129,392 +2106,8 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } -} - -void add_lto_linker(aflcc_state_t *aflcc) { - - unsetenv("AFL_LD"); - unsetenv("AFL_LD_CALLER"); - - u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { - - ld_path = strdup(getenv("AFL_REAL_LD")); - - } else { - - ld_path = strdup(AFL_REAL_LD); - - } - - if (!ld_path || !*ld_path) { - - if (ld_path) { - - // Freeing empty string - free(ld_path); - - } - - ld_path = strdup("ld.lld"); - - } - - if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 - insert_param(aflcc, alloc_printf("--ld-path=%s", ld_path)); -#else - insert_param(aflcc, alloc_printf("-fuse-ld=%s", ld_path)); -#endif - free(ld_path); - -} - -void add_lto_passes(aflcc_state_t *aflcc) { - -#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 - // The NewPM implementation only works fully since LLVM 15. - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,--load-pass-plugin=%s", - 0); -#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13 - insert_param(aflcc, "-Wl,--lto-legacy-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); -#else - insert_param(aflcc, "-fno-experimental-new-pass-manager"); - insert_object(aflcc, "SanitizerCoverageLTO.so", "-Wl,-mllvm=-load=%s", 0); -#endif - - insert_param(aflcc, "-Wl,--allow-multiple-definition"); - -} - -static void add_aflpplib(aflcc_state_t *aflcc) { - - if (!aflcc->need_aflpplib) return; - - u8 *afllib = find_object(aflcc, "libAFLDriver.a"); - - if (!be_quiet) { - - OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); - - } - - if (!afllib) { - - if (!be_quiet) { - - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); - - } - - } else { - - insert_param(aflcc, afllib); - -#ifdef __APPLE__ - insert_param(aflcc, "-Wl,-undefined"); - insert_param(aflcc, "dynamic_lookup"); -#endif - - } - -} - -void add_runtime(aflcc_state_t *aflcc) { - - if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { - - /* In the preprocessor_only case (-E), we are not actually compiling at - all but requesting the compiler to output preprocessed sources only. - We must not add the runtime in this case because the compiler will - simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ - return; - - } - - if (aflcc->compiler_mode != GCC_PLUGIN && aflcc->compiler_mode != GCC && - !getenv("AFL_LLVM_NO_RPATH")) { - - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - const char *libdir = LLVM_LIBDIR; - if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { - - u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); - insert_param(aflcc, libdir_opt); - - } - - } - -#ifndef __ANDROID__ - - #define M32_ERR_MSG "-m32 is not supported by your compiler" - #define M64_ERR_MSG "-m64 is not supported by your compiler" - - if (aflcc->compiler_mode != GCC && aflcc->compiler_mode != CLANG) { - - switch (aflcc->bit_mode) { - - case 0: - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "afl-compiler-rt.o", 0, 0); - if (aflcc->lto_mode) insert_object(aflcc, "afl-llvm-rt-lto.o", 0, 0); - break; - - case 32: - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "afl-compiler-rt-32.o", 0, M32_ERR_MSG); - if (aflcc->lto_mode) - insert_object(aflcc, "afl-llvm-rt-lto-32.o", 0, M32_ERR_MSG); - break; - - case 64: - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "afl-compiler-rt-64.o", 0, M64_ERR_MSG); - if (aflcc->lto_mode) - insert_object(aflcc, "afl-llvm-rt-lto-64.o", 0, M64_ERR_MSG); - break; - - } - - #if !defined(__APPLE__) && !defined(__sun) - if (!aflcc->shared_linking && !aflcc->partial_linking) - insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); - #endif - - #if defined(__APPLE__) - if (aflcc->shared_linking || aflcc->partial_linking) { - - insert_param(aflcc, "-Wl,-U"); - insert_param(aflcc, "-Wl,___afl_area_ptr"); - insert_param(aflcc, "-Wl,-U"); - insert_param(aflcc, "-Wl,___sanitizer_cov_trace_pc_guard_init"); - - } - - #endif - - } - -#endif - - add_aflpplib(aflcc); - -#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ - insert_param(aflcc, "-Wl,-lrt"); -#endif - -} - -/* Misc */ - -void add_assembler(aflcc_state_t *aflcc) { - - u8 *afl_as = find_object(aflcc, "as"); - - if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); - - u8 *slash = strrchr(afl_as, '/'); - if (slash) *slash = 0; - - insert_param(aflcc, "-B"); - insert_param(aflcc, afl_as); - - if (aflcc->compiler_mode == CLANG) insert_param(aflcc, "-no-integrated-as"); - -} - -void add_gcc_plugin(aflcc_state_t *aflcc) { - - if (aflcc->cmplog_mode) { - - insert_object(aflcc, "afl-gcc-cmplog-pass.so", "-fplugin=%s", 0); - insert_object(aflcc, "afl-gcc-cmptrs-pass.so", "-fplugin=%s", 0); - - } - - insert_object(aflcc, "afl-gcc-pass.so", "-fplugin=%s", 0); - - insert_param(aflcc, "-fno-if-conversion"); - insert_param(aflcc, "-fno-if-conversion2"); - -} - -void add_misc_params(aflcc_state_t *aflcc) { - - if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_ALL") || getenv("AFL_LLVM_CMPLOG") || - aflcc->lto_mode) { - - insert_param(aflcc, "-fno-builtin-strcmp"); - insert_param(aflcc, "-fno-builtin-strncmp"); - insert_param(aflcc, "-fno-builtin-strcasecmp"); - insert_param(aflcc, "-fno-builtin-strncasecmp"); - insert_param(aflcc, "-fno-builtin-memcmp"); - insert_param(aflcc, "-fno-builtin-bcmp"); - insert_param(aflcc, "-fno-builtin-strstr"); - insert_param(aflcc, "-fno-builtin-strcasestr"); - - } - - if (!aflcc->have_pic) { insert_param(aflcc, "-fPIC"); } - - if (getenv("AFL_HARDEN")) { - - insert_param(aflcc, "-fstack-protector-all"); - - if (!aflcc->fortify_set) add_defs_fortify(aflcc, 2); - - } - - if (!getenv("AFL_DONT_OPTIMIZE")) { - - insert_param(aflcc, "-g"); - if (!aflcc->have_o) insert_param(aflcc, "-O3"); - if (!aflcc->have_unroll) insert_param(aflcc, "-funroll-loops"); - // if (strlen(aflcc->march_opt) > 1 && aflcc->march_opt[0] == '-') - // insert_param(aflcc, aflcc->march_opt); - - } - - if (aflcc->x_set) { - - insert_param(aflcc, "-x"); - insert_param(aflcc, "none"); - - } - -} - -param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { - - param_st final_ = PARAM_MISS; - -// MACRO START -#define SCAN_KEEP(dst, src) \ - do { \ - \ - if (scan) { \ - \ - dst = src; \ - final_ = PARAM_SCAN; \ - \ - } else { \ - \ - final_ = PARAM_KEEP; \ - \ - } \ - \ - } while (0) - - // MACRO END - - if (!strncasecmp(cur_argv, "-fpic", 5)) { - - SCAN_KEEP(aflcc->have_pic, 1); - - } else if (!strcmp(cur_argv, "-m32") || - - !strcmp(cur_argv, "armv7a-linux-androideabi")) { - - SCAN_KEEP(aflcc->bit_mode, 32); - - } else if (!strcmp(cur_argv, "-m64")) { - - SCAN_KEEP(aflcc->bit_mode, 64); - - } else if (strstr(cur_argv, "FORTIFY_SOURCE")) { - - SCAN_KEEP(aflcc->fortify_set, 1); - - } else if (!strcmp(cur_argv, "-x")) { - - SCAN_KEEP(aflcc->x_set, 1); - - } else if (!strcmp(cur_argv, "-E")) { - - SCAN_KEEP(aflcc->preprocessor_only, 1); - - } else if (!strcmp(cur_argv, "--target=wasm32-wasi")) { - - SCAN_KEEP(aflcc->passthrough, 1); - - } else if (!strcmp(cur_argv, "-c")) { - - SCAN_KEEP(aflcc->have_c, 1); - - } else if (!strncmp(cur_argv, "-O", 2)) { - - SCAN_KEEP(aflcc->have_o, 1); - - } else if (!strncmp(cur_argv, "-funroll-loop", 13)) { - - SCAN_KEEP(aflcc->have_unroll, 1); - - } else if (!strncmp(cur_argv, "--afl", 5)) { - - if (scan) - final_ = PARAM_SCAN; - else - final_ = PARAM_DROP; - - } else if (!strncmp(cur_argv, "-fno-unroll", 11)) { - - if (scan) - final_ = PARAM_SCAN; - else - final_ = PARAM_DROP; - - } else if (!strcmp(cur_argv, "-pipe") && aflcc->compiler_mode == GCC_PLUGIN) { - - if (scan) - final_ = PARAM_SCAN; - else - final_ = PARAM_DROP; - - } else if (!strncmp(cur_argv, "-stdlib=", 8) && - - (aflcc->compiler_mode == GCC || - aflcc->compiler_mode == GCC_PLUGIN)) { - - if (scan) { - - final_ = PARAM_SCAN; - - } else { - - if (!be_quiet) WARNF("Found '%s' - stripping!", cur_argv); - final_ = PARAM_DROP; - - } - - } else if (cur_argv[0] != '-') { - - /* It's a weak, loose pattern, with very different purpose - than others. We handle it at last, cautiously and robustly. */ - - if (scan && cur_argv[0] != '@') // response file support - aflcc->non_dash = 1; - } -#undef SCAN_KEEP - - if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); - - return final_; - -} - -static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { - // Try to warn user for some unsupported cases if (scan && final_ == PARAM_MISS) { @@ -3435,6 +3028,14 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, free(tmpbuf); + continue; + + } + + if (!scan) insert_param(aflcc, cur); + + } + } /* Copy argv to cc_params, making the necessary edits. */ @@ -3580,56 +3181,6 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, /* Main entry point */ -int main(int argc, char **argv, char **envp) { - - aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); - aflcc_state_init(aflcc, (u8 *)argv[0]); - - check_environment_vars(envp); - - find_built_deps(aflcc); - - compiler_mode_by_callname(aflcc); - compiler_mode_by_environ(aflcc); - compiler_mode_by_cmdline(aflcc, argc, argv); - - instrument_mode_by_environ(aflcc); - - mode_final_checkout(aflcc, argc, argv); - - process_params(aflcc, 1, argc, argv); - - maybe_usage(aflcc, argc, argv); - - mode_notification(aflcc); - - if (aflcc->debug) debugf_args(argc, argv); - - edit_params(aflcc, argc, argv, envp); - - if (aflcc->debug) - debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); - - /* Inspect the command line parameters. */ - - process_params(aflcc, 0, argc, argv); - - add_sanitizers(aflcc, envp); - - add_misc_params(aflcc); - - add_defs_common(aflcc); - add_defs_selective_instr(aflcc); - add_defs_persistent_mode(aflcc); - - add_runtime(aflcc); - - insert_param(aflcc, NULL); - -} - -/* Main entry point */ - int main(int argc, char **argv, char **envp) { aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); -- cgit 1.4.1 From ba28c4982b7fed33a22214537b4f8ffcc08286d4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 24 Jan 2024 18:22:17 +0100 Subject: fix --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index ec25bf9d..ccbb4f8d 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1572,6 +1572,8 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { break; } + + aflcc->have_fortify = 1; } -- cgit 1.4.1 From d88c97ad2887962a8565473269057d39d75f998d Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:57:50 +0800 Subject: Fix afl-cc (#1968) - Check if too many cmdline params here, each time before insert a new param. - Check if it is "-fsanitize=..." before we do sth. - Remove improper param_st transfer. --- src/afl-cc.c | 87 ++++++++++++++++++++++++------------------------------------ 1 file changed, 34 insertions(+), 53 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index ccbb4f8d..174b3783 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -192,15 +192,11 @@ u8 *find_object(aflcc_state_t *, u8 *obj); void find_built_deps(aflcc_state_t *); -static inline void limit_params(aflcc_state_t *aflcc, u32 add) { +static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { - if (aflcc->cc_par_cnt + add >= MAX_PARAMS_NUM) + if (unlikely(aflcc->cc_par_cnt + 1 >= MAX_PARAMS_NUM)) FATAL("Too many command line parameters, please increase MAX_PARAMS_NUM."); -} - -static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { - aflcc->cc_params[aflcc->cc_par_cnt++] = param; } @@ -1572,7 +1568,7 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { break; } - + aflcc->have_fortify = 1; } @@ -1672,41 +1668,42 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; - if (strstr(cur_argv, "=address") || strstr(cur_argv, ",address")) { - - aflcc->have_asan = 1; - - } - - if (strstr(cur_argv, "=memory") || strstr(cur_argv, ",memory")) { - - aflcc->have_msan = 1; - - } - - if (strstr(cur_argv, "=undefined") || strstr(cur_argv, ",undefined")) { - - aflcc->have_ubsan = 1; - - } - - if (strstr(cur_argv, "=thread") || strstr(cur_argv, ",thread")) { - - aflcc->have_tsan = 1; +// MACRO START +#define HAVE_SANITIZER_SCAN_KEEP(v, k) \ + do { \ + \ + if (strstr(cur_argv, "=" STRINGIFY(k)) || \ + strstr(cur_argv, "," STRINGIFY(k))) { \ + \ + if (scan) { \ + \ + aflcc->have_##v = 1; \ + final_ = PARAM_SCAN; \ + \ + } else { \ + \ + final_ = PARAM_KEEP; \ + \ + } \ + \ + } \ + \ + } while (0) - } + // MACRO END - if (strstr(cur_argv, "=leak") || strstr(cur_argv, ",leak")) { + if (!strncmp(cur_argv, "-fsanitize=", strlen("-fsanitize="))) { - aflcc->have_lsan = 1; + HAVE_SANITIZER_SCAN_KEEP(asan, address); + HAVE_SANITIZER_SCAN_KEEP(msan, memory); + HAVE_SANITIZER_SCAN_KEEP(ubsan, undefined); + HAVE_SANITIZER_SCAN_KEEP(tsan, thread); + HAVE_SANITIZER_SCAN_KEEP(lsan, leak); + HAVE_SANITIZER_SCAN_KEEP(cfisan, cfi); } - if (strstr(cur_argv, "=cfi") || strstr(cur_argv, ",cfi")) { - - aflcc->have_cfisan = 1; - - } +#undef HAVE_SANITIZER_SCAN_KEEP if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && strstr(cur_argv, "list=")) { @@ -1718,7 +1715,7 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } else { - final_ = PARAM_KEEP; // may be set to DROP next + final_ = PARAM_KEEP; } @@ -1787,20 +1784,6 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - if (final_ == PARAM_MISS) { - - if (scan) { - - final_ = PARAM_SCAN; - - } else { - - final_ = PARAM_KEEP; - - } - - } - if (final_ == PARAM_KEEP) insert_param(aflcc, cur_argv); return final_; @@ -2880,8 +2863,6 @@ 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) { - limit_params(aflcc, argc); - // for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]); /* Process the argument list. */ -- cgit 1.4.1 From 4d493452a45655073d1b7b1dfe4ad04772b3c2b8 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 25 Jan 2024 17:00:53 +0100 Subject: tmp --- instrumentation/SanitizerCoverageLTO.so.cc | 55 ++++++++++++++++++++++++++++-- src/afl-cc.c | 10 ++++-- 2 files changed, 61 insertions(+), 4 deletions(-) (limited to 'src/afl-cc.c') diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 68423029..c74069e1 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -247,6 +247,7 @@ class ModuleSanitizerCoverageLTO uint32_t afl_global_id = 0; uint32_t unhandled = 0; uint32_t select_cnt = 0; + uint32_t instrument_ctx = 0; uint64_t map_addr = 0; const char *skip_nozero = NULL; const char *use_threadsafe_counters = nullptr; @@ -261,6 +262,7 @@ class ModuleSanitizerCoverageLTO LLVMContext *Ct = NULL; Module *Mo = NULL; GlobalVariable *AFLMapPtr = NULL; + GlobalVariable *AFLContext = NULL; Value *MapPtrFixed = NULL; std::ofstream dFile; size_t found = 0; @@ -420,11 +422,13 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( setvbuf(stdout, NULL, _IONBF, 0); if (getenv("AFL_DEBUG")) { debug = 1; } if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { autodictionary_no_main = 1; } + if (getenv("AFL_LLVM_CALLER")) { instrument_ctx = 1; } if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { SAYF(cCYA "afl-llvm-lto" VERSION cRST - " by Marc \"vanHauser\" Heuse \n"); + "%s by Marc \"vanHauser\" Heuse \n", + instrument_ctx ? " (CTX mode)" : ""); } else @@ -500,6 +504,10 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( } + AFLContext = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx", 0, + GlobalVariable::GeneralDynamicTLSModel, 0, false); + Zero = ConstantInt::get(Int8Tyi, 0); One = ConstantInt::get(Int8Tyi, 1); @@ -1284,7 +1292,50 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( const DominatorTree *DT = DTCallback(F); const PostDominatorTree *PDT = PDTCallback(F); bool IsLeafFunc = true; - uint32_t skip_next = 0; + uint32_t skip_next = 0, call_counter = 0; + Value *PrevCtx = NULL; + + MDNode *N = + MDNode::get(F.getContext(), MDString::get(F.getContext(), "nosanitize")); + + for (auto &BB : F) { + + if (/*F.size() > 1 &&*/ instrument_ctx && &BB == &F.getEntryBlock()) { + + // we insert a CTX value in all our callers: + LLVMContext &Context = F.getContext(); + IRBuilder<> Builder(Context); + for (auto *U : F.users()) { + + if (auto *CI = dyn_cast(U)) { + + fprintf(stderr, "Insert %s [%u] -> %s\n", + CI->getParent()->getParent()->getName().str().c_str(), + call_counter, F.getName().str().c_str()); + Builder.SetInsertPoint(CI); + StoreInst *StoreCtx = Builder.CreateStore( + ConstantInt::get(Type::getInt32Ty(Context), call_counter++), + AFLContext); + StoreCtx->setMetadata("nosanitize", N); + + } + + } + + // We read the CTX for this call + BasicBlock::iterator IP = BB.getFirstInsertionPt(); + IRBuilder<> IRB(&(*IP)); + LoadInst *PrevCtxLoad = IRB.CreateLoad( +#if LLVM_VERSION_MAJOR >= 14 + Builder.getInt32Ty(), +#endif + AFLContext); + PrevCtxLoad->setMetadata("nosanitize", N); + PrevCtx = PrevCtxLoad; + + } + + } for (auto &BB : F) { diff --git a/src/afl-cc.c b/src/afl-cc.c index 174b3783..4f6745ed 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1103,12 +1103,18 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } - if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM) + fprintf(stderr, "X %u %u\n", aflcc->compiler_mode, LTO); + + if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM && + !((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + aflcc->compiler_mode == LTO)) FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode"); if (aflcc->instrument_opt_mode && aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV && - aflcc->instrument_mode != INSTRUMENT_CLASSIC) + aflcc->instrument_mode != INSTRUMENT_CLASSIC && + !(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER && + aflcc->compiler_mode == LTO)) FATAL( "CALLER, CTX and NGRAM instrumentation options can only be used with " "the LLVM CLASSIC instrumentation mode."); -- cgit 1.4.1 From 2f9eeef60cdd4ad43f8066af78009acd660a426c Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 26 Jan 2024 14:41:23 +0100 Subject: Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969) --- src/afl-cc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 174b3783..6d8e1024 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -173,7 +173,8 @@ typedef struct aflcc_state { u8 fortify_set, x_set, bit_mode, preprocessor_only, have_unroll, have_o, have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp, have_flto, have_hidden, have_fortify, have_fcf, have_staticasan, - have_asan, have_msan, have_ubsan, have_lsan, have_tsan, have_cfisan; + have_rust_asanrt, have_asan, have_msan, have_ubsan, have_lsan, have_tsan, + have_cfisan; // u8 *march_opt; u8 need_aflpplib; @@ -1908,6 +1909,14 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { void add_native_pcguard(aflcc_state_t *aflcc) { + /* If there is a rust ASan runtime on the command line, it is likely we're + * linking from rust and adding native flags requiring the sanitizer runtime + * will trigger native clang to add yet another runtime, causing linker + * errors. For now we shouldn't add instrumentation here, we're linking + * anyway. + */ + if (aflcc->have_rust_asanrt) { return; } + /* If llvm-config doesn't figure out LLVM_MAJOR, just go on anyway and let compiler complain if doesn't work. */ @@ -2480,6 +2489,10 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { SCAN_KEEP(aflcc->have_staticasan, 1); + } else if (strstr(cur_argv, "librustc") && strstr(cur_argv, "_rt.asan.a")) { + + SCAN_KEEP(aflcc->have_rust_asanrt, 1); + } else if (!strcmp(cur_argv, "-fno-omit-frame-pointer")) { SCAN_KEEP(aflcc->have_fp, 1); -- cgit 1.4.1 From 58b80b68bc5538bad2cf4c858229111f58282424 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 26 Jan 2024 15:46:56 +0100 Subject: Dynamic instrumentation filtering for LLVM native (#1971) * Add two dynamic instrumentation filter methods to runtime * Always use pc-table with native pcguard * Add make_symbol_list.py and README --- instrumentation/afl-compiler-rt.o.c | 279 +++++++++++++++++++++++++--- src/afl-cc.c | 26 +-- utils/dynamic_covfilter/README.md | 55 ++++++ utils/dynamic_covfilter/make_symbol_list.py | 73 ++++++++ 4 files changed, 393 insertions(+), 40 deletions(-) create mode 100644 utils/dynamic_covfilter/README.md create mode 100644 utils/dynamic_covfilter/make_symbol_list.py (limited to 'src/afl-cc.c') diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 39a762b6..8e55d6a0 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -22,6 +22,10 @@ #define __USE_GNU #endif #include + +__attribute__((weak)) void __sanitizer_symbolize_pc(void *, const char *fmt, + char *out_buf, + size_t out_buf_size); #endif #ifdef __ANDROID__ @@ -124,8 +128,8 @@ struct afl_module_info_t { uintptr_t base_address; // PC Guard start/stop - u32 start; - u32 stop; + u32 *start; + u32 *stop; // PC Table begin/end const uintptr_t *pcs_beg; @@ -147,6 +151,18 @@ afl_module_info_t *__afl_module_info = NULL; u32 __afl_pcmap_size = 0; uintptr_t *__afl_pcmap_ptr = NULL; + +typedef struct { + + uintptr_t start; + u32 len; + +} FilterPCEntry; + +u32 __afl_filter_pcs_size = 0; +FilterPCEntry *__afl_filter_pcs = NULL; +u8 *__afl_filter_pcs_module = NULL; + #endif // __AFL_CODE_COVERAGE /* 1 if we are running in afl, and the forkserver was started, else 0 */ @@ -1587,15 +1603,116 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { } #ifdef __AFL_CODE_COVERAGE -void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, - const uintptr_t *pcs_end) { +void afl_read_pc_filter_file(const char *filter_file) { - if (__afl_debug) { + FILE *file; + char ch; + + file = fopen(filter_file, "r"); + if (file == NULL) { + + perror("Error opening file"); + return; + + } + + // Check how many PCs we expect to read + while ((ch = fgetc(file)) != EOF) { + + if (ch == '\n') { __afl_filter_pcs_size++; } + + } + + // Rewind to actually read the PCs + fseek(file, 0, SEEK_SET); + + __afl_filter_pcs = malloc(__afl_filter_pcs_size * sizeof(FilterPCEntry)); + if (!__afl_filter_pcs) { + + perror("Error allocating PC array"); + return; + + } + + for (size_t i = 0; i < __afl_filter_pcs_size; i++) { + + fscanf(file, "%lx", &(__afl_filter_pcs[i].start)); + ch = fgetc(file); // Read tab + fscanf(file, "%u", &(__afl_filter_pcs[i].len)); + ch = fgetc(file); // Read tab + + if (!__afl_filter_pcs_module) { + + // Read the module name and store it. + // TODO: We only support one module here right now although + // there is technically no reason to support multiple modules + // in one go. + size_t max_module_len = 255; + size_t i = 0; + __afl_filter_pcs_module = malloc(max_module_len); + while (i < max_module_len - 1 && + (__afl_filter_pcs_module[i] = fgetc(file)) != '\t') { + + ++i; + + } - fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init called\n"); + __afl_filter_pcs_module[i] = '\0'; + fprintf(stderr, "DEBUGXXX: Read module name %s\n", + __afl_filter_pcs_module); + + } + + while ((ch = fgetc(file)) != '\n' && ch != EOF) + ; + + } + + fclose(file); + +} + +u32 locate_in_pcs(uintptr_t needle, u32 *index) { + + size_t lower_bound = 0; + size_t upper_bound = __afl_filter_pcs_size - 1; + + while (lower_bound < __afl_filter_pcs_size && lower_bound <= upper_bound) { + + size_t current_index = lower_bound + (upper_bound - lower_bound) / 2; + + if (__afl_filter_pcs[current_index].start <= needle) { + + if (__afl_filter_pcs[current_index].start + + __afl_filter_pcs[current_index].len > + needle) { + + // Hit + *index = current_index; + return 1; + + } else { + + lower_bound = current_index + 1; + + } + + } else { + + if (!current_index) { break; } + upper_bound = current_index - 1; + + } } + return 0; + +} + +void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, + const uintptr_t *pcs_end) { + // If for whatever reason, we cannot get dlinfo here, then pc_guard_init also // couldn't get it and we'd end up attributing to the wrong module. Dl_info dlinfo; @@ -1608,6 +1725,16 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, } + if (__afl_debug) { + + fprintf( + stderr, + "DEBUG: (%u) __sanitizer_cov_pcs_init called for module %s with %ld " + "PCs\n", + getpid(), dlinfo.dli_fname, pcs_end - pcs_beg); + + } + afl_module_info_t *last_module_info = __afl_module_info; while (last_module_info && last_module_info->next) { @@ -1623,34 +1750,78 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, } + if (strcmp(dlinfo.dli_fname, last_module_info->name)) { + + // This can happen with modules being loaded after the forkserver + // where we decide to not track the module. In that case we must + // not track it here either. + fprintf( + stderr, + "WARNING: __sanitizer_cov_pcs_init module info mismatch: %s vs %s\n", + dlinfo.dli_fname, last_module_info->name); + return; + + } + last_module_info->pcs_beg = pcs_beg; last_module_info->pcs_end = pcs_end; + // This is a direct filter based on symbolizing inside the runtime. + // It should only be used with smaller binaries to avoid long startup + // times. Currently, this only supports a single token to scan for. + const char *pc_filter = getenv("AFL_PC_FILTER"); + + // This is a much faster PC filter based on pre-symbolized input data + // that is sorted for fast lookup through binary search. This method + // of filtering is suitable even for very large binaries. + const char *pc_filter_file = getenv("AFL_PC_FILTER_FILE"); + if (pc_filter_file && !__afl_filter_pcs) { + + afl_read_pc_filter_file(pc_filter_file); + + } + // Now update the pcmap. If this is the last module coming in, after all // pre-loaded code, then this will also map all of our delayed previous // modules. - - if (!__afl_pcmap_ptr) { return; } - + // for (afl_module_info_t *mod_info = __afl_module_info; mod_info; mod_info = mod_info->next) { if (mod_info->mapped) { continue; } + if (!mod_info->start) { + + fprintf(stderr, + "ERROR: __sanitizer_cov_pcs_init called with mod_info->start == " + "NULL (%s)\n", + mod_info->name); + abort(); + + } + PCTableEntry *start = (PCTableEntry *)(mod_info->pcs_beg); PCTableEntry *end = (PCTableEntry *)(mod_info->pcs_end); + if (!*mod_info->stop) { continue; } + u32 in_module_index = 0; while (start < end) { - if (mod_info->start + in_module_index >= __afl_map_size) { + if (*mod_info->start + in_module_index >= __afl_map_size) { - fprintf(stderr, "ERROR: __sanitizer_cov_pcs_init out of bounds?!\n"); + fprintf(stderr, + "ERROR: __sanitizer_cov_pcs_init out of bounds?! Start: %u " + "Stop: %u Map Size: %u (%s)\n", + *mod_info->start, *mod_info->stop, __afl_map_size, + mod_info->name); abort(); } + u32 orig_start_index = *mod_info->start; + uintptr_t PC = start->PC; // This is what `GetPreviousInstructionPc` in sanitizer runtime does @@ -1660,7 +1831,58 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, // Calculate relative offset in module PC = PC - mod_info->base_address; - __afl_pcmap_ptr[mod_info->start + in_module_index] = PC; + if (__afl_pcmap_ptr) { + + __afl_pcmap_ptr[orig_start_index + in_module_index] = PC; + + } + + if (pc_filter) { + + char PcDescr[1024]; + // This function is a part of the sanitizer run-time. + // To use it, link with AddressSanitizer or other sanitizer. + __sanitizer_symbolize_pc((void *)start->PC, "%p %F %L", PcDescr, + sizeof(PcDescr)); + + if (strstr(PcDescr, pc_filter)) { + + if (__afl_debug) + fprintf( + stderr, + "DEBUG: Selective instrumentation match: %s (PC %p Index %u)\n", + PcDescr, (void *)start->PC, + *(mod_info->start + in_module_index)); + // No change to guard needed + + } else { + + // Null out the guard to disable this edge + *(mod_info->start + in_module_index) = 0; + + } + + } + + if (__afl_filter_pcs && strstr(mod_info->name, __afl_filter_pcs_module)) { + + u32 result_index; + if (locate_in_pcs(PC, &result_index)) { + + if (__afl_debug) + fprintf(stderr, + "DEBUG: Selective instrumentation match: (PC %lx File " + "Index %u PC Index %u)\n", + PC, result_index, in_module_index); + + } else { + + // Null out the guard to disable this edge + *(mod_info->start + in_module_index) = 0; + + } + + } start++; in_module_index++; @@ -1671,8 +1893,10 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, if (__afl_debug) { - fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init initialized %u PCs\n", - in_module_index); + fprintf(stderr, + "DEBUG: __sanitizer_cov_pcs_init successfully mapped %s with %u " + "PCs\n", + mod_info->name, in_module_index); } @@ -1706,9 +1930,9 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { fprintf( stderr, "DEBUG: Running __sanitizer_cov_trace_pc_guard_init: %p-%p (%lu edges) " - "after_fs=%u\n", + "after_fs=%u *start=%u\n", start, stop, (unsigned long)(stop - start), - __afl_already_initialized_forkserver); + __afl_already_initialized_forkserver, *start); } @@ -1740,8 +1964,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { mod_info->id = last_module_info ? last_module_info->id + 1 : 0; mod_info->name = strdup(dlinfo.dli_fname); mod_info->base_address = (uintptr_t)dlinfo.dli_fbase; - mod_info->start = 0; - mod_info->stop = 0; + mod_info->start = NULL; + mod_info->stop = NULL; mod_info->pcs_beg = NULL; mod_info->pcs_end = NULL; mod_info->mapped = 0; @@ -1757,8 +1981,12 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { } - fprintf(stderr, "[pcmap] Module: %s Base Address: %p\n", dlinfo.dli_fname, - dlinfo.dli_fbase); + if (__afl_debug) { + + fprintf(stderr, "[pcmap] Module: %s Base Address: %p\n", + dlinfo.dli_fname, dlinfo.dli_fbase); + + } } @@ -1861,12 +2089,17 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { #ifdef __AFL_CODE_COVERAGE if (mod_info) { - mod_info->start = *orig_start; - mod_info->stop = *(stop - 1); + if (!mod_info->start) { + + mod_info->start = orig_start; + mod_info->stop = stop - 1; + + } + if (__afl_debug) { fprintf(stderr, "DEBUG: [pcmap] Start Index: %u Stop Index: %u\n", - mod_info->start, mod_info->stop); + *(mod_info->start), *(mod_info->stop)); } diff --git a/src/afl-cc.c b/src/afl-cc.c index 6d8e1024..73487188 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1920,35 +1920,27 @@ void add_native_pcguard(aflcc_state_t *aflcc) { /* If llvm-config doesn't figure out LLVM_MAJOR, just go on anyway and let compiler complain if doesn't work. */ - if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { - #if LLVM_MAJOR > 0 && LLVM_MAJOR < 6 - FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); + FATAL("pcguard instrumentation with pc-table requires LLVM 6.0.1+"); #else #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation with pc-table requires LLVM 6.0.1+" - " otherwise the compiler will fail"); + WARNF( + "pcguard instrumentation with pc-table requires LLVM 6.0.1+" + " otherwise the compiler will fail"); #endif + if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) { + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table"); -#endif } else { -#if LLVM_MAJOR > 0 && LLVM_MAJOR < 4 - FATAL("pcguard instrumentation requires LLVM 4.0.1+"); -#else - #if LLVM_MAJOR == 0 - WARNF( - "pcguard instrumentation requires LLVM 4.0.1+" - " otherwise the compiler will fail"); - #endif - insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); -#endif + insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard,pc-table"); } +#endif + } void add_optimized_pcguard(aflcc_state_t *aflcc) { diff --git a/utils/dynamic_covfilter/README.md b/utils/dynamic_covfilter/README.md new file mode 100644 index 00000000..a64836f1 --- /dev/null +++ b/utils/dynamic_covfilter/README.md @@ -0,0 +1,55 @@ +# Dynamic Instrumentation Filter + +Sometimes it can be beneficial to limit the instrumentation feedback to +specific code locations. It is possible to do so at compile-time by simply +not instrumenting any undesired locations. However, there are situations +where doing this dynamically without requiring a new build can be beneficial. +Especially when dealing with larger builds, it is much more convenient to +select the target code locations at runtime instead of doing so at build time. + +There are two ways of doing this in AFL++: + +## Simple Selection with `AFL_PC_FILTER` + +This approach requires a build with `AFL_INSTRUMENTATION=llvmnative` or +`llvmcodecov` as well as an AddressSanitizer build with debug information. + +By setting the environment variable `AFL_PC_FILTER` to a string, the runtime +symbolizer is enabled in the AFL++ runtime. At startup, the runtime will call +the `__sanitizer_symbolize_pc` API to resolve every PC in every loaded module. +The runtime then matches the result using `strstr` and disables the PC guard +if the symbolized PC does not contain the specified string. + +This approach has the benefit of being very easy to use. The downside is that +it causes significant startup delays with large binaries and that it requires +an AddressSanitizer build. + +This method has no additional runtime overhead after startup. + +## Selection using pre-symbolized data file with `AFL_PC_FILTER_FILE` + +To avoid large startup time delays, a specific module can be pre-symbolized +using the `make_symbol_list.py` script. This script outputs a sorted list of +functions with their respective relative offsets and lengths in the target +binary: + +`python3 make_symbol_list.py libxul.so > libxul.symbols.txt` + +The resulting list can be filtered, e.g. using grep: + +`grep -i "webgl" libxul.symbols.txt > libxul.webgl.symbols.txt` + +Finally, you can run with `AFL_PC_FILTER_FILE=libxul.webgl.symbols.txt` to +restrict instrumentation feedback to the given locations. This approach only +has a minimal startup time delay due to the implementation only using binary +search on the given file per PC rather than reading debug information for every +PC. It also works well with Nyx, where symbolizing is usually disabled for the +target process to avoid delays with frequent crashes. + +Similar to the previous method, This approach requires a build with +`AFL_INSTRUMENTATION=llvmnative` or `llvmcodecov` as well debug information. +However, it does not require the ASan runtime as it doesn't do the symbolizing +in process. Due to the way it maps PCs to symbols, it is less accurate when it +comes to includes and inlines (it assumes all PCs within a function belong to +that function and originate from the same file). For most purposes, this should +be a reasonable simplification to quickly process even the largest binaries. diff --git a/utils/dynamic_covfilter/make_symbol_list.py b/utils/dynamic_covfilter/make_symbol_list.py new file mode 100644 index 00000000..d1dd6ab3 --- /dev/null +++ b/utils/dynamic_covfilter/make_symbol_list.py @@ -0,0 +1,73 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Written by Christian Holler + +import json +import os +import sys +import subprocess + +if len(sys.argv) != 2: + print("Usage: %s binfile" % os.path.basename(sys.argv[0])) + sys.exit(1) + +binfile = sys.argv[1] + +addr2len = {} +addrs = [] + +output = subprocess.check_output(["objdump", "-t", binfile]).decode("utf-8") +for line in output.splitlines(): + line = line.replace("\t", " ") + components = [x for x in line.split(" ") if x] + if not components: + continue + try: + start_addr = int(components[0], 16) + except ValueError: + continue + + # Length has variable position in objdump output + length = None + for comp in components[1:]: + if len(comp) == 16: + try: + length = int(comp, 16) + break + except: + continue + + if length is None: + print("ERROR: Couldn't determine function section length: %s" % line) + + func = components[-1] + + addrs.append(start_addr) + addr2len[str(hex(start_addr))] = str(length) + +# The search implementation in the AFL runtime expects everything sorted. +addrs.sort() +addrs = [str(hex(addr)) for addr in addrs] + +# We symbolize in one go to speed things up with large binaries. +output = subprocess.check_output([ + "llvm-addr2line", + "--output-style=JSON", + "-f", "-C", "-a", "-e", + binfile], + input="\n".join(addrs).encode("utf-8")).decode("utf-8") + +output = output.strip().splitlines() +for line in output: + output = json.loads(line) + if "Symbol" in output and output["Address"] in addr2len: + final_output = [ + output["Address"], + addr2len[output["Address"]], + os.path.basename(output["ModuleName"]), + output["Symbol"][0]["FileName"], + output["Symbol"][0]["FunctionName"] + ] + print("\t".join(final_output)) -- cgit 1.4.1 From 644e0694509d4019e6f5075c4b900d412f29df32 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Tue, 30 Jan 2024 15:30:18 +0100 Subject: Fixes to afl-cc and documentation (#1974) * Always compile with -ldl when building for CODE_COVERAGE When building with CODE_COVERAGE, the afl runtime contains code that calls `dladdr` which requires -ldl. Under most circumstances, clang already adds this (e.g. when building with pc-table), but there are some circumstances where it isn't added automatically. * Add visibility declaration to __afl_connected When building with hidden visibility, the use of __AFL_LOOP inside such code can cause linker errors due to __afl_connected being declared "hidden". * Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter --- GNUmakefile | 4 ++++ src/afl-cc.c | 7 ++++++- utils/dynamic_covfilter/README.md | 7 ++++++- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile b/GNUmakefile index b67f9c15..be5b8146 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -66,6 +66,10 @@ ifdef MSAN_BUILD override LDFLAGS += -fsanitize=memory endif +ifdef CODE_COVERAGE + override CFLAGS += -D__AFL_CODE_COVERAGE=1 +endif + ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" "" ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" CFLAGS_FLTO ?= -flto=full diff --git a/src/afl-cc.c b/src/afl-cc.c index 73487188..d11419b0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1521,7 +1521,7 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { "({ static volatile const char *_B __attribute__((used,unused)); " " _B = (const char*)\"" PERSIST_SIG "\"; " - "extern int __afl_connected;" + "extern __attribute__((visibility(\"default\"))) int __afl_connected;" #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); " @@ -2311,6 +2311,11 @@ void add_runtime(aflcc_state_t *aflcc) { } + #if __AFL_CODE_COVERAGE + // Required for dladdr used in afl-compiler-rt.o + insert_param(aflcc, "-ldl"); + #endif + #if !defined(__APPLE__) && !defined(__sun) if (!aflcc->shared_linking && !aflcc->partial_linking) insert_object(aflcc, "dynamic_list.txt", "-Wl,--dynamic-list=%s", 0); diff --git a/utils/dynamic_covfilter/README.md b/utils/dynamic_covfilter/README.md index a64836f1..381e0855 100644 --- a/utils/dynamic_covfilter/README.md +++ b/utils/dynamic_covfilter/README.md @@ -7,7 +7,12 @@ where doing this dynamically without requiring a new build can be beneficial. Especially when dealing with larger builds, it is much more convenient to select the target code locations at runtime instead of doing so at build time. -There are two ways of doing this in AFL++: +There are two ways of doing this in AFL++. Both approaches require a build of +AFL++ with `CODE_COVERAGE=1`, so make sure to build AFL++ first by invoking + +`CODE_COVERAGE=1 make` + +Once you have built AFL++, you can choose out of two approaches: ## Simple Selection with `AFL_PC_FILTER` -- cgit 1.4.1 From 643df2b538b06561d5a6d6ae441322167d33f834 Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:17:48 +0800 Subject: Improve afl-cc (#1975) * update response file support - full support of rsp file - fix some segv issues * Improve afl-cc - remove dead code about allow/denylist options of sancov - missing `if (!aflcc->have_msan)` - add docs for each function - typo --- src/afl-cc.c | 488 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 368 insertions(+), 120 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index d11419b0..c300ddfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,7 +51,7 @@ #define MAX_PARAMS_NUM 2048 #endif -/* Global declarations */ +/** Global declarations -----BEGIN----- **/ typedef enum { @@ -187,12 +187,11 @@ typedef struct aflcc_state { void aflcc_state_init(aflcc_state_t *, u8 *argv0); -/* Try to find a specific runtime we need, the path to obj would be - allocated and returned. Otherwise it returns NULL on fail. */ u8 *find_object(aflcc_state_t *, u8 *obj); void find_built_deps(aflcc_state_t *); +/* Insert param into the new argv, raise error if MAX_PARAMS_NUM exceeded. */ static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { if (unlikely(aflcc->cc_par_cnt + 1 >= MAX_PARAMS_NUM)) @@ -202,6 +201,13 @@ static inline void insert_param(aflcc_state_t *aflcc, u8 *param) { } +/* + Insert a param which contains path to the object file. It uses find_object to + get the path based on the name `obj`, and then uses a sprintf like method to + format it with `fmt`. If `fmt` is NULL, the inserted arg is same as the path. + If `msg` provided, it should be an error msg raised if the path can't be + found. `obj` must not be NULL. +*/ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, u8 *msg) { @@ -231,6 +237,7 @@ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt, } +/* Insert params into the new argv, make clang load the pass. */ static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) { #if LLVM_MAJOR >= 11 /* use new pass manager */ @@ -291,8 +298,12 @@ void add_lto_linker(aflcc_state_t *); void add_lto_passes(aflcc_state_t *); void add_runtime(aflcc_state_t *); -/* Working state */ +/** Global declarations -----END----- **/ +/* + Init global state struct. We also extract the callname, + check debug options and if in C++ mode here. +*/ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { // Default NULL/0 is a good start @@ -352,7 +363,7 @@ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { } /* - in find_object() we look here: + Try to find a specific runtime we need, in here: 1. firstly we check the $AFL_PATH environment variable location if set 2. next we check argv[0] if it has path information and use it @@ -366,7 +377,6 @@ void aflcc_state_init(aflcc_state_t *aflcc, u8 *argv0) { if all these attempts fail - we return NULL and the caller has to decide what to do. Otherwise the path to obj would be allocated and returned. */ - u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { u8 *argv0 = aflcc->argv0; @@ -499,6 +509,10 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { } +/* + Deduce some info about compiler toolchains in current system, + from the building results of AFL++ +*/ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; @@ -571,8 +585,9 @@ void find_built_deps(aflcc_state_t *aflcc) { } -/* compiler_mode & instrument_mode selecting */ +/** compiler_mode & instrument_mode selecting -----BEGIN----- **/ +/* Select compiler_mode by callname, such as "afl-clang-fast", etc. */ void compiler_mode_by_callname(aflcc_state_t *aflcc) { if (strncmp(aflcc->callname, "afl-clang-fast", 14) == 0) { @@ -626,6 +641,10 @@ void compiler_mode_by_callname(aflcc_state_t *aflcc) { } +/* + Select compiler_mode by env AFL_CC_COMPILER. And passthrough mode can be + regarded as a special compiler_mode, so we check for it here, too. +*/ void compiler_mode_by_environ(aflcc_state_t *aflcc) { if (getenv("AFL_PASSTHROUGH") || getenv("AFL_NOOPT")) { @@ -682,7 +701,13 @@ void compiler_mode_by_environ(aflcc_state_t *aflcc) { } -// If it can be inferred, instrument_mode would also be set +/* + Select compiler_mode by command line options --afl-... + If it can be inferred, instrument_mode would also be set. + This can supersedes previous result based on callname + or AFL_CC_COMPILER. And "--afl_noopt"/"--afl-noopt" will + be overwritten by "-g". +*/ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { char *ptr = NULL; @@ -775,6 +800,12 @@ void compiler_mode_by_cmdline(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Select instrument_mode by those envs in old style: + - USE_TRACE_PC, AFL_USE_TRACE_PC, AFL_LLVM_USE_TRACE_PC, AFL_TRACE_PC + - AFL_LLVM_CALLER, AFL_LLVM_CTX, AFL_LLVM_CTX_K + - AFL_LLVM_NGRAM_SIZE +*/ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || @@ -834,7 +865,11 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } -// compiler_mode would also be set if depended by the instrument_mode +/* + Select instrument_mode by env 'AFL_LLVM_INSTRUMENT'. + Previous compiler_mode will be superseded, if required by some + values of instrument_mode. +*/ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { if (!getenv("AFL_LLVM_INSTRUMENT")) { return; } @@ -1058,6 +1093,11 @@ static void instrument_mode_new_environ(aflcc_state_t *aflcc) { } +/* + Select instrument_mode by envs, the top wrapper. We check + have_instr_env firstly, then call instrument_mode_old_environ + and instrument_mode_new_environ sequentially. +*/ void instrument_mode_by_environ(aflcc_state_t *aflcc) { if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") || @@ -1081,6 +1121,10 @@ void instrument_mode_by_environ(aflcc_state_t *aflcc) { } +/* + Workaround to ensure CALLER, CTX, K-CTX and NGRAM + instrumentation were used correctly. +*/ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && @@ -1116,6 +1160,11 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } +/* + Last step of compiler_mode & instrument_mode selecting. + We have a few of workarounds here, to check any corner cases, + prepare for a series of fallbacks, and raise warnings or errors. +*/ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { if (aflcc->instrument_opt_mode && @@ -1320,6 +1369,10 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Print welcome message on screen, giving brief notes about + compiler_mode and instrument_mode. +*/ void mode_notification(aflcc_state_t *aflcc) { char *ptr2 = alloc_printf(" + NGRAM-%u", aflcc->ngram_size); @@ -1358,6 +1411,17 @@ void mode_notification(aflcc_state_t *aflcc) { } +/* + Set argv[0] required by execvp. It can be + - specified by env AFL_CXX + - g++ or clang++ + - CLANGPP_BIN or LLVM_BINDIR/clang++ + when in C++ mode, or + - specified by env AFL_CC + - gcc or clang + - CLANG_BIN or LLVM_BINDIR/clang + otherwise. +*/ void add_real_argv0(aflcc_state_t *aflcc) { static u8 llvm_fullpath[PATH_MAX]; @@ -1424,7 +1488,9 @@ void add_real_argv0(aflcc_state_t *aflcc) { } -/* Macro defs for the preprocessor */ +/** compiler_mode & instrument_mode selecting -----END----- **/ + +/** Macro defs for the preprocessor -----BEGIN----- **/ void add_defs_common(aflcc_state_t *aflcc) { @@ -1433,8 +1499,11 @@ void add_defs_common(aflcc_state_t *aflcc) { } -/* See instrumentation/README.instrument_list.md# - 2-selective-instrumentation-with-_afl_coverage-directives */ +/* + __afl_coverage macro defs. See + instrumentation/README.instrument_list.md# + 2-selective-instrumentation-with-_afl_coverage-directives +*/ void add_defs_selective_instr(aflcc_state_t *aflcc) { if (aflcc->plusplus_mode) { @@ -1468,9 +1537,11 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) { } -/* As documented in instrumentation/README.persistent_mode.md, deferred - forkserver initialization and persistent mode are not available in afl-gcc - and afl-clang. */ +/* + Macro defs for persistent mode. As documented in + instrumentation/README.persistent_mode.md, deferred forkserver initialization + and persistent mode are not available in afl-gcc and afl-clang. +*/ void add_defs_persistent_mode(aflcc_state_t *aflcc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == CLANG) return; @@ -1549,7 +1620,11 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { } -/* Control _FORTIFY_SOURCE */ +/* + Control macro def of _FORTIFY_SOURCE. It will do nothing + if we detect this routine has been called previously, or + the macro already here in these existing args. +*/ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { if (aflcc->have_fortify) { return; } @@ -1574,6 +1649,7 @@ void add_defs_fortify(aflcc_state_t *aflcc, u8 action) { } +/* Macro defs of __AFL_LEAK_CHECK, __AFL_LSAN_ON and __AFL_LSAN_OFF */ void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { insert_param(aflcc, "-includesanitizer/lsan_interface.h"); @@ -1586,7 +1662,9 @@ void add_defs_lsan_ctrl(aflcc_state_t *aflcc) { } -/* About fsanitize (including PCGUARD features) */ +/** Macro defs for the preprocessor -----END----- **/ + +/** About -fsanitize -----BEGIN----- **/ /* For input "-fsanitize=...", it: @@ -1665,6 +1743,16 @@ static u8 fsanitize_fuzzer_comma(char *string) { } +/* + Parse and process possible -fsanitize related args, return PARAM_MISS + if nothing matched. We have 3 main tasks here for these args: + - Check which one of those sanitizers present here. + - Check if libfuzzer present. We need to block the request of enable + libfuzzer, and link harness with our libAFLDriver.a later. + - Check if SanCov allow/denylist options present. We need to try switching + to LLVMNATIVE instead of using our optimized PCGUARD anyway. If we + can't make it finally for various reasons, just drop these options. +*/ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; @@ -1706,22 +1794,8 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { #undef HAVE_SANITIZER_SCAN_KEEP - if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && - strstr(cur_argv, "list=")) { - - if (scan) { - - aflcc->have_instr_list = 1; - final_ = PARAM_SCAN; - - } else { - - final_ = PARAM_KEEP; - - } - - } - + // We can't use a "else if" there, because some of the following + // matching rules overlap with those in the if-statement above. if (!strcmp(cur_argv, "-fsanitize=fuzzer")) { if (scan) { @@ -1761,25 +1835,27 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } - } else if ((!strncmp(cur_argv, "-fsanitize=fuzzer-", + } else if (!strncmp(cur_argv, "-fsanitize-coverage-", 20) && - strlen("-fsanitize=fuzzer-")) || - !strncmp(cur_argv, "-fsanitize-coverage", - strlen("-fsanitize-coverage"))) && - (strncmp(cur_argv, "sanitize-coverage-allow", - strlen("sanitize-coverage-allow")) && - strncmp(cur_argv, "sanitize-coverage-deny", - strlen("sanitize-coverage-deny")) && - aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE)) { + strstr(cur_argv, "list=")) { if (scan) { + aflcc->have_instr_list = 1; final_ = PARAM_SCAN; } else { - if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } - final_ = PARAM_DROP; + if (aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur_argv); } + final_ = PARAM_DROP; + + } else { + + final_ = PARAM_KEEP; + + } } @@ -1791,6 +1867,16 @@ param_st parse_fsanitize(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } +/* + Add params for sanitizers. Here we need to consider: + - Use static runtime for asan, as much as possible. + - ASAN, MSAN, AFL_HARDEN are mutually exclusive. + - Add options if not found there, on request of AFL_USE_ASAN, AFL_USE_MSAN, + etc. + - Update have_* so that functions called after this can have correct context. + However this also means any functions called before should NOT depend on + these have_*, otherwise they may not work as expected. +*/ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { if (getenv("AFL_USE_ASAN") || aflcc->have_asan) { @@ -1820,7 +1906,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { FATAL("MSAN and AFL_HARDEN are mutually exclusive"); add_defs_fortify(aflcc, 0); - insert_param(aflcc, "-fsanitize=memory"); + if (!aflcc->have_msan) { insert_param(aflcc, "-fsanitize=memory"); } aflcc->have_msan = 1; } @@ -1907,6 +1993,7 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } +/* Add params to enable LLVM SanCov, the native PCGUARD */ void add_native_pcguard(aflcc_state_t *aflcc) { /* If there is a rust ASan runtime on the command line, it is likely we're @@ -1943,6 +2030,11 @@ void add_native_pcguard(aflcc_state_t *aflcc) { } +/* + Add params to launch our optimized PCGUARD on request. + It will fallback to use the native PCGUARD in some cases. If so, plz + bear in mind that instrument_mode will be set to INSTRUMENT_LLVMNATIVE. +*/ void add_optimized_pcguard(aflcc_state_t *aflcc) { #if LLVM_MAJOR >= 13 @@ -1959,7 +2051,7 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { SAYF( "Using unoptimized trace-pc-guard, due usage of " "-fsanitize-coverage-allow/denylist, you can use " - "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n"); + "AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST instead.\n"); insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard"); aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE; @@ -1994,8 +2086,14 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) { } -/* Linking behaviors */ +/** About -fsanitize -----END----- **/ +/** Linking behaviors -----BEGIN----- **/ + +/* + Parse and process possible linking stage related args, + return PARAM_MISS if nothing matched. +*/ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, u8 *skip_next, char **argv) { @@ -2158,6 +2256,7 @@ param_st parse_linking_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan, } +/* Add params to specify the linker used in LTO */ void add_lto_linker(aflcc_state_t *aflcc) { unsetenv("AFL_LD"); @@ -2197,6 +2296,7 @@ void add_lto_linker(aflcc_state_t *aflcc) { } +/* Add params to launch SanitizerCoverageLTO.so when linking */ void add_lto_passes(aflcc_state_t *aflcc) { #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15 @@ -2215,6 +2315,7 @@ void add_lto_passes(aflcc_state_t *aflcc) { } +/* Add params to link with libAFLDriver.a on request */ static void add_aflpplib(aflcc_state_t *aflcc) { if (!aflcc->need_aflpplib) return; @@ -2250,6 +2351,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) { } +/* Add params to link with runtimes depended by our instrumentation */ void add_runtime(aflcc_state_t *aflcc) { if (aflcc->preprocessor_only || aflcc->have_c || !aflcc->non_dash) { @@ -2345,8 +2447,14 @@ void add_runtime(aflcc_state_t *aflcc) { } -/* Misc */ +/** Linking behaviors -----END----- **/ + +/** Miscellaneous routines -----BEGIN----- **/ +/* + Add params to make compiler driver use our afl-as + as assembler, required by the vanilla instrumentation. +*/ void add_assembler(aflcc_state_t *aflcc) { u8 *afl_as = find_object(aflcc, "as"); @@ -2363,6 +2471,7 @@ void add_assembler(aflcc_state_t *aflcc) { } +/* Add params to launch the gcc plugins for instrumentation. */ void add_gcc_plugin(aflcc_state_t *aflcc) { if (aflcc->cmplog_mode) { @@ -2379,6 +2488,7 @@ void add_gcc_plugin(aflcc_state_t *aflcc) { } +/* Add some miscellaneous params required by our instrumentation. */ void add_misc_params(aflcc_state_t *aflcc) { if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") || @@ -2425,6 +2535,10 @@ void add_misc_params(aflcc_state_t *aflcc) { } +/* + Parse and process a variety of args under our matching rules, + return PARAM_MISS if nothing matched. +*/ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { param_st final_ = PARAM_MISS; @@ -2575,6 +2689,9 @@ param_st parse_misc_params(aflcc_state_t *aflcc, u8 *cur_argv, u8 scan) { } +/** Miscellaneous routines -----END----- **/ + +/* Print help message on request */ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { @@ -2870,6 +2987,24 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { } +/* + Process params passed to afl-cc. + + We have two working modes, *scan* and *non-scan*. In scan mode, + the main task is to set some variables in aflcc according to current argv[i], + while in non-scan mode, is to choose keep or drop current argv[i]. + + We have several matching routines being called sequentially in the while-loop, + and each of them try to parse and match current argv[i] according to their own + rules. If one miss match, the next will then take over. In non-scan mode, each + argv[i] mis-matched by all the routines will be kept. + + These routines are: + 1. parse_misc_params + 2. parse_fsanitize + 3. parse_linking_params + 4. `if (*cur == '@') {...}`, i.e., parse response files +*/ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, char **argv) { @@ -2896,134 +3031,249 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, 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 == '@') { - // response file support. - // 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. - // We do *not* support quotes in the rsp files to cope with spaces in - // filenames etc! If you need that then send a patch! u8 *filename = cur + 1; if (aflcc->debug) { DEBUGF("response file=%s\n", filename); } - FILE *f = fopen(filename, "r"); - struct stat st; // Check not found or empty? let the compiler complain if so. - if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) { + FILE *f = fopen(filename, "r"); + if (!f) { if (!scan) insert_param(aflcc, cur); continue; } - u8 *tmpbuf = malloc(st.st_size + 2), *ptr; - char **args = malloc(sizeof(char *) * (st.st_size >> 1)); - int count = 1, cont = 0, cont_act = 0; + struct stat st; + if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode) || st.st_size < 1) { - while (fgets(tmpbuf, st.st_size + 1, f)) { + fclose(f); + if (!scan) insert_param(aflcc, cur); + continue; - ptr = tmpbuf; - // fprintf(stderr, "1: %s\n", ptr); - // no leading whitespace - while (isspace(*ptr)) { + } - ++ptr; - cont_act = 0; + // 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!"); - // no comments, no empty lines - if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; } - // remove LF - if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; } - // remove CR - if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; } - // handle \ at end of line - if (*ptr && ptr[strlen(ptr) - 1] == '\\') { + --rsp_count; - cont = 1; - ptr[strlen(ptr) - 1] = 0; + } - } + // 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 { + + 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 + + }; + + // Workaround to append c to arg buffer, and append the buffer to argv +#define ARG_ALLOC(c) \ + do { \ + \ + ++arg_len; \ + arg_buf = ck_realloc(arg_buf, (arg_len + 1) * sizeof(char)); \ + arg_buf[arg_len] = '\0'; \ + arg_buf[arg_len - 1] = (char)c; \ + \ + } while (0) + +#define ARG_STORE() \ + do { \ + \ + ++argc_read; \ + argv_read = ck_realloc(argv_read, argc_read * sizeof(char *)); \ + argv_read[argc_read - 1] = arg_buf; \ + arg_buf = NULL; \ + arg_len = 0; \ + \ + } while (0) - // fprintf(stderr, "2: %s\n", ptr); + int cur_chr = (int)' '; // init as whitespace, as a good start :) + enum fsm_state state_ = fsm_whitespace; - // remove whitespace at end - while (*ptr && isspace(ptr[strlen(ptr) - 1])) { + while (cur_chr != EOF) { - ptr[strlen(ptr) - 1] = 0; - cont = 0; + switch (state_) { - } + case fsm_whitespace: + + if (arg_buf) { + + ARG_STORE(); + break; + + } - // fprintf(stderr, "3: %s\n", ptr); - if (*ptr) { + if (isspace(cur_chr)) { - do { + cur_chr = fgetc(f); - u8 *value = ptr; - while (*ptr && !isspace(*ptr)) { + } else if (cur_chr == (int)'\'') { - ++ptr; + state_ = fsm_single_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'"') { + + state_ = fsm_double_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\\') { + + state_ = fsm_backslash; + cur_chr = fgetc(f); + + } else { + + state_ = fsm_normal; } - while (*ptr && isspace(*ptr)) { + break; + + case fsm_normal: - *ptr++ = 0; + if (isspace(cur_chr)) { + + state_ = fsm_whitespace; + + } else if (cur_chr == (int)'\'') { + + state_ = fsm_single_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\"') { + + state_ = fsm_double_quote; + cur_chr = fgetc(f); + + } else if (cur_chr == (int)'\\') { + + state_ = fsm_backslash; + cur_chr = fgetc(f); + + } else { + + ARG_ALLOC(cur_chr); + cur_chr = fgetc(f); } - if (cont_act) { + break; + + case fsm_backslash: + + ARG_ALLOC(cur_chr); + cur_chr = fgetc(f); + state_ = fsm_normal; + + break; + + case fsm_single_quote: + + if (cur_chr == (int)'\\') { + + cur_chr = fgetc(f); + if (cur_chr == EOF) break; + ARG_ALLOC(cur_chr); + + } else if (cur_chr == (int)'\'') { - u32 len = strlen(args[count - 1]) + strlen(value) + 1; - u8 *tmp = malloc(len); - snprintf(tmp, len, "%s%s", args[count - 1], value); - free(args[count - 1]); - args[count - 1] = tmp; - cont_act = 0; + state_ = fsm_normal; } else { - args[count++] = strdup(value); + ARG_ALLOC(cur_chr); } - } while (*ptr); + cur_chr = fgetc(f); + break; - } + case fsm_double_quote: + + if (cur_chr == (int)'\\') { + + cur_chr = fgetc(f); + if (cur_chr == EOF) break; + ARG_ALLOC(cur_chr); + + } else if (cur_chr == (int)'"') { + + state_ = fsm_normal; + + } else { + + ARG_ALLOC(cur_chr); - if (cont) { + } + + cur_chr = fgetc(f); + break; - cont_act = 1; - cont = 0; + default: + break; } } - if (count) { process_params(aflcc, scan, count, args); } + if (arg_buf) { ARG_STORE(); } // save the pending arg after EOF - // we cannot free args[] unless we don't need - // to keep any reference in cc_params - if (scan) { +#undef ARG_ALLOC +#undef ARG_STORE - if (count) do { + if (argc_read > 1) { process_params(aflcc, scan, argc_read, argv_read); } - free(args[--count]); + // We cannot free argv_read[] unless we don't need to keep any + // reference in cc_params. Never free argv[0], the const "". + if (scan) { - } while (count); + while (argc_read > 1) + ck_free(argv_read[--argc_read]); - free(args); + ck_free(argv_read); } - free(tmpbuf); - continue; - } + } /* Response file support -----END----- */ if (!scan) insert_param(aflcc, cur); @@ -3031,8 +3281,7 @@ static void process_params(aflcc_state_t *aflcc, u8 scan, u32 argc, } -/* Copy argv to cc_params, making the necessary edits. */ - +/* 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) { @@ -3173,7 +3422,6 @@ static void edit_params(aflcc_state_t *aflcc, u32 argc, char **argv, } /* Main entry point */ - int main(int argc, char **argv, char **envp) { aflcc_state_t *aflcc = malloc(sizeof(aflcc_state_t)); -- cgit 1.4.1 From 97ba817aa78888b318a76fa278a6fc4454cec1b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 09:56:31 +0100 Subject: debug ci --- src/afl-cc.c | 5 +++++ test/test-nyx-mode.sh | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index c300ddfc..5e28ff6f 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,6 +51,9 @@ #define MAX_PARAMS_NUM 2048 #endif +#undef LLVM_MAJOR +#define LLVM_MAJOR 10 + /** Global declarations -----BEGIN----- **/ typedef enum { @@ -3452,6 +3455,8 @@ int main(int argc, char **argv, char **envp) { if (aflcc->debug) debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); + printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + if (aflcc->passthrough) { argv[0] = aflcc->cc_params[0]; diff --git a/test/test-nyx-mode.sh b/test/test-nyx-mode.sh index 99267ece..5b63d1b7 100755 --- a/test/test-nyx-mode.sh +++ b/test/test-nyx-mode.sh @@ -4,13 +4,11 @@ $ECHO "$BLUE[*] Testing: nyx_mode" +apt-cache search clang|grep -E '^clang-1' ls -al ../libnyx.so ../afl-* ../*.so ../afl-cc -h -../afl-clang-fast -v echo AFL-CC AFL_DEBUG=1 ../afl-cc -v -o test-inst ../test-instr.c 2>&1 -echo AFL-CLANG-FAST -AFL_DEBUG=1 ../afl-clang-fast -v -o test-inst ../test-instr.c 2>&1 ls -l test-instr test -e ../libnyx.so && { ../afl-cc -o test-instr ../test-instr.c > errors 2>&1 -- cgit 1.4.1 From 7793692590b08ff05e513ad679df419bed974723 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 10:26:16 +0100 Subject: debug ci --- src/afl-cc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5e28ff6f..8b247597 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -51,9 +51,6 @@ #define MAX_PARAMS_NUM 2048 #endif -#undef LLVM_MAJOR -#define LLVM_MAJOR 10 - /** Global declarations -----BEGIN----- **/ typedef enum { @@ -3442,6 +3439,8 @@ int main(int argc, char **argv, char **envp) { mode_final_checkout(aflcc, argc, argv); + printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + process_params(aflcc, 1, argc, argv); maybe_usage(aflcc, argc, argv); -- cgit 1.4.1 From 76a033431d1d7ca7bcbe47e4ff42cf03b9874f57 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 11:16:16 +0100 Subject: debug ci --- src/afl-cc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 8b247597..a3b453fc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -3439,22 +3439,28 @@ int main(int argc, char **argv, char **envp) { mode_final_checkout(aflcc, argc, argv); - printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + printf("DEBUGXXX0: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); process_params(aflcc, 1, argc, argv); maybe_usage(aflcc, argc, argv); + printf("DEBUGXXX1: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + mode_notification(aflcc); if (aflcc->debug) debugf_args(argc, argv); + printf("DEBUGXXX2: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + edit_params(aflcc, argc, argv, envp); + printf("DEBUGXXX3: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + if (aflcc->debug) debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); - printf("DEBUGXXX: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); + printf("DEBUGXXX4: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); if (aflcc->passthrough) { -- cgit 1.4.1 From e5d305ad42dc29030cb256f3182a316cc806b6da Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 11:43:04 +0100 Subject: debug ci --- .github/workflows/ci.yml | 7 +++---- src/afl-cc.c | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/afl-cc.c') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdf618b9..0a18a891 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,17 +23,16 @@ jobs: - name: debug run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format- - name: update - run: sudo apt-get update - # && sudo apt-get upgrade -y + run: sudo apt-get update && sudo apt-get upgrade -y - name: install packages #run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip - run: sudo apt-get install -y -m -f build-essential git libtool libtool-bin automake flex bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip + run: sudo apt-get install -y -m -f build-essential git libtool libtool-bin automake flex bison libglib2.0-0 clang-12 llvm-12-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip - name: compiler installed run: gcc -v; echo; clang -v - name: install gcc plugin run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev - name: build afl++ - run: make distrib ASAN_BUILD=1 NO_NYX=1 + run: make distrib ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 - name: run tests run: sudo -E ./afl-system-config; make tests # macos: diff --git a/src/afl-cc.c b/src/afl-cc.c index a3b453fc..24dc1055 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1458,11 +1458,13 @@ void add_real_argv0(aflcc_state_t *aflcc) { } else { u8 *alt_cc = getenv("AFL_CC"); +printf("AFL_CC=%s\n", alt_cc); if (!alt_cc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { +printf("is gcc %d == %d || %d == %d\n", aflcc->compiler_mode, GCC, aflcc->compiler_mode, GCC_PLUGIN); alt_cc = "gcc"; } else if (aflcc->compiler_mode == CLANG) { @@ -1478,6 +1480,8 @@ void add_real_argv0(aflcc_state_t *aflcc) { snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); alt_cc = llvm_fullpath; +printf("use_bindir=%s llvm_fullpath=%s\n", USE_BINDIR ? "true" : "false", llvm_fullpath); + } } -- cgit 1.4.1 From eb52f1cc08e0aacc3c46d1c5a9742526657c842a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 1 Feb 2024 12:58:51 +0100 Subject: fix ci --- .github/workflows/ci.yml | 2 +- GNUmakefile | 14 +++++++------- src/afl-cc.c | 14 -------------- 3 files changed, 8 insertions(+), 22 deletions(-) (limited to 'src/afl-cc.c') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b2031ae..bd16602f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: install gcc plugin run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev - name: build afl++ - run: make distrib ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 + run: export NO_NYX=1; export ASAN_BUILD=1; export LLVM_CONFIG=llvm-config-12; make distrib ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 - name: run tests run: sudo -E ./afl-system-config; make tests # macos: diff --git a/GNUmakefile b/GNUmakefile index be5b8146..2226b5a7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -653,16 +653,16 @@ endif # -$(MAKE) -C utils/plot_ui -$(MAKE) -C frida_mode ifneq "$(SYS)" "Darwin" - ifeq "$(ARCH)" "aarch64" - ifndef NO_CORESIGHT +ifeq "$(ARCH)" "aarch64" + ifndef NO_CORESIGHT -$(MAKE) -C coresight_mode - endif endif - ifeq "$(SYS)" "Linux" - ifndef NO_NYX +endif +ifeq "$(SYS)" "Linux" +ifndef NO_NYX -cd nyx_mode && ./build_nyx_support.sh - endif - endif +endif +endif -cd qemu_mode && sh ./build_qemu_support.sh ifeq "$(ARCH)" "aarch64" ifndef NO_UNICORN_ARM64 diff --git a/src/afl-cc.c b/src/afl-cc.c index 24dc1055..c300ddfc 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1458,13 +1458,11 @@ void add_real_argv0(aflcc_state_t *aflcc) { } else { u8 *alt_cc = getenv("AFL_CC"); -printf("AFL_CC=%s\n", alt_cc); if (!alt_cc) { if (aflcc->compiler_mode == GCC || aflcc->compiler_mode == GCC_PLUGIN) { -printf("is gcc %d == %d || %d == %d\n", aflcc->compiler_mode, GCC, aflcc->compiler_mode, GCC_PLUGIN); alt_cc = "gcc"; } else if (aflcc->compiler_mode == CLANG) { @@ -1480,8 +1478,6 @@ printf("is gcc %d == %d || %d == %d\n", aflcc->compiler_mode, GCC, aflcc->compil snprintf(llvm_fullpath, sizeof(llvm_fullpath), CLANG_BIN); alt_cc = llvm_fullpath; -printf("use_bindir=%s llvm_fullpath=%s\n", USE_BINDIR ? "true" : "false", llvm_fullpath); - } } @@ -3443,29 +3439,19 @@ int main(int argc, char **argv, char **envp) { mode_final_checkout(aflcc, argc, argv); - printf("DEBUGXXX0: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - process_params(aflcc, 1, argc, argv); maybe_usage(aflcc, argc, argv); - printf("DEBUGXXX1: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - mode_notification(aflcc); if (aflcc->debug) debugf_args(argc, argv); - printf("DEBUGXXX2: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - edit_params(aflcc, argc, argv, envp); - printf("DEBUGXXX3: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - if (aflcc->debug) debugf_args((s32)aflcc->cc_par_cnt, (char **)aflcc->cc_params); - printf("DEBUGXXX4: param0=%s aflcc->compiler_mode=%d aflcc->instrument_mode=%d\n", aflcc->cc_params[0], aflcc->compiler_mode, aflcc->instrument_mode); - if (aflcc->passthrough) { argv[0] = aflcc->cc_params[0]; -- cgit 1.4.1 From bd13d32437ebf0c1f7304dc4c8f9797dc4cce7fb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 2 Feb 2024 09:54:24 +0100 Subject: final touches --- instrumentation/SanitizerCoverageLTO.so.cc | 299 ++++++++++++++++++----------- src/afl-cc.c | 2 - 2 files changed, 185 insertions(+), 116 deletions(-) (limited to 'src/afl-cc.c') diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index f6d60099..31d26ca3 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1394,10 +1394,14 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( uint32_t inst_save = inst, save_global = afl_global_id; uint32_t inst_in_this_func = 0; Function *caller = NULL; + LoadInst *PrevCtxLoad = NULL; CTX_add = NULL; - if (debug) fprintf(stderr, "Function: %s\n", F.getName().str().c_str()); + if (debug) + fprintf(stderr, + "Function: %s (%u %u) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n", + F.getName().str().c_str(), inst, afl_global_id); if (instrument_ctx) { @@ -1585,7 +1589,8 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( Value *CTX_offset; BasicBlock::iterator IP = BB.getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); - LoadInst *PrevCtxLoad = IRB.CreateLoad( + + PrevCtxLoad = IRB.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 IRB.getInt32Ty(), #endif @@ -1608,20 +1613,78 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( } - } + // bool loaded = false, multicall = false; + for (auto &IN : BB) { + + // check all calls and where callee count == 1 instrument + // our current caller_id to __afl_ctx + if (auto callInst = dyn_cast(&IN)) { - inst = inst_save; + Function *Callee = callInst->getCalledFunction(); + if (countCallers(Callee) == 1) { + + if (debug) + fprintf(stderr, "DEBUG: %s call to %s with only one caller\n", + F.getName().str().c_str(), + Callee->getName().str().c_str()); + /* if (loaded == false || multicall == true) { // } */ + IRBuilder<> Builder(IN.getContext()); + Builder.SetInsertPoint(callInst); + StoreInst *StoreCtx = + Builder.CreateStore(PrevCtxLoad, AFLContext); + StoreCtx->setMetadata("nosanitize", N); + // multicall = false; loaded = true; + + } // else { multicall = true; } + + } + + } + + } } } + inst = inst_save; + } + /* if (debug) + fprintf(stderr, "Next instrumentation (%u-%u=%u %u-%u=%u)\n", inst, + inst_save, inst - inst_save, afl_global_id, save_global, + afl_global_id - save_global);*/ + for (auto &BB : F) { + skip_next = 0; + + /* + uint32_t j = 0; + fprintf(stderr, "BB %p ============================================\n", + CTX_add);*/ + for (auto &IN : BB) { + /* j++; + uint32_t i = 1; + std::string errMsg; + raw_string_ostream os(errMsg); + IN.print(os); + fprintf(stderr, "Next instruction, BB size now %zu: %02u %s\n", + BB.size(), j, os.str().c_str()); for (auto &IN2 : BB) { + + std::string errMsg2; + raw_string_ostream os2(errMsg2); + IN2.print(os2); + fprintf( + stderr, "%s %02u: %s\n", + strcmp(os.str().c_str(), os2.str().c_str()) == 0 ? ">>>" : " + ", i++, os2.str().c_str()); + + }*/ + CallInst *callInst = nullptr; if ((callInst = dyn_cast(&IN))) { @@ -1665,83 +1728,62 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( SelectInst *selectInst = nullptr; - /* - std::string errMsg; - raw_string_ostream os(errMsg); - IN.print(os); - fprintf(stderr, "X(%u): %s\n", skip_next, os.str().c_str()); - */ - if (!skip_next && (selectInst = dyn_cast(&IN))) { - - uint32_t vector_cnt = 0; - Value *condition = selectInst->getCondition(); - Value *result; - auto t = condition->getType(); - IRBuilder<> IRB(selectInst->getNextNode()); + if ((selectInst = dyn_cast(&IN))) { - ++select_cnt; + if (!skip_next) { - if (t->getTypeID() == llvm::Type::IntegerTyID) { + // fprintf(stderr, "Select in\n"); - Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); - Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); - if (CTX_add) { - - LoadInst *CTX_load = IRB.CreateLoad( -#if LLVM_VERSION_MAJOR >= 14 - IRB.getInt32Ty(), -#endif - CTX_add); - val1 = IRB.CreateAdd(val1, CTX_load); - val2 = IRB.CreateAdd(val2, CTX_load); + uint32_t vector_cnt = 0; + Value *condition = selectInst->getCondition(); + Value *result; + auto t = condition->getType(); + IRBuilder<> IRB(selectInst->getNextNode()); - } + ++select_cnt; - result = IRB.CreateSelect(condition, val1, val2); - skip_next = 1; - inst += 2; + if (t->getTypeID() == llvm::Type::IntegerTyID) { - } else + Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); + Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); + if (CTX_add) { + LoadInst *CTX_load = IRB.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 - if (t->getTypeID() == llvm::Type::FixedVectorTyID) { - - FixedVectorType *tt = dyn_cast(t); - if (tt) { + IRB.getInt32Ty(), +#endif + CTX_add); + val1 = IRB.CreateAdd(val1, CTX_load); + val2 = IRB.CreateAdd(val2, CTX_load); - uint32_t elements = tt->getElementCount().getFixedValue(); - vector_cnt = elements; - inst += vector_cnt * 2; - if (elements) { + } - FixedVectorType *GuardPtr1 = - FixedVectorType::get(Int32Ty, elements); - FixedVectorType *GuardPtr2 = - FixedVectorType::get(Int32Ty, elements); - Value *x, *y; + result = IRB.CreateSelect(condition, val1, val2); + skip_next = 1; + inst += 2; - Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); - Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); - if (CTX_add) { + } else - LoadInst *CTX_load = IRB.CreateLoad( - #if LLVM_VERSION_MAJOR >= 14 - IRB.getInt32Ty(), - #endif - CTX_add); - val1 = IRB.CreateAdd(val1, CTX_load); - val2 = IRB.CreateAdd(val2, CTX_load); +#if LLVM_VERSION_MAJOR >= 14 + if (t->getTypeID() == llvm::Type::FixedVectorTyID) { - } + FixedVectorType *tt = dyn_cast(t); + if (tt) { - x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); - y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); + uint32_t elements = tt->getElementCount().getFixedValue(); + vector_cnt = elements; + inst += vector_cnt * 2; + if (elements) { - for (uint64_t i = 1; i < elements; i++) { + FixedVectorType *GuardPtr1 = + FixedVectorType::get(Int32Ty, elements); + FixedVectorType *GuardPtr2 = + FixedVectorType::get(Int32Ty, elements); + Value *x, *y; - val1 = ConstantInt::get(Int32Ty, ++afl_global_id); - val2 = ConstantInt::get(Int32Ty, ++afl_global_id); - /*if (CTX_add) { // already loaded I guess + Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); + Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); + if (CTX_add) { LoadInst *CTX_load = IRB.CreateLoad( #if LLVM_VERSION_MAJOR >= 14 @@ -1751,92 +1793,116 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( val1 = IRB.CreateAdd(val1, CTX_load); val2 = IRB.CreateAdd(val2, CTX_load); - }*/ + } - x = IRB.CreateInsertElement(GuardPtr1, val1, i); - y = IRB.CreateInsertElement(GuardPtr2, val2, i); + x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); + y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); - } + for (uint64_t i = 1; i < elements; i++) { - result = IRB.CreateSelect(condition, x, y); - skip_next = 1; + val1 = ConstantInt::get(Int32Ty, ++afl_global_id); + val2 = ConstantInt::get(Int32Ty, ++afl_global_id); + /*if (CTX_add) { // already loaded I guess - } + LoadInst *CTX_load = IRB.CreateLoad( + #if LLVM_VERSION_MAJOR >= 14 + IRB.getInt32Ty(), + #endif + CTX_add); + val1 = IRB.CreateAdd(val1, CTX_load); + val2 = IRB.CreateAdd(val2, CTX_load); - } + }*/ + + x = IRB.CreateInsertElement(GuardPtr1, val1, i); + y = IRB.CreateInsertElement(GuardPtr2, val2, i); + + } + + result = IRB.CreateSelect(condition, x, y); + skip_next = 1; - } else + } + + } + + } else #endif - { + { - ++unhandled; - continue; + ++unhandled; + continue; - } + } - uint32_t vector_cur = 0; - /* Load SHM pointer */ - LoadInst *MapPtr = - IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); - ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr); + uint32_t vector_cur = 0; + /* Load SHM pointer */ + LoadInst *MapPtr = + IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr); - while (1) { + while (1) { - /* Get CurLoc */ - Value *MapPtrIdx = nullptr; + /* Get CurLoc */ + Value *MapPtrIdx = nullptr; - /* Load counter for CurLoc */ - if (!vector_cnt) { + /* Load counter for CurLoc */ + if (!vector_cnt) { - MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, result); + MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, result); - } else { + } else { - auto element = IRB.CreateExtractElement(result, vector_cur++); - MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, element); + auto element = IRB.CreateExtractElement(result, vector_cur++); + MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, element); - } + } - if (use_threadsafe_counters) { + if (use_threadsafe_counters) { - IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, + One, #if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), + llvm::MaybeAlign(1), #endif - llvm::AtomicOrdering::Monotonic); + llvm::AtomicOrdering::Monotonic); + + } else { - } else { + LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(Counter); - LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); - ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(Counter); + /* Update bitmap */ - /* Update bitmap */ + Value *Incr = IRB.CreateAdd(Counter, One); - Value *Incr = IRB.CreateAdd(Counter, One); + if (skip_nozero == NULL) { - if (skip_nozero == NULL) { + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); - auto cf = IRB.CreateICmpEQ(Incr, Zero); - auto carry = IRB.CreateZExt(cf, Int8Ty); - Incr = IRB.CreateAdd(Incr, carry); + } + + auto nosan = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(nosan); } - auto nosan = IRB.CreateStore(Incr, MapPtrIdx); - ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(nosan); + if (!vector_cnt || vector_cnt == vector_cur) { break; } } - if (!vector_cnt || vector_cnt == vector_cur) { break; } - - } + skip_next = 1; + // fprintf(stderr, "Select out\n"); - skip_next = 1; + } else { - } else { + // fprintf(stderr, "Select skip\n"); + skip_next = 0; - skip_next = 0; + } } @@ -1862,6 +1928,11 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( InjectCoverage(F, BlocksToInstrument, IsLeafFunc); // InjectCoverageForIndirectCalls(F, IndirCalls); + /*if (debug) + fprintf(stderr, "Done instrumentation (%u-%u=%u %u-%u=%u)\n", inst, + inst_save, inst - inst_save, afl_global_id, save_global, + afl_global_id - save_global);*/ + if (inst_in_this_func && call_counter > 1) { if (inst_in_this_func != afl_global_id - save_global) { diff --git a/src/afl-cc.c b/src/afl-cc.c index 4f6745ed..fd466541 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1103,8 +1103,6 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { } - fprintf(stderr, "X %u %u\n", aflcc->compiler_mode, LTO); - if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM && !((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && aflcc->compiler_mode == LTO)) -- cgit 1.4.1 From 1e7485dcee1f19d8eb78562d62c30f2aae5a101d Mon Sep 17 00:00:00 2001 From: Khaled Yakdan Date: Sat, 3 Feb 2024 10:49:45 +0100 Subject: Fix type in AFL_NOOPT env variable in afl-cc help message (#1982) --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index c300ddfc..98310545 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2830,7 +2830,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" " AFL_NO_BUILTIN: no builtins for string compare functions (for " "libtokencap.so)\n" - " AFL_NOOP: behave like a normal compiler (to pass configure " + " AFL_NOOPT: behave like a normal compiler (to pass configure " "tests)\n" " AFL_PATH: path to instrumenting pass and runtime " "(afl-compiler-rt.*o)\n" -- cgit 1.4.1 From ed1a6f8a570c6fcabee962f402d8d58f6cea77b7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 11:01:31 +0100 Subject: 2024 v4.10c release --- GNUmakefile.gcc_plugin | 2 +- README.md | 4 ++-- afl-cmin.bash | 2 +- afl-whatsup | 2 +- docs/Changelog.md | 3 +-- frida_mode/Scripting.md | 2 +- frida_mode/test/cmplog/cmplog.c | 2 +- frida_mode/test/deferred/testinstr.c | 2 +- frida_mode/test/dynamic/testinstr.c | 2 +- frida_mode/test/entry_point/testinstr.c | 2 +- frida_mode/test/exe/testinstr.c | 2 +- frida_mode/test/js/test.c | 2 +- frida_mode/test/js/test2.c | 2 +- frida_mode/test/output/testinstr.c | 2 +- frida_mode/test/perf/perf.c | 2 +- frida_mode/test/persistent_ret/testinstr.c | 2 +- frida_mode/test/testinstr/testinstr.c | 2 +- frida_mode/test/unstable/unstable.c | 2 +- frida_mode/util/frida_get_symbol_addr.sh | 2 +- include/afl-as.h | 2 +- include/afl-fuzz.h | 2 +- include/afl-prealloc.h | 2 +- include/alloc-inl.h | 2 +- include/cmplog.h | 2 +- include/common.h | 2 +- include/config.h | 4 ++-- include/debug.h | 2 +- include/forkserver.h | 2 +- include/hash.h | 2 +- include/list.h | 2 +- include/sharedmem.h | 2 +- include/snapshot-inl.h | 2 +- include/types.h | 2 +- include/xxhash.h | 2 +- instrumentation/afl-compiler-rt.o.c | 2 +- instrumentation/afl-gcc-cmplog-pass.so.cc | 2 +- instrumentation/afl-gcc-cmptrs-pass.so.cc | 2 +- instrumentation/afl-gcc-common.h | 2 +- instrumentation/afl-gcc-pass.so.cc | 2 +- instrumentation/afl-llvm-dict2file.so.cc | 2 +- instrumentation/afl-llvm-lto-instrumentlist.so.cc | 2 +- instrumentation/afl-llvm-pass.so.cc | 2 +- instrumentation/cmplog-instructions-pass.cc | 2 +- instrumentation/cmplog-routines-pass.cc | 2 +- instrumentation/cmplog-switches-pass.cc | 2 +- instrumentation/injection-pass.cc | 2 +- qemu_mode/build_qemu_support.sh | 2 +- qemu_mode/fastexit/Makefile | 2 +- qemu_mode/libcompcov/Makefile | 2 +- qemu_mode/libcompcov/compcovtest.cc | 2 +- qemu_mode/libcompcov/libcompcov.so.c | 2 +- qemu_mode/libqasan/Makefile | 2 +- qemu_mode/libqasan/hooks.c | 2 +- qemu_mode/libqasan/libqasan.c | 2 +- qemu_mode/libqasan/libqasan.h | 2 +- qemu_mode/libqasan/malloc.c | 2 +- qemu_mode/libqasan/patch.c | 2 +- qemu_mode/libqasan/string.c | 2 +- qemu_mode/libqasan/uninstrument.c | 2 +- qemu_mode/unsigaction/Makefile | 2 +- qemu_mode/util/qemu_get_symbol_addr.sh | 2 +- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 2 +- src/afl-common.c | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 2 +- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- test-instr.c | 2 +- unicorn_mode/build_unicorn_support.sh | 2 +- utils/afl_network_proxy/afl-network-client.c | 2 +- utils/afl_network_proxy/afl-network-server.c | 2 +- utils/afl_proxy/afl-proxy.c | 2 +- utils/afl_untracer/afl-untracer.c | 2 +- utils/afl_untracer/libtestinstr.c | 2 +- utils/argv_fuzzing/Makefile | 2 +- utils/argv_fuzzing/argvfuzz.c | 2 +- utils/distributed_fuzzing/sync_script.sh | 2 +- utils/libdislocator/libdislocator.so.c | 2 +- utils/libtokencap/libtokencap.so.c | 2 +- utils/persistent_mode/test-instr.c | 2 +- 97 files changed, 99 insertions(+), 100 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin index 16c98399..8f06792d 100644 --- a/GNUmakefile.gcc_plugin +++ b/GNUmakefile.gcc_plugin @@ -11,7 +11,7 @@ # from Laszlo Szekeres. # # Copyright 2015 Google Inc. All rights reserved. -# Copyright 2019-2023 AFLplusplus Project. All rights reserved. +# Copyright 2019-2024 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index fd48cb14..f713e971 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.09c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.10a +GitHub version: 4.10c Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/afl-cmin.bash b/afl-cmin.bash index fda48fb4..6c271220 100755 --- a/afl-cmin.bash +++ b/afl-cmin.bash @@ -7,7 +7,7 @@ # # Copyright 2014, 2015 Google Inc. All rights reserved. # -# Copyright 2019-2023 AFLplusplus +# Copyright 2019-2024 AFLplusplus # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/afl-whatsup b/afl-whatsup index 5b7cbcd6..aa081e41 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2015 Google Inc. All rights reserved. -# Copyright 2019-2023 AFLplusplus Project. All rights reserved. +# Copyright 2019-2024 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/Changelog.md b/docs/Changelog.md index 29081549..48003f4b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,7 +3,7 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. -### Version ++4.10a (dev) +### Version ++4.10c (release) - afl-fuzz: - default power schedule is now EXPLORE, due a fix in fast schedules explore is slightly better now. @@ -34,7 +34,6 @@ - updated the custom grammar mutator - document afl-cmin does not work on macOS (but afl-cmin.bash does) - ### Version ++4.09c (release) - afl-fuzz: - fixed the new mutation implementation for two bugs diff --git a/frida_mode/Scripting.md b/frida_mode/Scripting.md index dfd09e7b..653687f0 100644 --- a/frida_mode/Scripting.md +++ b/frida_mode/Scripting.md @@ -390,7 +390,7 @@ Consider the [following](test/js/test2.c) test code... -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/cmplog/cmplog.c b/frida_mode/test/cmplog/cmplog.c index 2565b35c..d397f36e 100644 --- a/frida_mode/test/cmplog/cmplog.c +++ b/frida_mode/test/cmplog/cmplog.c @@ -2,7 +2,7 @@ // // Author: Mateusz Jurczyk (mjurczyk@google.com) // -// Copyright 2019-2023 Google LLC +// Copyright 2019-2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c index 0ab44582..4e5124ed 100644 --- a/frida_mode/test/deferred/testinstr.c +++ b/frida_mode/test/deferred/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/dynamic/testinstr.c b/frida_mode/test/dynamic/testinstr.c index 8b285f6d..0abc61fd 100644 --- a/frida_mode/test/dynamic/testinstr.c +++ b/frida_mode/test/dynamic/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c index 24d9a615..75e71bda 100644 --- a/frida_mode/test/entry_point/testinstr.c +++ b/frida_mode/test/entry_point/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c index d965502e..7b603659 100644 --- a/frida_mode/test/exe/testinstr.c +++ b/frida_mode/test/exe/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test.c b/frida_mode/test/js/test.c index 87c9cdf6..9799bf3b 100644 --- a/frida_mode/test/js/test.c +++ b/frida_mode/test/js/test.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test2.c b/frida_mode/test/js/test2.c index 6b680a24..60b30eb5 100644 --- a/frida_mode/test/js/test2.c +++ b/frida_mode/test/js/test2.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/output/testinstr.c b/frida_mode/test/output/testinstr.c index d965502e..7b603659 100644 --- a/frida_mode/test/output/testinstr.c +++ b/frida_mode/test/output/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/perf/perf.c b/frida_mode/test/perf/perf.c index d9626974..55efba26 100644 --- a/frida_mode/test/perf/perf.c +++ b/frida_mode/test/perf/perf.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c index 12365ceb..85aa2b80 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/testinstr/testinstr.c b/frida_mode/test/testinstr/testinstr.c index d965502e..7b603659 100644 --- a/frida_mode/test/testinstr/testinstr.c +++ b/frida_mode/test/testinstr/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/unstable/unstable.c b/frida_mode/test/unstable/unstable.c index a87b6c74..16978e7e 100644 --- a/frida_mode/test/unstable/unstable.c +++ b/frida_mode/test/unstable/unstable.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/util/frida_get_symbol_addr.sh b/frida_mode/util/frida_get_symbol_addr.sh index 2e682255..53d5b802 100755 --- a/frida_mode/util/frida_get_symbol_addr.sh +++ b/frida_mode/util/frida_get_symbol_addr.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023 AFLplusplus +# Copyright 2024 AFLplusplus # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/include/afl-as.h b/include/afl-as.h index 486314e2..612f34f4 100644 --- a/include/afl-as.h +++ b/include/afl-as.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index c2b09b2e..c24f39e2 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index d19a7b52..3c621d79 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/alloc-inl.h b/include/alloc-inl.h index cff808b2..0aa417be 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/cmplog.h b/include/cmplog.h index e4821444..6bfc146b 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/common.h b/include/common.h index a9739a7d..0df07dee 100644 --- a/include/common.h +++ b/include/common.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/config.h b/include/config.h index 7ad73c2f..9349828f 100644 --- a/include/config.h +++ b/include/config.h @@ -10,7 +10,7 @@ Heiko Eissfeldt , Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.10a" +#define VERSION "++4.10c" /****************************************************** * * diff --git a/include/debug.h b/include/debug.h index 234d8fc4..4b812f8e 100644 --- a/include/debug.h +++ b/include/debug.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/forkserver.h b/include/forkserver.h index f1d3b5b1..be7f9e8d 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -12,7 +12,7 @@ Dominik Maier > Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/hash.h b/include/hash.h index 0243c5b7..5d56a108 100644 --- a/include/hash.h +++ b/include/hash.h @@ -15,7 +15,7 @@ Other code written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/list.h b/include/list.h index 283bf035..441eccd3 100644 --- a/include/list.h +++ b/include/list.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/sharedmem.h b/include/sharedmem.h index d32bd845..4484066e 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h index 3864e473..b2c81402 100644 --- a/include/snapshot-inl.h +++ b/include/snapshot-inl.h @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/types.h b/include/types.h index d6476d82..22332135 100644 --- a/include/types.h +++ b/include/types.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/xxhash.h b/include/xxhash.h index a8bd6f27..9a880470 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (C) 2012-2023 Yann Collet + * Copyright (C) 2012-2024 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 8e55d6a0..caa3c3a8 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -3,7 +3,7 @@ ------------------------------------------------ Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-gcc-cmplog-pass.so.cc b/instrumentation/afl-gcc-cmplog-pass.so.cc index b4e6fda9..774dd5fd 100644 --- a/instrumentation/afl-gcc-cmplog-pass.so.cc +++ b/instrumentation/afl-gcc-cmplog-pass.so.cc @@ -3,7 +3,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL++ LLVM CmpLog pass by Andrea Fioraldi , and diff --git a/instrumentation/afl-gcc-cmptrs-pass.so.cc b/instrumentation/afl-gcc-cmptrs-pass.so.cc index c56263dd..929a9d7a 100644 --- a/instrumentation/afl-gcc-cmptrs-pass.so.cc +++ b/instrumentation/afl-gcc-cmptrs-pass.so.cc @@ -3,7 +3,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL++ LLVM CmpLog Routines pass by Andrea Fioraldi diff --git a/instrumentation/afl-gcc-common.h b/instrumentation/afl-gcc-common.h index 1d5eb466..80ded57d 100644 --- a/instrumentation/afl-gcc-common.h +++ b/instrumentation/afl-gcc-common.h @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL++ GCC plugin. diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc index 4d7fd0ef..41b1e5af 100644 --- a/instrumentation/afl-gcc-pass.so.cc +++ b/instrumentation/afl-gcc-pass.so.cc @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AdaCore + Copyright 2019-2024 AdaCore Written by Alexandre Oliva , based on the AFL LLVM pass by Laszlo Szekeres and Michal diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index c60f3e06..ac497b5b 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 61f97d77..e0899cd3 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -9,7 +9,7 @@ from afl-as.c are Michal's fault. Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 052488a9..62f5023d 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -12,7 +12,7 @@ NGRAM previous location coverage comes from Adrian Herrera. Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 8be8c294..dc60221e 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index b27e06e0..78317d5d 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 01da6da7..3e05c13d 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/injection-pass.cc b/instrumentation/injection-pass.cc index 971b103b..2280208b 100644 --- a/instrumentation/injection-pass.cc +++ b/instrumentation/injection-pass.cc @@ -5,7 +5,7 @@ Written by Marc Heuse Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 3f8a88f2..45019cc8 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -13,7 +13,7 @@ # counters by Andrea Fioraldi # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. -# Copyright 2019-2023 AFLplusplus Project. All rights reserved. +# Copyright 2019-2024 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/fastexit/Makefile b/qemu_mode/fastexit/Makefile index c7b79277..be80207d 100644 --- a/qemu_mode/fastexit/Makefile +++ b/qemu_mode/fastexit/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/Makefile b/qemu_mode/libcompcov/Makefile index 7260df87..4761ac02 100644 --- a/qemu_mode/libcompcov/Makefile +++ b/qemu_mode/libcompcov/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/compcovtest.cc b/qemu_mode/libcompcov/compcovtest.cc index 23215013..11797091 100644 --- a/qemu_mode/libcompcov/compcovtest.cc +++ b/qemu_mode/libcompcov/compcovtest.cc @@ -2,7 +2,7 @@ // // Author: Mateusz Jurczyk (mjurczyk@google.com) // -// Copyright 2019-2023 Google LLC +// Copyright 2019-2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index b57e9701..36f7b2e2 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -5,7 +5,7 @@ Written and maintained by Andrea Fioraldi - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/qemu_mode/libqasan/Makefile b/qemu_mode/libqasan/Makefile index 61782894..7366d6f6 100644 --- a/qemu_mode/libqasan/Makefile +++ b/qemu_mode/libqasan/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c index a9fd0ce9..cf1b0820 100644 --- a/qemu_mode/libqasan/hooks.c +++ b/qemu_mode/libqasan/hooks.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/libqasan.c b/qemu_mode/libqasan/libqasan.c index 12be7778..45f47d5a 100644 --- a/qemu_mode/libqasan/libqasan.c +++ b/qemu_mode/libqasan/libqasan.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/libqasan.h b/qemu_mode/libqasan/libqasan.h index a430c868..f0844e23 100644 --- a/qemu_mode/libqasan/libqasan.h +++ b/qemu_mode/libqasan/libqasan.h @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/malloc.c b/qemu_mode/libqasan/malloc.c index 4448f480..ae470b56 100644 --- a/qemu_mode/libqasan/malloc.c +++ b/qemu_mode/libqasan/malloc.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/patch.c b/qemu_mode/libqasan/patch.c index 38e0903b..4ce8c3d8 100644 --- a/qemu_mode/libqasan/patch.c +++ b/qemu_mode/libqasan/patch.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/string.c b/qemu_mode/libqasan/string.c index e17cff4b..cd14d57b 100644 --- a/qemu_mode/libqasan/string.c +++ b/qemu_mode/libqasan/string.c @@ -1,5 +1,5 @@ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/libqasan/uninstrument.c b/qemu_mode/libqasan/uninstrument.c index e37a9b46..996f2a74 100644 --- a/qemu_mode/libqasan/uninstrument.c +++ b/qemu_mode/libqasan/uninstrument.c @@ -7,7 +7,7 @@ for some strange reason. */ /******************************************************************************* -Copyright (c) 2019-2023, Andrea Fioraldi +Copyright (c) 2019-2024, Andrea Fioraldi Redistribution and use in source and binary forms, with or without diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile index c1a7397f..d5e807d8 100644 --- a/qemu_mode/unsigaction/Makefile +++ b/qemu_mode/unsigaction/Makefile @@ -4,7 +4,7 @@ # # Written by Andrea Fioraldi # -# Copyright 2019-2023 Andrea Fioraldi. All rights reserved. +# Copyright 2019-2024 Andrea Fioraldi. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/util/qemu_get_symbol_addr.sh b/qemu_mode/util/qemu_get_symbol_addr.sh index e0a7ae80..5e00f1b2 100755 --- a/qemu_mode/util/qemu_get_symbol_addr.sh +++ b/qemu_mode/util/qemu_get_symbol_addr.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023 AFLplusplus +# Copyright 2024 AFLplusplus # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 5b122741..95f32fee 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-as.c b/src/afl-as.c index 772e31b3..09ba75bf 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-cc.c b/src/afl-cc.c index 98310545..e9564277 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -5,7 +5,7 @@ Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-common.c b/src/afl-common.c index ba498b3b..87003b03 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ded0c21d..0a77d61c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -13,7 +13,7 @@ Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 5f67347c..d056ac9f 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 3e6432ca..21f34e12 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 905431d1..3b1d13f1 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 057d8cf5..76291cc4 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 17fb9368..ae4d6668 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index c163a420..d9c074ec 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 4c7da774..16a398fd 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 67931bba..1ea50418 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 9e9b3822..eead7a8b 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 1ee8ebe7..d764952c 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index b647ac84..4467cae8 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4b83ad29..76577081 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 69064d51..12d67fe7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 4f851099..7aee2985 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -9,7 +9,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 7ce5de41..513c1ae9 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -9,7 +9,7 @@ Andrea Fioraldi Dominik Maier - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index a2c81586..daea8f46 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -11,7 +11,7 @@ Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 7a639cf6..20ba5a5e 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-tmin.c b/src/afl-tmin.c index e7442d1d..4e5dab41 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/test-instr.c b/test-instr.c index eda5189c..28552893 100644 --- a/test-instr.c +++ b/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index d3d16ad5..baca2171 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -14,7 +14,7 @@ # # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2023 AFLplusplus Project. All rights reserved. +# Copyright 2019-2024 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c index 0416f0f9..1f04dd87 100644 --- a/utils/afl_network_proxy/afl-network-client.c +++ b/utils/afl_network_proxy/afl-network-client.c @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index 95b0a551..c4a700f4 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -12,7 +12,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index 531a97a2..6cf47636 100644 --- a/utils/afl_proxy/afl-proxy.c +++ b/utils/afl_proxy/afl-proxy.c @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index 0e3f8a45..e6a74518 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -4,7 +4,7 @@ Written by Marc Heuse - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c index b7afc325..0a98778a 100644 --- a/utils/afl_untracer/libtestinstr.c +++ b/utils/afl_untracer/libtestinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/utils/argv_fuzzing/Makefile b/utils/argv_fuzzing/Makefile index 6786467a..ba977e5f 100644 --- a/utils/argv_fuzzing/Makefile +++ b/utils/argv_fuzzing/Makefile @@ -2,7 +2,7 @@ # american fuzzy lop++ - argvfuzz # -------------------------------- # -# Copyright 2019-2023 Kjell Braden +# Copyright 2019-2024 Kjell Braden # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/argv_fuzzing/argvfuzz.c b/utils/argv_fuzzing/argvfuzz.c index 41eead0c..47383138 100644 --- a/utils/argv_fuzzing/argvfuzz.c +++ b/utils/argv_fuzzing/argvfuzz.c @@ -2,7 +2,7 @@ american fuzzy lop++ - LD_PRELOAD for fuzzing argv in binaries ------------------------------------------------------------ - Copyright 2019-2023 Kjell Braden + Copyright 2019-2024 Kjell Braden Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh index b22816f1..861b65c8 100755 --- a/utils/distributed_fuzzing/sync_script.sh +++ b/utils/distributed_fuzzing/sync_script.sh @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2014 Google Inc. All rights reserved. -# Copyright 2019-2023 AFLplusplus Project. All rights reserved. +# Copyright 2019-2024 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index 1cd7abc6..b80be1a1 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index f4024799..cc499150 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 4ead6577..72e26e93 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2023 AFLplusplus Project. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: -- cgit 1.4.1 From dc151caa1839162e470e003837e630db6d5d543e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 3 Feb 2024 15:53:54 +0100 Subject: add lto caller instrumentation --- docs/Changelog.md | 5 +++++ docs/env_variables.md | 3 +++ instrumentation/SanitizerCoverageLTO.so.cc | 27 ++++++++++++++++++++++++--- src/afl-cc.c | 5 +++-- 4 files changed, 35 insertions(+), 5 deletions(-) (limited to 'src/afl-cc.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 2f0fba33..e5169daf 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -7,6 +7,11 @@ - afl-fuzz: - the new deterministic fuzzing feature is now activated by default, deactivate with -z. Parameters -d and -D are ignored. + - afl-cc: + - added collision free caller instrumentation to LTO mode. activate with + `AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single + block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0) + ### Version ++4.10c (release) - afl-fuzz: diff --git a/docs/env_variables.md b/docs/env_variables.md index a972b6da..1e4fc7ba 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -248,6 +248,9 @@ use (which only ever the author of this LTO implementation will use). These are used if several separated instrumentations are performed which are then later combined. + - `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation + - `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions + to dig deeper into a real function. Default 0. - `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given to which function. This helps to identify functions with variable bytes or which functions were touched by an input. diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 65602109..b93b72bf 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -251,6 +251,7 @@ class ModuleSanitizerCoverageLTO uint32_t unhandled = 0; uint32_t select_cnt = 0; uint32_t instrument_ctx = 0; + uint32_t instrument_ctx_max_depth = 0; uint32_t extra_ctx_inst = 0; uint64_t map_addr = 0; const char *skip_nozero = NULL; @@ -428,12 +429,31 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( setvbuf(stdout, NULL, _IONBF, 0); if (getenv("AFL_DEBUG")) { debug = 1; } if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { autodictionary_no_main = 1; } - if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_CTX")) { + if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_CTX") || + getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX")) { instrument_ctx = 1; } + if (getenv("AFL_LLVM_LTO_CALLER_DEPTH")) { + + instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_LTO_CALLER_DEPTH")); + + } else if (getenv("AFL_LLVM_LTO_CTX_DEPTH")) { + + instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_LTO_CTX_DEPTH")); + + } else if (getenv("AFL_LLVM_CALLER_DEPTH")) { + + instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_CALLER_DEPTH")); + + } else if (getenv("AFL_LLVM_CTX_DEPTH")) { + + instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_CTX_DEPTH")); + + } + if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { SAYF(cCYA "afl-llvm-lto" VERSION cRST @@ -1406,11 +1426,12 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( call_counter = countCallers(caller); Function *callee = caller; - if (call_counter == 1) { + if (call_counter == 1 && instrument_ctx_max_depth) { ++call_depth; - while (((caller = returnOnlyCaller(callee)) || 1 == 1) && + while (instrument_ctx_max_depth >= call_depth && + ((caller = returnOnlyCaller(callee)) || 1 == 1) && (call_counter = countCallers(callee)) == 1) { if (debug && caller && callee) diff --git a/src/afl-cc.c b/src/afl-cc.c index 7d33b9f5..4d586ce8 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2921,11 +2921,12 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding " "functions\n" " into this file (LTO mode)\n" + " AFL_LLVM_LTO_CALLER: activate CALLER/CTX instrumentation\n" + " AFL_LLVM_LTO_CALLER_DEPTH: skip how many empty functions\n" " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " "global var\n" " AFL_LLVM_LTO_STARTID: from which ID to start counting from for " - "a " - "bb\n" + "a bb\n" " AFL_REAL_LD: use this lld linker instead of the compiled in " "path\n" " AFL_LLVM_LTO_SKIPINIT: don't inject initialization code " -- cgit 1.4.1 From 88e41f01c839ed5c46882222ad7e1f5c3e7d9e20 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 8 Feb 2024 15:28:19 +0100 Subject: env fix --- instrumentation/SanitizerCoverageLTO.so.cc | 10 +++++++++- src/afl-cc.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index b93b72bf..f55aeca2 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -456,9 +456,17 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( if ((isatty(2) && !getenv("AFL_QUIET")) || debug) { + char buf[64] = {}; + if (instrument_ctx) { + + snprintf(buf, sizeof(buf), " (CTX mode, depth %u)\n", + instrument_ctx_max_depth); + + } + SAYF(cCYA "afl-llvm-lto" VERSION cRST "%s by Marc \"vanHauser\" Heuse \n", - instrument_ctx ? " (CTX mode)" : ""); + buf); } else { diff --git a/src/afl-cc.c b/src/afl-cc.c index 4d586ce8..3a32a0d1 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -828,7 +828,7 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER")) + if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; if (getenv("AFL_LLVM_NGRAM_SIZE")) { -- cgit 1.4.1 From 6dc58750cf2b321b5cb42a2080410e6d9420548b Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 15 Feb 2024 19:19:51 -0500 Subject: issue #2001: fix passing rpath to linker on macOS Seems on macOS, `ld` does not want an `=` when specifying `-rpath`. --- src/afl-cc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 3a32a0d1..6aa0da6a 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2379,7 +2379,11 @@ void add_runtime(aflcc_state_t *aflcc) { if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && strncmp(libdir, "/lib", 4)) { +#ifdef __APPLE__ + u8 *libdir_opt = strdup("-Wl,-rpath," LLVM_LIBDIR); +#else u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR); +#endif insert_param(aflcc, libdir_opt); } -- cgit 1.4.1 From 036a79268b48a0e3e061d5e3387711f69bed8d56 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 29 Feb 2024 09:10:22 +0100 Subject: gcc cmplog fix --- docs/Changelog.md | 3 ++- include/t1ha_bits.h | 15 ++++++++------- include/xxhash.h | 30 ++++++++++++++++++------------ instrumentation/afl-gcc-cmptrs-pass.so.cc | 15 +++++++++------ src/afl-cc.c | 3 ++- src/afl-fuzz.c | 14 ++++++-------- 6 files changed, 45 insertions(+), 35 deletions(-) (limited to 'src/afl-cc.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index ead015eb..da4b3a20 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -27,8 +27,9 @@ - added collision free caller instrumentation to LTO mode. activate with `AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0) + - fix for GCC_PLUGIN cmplog that broke on std::strings - afl-whatsup: - - Now also displays current average speed + - now also displays current average speed - small bugfixes - Minor edits to afl-persistent-config - Prevent temporary files being left behind on aborted afl-whatsup diff --git a/include/t1ha_bits.h b/include/t1ha_bits.h index e7a8d53c..0b9bbda5 100644 --- a/include/t1ha_bits.h +++ b/include/t1ha_bits.h @@ -207,7 +207,7 @@ static __maybe_unused __always_inline unsigned e2k_add64carry_first( return (unsigned)__builtin_e2k_addcd_c(base, addend, 0); } -\ + #define add64carry_first(base, addend, sum) \ e2k_add64carry_first(base, addend, sum) @@ -218,7 +218,7 @@ static __maybe_unused __always_inline unsigned e2k_add64carry_next( return (unsigned)__builtin_e2k_addcd_c(base, addend, carry); } -\ + #define add64carry_next(carry, base, addend, sum) \ e2k_add64carry_next(carry, base, addend, sum) @@ -230,7 +230,7 @@ static __maybe_unused __always_inline void e2k_add64carry_last(unsigned carry, *sum = __builtin_e2k_addcd(base, addend, carry); } -\ + #define add64carry_last(carry, base, addend, sum) \ e2k_add64carry_last(carry, base, addend, sum) #endif /* __iset__ >= 5 */ @@ -311,7 +311,7 @@ static __forceinline char msvc32_add64carry_first(uint64_t base, base_32h, addend_32h, sum32 + 1); } -\ + #define add64carry_first(base, addend, sum) \ msvc32_add64carry_first(base, addend, sum) @@ -328,7 +328,7 @@ static __forceinline char msvc32_add64carry_next(char carry, uint64_t base, base_32h, addend_32h, sum32 + 1); } -\ + #define add64carry_next(carry, base, addend, sum) \ msvc32_add64carry_next(carry, base, addend, sum) @@ -345,7 +345,7 @@ static __forceinline void msvc32_add64carry_last(char carry, uint64_t base, addend_32h, sum32 + 1); } -\ + #define add64carry_last(carry, base, addend, sum) \ msvc32_add64carry_last(carry, base, addend, sum) #endif /* _MSC_FULL_VER >= 190024231 */ @@ -454,7 +454,7 @@ typedef struct { uint64_t unaligned_64; } __attribute__((__packed__)) t1ha_unaligned_proxy; -\ + #define read_unaligned(ptr, bits) \ (((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \ t1ha_unaligned_proxy, unaligned_##bits))) \ @@ -539,6 +539,7 @@ static __always_inline const uint64_t *__attribute__(( (void)(ptr); \ \ } while (0) + #endif #endif /* prefetch */ diff --git a/include/xxhash.h b/include/xxhash.h index 7697d0f2..991a8f1e 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -1734,7 +1734,7 @@ XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t *src); * These declarations should only be used with static linking. * Never use them in association with dynamic linking! ***************************************************************************** -*/ + */ /* * These definitions are only present to allow static allocation @@ -2399,9 +2399,9 @@ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed( #define XXH_NO_STREAM #undef XXH_NO_STREAM /* don't actually */ #endif /* XXH_DOXYGEN */ -/*! - * @} - */ + /*! + * @} + */ #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command \ line for example */ @@ -2614,6 +2614,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) { _Static_assert((c), m); \ \ } while (0) + #elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ #define XXH_STATIC_ASSERT_WITH_MESSAGE(c, m) \ do { \ @@ -2621,6 +2622,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) { static_assert((c), m); \ \ } while (0) + #else #define XXH_STATIC_ASSERT_WITH_MESSAGE(c, m) \ do { \ @@ -2632,6 +2634,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) { }; \ \ } while (0) + #endif #define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c), #c) #endif @@ -2850,7 +2853,7 @@ static int XXH_isLittleEndian(void) { return one.c[0]; } -\ + #define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() #endif #endif @@ -4679,6 +4682,7 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) { acc = svadd_u64_x(mask, acc, mul); \ \ } while (0) + #endif /* XXH_VECTOR == XXH_SVE */ /* prefetch @@ -4737,12 +4741,14 @@ static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { }; -static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< - 0b0001011001010110011001111001000110011110001101110111100111111001 - */ -static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< - 0b1001111110110010000111000110010100011110100110001101111100100101 - */ +static const xxh_u64 PRIME_MX1 = + 0x165667919E3779F9ULL; /*!< + 0b0001011001010110011001111001000110011110001101110111100111111001 + */ +static const xxh_u64 PRIME_MX2 = + 0x9FB21C651E98DF25ULL; /*!< + 0b1001111110110010000111000110010100011110100110001101111100100101 + */ #ifdef XXH_OLD_NAMES #define kSecret XXH3_kSecret @@ -7854,7 +7860,7 @@ XXH3_128bits_digest(XXH_NOESCAPE const XXH3_state_t *state) { } #endif /* !XXH_NO_STREAM */ - /* 128-bit utility functions */ + /* 128-bit utility functions */ #include /* memcmp, memcpy */ diff --git a/instrumentation/afl-gcc-cmptrs-pass.so.cc b/instrumentation/afl-gcc-cmptrs-pass.so.cc index 929a9d7a..96bd5ba8 100644 --- a/instrumentation/afl-gcc-cmptrs-pass.so.cc +++ b/instrumentation/afl-gcc-cmptrs-pass.so.cc @@ -180,19 +180,19 @@ struct afl_cmptrs_pass : afl_base_pass { c = DECL_CONTEXT(c); if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false; - /* Check that the first nonstatic data member of the record type + /* Check that the first nonstatic named data member of the record type is named _M_dataplus. */ for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c)) - if (TREE_CODE(c) == FIELD_DECL) break; + if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break; if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) || strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0) return false; - /* Check that the second nonstatic data member of the record type + /* Check that the second nonstatic named data member of the record type is named _M_string_length. */ tree f2; for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2)) - if (TREE_CODE(f2) == FIELD_DECL) break; + if (TREE_CODE(f2) == FIELD_DECL && DECL_NAME(f2)) break; if (!f2 /* No need to check this field's offset. */ || strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0) return false; @@ -208,9 +208,12 @@ struct afl_cmptrs_pass : afl_base_pass { strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0) return false; - /* And its first data member is named _M_p. */ + /* And its first nonstatic named data member should be named _M_p. + There may be (unnamed) subobjects from empty base classes. We + skip the subobjects, then check the offset of the first data + member. */ for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c)) - if (TREE_CODE(c) == FIELD_DECL) break; + if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break; if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) || strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0) return false; diff --git a/src/afl-cc.c b/src/afl-cc.c index 6aa0da6a..faa46103 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -828,7 +828,8 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) { } if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX; - if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX")) + if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || + getenv("AFL_LLVM_LTO_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER; if (getenv("AFL_LLVM_NGRAM_SIZE")) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 08f716fa..443d93b0 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -2493,17 +2493,15 @@ int main(int argc, char **argv_orig, char **envp) { for (entry = 0; entry < afl->queued_items; ++entry) if (!afl->queue_buf[entry]->disabled) - if ((afl->queue_buf[entry]->exec_us/1000) > max_ms) - max_ms = afl->queue_buf[entry]->exec_us/1000; - + if ((afl->queue_buf[entry]->exec_us / 1000) > max_ms) + max_ms = afl->queue_buf[entry]->exec_us / 1000; + // Add 20% as a safety margin, capped to exec_tmout given in -t option max_ms *= 1.2; - if(max_ms > afl->fsrv.exec_tmout) - max_ms = afl->fsrv.exec_tmout; - + if (max_ms > afl->fsrv.exec_tmout) max_ms = afl->fsrv.exec_tmout; + // Ensure that there is a sensible timeout even for very fast binaries - if(max_ms < 5) - max_ms = 5; + if (max_ms < 5) max_ms = 5; afl->fsrv.exec_tmout = max_ms; afl->timeout_given = 1; -- cgit 1.4.1 From 45603367bfb71948f56715ac88e34c05c0dc0486 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 7 Apr 2024 09:44:33 +0200 Subject: fix llvm modules --- docs/Changelog.md | 1 + instrumentation/SanitizerCoverageLTO.so.cc | 9 +++++-- instrumentation/afl-llvm-dict2file.so.cc | 2 +- instrumentation/afl-llvm-pass.so.cc | 10 ++++---- instrumentation/cmplog-instructions-pass.cc | 9 ++++--- instrumentation/cmplog-routines-pass.cc | 12 ++++----- instrumentation/cmplog-switches-pass.cc | 12 ++++----- instrumentation/compare-transform-pass.so.cc | 27 ++++++++++++++------ instrumentation/injection-pass.cc | 17 +++++++------ instrumentation/split-compares-pass.so.cc | 37 +++++++++++++--------------- instrumentation/split-switches-pass.so.cc | 17 +++++++------ src/afl-cc.c | 7 ++++++ 12 files changed, 95 insertions(+), 65 deletions(-) (limited to 'src/afl-cc.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 70f4e375..72e20a18 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -29,6 +29,7 @@ - added collision free caller instrumentation to LTO mode. activate with `AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0) + - fixes for COMPCOV/LAF and most other modules - fix for GCC_PLUGIN cmplog that broke on std::strings - afl-whatsup: - now also displays current average speed diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 43c6ca40..4518c1c7 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -341,7 +341,7 @@ llvmGetPassPluginInfo() { using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif #if LLVM_VERSION_MAJOR >= 15 - PB.registerFullLinkTimeOptimizationLastEPCallback( + PB.registerFullLinkTimeOptimizationEarlyEPCallback( #else PB.registerOptimizerLastEPCallback( #endif @@ -1304,7 +1304,12 @@ u32 countCallers(Function *F) { for (auto *U : F->users()) { - if (auto *CI = dyn_cast(U)) { ++callers; } + if (auto *CI = dyn_cast(U)) { + + ++callers; + (void)(CI); + + } } diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index ac497b5b..b93f61f0 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -746,7 +746,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { auto PA = PreservedAnalyses::all(); return PA; #else - return true; + return false; #endif } diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 62f5023d..75b8532b 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -128,7 +128,11 @@ llvmGetPassPluginInfo() { #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif + #if LLVM_VERSION_MAJOR >= 16 + PB.registerOptimizerEarlyEPCallback( + #else PB.registerOptimizerLastEPCallback( + #endif [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(AFLCoverage()); @@ -212,10 +216,6 @@ bool AFLCoverage::runOnModule(Module &M) { u32 rand_seed; unsigned int cur_loc = 0; -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif - /* Setup random() so we get Actually Random(TM) outputs from AFL_R() */ gettimeofday(&tv, &tz); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); @@ -1081,7 +1081,7 @@ bool AFLCoverage::runOnModule(Module &M) { } #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - return PA; + return PreservedAnalyses(); #else return true; #endif diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index dc60221e..fe5c2926 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -680,13 +680,16 @@ bool CmpLogInstructions::runOnModule(Module &M) { printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; - hookInstrs(M); + bool ret = hookInstrs(M); verifyModule(M); #if LLVM_MAJOR >= 11 /* use new pass manager */ - return PreservedAnalyses::all(); + if (ret == false) + return PreservedAnalyses::all(); + else + return PreservedAnalyses(); #else - return true; + return ret; #endif } diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 78317d5d..560bd73b 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -758,16 +758,16 @@ bool CmpLogRoutines::runOnModule(Module &M) { printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; - hookRtns(M); -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif + bool ret = hookRtns(M); verifyModule(M); #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - return PA; + if (ret == false) + return PreservedAnalyses::all(); + else + return PreservedAnalyses(); #else - return true; + return ret; #endif } diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 3e05c13d..2b87ea8c 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -442,16 +442,16 @@ bool CmplogSwitches::runOnModule(Module &M) { printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n"); else be_quiet = 1; - hookInstrs(M); -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif + bool ret = hookInstrs(M); verifyModule(M); #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - return PA; + if (ret == false) + return PreservedAnalyses::all(); + else + return PreservedAnalyses(); #else - return true; + return ret; #endif } diff --git a/instrumentation/compare-transform-pass.so.cc b/instrumentation/compare-transform-pass.so.cc index b0d6355a..f8ba9de5 100644 --- a/instrumentation/compare-transform-pass.so.cc +++ b/instrumentation/compare-transform-pass.so.cc @@ -89,7 +89,7 @@ class CompareTransform : public ModulePass { #endif - return "cmplog transform"; + return "compcov transform"; } @@ -123,7 +123,11 @@ llvmGetPassPluginInfo() { #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif + #if LLVM_VERSION_MAJOR >= 16 + PB.registerOptimizerEarlyEPCallback( + #else PB.registerOptimizerLastEPCallback( + #endif [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(CompareTransform()); @@ -746,6 +750,8 @@ bool CompareTransform::runOnModule(Module &M) { #endif + bool ret = false; + if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) printf( "Running compare-transform-pass by laf.intel@gmail.com, extended by " @@ -753,11 +759,7 @@ bool CompareTransform::runOnModule(Module &M) { else be_quiet = 1; -#if LLVM_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif - - transformCmps(M, true, true, true, true, true); + if (transformCmps(M, true, true, true, true, true) == true) ret = true; verifyModule(M); #if LLVM_MAJOR >= 11 /* use new pass manager */ @@ -767,9 +769,18 @@ bool CompareTransform::runOnModule(Module &M) { }*/ - return PA; + if (ret == true) { + + return PreservedAnalyses(); + + } else { + + return PreservedAnalyses::all(); + + } + #else - return true; + return ret; #endif } diff --git a/instrumentation/injection-pass.cc b/instrumentation/injection-pass.cc index 2280208b..47ddabd9 100644 --- a/instrumentation/injection-pass.cc +++ b/instrumentation/injection-pass.cc @@ -204,6 +204,8 @@ bool InjectionRoutines::hookRtns(Module &M) { Function *FuncPtr; #endif + bool ret = false; + /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { @@ -281,6 +283,7 @@ bool InjectionRoutines::hookRtns(Module &M) { IRBuilder<> IRB(callInst->getParent()); IRB.SetInsertPoint(callInst); + ret = true; Value *parameter = callInst->getArgOperand(param); @@ -299,7 +302,7 @@ bool InjectionRoutines::hookRtns(Module &M) { } - return true; + return ret; } @@ -328,16 +331,16 @@ bool InjectionRoutines::runOnModule(Module &M) { if (getenv("AFL_LLVM_INJECTIONS_LDAP")) { doLDAP = true; } if (getenv("AFL_LLVM_INJECTIONS_XSS")) { doXSS = true; } - hookRtns(M); -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif + bool ret = hookRtns(M); verifyModule(M); #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - return PA; + if (ret == false) + return PreservedAnalyses::all(); + else + return PreservedAnalyses(); #else - return true; + return ret; #endif } diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 144025fb..421a7c39 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -189,7 +189,11 @@ llvmGetPassPluginInfo() { #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif + #if LLVM_VERSION_MAJOR >= 16 + PB.registerOptimizerEarlyEPCallback( + #else PB.registerOptimizerLastEPCallback( + #endif [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(SplitComparesTransform()); @@ -935,7 +939,7 @@ size_t SplitComparesTransform::nextPowerOfTwo(size_t in) { /* splits fcmps into two nested fcmps with sign compare and the rest */ size_t SplitComparesTransform::splitFPCompares(Module &M) { - size_t count = 0; + size_t counts = 0; LLVMContext &C = M.getContext(); @@ -951,7 +955,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } else { - return count; + return counts; } @@ -1004,7 +1008,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { } - if (!fcomps.size()) { return count; } + if (!fcomps.size()) { return counts; } IntegerType *Int1Ty = IntegerType::getInt1Ty(C); @@ -1690,11 +1694,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { #else ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN); #endif - ++count; + ++counts; } - return count; + return counts; } @@ -1743,10 +1747,6 @@ bool SplitComparesTransform::runOnModule(Module &M) { } -#if LLVM_MAJOR >= 11 - auto PA = PreservedAnalyses::all(); -#endif - if (enableFPSplit) { simplifyFPCompares(M); @@ -1778,15 +1778,7 @@ bool SplitComparesTransform::runOnModule(Module &M) { auto op0 = CI->getOperand(0); auto op1 = CI->getOperand(1); - if (!op0 || !op1) { - -#if LLVM_MAJOR >= 11 - return PA; -#else - return false; -#endif - - } + if (!op0 || !op1) { continue; } auto iTy1 = dyn_cast(op0->getType()); if (iTy1 && isa(op1->getType())) { @@ -1814,6 +1806,8 @@ bool SplitComparesTransform::runOnModule(Module &M) { } + bool ret = count == 0 ? false : true; + bool brokenDebug = false; if (verifyModule(M, &errs() #if LLVM_VERSION_MAJOR >= 4 || \ @@ -1852,9 +1846,12 @@ bool SplitComparesTransform::runOnModule(Module &M) { }*/ - return PA; + if (ret == false) + return PreservedAnalyses::all(); + else + return PreservedAnalyses(); #else - return true; + return ret; #endif } diff --git a/instrumentation/split-switches-pass.so.cc b/instrumentation/split-switches-pass.so.cc index e3dfea0d..aa552a42 100644 --- a/instrumentation/split-switches-pass.so.cc +++ b/instrumentation/split-switches-pass.so.cc @@ -137,7 +137,11 @@ llvmGetPassPluginInfo() { #if LLVM_VERSION_MAJOR <= 13 using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif + #if LLVM_VERSION_MAJOR >= 16 + PB.registerOptimizerEarlyEPCallback( + #else PB.registerOptimizerLastEPCallback( + #endif [](ModulePassManager &MPM, OptimizationLevel OL) { MPM.addPass(SplitSwitchesTransform()); @@ -516,11 +520,7 @@ bool SplitSwitchesTransform::runOnModule(Module &M) { else be_quiet = 1; -#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ - auto PA = PreservedAnalyses::all(); -#endif - - splitSwitches(M); + bool ret = splitSwitches(M); verifyModule(M); #if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ @@ -530,9 +530,12 @@ bool SplitSwitchesTransform::runOnModule(Module &M) { }*/ - return PA; + if (ret == false) + return PreservedAnalyses::all(); + else + return PreservedAnalyses(); #else - return true; + return ret; #endif } diff --git a/src/afl-cc.c b/src/afl-cc.c index faa46103..45fd398b 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1369,6 +1369,13 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { } + if (getenv("AFL_LLVM_DICT2FILE") && + (getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") || + getenv("AFL_LLVM_LAF_SPLIT_COMPARES") || + getenv("AFL_LLVM_LAF_SPLIT_FLOATS") || + getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES"))) + FATAL("AFL_LLVM_DICT2FILE is incompatible with AFL_LLVM_LAF_*"); + aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") || getenv("AFL_GCC_CMPLOG"); -- cgit 1.4.1 From d84cc73d1350409b13c035da1179d7fd270041c8 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Tue, 16 Apr 2024 14:15:32 +0700 Subject: afl-cc: Add missing debug statement For each path that is tried, there's a debug log printed, _except_ for this one. Fix it. --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 45fd398b..5c059be2 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -464,6 +464,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) { *slash = 0; tmp = alloc_printf("%s/%s", exepath, obj); + if (aflcc->debug) DEBUGF("Trying %s\n", tmp); + if (!access(tmp, R_OK)) { return tmp; } ck_free(tmp); -- cgit 1.4.1 From 626a4434edc5c0cb381779f7e13d1b54c1ed1738 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Tue, 16 Apr 2024 15:10:51 +0700 Subject: afl-cc: Use afl-as (rather than as) to find obj path --- src/afl-cc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 5c059be2..15e0fcc7 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2475,9 +2475,9 @@ void add_runtime(aflcc_state_t *aflcc) { */ void add_assembler(aflcc_state_t *aflcc) { - u8 *afl_as = find_object(aflcc, "as"); + u8 *afl_as = find_object(aflcc, "afl-as"); - if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as')."); + if (!afl_as) FATAL("Cannot find 'afl-as'."); u8 *slash = strrchr(afl_as, '/'); if (slash) *slash = 0; -- cgit 1.4.1 From 50839cf6e92c5f518ee2045452e7ff7a522c4d6f Mon Sep 17 00:00:00 2001 From: Sonic <50692172+SonicStark@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:34:14 +0700 Subject: afl-cc: Complete fix for afl-as Look for afl-as, and then make sure that there's a 'as' binary in the same directory, that seems to be either a symlink to, or a copy of, afl-as. --- src/afl-cc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 15e0fcc7..dd4fb4ea 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -17,6 +17,10 @@ #define AFL_MAIN +#ifndef _GNU_SOURCE + #define _GNU_SOURCE 1 +#endif + #include "common.h" #include "config.h" #include "types.h" @@ -32,7 +36,9 @@ #include #include #include +#include #include +#include #if (LLVM_MAJOR - 0 == 0) #undef LLVM_MAJOR @@ -520,7 +526,7 @@ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; #if defined(__x86_64__) - if ((ptr = find_object(aflcc, "as")) != NULL) { + if ((ptr = find_object(aflcc, "afl-as")) != NULL) { #ifndef __APPLE__ // on OSX clang masquerades as GCC @@ -2482,6 +2488,53 @@ void add_assembler(aflcc_state_t *aflcc) { u8 *slash = strrchr(afl_as, '/'); if (slash) *slash = 0; + // Search for 'as' may be unreliable in some cases (see #2058) + // so use 'afl-as' instead, because 'as' is usually a symbolic link, + // or can be a renamed copy of 'afl-as' created in the same dir. + // Now we should verify if the compiler can find the 'as' we need. + +#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')" + + u8 *afl_as_dup = alloc_printf("%s/as", afl_as); + + int fd = open(afl_as_dup, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); } + + struct stat st; + if (fstat(fd, &st) < 0) { + + PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup); + + } + + u32 f_len = st.st_size; + + u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + if (f_data == MAP_FAILED) { + + PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup); + + } + + close(fd); + + // "AFL_AS" is a const str passed to getenv in afl-as.c + if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) { + + FATAL( + "Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. " + "It is a prerequisite to override system-wide 'as' for " + "instrumentation.", + afl_as_dup, afl_as); + + } + + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } + + ck_free(afl_as_dup); + +#undef AFL_AS_ERR + insert_param(aflcc, "-B"); insert_param(aflcc, afl_as); -- cgit 1.4.1 From 58206a3180479416e14ea324607be71ee69caa6f Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Wed, 17 Apr 2024 14:40:41 -0400 Subject: Set explicit visibility on shared memory variables. --- src/afl-cc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index dd4fb4ea..57089ae0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1591,8 +1591,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) { insert_param(aflcc, "-D__AFL_FUZZ_INIT()=" "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int *__afl_fuzz_len;" - "extern unsigned char *__afl_fuzz_ptr;" + "extern __attribute__((visibility(\"default\"))) " + "unsigned int *__afl_fuzz_len;" + "extern __attribute__((visibility(\"default\"))) " + "unsigned char *__afl_fuzz_ptr;" "unsigned char __afl_fuzz_alt[1048576];" "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;"); -- cgit 1.4.1 From 476aca5b67f2926f0cdc7c50e9669e68cad9a851 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Apr 2024 15:45:00 +0200 Subject: nits --- include/afl-as.h | 2 +- include/afl-prealloc.h | 2 +- include/alloc-inl.h | 2 +- include/cmplog.h | 2 +- include/common.h | 2 +- include/debug.h | 2 +- include/forkserver.h | 2 +- include/list.h | 2 +- include/sharedmem.h | 2 +- include/snapshot-inl.h | 2 +- include/types.h | 2 +- instrumentation/split-compares-pass.so.cc | 4 ++-- src/afl-analyze.c | 2 +- src/afl-as.c | 2 +- src/afl-cc.c | 8 ++++---- src/afl-common.c | 2 +- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-extras.c | 2 +- src/afl-fuzz-init.c | 2 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 2 +- src/afl-fuzz-python.c | 2 +- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 2 +- src/afl-fuzz-run.c | 5 ++--- src/afl-fuzz-state.c | 2 +- src/afl-fuzz-stats.c | 9 +++++---- src/afl-gotcpu.c | 2 +- src/afl-ld-lto.c | 2 +- src/afl-sharedmem.c | 2 +- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- 34 files changed, 43 insertions(+), 43 deletions(-) (limited to 'src/afl-cc.c') diff --git a/include/afl-as.h b/include/afl-as.h index 612f34f4..c005d43d 100644 --- a/include/afl-as.h +++ b/include/afl-as.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index 3c621d79..bcccb6b4 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 0aa417be..dad0652f 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/cmplog.h b/include/cmplog.h index a6162b59..a4449a60 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/common.h b/include/common.h index 0df07dee..a78dd60a 100644 --- a/include/common.h +++ b/include/common.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/debug.h b/include/debug.h index 4b812f8e..5496135c 100644 --- a/include/debug.h +++ b/include/debug.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/forkserver.h b/include/forkserver.h index be7f9e8d..68907376 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier > diff --git a/include/list.h b/include/list.h index 441eccd3..bec9abbc 100644 --- a/include/list.h +++ b/include/list.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/sharedmem.h b/include/sharedmem.h index 4484066e..036fa560 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h index b2c81402..e577b013 100644 --- a/include/snapshot-inl.h +++ b/include/snapshot-inl.h @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/include/types.h b/include/types.h index 18c5df91..cfb2f3d5 100644 --- a/include/types.h +++ b/include/types.h @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt , + Heiko Eissfeldt , Andrea Fioraldi , Dominik Maier diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 421a7c39..728ebc22 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -1,7 +1,7 @@ /* * Copyright 2016 laf-intel - * extended for floating point by Heiko Eißfeldt - * adapted to new pass manager by Heiko Eißfeldt + * extended for floating point by Heiko Eissfeldt + * adapted to new pass manager by Heiko Eissfeldt * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 95f32fee..d089cd08 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-as.c b/src/afl-as.c index 09ba75bf..d4ddb94d 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-cc.c b/src/afl-cc.c index 57089ae0..202e8145 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2490,10 +2490,10 @@ void add_assembler(aflcc_state_t *aflcc) { u8 *slash = strrchr(afl_as, '/'); if (slash) *slash = 0; - // Search for 'as' may be unreliable in some cases (see #2058) - // so use 'afl-as' instead, because 'as' is usually a symbolic link, - // or can be a renamed copy of 'afl-as' created in the same dir. - // Now we should verify if the compiler can find the 'as' we need. + // Search for 'as' may be unreliable in some cases (see #2058) + // so use 'afl-as' instead, because 'as' is usually a symbolic link, + // or can be a renamed copy of 'afl-as' created in the same dir. + // Now we should verify if the compiler can find the 'as' we need. #define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')" diff --git a/src/afl-common.c b/src/afl-common.c index 6d915b00..d86b431b 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index f28a2a64..149a973e 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index d8561dde..5d4d80af 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 21f34e12..8c48eb49 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index c06896ef..55b6be04 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 21a8ba7e..2a8267cc 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index ae4d6668..2f6af4bc 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -5,7 +5,7 @@ Originally written by Shengtuo Hu Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Dominik Maier diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index d9c074ec..74bb8cbc 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 16a398fd..873b25e2 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 1ea50418..df4e7d79 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index be41d6c4..100b0dd6 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index edcddc8e..ab96c778 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier @@ -829,8 +829,7 @@ void sync_fuzzers(afl_state_t *afl) { if (afl->stop_soon) { goto close_sync; } afl->syncing_party = sd_ent->d_name; - afl->queued_imported += - save_if_interesting(afl, mem, new_len, fault); + afl->queued_imported += save_if_interesting(afl, mem, new_len, fault); afl->syncing_party = 0; munmap(mem, st.st_size); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index c61f00bd..c21ae6be 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 7e1a3b92..755e1c50 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -5,8 +5,9 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and - Andrea Fioraldi + Dominik Meier , + Andrea Fioraldi , and + Heiko Eissfeldt Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2024 AFLplusplus Project. All rights reserved. @@ -382,8 +383,8 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, ? 0 : (cur_time - afl->last_find_time) / 1000), (runtime - - (afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / - 1000) / + ((afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / + 1000)) / 1000, afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000, afl->trim_time_us / 1000000, afl->fsrv.total_execs, diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 7aee2985..6a3bd037 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -5,7 +5,7 @@ Originally written by Michal Zalewski Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 513c1ae9..578552ba 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -5,7 +5,7 @@ Written by Marc Heuse for AFL++ Maintained by Marc Heuse , - Heiko Eißfeldt + Heiko Eissfeldt Andrea Fioraldi Dominik Maier diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index daea8f46..8f685633 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi Copyright 2016, 2017 Google Inc. All rights reserved. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 20ba5a5e..07a4844a 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 994174ed..23e0ff13 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -7,7 +7,7 @@ Forkserver design by Jann Horn Now maintained by Marc Heuse , - Heiko Eißfeldt and + Heiko Eissfeldt and Andrea Fioraldi and Dominik Maier -- cgit 1.4.1 From 458b939bc4f0ed4016c2741529435a72283ffc74 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 19 Apr 2024 17:34:50 +0200 Subject: LTO fix --- docs/Changelog.md | 3 ++- instrumentation/SanitizerCoverageLTO.so.cc | 2 +- src/afl-cc.c | 5 ----- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src/afl-cc.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index a7eb239b..4e34baea 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -4,7 +4,8 @@ release of the tool. See README.md for the general instruction manual. ### Version ++4.21a (dev) - * your PR? :-) + * afl-cc: + - fixes for LTO and outdated afl-gcc mode ### Version ++4.20c (release) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 4518c1c7..14482deb 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -341,7 +341,7 @@ llvmGetPassPluginInfo() { using OptimizationLevel = typename PassBuilder::OptimizationLevel; #endif #if LLVM_VERSION_MAJOR >= 15 - PB.registerFullLinkTimeOptimizationEarlyEPCallback( + PB.registerFullLinkTimeOptimizationLastEPCallback( #else PB.registerOptimizerLastEPCallback( #endif diff --git a/src/afl-cc.c b/src/afl-cc.c index 202e8145..15a5bd8e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1269,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) { aflcc->instrument_mode == INSTRUMENT_PCGUARD) { aflcc->lto_mode = 1; - // force CFG - // if (!aflcc->instrument_mode) { - aflcc->instrument_mode = INSTRUMENT_PCGUARD; - // } - } else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) { aflcc->lto_mode = 1; -- cgit 1.4.1 From 5d623a27edcd4e6608178f80c7e29ede73138db6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 30 Apr 2024 11:59:42 +0200 Subject: try enhanced asan support --- src/afl-cc.c | 8 +++++++- src/afl-common.c | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 15a5bd8e..fa3318de 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1911,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } add_defs_fortify(aflcc, 0); - if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); } + 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) { diff --git a/src/afl-common.c b/src/afl-common.c index d86b431b..9a27824d 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -108,9 +108,10 @@ void set_sanitizer_defaults() { u8 *have_lsan_options = getenv("LSAN_OPTIONS"); u8 have_san_options = 0; u8 default_options[1024] = - "detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_" - "return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_" - "sigfpe=0:handle_sigill=0:"; + "detect_odr_violation=0:abort_on_error=1:symbolize=0:" + "allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:" + "handle_abort=0:handle_sigfpe=0:handle_sigill=0:" + "detect_stack_use_after_return=0:check_initialization_order=0:"; if (have_asan_options || have_ubsan_options || have_msan_options || have_lsan_options) { -- cgit 1.4.1 From 4d4880b428c485a33eed924a488dc7c3542dbcf4 Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Fri, 10 May 2024 23:45:46 +0700 Subject: afl-cc: Re-enable i386 Was disabled in 136febaf6855ac1e04c8ea4ecbcb84eb42de2143 Closes: #2081 --- src/afl-cc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index fa3318de..7acee8e4 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -525,7 +525,7 @@ void find_built_deps(aflcc_state_t *aflcc) { char *ptr = NULL; -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__i386__) if ((ptr = find_object(aflcc, "afl-as")) != NULL) { #ifndef __APPLE__ -- cgit 1.4.1 From ba7ae6c59d52d4a007fe53f415106277ae68b067 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 16 May 2024 14:21:00 +0200 Subject: nits --- src/afl-cc.c | 10 +++++----- src/afl-fuzz-run.c | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index 7acee8e4..c872b2eb 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -2794,11 +2794,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { "MODES: NCC PERSIST DICT LAF " "CMPLOG SELECT\n" " [LLVM] LLVM: %s%s\n" - " PCGUARD %s yes yes module yes yes " + " PCGUARD %s yes yes module yes yes " "yes\n" " NATIVE AVAILABLE no yes no no " "part. yes\n" - " CLASSIC %s no yes module yes yes " + " CLASSIC %s no yes module yes yes " "yes\n" " - NORMAL\n" " - CALLER\n" @@ -2815,10 +2815,10 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " [GCC/CLANG] simple gcc/clang: %s%s\n" " CLASSIC DEFAULT no no no no no " "no\n\n", - aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE " : "unavailable!", aflcc->compiler_mode == LLVM ? " [SELECTED]" : "", - aflcc->have_llvm ? "AVAILABLE" : "unavailable!", - aflcc->have_llvm ? "AVAILABLE" : "unavailable!", + aflcc->have_llvm ? "AVAILABLE " : "unavailable!", + aflcc->have_llvm ? "AVAILABLE " : "unavailable!", aflcc->have_lto ? "AVAILABLE" : "unavailable!", aflcc->compiler_mode == LTO ? " [SELECTED]" : "", aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!", diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 2a55da00..4e2cceff 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -606,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } q->exec_us = diff_us / afl->stage_max; + if (unlikely(!q->exec_us)) { q->exec_us = 1; } + q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits); q->handicap = handicap; q->cal_failed = 0; -- cgit 1.4.1