diff options
-rw-r--r-- | examples/custom_mutators/example.c | 36 | ||||
-rw-r--r-- | include/envs.h | 35 | ||||
-rw-r--r-- | llvm_mode/Makefile | 5 | ||||
-rw-r--r-- | llvm_mode/README.lto.md | 82 | ||||
-rw-r--r-- | llvm_mode/afl-clang-fast.c | 120 | ||||
-rw-r--r-- | llvm_mode/afl-ld.c | 98 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-lto-instrumentation.so.cc | 52 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-tcg-runtime-inl.h | 11 | ||||
-rw-r--r-- | src/afl-fuzz-globals.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 7 | ||||
-rw-r--r-- | src/afl-fuzz-mutators.c | 39 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 30 | ||||
-rw-r--r-- | src/afl-fuzz-python.c | 34 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz.c | 6 | ||||
-rw-r--r-- | src/afl-showmap.c | 5 | ||||
-rw-r--r-- | src/afl-tmin.c | 42 | ||||
-rwxr-xr-x | test/test.sh | 28 |
18 files changed, 386 insertions, 248 deletions
diff --git a/examples/custom_mutators/example.c b/examples/custom_mutators/example.c index 178d39b3..127f971e 100644 --- a/examples/custom_mutators/example.c +++ b/examples/custom_mutators/example.c @@ -38,18 +38,17 @@ void afl_custom_init(unsigned int seed) { * produce data larger than max_size. * @return Size of the mutated output. */ -size_t afl_custom_fuzz(uint8_t **buf, size_t buf_size, - uint8_t *add_buf,size_t add_buf_size, // add_buf can be NULL +size_t afl_custom_fuzz(uint8_t **buf, size_t buf_size, uint8_t *add_buf, + size_t add_buf_size, // add_buf can be NULL size_t max_size) { // Make sure that the packet size does not exceed the maximum size expected by // the fuzzer size_t mutated_size = data_size <= max_size ? data_size : max_size; - if (mutated_size > buf_size) - *buf = realloc(*buf, mutated_size); - - uint8_t* mutated_out = *buf; + if (mutated_size > buf_size) *buf = realloc(*buf, mutated_size); + + uint8_t *mutated_out = *buf; // Randomly select a command string to add as a header to the packet memcpy(mutated_out, commands[rand() % 3], 3); @@ -94,9 +93,9 @@ size_t afl_custom_pre_save(uint8_t *buf, size_t buf_size, uint8_t **out_buf) { } static uint8_t *trim_buf; -static size_t trim_buf_size; -static int trimmming_steps; -static int cur_step; +static size_t trim_buf_size; +static int trimmming_steps; +static int cur_step; /** * This method is called at the start of each trimming operation and receives @@ -147,7 +146,7 @@ int afl_custom_init_trim(uint8_t *buf, size_t buf_size) { * the memory after saving the test case. * @param[out] out_buf_size Pointer to the size of the trimmed test case */ -void afl_custom_trim(uint8_t **out_buf, size_t* out_buf_size) { +void afl_custom_trim(uint8_t **out_buf, size_t *out_buf_size) { *out_buf_size = trim_buf_size - 1; @@ -172,8 +171,10 @@ void afl_custom_trim(uint8_t **out_buf, size_t* out_buf_size) { int afl_custom_post_trim(int success) { if (success) { + ++cur_step; return cur_step; + } return trimmming_steps; @@ -193,7 +194,8 @@ int afl_custom_post_trim(int success) { * not produce data larger than max_size. * @return Size of the mutated output. */ -size_t afl_custom_havoc_mutation(uint8_t** buf, size_t buf_size, size_t max_size) { +size_t afl_custom_havoc_mutation(uint8_t **buf, size_t buf_size, + size_t max_size) { if (buf_size == 0) { @@ -205,7 +207,7 @@ size_t afl_custom_havoc_mutation(uint8_t** buf, size_t buf_size, size_t max_size size_t victim = rand() % buf_size; (*buf)[victim] += rand() % 10; - + return buf_size; } @@ -220,7 +222,7 @@ size_t afl_custom_havoc_mutation(uint8_t** buf, size_t buf_size, size_t max_size */ uint8_t afl_custom_havoc_mutation_probability(void) { - return 5; // 5 % + return 5; // 5 % } @@ -233,14 +235,14 @@ uint8_t afl_custom_havoc_mutation_probability(void) { * @return Return True(1) if the fuzzer will fuzz the queue entry, and * False(0) otherwise. */ -uint8_t afl_custom_queue_get(const uint8_t* filename) { +uint8_t afl_custom_queue_get(const uint8_t *filename) { return 1; } /** - * Allow for additional analysis (e.g. calling a different tool that does a + * Allow for additional analysis (e.g. calling a different tool that does a * different kind of coverage and saves this for the custom mutator). * * (Optional) @@ -248,8 +250,8 @@ uint8_t afl_custom_queue_get(const uint8_t* filename) { * @param filename_new_queue File name of the new queue entry * @param filename_orig_queue File name of the original queue entry */ -void afl_custom_queue_new_entry(const uint8_t* filename_new_queue, - const uint8_t* filename_orig_queue) { +void afl_custom_queue_new_entry(const uint8_t *filename_new_queue, + const uint8_t *filename_orig_queue) { /* Additional analysis on the original or new test case */ diff --git a/include/envs.h b/include/envs.h index fee74fd7..b131f406 100644 --- a/include/envs.h +++ b/include/envs.h @@ -1,11 +1,10 @@ const char *afl_environment_variables[] = { "AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", "AFL_AS", - "AFL_AUTORESUME", - "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE", "AFL_BENCH_UNTIL_CRASH", - "AFL_CAL_FAST", "AFL_CC", "AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", - "AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME", - "AFL_COMPCOV_LEVEL", "AFL_CUSTOM_MUTATOR_LIBRARY", + "AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE", + "AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CMIN_ALLOW_ANY", + "AFL_CMIN_CRASHES_ONLY", "AFL_CODE_END", "AFL_CODE_START", + "AFL_COMPCOV_BINNAME", "AFL_COMPCOV_LEVEL", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CXX", "AFL_DEBUG", "AFL_DEBUG_CHILD_OUTPUT", //"AFL_DEFER_FORKSRV", // not implemented anymore, so warn additionally "AFL_DISABLE_TRIM", "AFL_DONT_OPTIMIZE", "AFL_DUMB_FORKSRV", @@ -19,21 +18,19 @@ const char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", - "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", - "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", - "AFL_NO_UI", + "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", + "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally - "AFL_POST_LIBRARY", "AFL_PRELOAD", "AFL_PYTHON_MODULE", - "AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", - "AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_PERSISTENT_ADDR", - "AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR", - "AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_RET", - "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QUIET", - "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH", "AFL_SHUFFLE_QUEUE", - "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", - "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", - "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", - "AFL_WINE_PATH", NULL}; + "AFL_POST_LIBRARY", "AFL_PRELOAD", "AFL_PYTHON_MODULE", "AFL_QEMU_COMPCOV", + "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE", + "AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT", + "AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK", + "AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", + "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH", + "AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", + "AFL_SKIP_CRASHES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", + "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", + "AFL_USE_UBSAN", "AFL_WINE_PATH", NULL}; diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index a4c60ea4..b4746da3 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -136,7 +136,8 @@ override CFLAGS = -Wall \ -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I ../include/ \ -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \ - -DLLVM_VERSION=\"$(LLVMVER)\" -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" + -DLLVM_VERSION=\"$(LLVMVER)\" -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \ + -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" ifdef AFL_TRACE_PC CFLAGS += -DUSE_TRACE_PC=1 endif @@ -253,7 +254,7 @@ endif ../afl-ld: afl-ld.c ifneq "$(AFL_CLANG_FLTO)" "" ifeq "$(LLVM_LTO)" "1" - $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" + $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) ln -sf afl-ld ../ld @rm -f .test-instr @-export AFL_QUIET=1 AFL_PATH=.. PATH="..:$(PATH)" ; ../afl-clang-lto -Wl,--afl -o .test-instr ../test-instr.c && echo "[+] afl-clang-lto and afl-ld seem to work fine :)" || echo "[!] WARNING: clang seems to have a hardcoded "'/bin/ld'" - check README.lto" diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 2fe29069..66d0de79 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -2,13 +2,16 @@ ## TLDR; -1. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better +1. This compile mode is very frickle if it works it is amazing, if it fails + - well use afl-clang-fast + +2. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better coverage than anything else that is out there in the AFL world -2. You can use it together with llvm_mode: laf-intel and whitelisting +3. You can use it together with llvm_mode: laf-intel and whitelisting features and can be combined with cmplog/Redqueen -3. It only works with llvm 9 (and likely 10+ but is not tested there yet) +4. It only works with llvm 9 (and likely 10+ but is not tested there yet) ## Introduction and problem description @@ -100,6 +103,32 @@ need to link all llvm IR LTO files does not support this - yet (hopefully). Hence if you see this error either you have to remove the duplicate global variable (think `#ifdef` ...) or you are out of luck. :-( +### "expected top-level entity" + binary ouput error + +This happens if multiple .a archives are to be linked and they contain the +same object filenames, the first in LTO form, the other in ELF form. +This can not be fixed programmatically, but can be fixed by hand. +You can try to delete the file from either archive +(`llvm-ar d <archive>.a <file>.o`) or performing the llvm-linking, optimizing +and instrumentation by hand (see below). + +### "undefined reference to ..." + +This *can* be the opposite situation of the "expected top-level entity" error - +the library with the ELF file is before the LTO library. +However it can also be a bug in the program - try to compile it normally. If +fails then it is a bug in the program. +Solutions: You can try to delete the file from either archive, e.g. +(`llvm-ar d <archive>.a <file>.o`) or performing the llvm-linking, optimizing +and instrumentation by hand (see below). + +### "File format not recognized" + +This happens if the build system has fixed LDFLAGS, CPPFLAGS, CXXFLAGS and/or +CFLAGS. Ensure that they all contain the `-flto` flag that afl-clang-lto was +compiled with (you can see that by typing `afl-clang-lto -h` and inspecting +the last line of the help output) and add them otherwise + ### clang is hardcoded to /bin/ld Some clang packages have 'ld' hardcoded to /bin/ld. This is an issue as this @@ -129,6 +158,53 @@ This can result in two problems though: When you install an updated gcc/clang/... package, your OS might restore the ld link. +### Performing the steps by hand + +It is possible to perform all the steps afl-ld by hand to workaround issues +in the target. + +1. Recompile with AFL_DEBUG=1 and collect the afl-clang-lto command that fails + e.g.: `AFL_DEBUG=1 make 2>&1 | grep afl-clang-lto | tail -n 1` + +2. run this command prepended with AFL_DEBUG=1 and collect the afl-ld command + parameters, e.g. `AFL_DEBUG=1 afl-clang-lto[++] .... | grep /afl/ld` + +3. for every .a archive you want to instrument unpack it into a seperate + directory, e.g. + `mkdir archive1.dir ; cd archive1.dir ; llvm-link x ../<archive>.a` + +4. run `file archive*.dir/*.o` and make two lists, one containing all ELF files + and one containing all LLVM IR bitcode files. + You do the same for all .o files of the ../afl/ld command options + +5. Create a single bitcode file by using llvm-link, e.g. + `llvm-link -o all-bitcode.bc <list of all LLVM IR .o files>` + If this fails it is game over - or you modify the source code + +6. Run the optimizer on the new bitcode file: + `opt -O3 --polly -o all-optimized.bc all-bitcode.bc` + +7. Instrument the optimized bitcode file: + `opt --load=$AFL_PATH/afl-llvm-lto-instrumentation.so --disable-opt --afl-lto all-optimized.bc -o all-instrumented.bc + +8. If the parameter `--allow-multiple-definition` is not in the list, add it + as first command line option. + +9. Link everything together. + a) You use the afl-ld command and instead of e.g. `/usr/local/lib/afl/ld` + you replace that with `ld`, the real linker. + b) Every .a archive you instrumented files from you remove the <archive>.a + or -l<archive> from the command + c) If you have entries in your ELF files list (see step 4), you put them to + the command line - but them in the same order! + d) put the all-instrumented.bc before the first library or .o file + e) run the command and hope it compiles, if it doesn't you have to analyze + what the issue is and fix that in the approriate step above. + +Yes this is long and complicated. That is why there is afl-ld doing this and +that why this can easily fail and not all different ways how it *can* fail can +be implemented ... + ### compiling programs still fail afl-clang-lto is still work in progress. diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 4c4f802d..bd2579c0 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -291,11 +291,11 @@ static void edit_params(u32 argc, char** argv) { cc_params[cc_par_cnt++] = AFL_PATH; cc_params[cc_par_cnt++] = lto_flag; - + } else - if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") || - getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) { + 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++] = "-fsanitize-coverage=trace-pc-guard"; // edge coverage by default @@ -533,7 +533,7 @@ int main(int argc, char** argv, char** envp) { } - if (strstr(argv[0], "afl-clang-lto") == NULL) callname = "afl-clang-lto"; + if (strstr(argv[0], "afl-clang-lto") != NULL) callname = "afl-clang-lto"; if (argc < 2 || strcmp(argv[1], "-h") == 0) { @@ -554,55 +554,68 @@ int main(int argc, char** argv, char** envp) { #endif /* ^USE_TRACE_PC */ - SAYF( - "\n" - "%s[++] [options]\n" - "\n" - "This is a helper application for afl-fuzz. It serves as a drop-in " - "replacement\n" - "for clang, letting you recompile third-party code with the required " - "runtime\n" - "instrumentation. A common use pattern would be one of the " - "following:\n\n" - - " CC=%s/afl-clang-fast ./configure\n" - " CXX=%s/afl-clang-fast++ ./configure\n\n" - - "In contrast to the traditional afl-clang tool, this version is " - "implemented as\n" - "an LLVM pass and tends to offer improved performance with slow " - "programs.\n\n" - - "Environment variables used:\n" - "AFL_CC: path to the C compiler to use\n" - "AFL_CXX: path to the C++ compiler to use\n" - "AFL_PATH: path to instrumenting pass and runtime (afl-llvm-rt.*o)\n" - "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" - "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" - "AFL_INST_RATIO: percentage of branches to instrument\n" - "AFL_QUIET: suppress verbose output\n" - "AFL_DEBUG: enable developer debugging output\n" - "AFL_HARDEN: adds code hardening to catch memory bugs\n" - "AFL_USE_ASAN: activate address sanitizer\n" - "AFL_USE_MSAN: activate memory sanitizer\n" - "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" - "AFL_LLVM_WHITELIST: enable whitelisting (selective instrumentation)\n" - "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" - "AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" - "AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" - "AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n" - "AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison " - "function calls\n" - " to cascaded comparisons\n" - "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to cascaded " - "comp.\n" - "AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" - "AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" - "AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed\n" - "AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n" - "\nafl-clang-fast was built for llvm %s with the llvm binary path of " - "\"%s\".\n\n", - callname, BIN_PATH, BIN_PATH, LLVM_VERSION, LLVM_BINDIR); + SAYF( + "\n" + "%s[++] [options]\n" + "\n" + "This is a helper application for afl-fuzz. It serves as a drop-in " + "replacement\n" + "for clang, letting you recompile third-party code with the " + "required " + "runtime\n" + "instrumentation. A common use pattern would be one of the " + "following:\n\n" + + " CC=%s/afl-clang-fast ./configure\n" + " CXX=%s/afl-clang-fast++ ./configure\n\n" + + "In contrast to the traditional afl-clang tool, this version is " + "implemented as\n" + "an LLVM pass and tends to offer improved performance with slow " + "programs.\n\n" + + "Environment variables used:\n" + "AFL_CC: path to the C compiler to use\n" + "AFL_CXX: path to the C++ compiler to use\n" + "AFL_PATH: path to instrumenting pass and runtime " + "(afl-llvm-rt.*o)\n" + "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" + "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" + "AFL_INST_RATIO: percentage of branches to instrument\n" + "AFL_QUIET: suppress verbose output\n" + "AFL_DEBUG: enable developer debugging output\n" + "AFL_HARDEN: adds code hardening to catch memory bugs\n" + "AFL_USE_ASAN: activate address sanitizer\n" + "AFL_USE_MSAN: activate memory sanitizer\n" + "AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" + "AFL_LLVM_WHITELIST: enable whitelisting (selective " + "instrumentation)\n" + "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" + "AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" + "AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" + "AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n" + "AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison " + "function calls\n" + " to cascaded comparisons\n" + "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to " + "cascaded " + "comp.\n" + "AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" + "AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" + "AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed\n" + "AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n" + "\nafl-clang-fast was built for llvm %s with the llvm binary path " + "of " + "\"%s\".\n", + callname, BIN_PATH, BIN_PATH, LLVM_VERSION, LLVM_BINDIR); + + if (strcmp(callname, "afl-clang-lto") == 0) + SAYF( + "Compiled with linker target \"%s\" and LTO flags \"%s\"\n\n" + "If anything fails - be sure to read README.lto.md!\n\n", + AFL_REAL_LD, AFL_CLANG_FLTO); + + SAYF("\n"); exit(1); @@ -665,3 +678,4 @@ int main(int argc, char** argv, char** envp) { return 0; } + diff --git a/llvm_mode/afl-ld.c b/llvm_mode/afl-ld.c index 7cbf89dc..0e85795a 100644 --- a/llvm_mode/afl-ld.c +++ b/llvm_mode/afl-ld.c @@ -44,6 +44,8 @@ #include <dirent.h> +#define MAX_PARAM_COUNT 4096 + static u8 **ld_params, /* Parameters passed to the real 'ld' */ **link_params, /* Parameters passed to 'llvm-link' */ **opt_params, /* Parameters passed to 'opt' opt */ @@ -145,15 +147,21 @@ int is_llvm_file(const char* file) { int fd; u8 buf[5]; - if ((fd = open(file, O_RDONLY)) < 0) return 0; + if ((fd = open(file, O_RDONLY)) < 0) { + + if (debug) SAYF(cMGN "[D] " cRST "File %s not found", file); + return 0; - if (read(fd, buf, sizeof(buf)) != sizeof(buf)) return 0; + } + + if (read(fd, buf, 4) != 4) return 0; buf[sizeof(buf) - 1] = 0; close(fd); if (strncmp(buf, "; Mo", 4) == 0) return 1; - if (buf[0] == 'B' && buf[1] == 'C' && buf[2] == 0xC0 && buf[3] == 0xDE) + + if (buf[0] == 'B' && buf[1] == 'C' && buf[2] == 0xc0 && buf[3] == 0xde) return 1; return 0; @@ -186,7 +194,7 @@ int is_duplicate(u8** params, u32 ld_param_cnt, u8* ar_file) { static void edit_params(int argc, char** argv) { u32 i, have_lto = 0, libdir_index; - u8 libdir_file[4096]; + u8 libdir_file[4096]; if (tmp_dir == NULL) { @@ -204,13 +212,13 @@ static void edit_params(int argc, char** argv) { final_file = alloc_printf("%s/.afl-%u-%u-3.bc", tmp_dir, getpid(), (u32)time(NULL)); - ld_params = ck_alloc((argc + 4096) * sizeof(u8*)); - link_params = ck_alloc((argc + 4096) * sizeof(u8*)); + ld_params = ck_alloc(4096 * sizeof(u8*)); + link_params = ck_alloc(4096 * sizeof(u8*)); inst_params = ck_alloc(12 * sizeof(u8*)); opt_params = ck_alloc(12 * sizeof(u8*)); ld_params[0] = (u8*)real_ld; - ld_params[argc] = 0; + ld_params[ld_param_cnt++] = "--allow-multiple-definition"; link_params[0] = alloc_printf("%s/%s", LLVM_BINDIR, "llvm-link"); link_params[link_param_cnt++] = "-S"; // we create the linked file as .ll @@ -224,6 +232,7 @@ static void edit_params(int argc, char** argv) { opt_params[opt_param_cnt++] = "--polly"; } else + opt_params[opt_param_cnt++] = "-O0"; // opt_params[opt_param_cnt++] = "-S"; // only when debugging opt_params[opt_param_cnt++] = linked_file; // input: .ll file @@ -243,11 +252,16 @@ static void edit_params(int argc, char** argv) { // first we must collect all library search paths for (i = 1; i < argc; i++) if (strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == 'L') - libdirs[libdir_cnt++] = argv[i] + 2; + libdirs[libdir_cnt++] = argv[i] + 2; // then we inspect all options to the target linker for (i = 1; i < argc; i++) { + if (ld_param_cnt >= MAX_PARAM_COUNT || link_param_cnt >= MAX_PARAM_COUNT) + FATAL( + "Too many command line parameters because of unpacking .a archives, " + "this would need to be done by hand ... sorry! :-("); + if (strncmp(argv[i], "-flto", 5) == 0) have_lto = 1; if (!strcmp(argv[i], "-version")) { @@ -266,23 +280,26 @@ static void edit_params(int argc, char** argv) { exit(0); } - + // if a -l library is linked and no .so is found but an .a archive is there // then the archive will be used. So we have to emulate this and check // if an archive will be used and if yes we will instrument it too libdir_file[0] = 0; libdir_index = libdir_cnt; - if (strncmp(argv[i], "-l", 2) == 0 && libdir_cnt > 0 && strncmp(argv[i], "-lgcc", 5) != 0) { - + if (strncmp(argv[i], "-l", 2) == 0 && libdir_cnt > 0 && + strncmp(argv[i], "-lgcc", 5) != 0) { + u8 found = 0; - + for (uint32_t j = 0; j < libdir_cnt && !found; j++) { - snprintf(libdir_file, sizeof(libdir_file), "%s/lib%s%s", libdirs[j], argv[i] + 2, ".so"); - if (access(libdir_file, R_OK) != 0) { // no .so found? + snprintf(libdir_file, sizeof(libdir_file), "%s/lib%s%s", libdirs[j], + argv[i] + 2, ".so"); + if (access(libdir_file, R_OK) != 0) { // no .so found? - snprintf(libdir_file, sizeof(libdir_file), "%s/lib%s%s", libdirs[j], argv[i] + 2, ".a"); - if (access(libdir_file, R_OK) == 0) { // but .a found? + snprintf(libdir_file, sizeof(libdir_file), "%s/lib%s%s", libdirs[j], + argv[i] + 2, ".a"); + if (access(libdir_file, R_OK) == 0) { // but .a found? libdir_index = j; found = 1; @@ -294,16 +311,18 @@ static void edit_params(int argc, char** argv) { found = 1; if (debug) SAYF(cMGN "[D] " cRST "Found %s\n", libdir_file); - + } } - + } // is the parameter an .a AR archive? If so, unpack and check its files - if (libdir_index < libdir_cnt || (argv[i][0] != '-' && strlen(argv[i]) > 2 && - argv[i][strlen(argv[i]) - 1] == 'a' && argv[i][strlen(argv[i]) - 2] == '.')) { + if (libdir_index < libdir_cnt || + (argv[i][0] != '-' && strlen(argv[i]) > 2 && + argv[i][strlen(argv[i]) - 1] == 'a' && + argv[i][strlen(argv[i]) - 2] == '.')) { // This gets a bit odd. I encountered several .a files being linked and // where the same "foo.o" was in both .a archives. llvm-link does not @@ -317,8 +336,7 @@ static void edit_params(int argc, char** argv) { DIR* arx; struct dirent* dir_ent; - if (libdir_index < libdir_cnt) - file = libdir_file; + if (libdir_index < libdir_cnt) file = libdir_file; if (ar_dir_cnt == 0) { // first archive, we setup up the basics @@ -376,7 +394,7 @@ static void edit_params(int argc, char** argv) { if (dir_ent->d_name[strlen(dir_ent->d_name) - 1] == 'o' && dir_ent->d_name[strlen(dir_ent->d_name) - 2] == '.') { - if (passthrough || argv[i][0] == '-' || is_llvm_file(ar_file) == 0) { + if (passthrough || is_llvm_file(ar_file) == 0) { if (is_duplicate(ld_params, ld_param_cnt, ar_file) == 0) { @@ -428,7 +446,7 @@ static void edit_params(int argc, char** argv) { ld_params[ld_param_cnt++] = "-plugin-opt=O2"; else ld_params[ld_param_cnt++] = argv[i]; - + } else { if (we_link == 0) { // we have to honor order ... @@ -618,7 +636,11 @@ int main(int argc, char** argv) { edit_params(argc, argv); // here most of the magic happens :-) - if (debug) SAYF(cMGN "[D] " cRST "param counts: ar:%u lib:%u ld:%u link:%u opt:%u instr:%u\n", ar_dir_cnt, libdir_cnt, ld_param_cnt, link_param_cnt, opt_param_cnt, inst_param_cnt); + if (debug) + SAYF(cMGN "[D] " cRST + "param counts: ar:%u lib:%u ld:%u link:%u opt:%u instr:%u\n", + ar_dir_cnt, libdir_cnt, ld_param_cnt, link_param_cnt, opt_param_cnt, + inst_param_cnt); if (!just_version) { @@ -650,15 +672,25 @@ int main(int argc, char** argv) { if (pid < 0) PFATAL("fork() failed"); if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); - if (WEXITSTATUS(status) != 0) { - - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] PROGRAM ABORT : " cRST); - SAYF( "llvm-link failed, if this is because of a \"linking globals\n" - " named '...': symbol multiply defined\" error then there is nothing we can do -\n" - "llvm-link is missing an important feature :-(\n\n"); + if (WEXITSTATUS(status) != 0) { + + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD + "\n[-] PROGRAM ABORT : " cRST); + SAYF( + "llvm-link failed! Probable causes:\n\n" + " #1 If the error is \"linking globals named '...': symbol " + "multiply defined\"\n" + " then there is nothing we can do - llvm-link is missing an " + "important feature\n\n" + " #2 If the error is \"expected top-level entity\" and then " + "binary output, this\n" + " is because the same file is present in different .a archives " + "in different\n" + " formats. This can be fixed by manual doing the steps afl-ld " + "is doing but\n" + " programmatically - sorry!\n\n"); exit(WEXITSTATUS(status)); - + } /* then we perform an optimization on the collected objects files */ diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 4075d966..d3224700 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -99,6 +99,7 @@ class AFLLTOPass : public ModulePass { AU.addRequired<LoopInfoWrapperPass>(); } + #endif // Calculate the number of average collisions that would occur if all @@ -120,29 +121,30 @@ class AFLLTOPass : public ModulePass { // Get the internal llvm name of a basic block // This is an ugly debug support so it is commented out :-) -/* - static char *getBBName(const BasicBlock *BB) { + /* + static char *getBBName(const BasicBlock *BB) { - static char *name; + static char *name; - if (!BB->getName().empty()) { - - name = strdup(BB->getName().str().c_str()); - return name; - - } + if (!BB->getName().empty()) { - std::string Str; - raw_string_ostream OS(Str); + name = strdup(BB->getName().str().c_str()); + return name; - BB->printAsOperand(OS, false); - - name = strdup(OS.str().c_str()); - - return name; + } - } -*/ + std::string Str; + raw_string_ostream OS(Str); + + BB->printAsOperand(OS, false); + + name = strdup(OS.str().c_str()); + + return name; + + } + + */ static bool isBlacklisted(const Function *F) { @@ -236,8 +238,7 @@ bool AFLLTOPass::runOnModule(Module &M) { for (succ_iterator SI = succ_begin(&BB), SE = succ_end(&BB); SI != SE; ++SI) - if ((*SI)->size() > 0) - succ++; + if ((*SI)->size() > 0) succ++; if (succ < 2) // no need to instrument continue; @@ -249,13 +250,13 @@ bool AFLLTOPass::runOnModule(Module &M) { if (InsBlocks.size() > 0) { uint32_t i = InsBlocks.size(); - + do { --i; - BasicBlock *origBB = &(*InsBlocks[i]); + BasicBlock * origBB = &(*InsBlocks[i]); std::vector<BasicBlock *> Successors; - Instruction *TI = origBB->getTerminator(); + Instruction * TI = origBB->getTerminator(); for (succ_iterator SI = succ_begin(origBB), SE = succ_end(origBB); SI != SE; ++SI) { @@ -267,7 +268,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if (TI == NULL || TI->getNumSuccessors() < 2) continue; - //if (Successors.size() != TI->getNumSuccessors()) + // if (Successors.size() != TI->getNumSuccessors()) // FATAL("Different successor numbers %lu <-> %u\n", Successors.size(), // TI->getNumSuccessors()); @@ -396,7 +397,8 @@ bool AFLLTOPass::runOnModule(Module &M) { getenv("AFL_USE_ASAN") ? ", ASAN" : "", getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); - OKF("Instrumented %u locations with no collisions (on average %llu collisions would be in afl-gcc/afl-clang-fast) (%s mode).", + OKF("Instrumented %u locations with no collisions (on average %llu " + "collisions would be in afl-gcc/afl-clang-fast) (%s mode).", inst_blocks, calculateCollisions(inst_blocks), modeline); } diff --git a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h index 9cdba901..a510ac83 100644 --- a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h +++ b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h @@ -34,7 +34,7 @@ #include "afl-qemu-common.h" #include "tcg.h" -void HELPER(afl_entry_routine)(CPUArchState *env) { +void HELPER(afl_entry_routine)(CPUArchState* env) { afl_forkserver(ENV_GET_CPU(env)); @@ -171,7 +171,7 @@ static int area_is_mapped(void* ptr, size_t len) { } -void HELPER(afl_cmplog_rtn)(CPUX86State *env) { +void HELPER(afl_cmplog_rtn)(CPUX86State* env) { #if defined(TARGET_X86_64) @@ -181,9 +181,9 @@ void HELPER(afl_cmplog_rtn)(CPUX86State *env) { #elif defined(TARGET_I386) target_ulong* stack = g2h(env->regs[R_ESP]); - - if (!area_is_mapped(stack, sizeof(target_ulong)*2)) return; - + + if (!area_is_mapped(stack, sizeof(target_ulong) * 2)) return; + // when this hook is executed, the retaddr is not on stack yet void* ptr1 = g2h(stack[0]); void* ptr2 = g2h(stack[1]); @@ -217,3 +217,4 @@ void HELPER(afl_cmplog_rtn)(CPUX86State *env) { ptr2, 32); } + diff --git a/src/afl-fuzz-globals.c b/src/afl-fuzz-globals.c index 87418753..9412463d 100644 --- a/src/afl-fuzz-globals.c +++ b/src/afl-fuzz-globals.c @@ -256,7 +256,7 @@ u8 *cmplog_binary; s32 cmplog_child_pid, cmplog_forksrv_pid; /* Custom mutator */ -struct custom_mutator* mutator; +struct custom_mutator *mutator; /* Interesting values, as per config.h */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 08b6de60..8cabd9eb 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -990,7 +990,7 @@ dir_cleanup_failed: } /* Delete fuzzer output directory if we recognize it as ours, if the fuzzer - is not currently running, and if the last run time isn't too great. + is not currently running, and if the last run time isn't too great. Resume fuzzing if `-` is set as in_dir or if AFL_AUTORESUME is set */ static void handle_existing_out_dir(void) { @@ -1036,10 +1036,11 @@ static void handle_existing_out_dir(void) { fclose(f); - /* Autoresume treats a normal run as in_place_resume if a valid out dir already exists */ + /* Autoresume treats a normal run as in_place_resume if a valid out dir + * already exists */ if (!in_place_resume && autoresume) { - + OKF("Detected prior run with AFL_AUTORESUME set. Resuming."); in_place_resume = 1; diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 28d21636..b31e678b 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -36,6 +36,7 @@ void setup_custom_mutator(void) { u8* fn = getenv("AFL_CUSTOM_MUTATOR_LIBRARY"); if (fn) { + if (limit_time_sig) FATAL( "MOpt and custom mutator are mutually exclusive. We accept pull " @@ -45,6 +46,7 @@ void setup_custom_mutator(void) { load_custom_mutator(fn); return; + } /* Try Python module */ @@ -65,6 +67,7 @@ void setup_custom_mutator(void) { load_custom_mutator_py(module_name); } + #else if (getenv("AFL_PYTHON_MODULE")) FATAL("Your AFL binary was built without Python support"); @@ -75,16 +78,20 @@ void setup_custom_mutator(void) { void destroy_custom_mutator(void) { if (mutator) { + if (mutator->dh) dlclose(mutator->dh); else { + /* Python mutator */ #ifdef USE_PYTHON finalize_py_module(); #endif + } ck_free(mutator); + } } @@ -104,8 +111,7 @@ void load_custom_mutator(const char* fn) { /* Mutator */ /* "afl_custom_init", optional for backward compatibility */ mutator->afl_custom_init = dlsym(dh, "afl_custom_init"); - if (!mutator->afl_custom_init) - WARNF("Symbol 'afl_custom_init' not found."); + if (!mutator->afl_custom_init) WARNF("Symbol 'afl_custom_init' not found."); /* "afl_custom_fuzz" or "afl_custom_mutator", required */ mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz"); @@ -133,8 +139,7 @@ void load_custom_mutator(const char* fn) { /* "afl_custom_trim", optional */ mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim"); - if (!mutator->afl_custom_trim) - WARNF("Symbol 'afl_custom_trim' not found."); + if (!mutator->afl_custom_trim) WARNF("Symbol 'afl_custom_trim' not found."); /* "afl_custom_post_trim", optional */ mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim"); @@ -151,14 +156,15 @@ void load_custom_mutator(const char* fn) { "trimming will be used."); } - + /* "afl_custom_havoc_mutation", optional */ mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation"); if (!mutator->afl_custom_havoc_mutation) WARNF("Symbol 'afl_custom_havoc_mutation' not found."); /* "afl_custom_havoc_mutation", optional */ - mutator->afl_custom_havoc_mutation_probability = dlsym(dh, "afl_custom_havoc_mutation_probability"); + mutator->afl_custom_havoc_mutation_probability = + dlsym(dh, "afl_custom_havoc_mutation_probability"); if (!mutator->afl_custom_havoc_mutation_probability) WARNF("Symbol 'afl_custom_havoc_mutation_probability' not found."); @@ -175,8 +181,7 @@ void load_custom_mutator(const char* fn) { OKF("Custom mutator '%s' installed successfully.", fn); /* Initialize the custom mutator */ - if (mutator->afl_custom_init) - mutator->afl_custom_init(UR(0xFFFFFFFF)); + if (mutator->afl_custom_init) mutator->afl_custom_init(UR(0xFFFFFFFF)); } @@ -309,8 +314,7 @@ void load_custom_mutator_py(const char* module_name) { mutator->name = module_name; ACTF("Loading Python mutator library from '%s'...", module_name); - if (py_functions[PY_FUNC_INIT]) - mutator->afl_custom_init = init_py; + if (py_functions[PY_FUNC_INIT]) mutator->afl_custom_init = init_py; /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator is quite different from the custom mutator. */ @@ -325,14 +329,14 @@ void load_custom_mutator_py(const char* module_name) { if (py_functions[PY_FUNC_POST_TRIM]) mutator->afl_custom_post_trim = post_trim_py; - if (py_functions[PY_FUNC_TRIM]) - mutator->afl_custom_trim = trim_py; - + if (py_functions[PY_FUNC_TRIM]) mutator->afl_custom_trim = trim_py; + if (py_functions[PY_FUNC_HAVOC_MUTATION]) mutator->afl_custom_havoc_mutation = havoc_mutation_py; - + if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) - mutator->afl_custom_havoc_mutation_probability = havoc_mutation_probability_py; + mutator->afl_custom_havoc_mutation_probability = + havoc_mutation_probability_py; if (py_functions[PY_FUNC_QUEUE_GET]) mutator->afl_custom_queue_get = queue_get_py; @@ -343,8 +347,9 @@ void load_custom_mutator_py(const char* module_name) { OKF("Python mutator '%s' installed successfully.", module_name); /* Initialize the custom mutator */ - if (mutator->afl_custom_init) - mutator->afl_custom_init(UR(0xFFFFFFFF)); + if (mutator->afl_custom_init) mutator->afl_custom_init(UR(0xFFFFFFFF)); } + #endif + diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 1817bd03..c6dbb858 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -359,8 +359,7 @@ u8 fuzz_one_original(char** argv) { /* The custom mutator will decide to skip this test case or not. */ - if (!mutator->afl_custom_queue_get(queue_cur->fname)) - return 1; + if (!mutator->afl_custom_queue_get(queue_cur->fname)) return 1; } @@ -1552,7 +1551,7 @@ custom_mutator_stage: const u32 max_seed_size = MAX_FILE; orig_hit_cnt = queued_paths + unique_crashes; - + for (stage_cur = 0; stage_cur < stage_max; ++stage_cur) { struct queue_entry* target; @@ -1597,10 +1596,9 @@ custom_mutator_stage: new_buf = ck_alloc_nozero(target->len); ck_read(fd, new_buf, target->len, target->fname); close(fd); - - size_t mutated_size = mutator->afl_custom_fuzz(&out_buf, len, - new_buf, target->len, - max_seed_size); + + size_t mutated_size = mutator->afl_custom_fuzz(&out_buf, len, new_buf, + target->len, max_seed_size); ck_free(new_buf); @@ -1629,7 +1627,7 @@ custom_mutator_stage: } } - + if (mutated_size < len) out_buf = ck_realloc(out_buf, len); memcpy(out_buf, in_buf, len); @@ -1688,13 +1686,15 @@ havoc_stage: havoc_queued = queued_paths; u8 stacked_custom = (mutator && mutator->afl_custom_havoc_mutation); - u8 stacked_custom_prob = 6; // like one of the default mutations in havoc + u8 stacked_custom_prob = 6; // like one of the default mutations in havoc if (stacked_custom && mutator->afl_custom_havoc_mutation_probability) { stacked_custom_prob = mutator->afl_custom_havoc_mutation_probability(); if (stacked_custom_prob > 100) - FATAL("The probability returned by afl_custom_havoc_mutation_propability has to be in the range 0-100."); + FATAL( + "The probability returned by afl_custom_havoc_mutation_propability " + "has to be in the range 0-100."); } @@ -1708,12 +1708,12 @@ havoc_stage: stage_cur_val = use_stacking; for (i = 0; i < use_stacking; ++i) { - + if (stacked_custom && UR(100) < stacked_custom_prob) { - - temp_len = mutator->afl_custom_havoc_mutation(&out_buf, temp_len, - MAX_FILE); - + + temp_len = + mutator->afl_custom_havoc_mutation(&out_buf, temp_len, MAX_FILE); + } switch (UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))) { diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 4e72905d..28b101f3 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -80,6 +80,7 @@ int init_py_module(u8* module_name) { py_notrim = 1; } else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) && + (py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) { // Implenting the havoc and queue API is optional for now @@ -140,6 +141,7 @@ void finalize_py_module() { } void init_py(unsigned int seed) { + PyObject *py_args, *py_value; /* Provide the init function a seed for the Python RNG */ @@ -171,12 +173,13 @@ void init_py(unsigned int seed) { return; } + } size_t fuzz_py(u8** buf, size_t buf_size, u8* add_buf, size_t add_buf_size, size_t max_size) { - size_t mutated_size; + size_t mutated_size; PyObject *py_args, *py_value; py_args = PyTuple_New(3); @@ -224,8 +227,7 @@ size_t fuzz_py(u8** buf, size_t buf_size, u8* add_buf, size_t add_buf_size, if (py_value != NULL) { mutated_size = PyByteArray_Size(py_value); - if (buf_size < mutated_size) - *buf = ck_realloc(*buf, mutated_size); + if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size); memcpy(*buf, PyByteArray_AsString(py_value), mutated_size); Py_DECREF(py_value); @@ -242,7 +244,7 @@ size_t fuzz_py(u8** buf, size_t buf_size, u8* add_buf, size_t add_buf_size, size_t pre_save_py(u8* buf, size_t buf_size, u8** out_buf) { - size_t out_buf_size; + size_t out_buf_size; PyObject *py_args, *py_value; py_args = PyTuple_New(1); py_value = PyByteArray_FromStringAndSize(buf, buf_size); @@ -377,7 +379,7 @@ void trim_py(u8** out_buf, size_t* out_buf_size) { size_t havoc_mutation_py(u8** buf, size_t buf_size, size_t max_size) { - size_t mutated_size; + size_t mutated_size; PyObject *py_args, *py_value; py_args = PyTuple_New(2); @@ -414,9 +416,8 @@ size_t havoc_mutation_py(u8** buf, size_t buf_size, size_t max_size) { if (py_value != NULL) { mutated_size = PyByteArray_Size(py_value); - if (buf_size < mutated_size) - *buf = ck_realloc(*buf, mutated_size); - + if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size); + memcpy(*buf, PyByteArray_AsString(py_value), mutated_size); Py_DECREF(py_value); @@ -436,7 +437,8 @@ u8 havoc_mutation_probability_py(void) { PyObject *py_args, *py_value; py_args = PyTuple_New(0); - py_value = PyObject_CallObject(py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], py_args); + py_value = PyObject_CallObject( + py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], py_args); Py_DECREF(py_args); if (py_value != NULL) { @@ -483,7 +485,7 @@ u8 queue_get_py(const u8* filename) { int ret = PyObject_IsTrue(py_value); Py_DECREF(py_value); - + if (ret == -1) { PyErr_Print(); @@ -491,10 +493,10 @@ u8 queue_get_py(const u8* filename) { } - return (u8) ret & 0xFF; + return (u8)ret & 0xFF; } else { - + PyErr_Print(); FATAL("Call failed"); @@ -516,7 +518,7 @@ void queue_new_entry_py(const u8* filename_new_queue, py_value = PyString_FromString(filename_new_queue); #endif if (!py_value) { - + Py_DECREF(py_args); FATAL("Failed to convert arguments"); @@ -534,7 +536,7 @@ void queue_new_entry_py(const u8* filename_new_queue, py_value = PyString_FromString(filename_orig_queue); #endif if (!py_value) { - + Py_DECREF(py_args); FATAL("Failed to convert arguments"); @@ -545,8 +547,8 @@ void queue_new_entry_py(const u8* filename_new_queue, PyTuple_SetItem(py_args, 1, py_value); // Call - py_value = PyObject_CallObject(py_functions[PY_FUNC_QUEUE_NEW_ENTRY], - py_args); + py_value = + PyObject_CallObject(py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args); Py_DECREF(py_args); if (py_value == NULL) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 58985d8b..f0ba2fe8 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -662,7 +662,7 @@ void sync_fuzzers(char** argv) { ck_write(id_fd, &next_min_accept, sizeof(u32), qd_synced_path); -close_sync: + close_sync: close(id_fd); closedir(qd); ck_free(qd_path); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 12c7853c..778ada9a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -119,7 +119,8 @@ static void usage(u8* argv0, int more_help) { " if using QEMU, just use -c 0.\n\n" "Fuzzing behavior settings:\n" - " -N - do not unlink the fuzzing input file (only for devices etc.!)\n" + " -N - do not unlink the fuzzing input file (only for " + "devices etc.!)\n" " -d - quick & dirty mode (skips deterministic steps)\n" " -n - fuzz without instrumentation (dumb mode)\n" " -x dir - optional fuzzer dictionary (see README.md, its really " @@ -752,8 +753,7 @@ int main(int argc, char** argv, char** envp) { if (get_afl_env("AFL_AUTORESUME")) { autoresume = 1; - if (in_place_resume) - SAYF("AFL_AUTORESUME has no effect for '-i -'"); + if (in_place_resume) SAYF("AFL_AUTORESUME has no effect for '-i -'"); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 6075027f..ffdb67e4 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -730,9 +730,8 @@ int main(int argc, char** argv, char** envp) { char** use_argv; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - - if (getenv("AFL_QUIET") != NULL) - be_quiet = 1; + + if (getenv("AFL_QUIET") != NULL) be_quiet = 1; while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 509943ff..31296cb5 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -99,7 +99,6 @@ static volatile u8 stop_soon; /* Ctrl-C pressed? */ static u8 qemu_mode; - /* * forkserver section */ @@ -533,7 +532,7 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) { return 0; } - + /* Handle crashing inputs depending on current mode. */ if (WIFSIGNALED(status) || @@ -822,14 +821,15 @@ finalize_all: if (hang_mode) { - SAYF("\n" cGRA " File size reduced by : " cRST - "%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST - "%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA - " Fruitless execs : " cRST "termination=%u crash=%u\n\n", - 100 - ((double)in_len) * 100 / orig_len, in_len, in_len == 1 ? "" : "s", - ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), total_execs, - missed_paths, missed_crashes); - return; + SAYF("\n" cGRA " File size reduced by : " cRST + "%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST + "%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA + " Fruitless execs : " cRST "termination=%u crash=%u\n\n", + 100 - ((double)in_len) * 100 / orig_len, in_len, + in_len == 1 ? "" : "s", + ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), total_execs, + missed_paths, missed_crashes); + return; } @@ -1146,7 +1146,8 @@ int main(int argc, char** argv, char** envp) { case 'e': if (edges_only) FATAL("Multiple -e options not supported"); - if (hang_mode) FATAL("Edges only and hang mode are mutually exclusive."); + if (hang_mode) + FATAL("Edges only and hang mode are mutually exclusive."); edges_only = 1; break; @@ -1232,12 +1233,13 @@ int main(int argc, char** argv, char** envp) { break; - case 'H': /* Hang Mode */ - + case 'H': /* Hang Mode */ + /* Minimizes a testcase to the minimum that still times out */ if (hang_mode) FATAL("Multipe -H options not supported"); - if (edges_only) FATAL("Edges only and hang mode are mutually exclusive."); + if (edges_only) + FATAL("Edges only and hang mode are mutually exclusive."); hang_mode = 1; break; @@ -1314,14 +1316,18 @@ int main(int argc, char** argv, char** envp) { run_target(use_argv, in_data, in_len, 1); if (hang_mode && !child_timed_out) - FATAL("Target binary did not time out but hang minimization mode " - "(-H) was set (-t %u).", exec_tmout); + FATAL( + "Target binary did not time out but hang minimization mode " + "(-H) was set (-t %u).", + exec_tmout); if (child_timed_out && !hang_mode) - FATAL("Target binary times out (adjusting -t may help). Use -H to minimize a hang."); + FATAL( + "Target binary times out (adjusting -t may help). Use -H to minimize a " + "hang."); if (hang_mode) { - + OKF("Program hangs as expected, minimizing in " cCYA "hang" cRST " mode."); } else if (!crash_mode) { diff --git a/test/test.sh b/test/test.sh index 1a3f562c..f4cc1db6 100755 --- a/test/test.sh +++ b/test/test.sh @@ -423,7 +423,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { } rm -f test-instr.plain -# Disabled whitelist and persistent until I have a different solution -mh +# Disabled whitelist until I have a different solution -mh # echo foobar.c > whitelist.txt # AFL_LLVM_WHITELIST=whitelist.txt ../afl-clang-lto -o test-compcov test-compcov.c > test.out 2>&1 # test -e test-compcov && { @@ -438,19 +438,19 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && { # CODE=1 # } # rm -f test-compcov test.out whitelist.txt -# ../afl-clang-lto -o test-persistent ../experimental/persistent_demo/persistent_demo.c > /dev/null 2>&1 -# test -e test-persistent && { -# echo foo | ../afl-showmap -o /dev/null -q -r ./test-persistent && { -# $ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly" -# } || { -# $ECHO "$RED[!] llvm_mode LTO persistent mode feature failed to work" -# CODE=1 -# } -# } || { -# $ECHO "$RED[!] llvm_mode LTO persistent mode feature compilation failed" -# CODE=1 -# } -# rm -f test-persistent + ../afl-clang-lto -o test-persistent ../examples/persistent_demo/persistent_demo.c > /dev/null 2>&1 + test -e test-persistent && { + echo foo | ../afl-showmap -o /dev/null -q -r ./test-persistent && { + $ECHO "$GREEN[+] llvm_mode LTO persistent mode feature works correctly" + } || { + $ECHO "$RED[!] llvm_mode LTO persistent mode feature failed to work" + CODE=1 + } + } || { + $ECHO "$RED[!] llvm_mode LTO persistent mode feature compilation failed" + CODE=1 + } + rm -f test-persistent } || { $ECHO "$YELLOW[-] LTO llvm_mode not compiled, cannot test" INCOMPLETE=1 |