| Index: third_party/afl/src/afl-gcc.c
|
| diff --git a/third_party/afl/src/afl-gcc.c b/third_party/afl/src/afl-gcc.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b6cbc05c801fdda24e0cc66508c602d100b68806
|
| --- /dev/null
|
| +++ b/third_party/afl/src/afl-gcc.c
|
| @@ -0,0 +1,318 @@
|
| +/*
|
| + american fuzzy lop - wrapper for GCC and clang
|
| + ----------------------------------------------
|
| +
|
| + Written and maintained by Michal Zalewski <lcamtuf@google.com>
|
| +
|
| + Copyright 2013, 2014, 2015 Google Inc. 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:
|
| +
|
| + http://www.apache.org/licenses/LICENSE-2.0
|
| +
|
| + This program is a drop-in replacement for GCC or clang. The most common way
|
| + of using it is to pass the path to afl-gcc or afl-clang via CC when invoking
|
| + ./configure.
|
| +
|
| + (Of course, use CXX and point it to afl-g++ / afl-clang++ for C++ code.)
|
| +
|
| + The wrapper needs to know the path to afl-as (renamed to 'as'). The default
|
| + is /usr/local/lib/afl/. A convenient way to specify alternative directories
|
| + would be to set AFL_PATH.
|
| +
|
| + If AFL_HARDEN is set, the wrapper will compile the target app with various
|
| + hardening options that may help detect memory management issues more
|
| + reliably. You can also specify AFL_USE_ASAN to enable ASAN.
|
| +
|
| + If you want to call a non-default compiler as a next step of the chain,
|
| + specify its location via AFL_CC or AFL_CXX.
|
| +
|
| + */
|
| +
|
| +#define AFL_MAIN
|
| +
|
| +#include "config.h"
|
| +#include "types.h"
|
| +#include "debug.h"
|
| +#include "alloc-inl.h"
|
| +
|
| +#include <stdio.h>
|
| +#include <unistd.h>
|
| +#include <stdlib.h>
|
| +#include <string.h>
|
| +
|
| +static u8* as_path; /* Path to the AFL 'as' wrapper */
|
| +static u8** cc_params; /* Parameters passed to the real CC */
|
| +static u32 cc_par_cnt = 1; /* Param count, including argv0 */
|
| +static u8 be_quiet, /* Quiet mode */
|
| + clang_mode; /* Invoked as afl-clang*? */
|
| +
|
| +
|
| +/* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
|
| + from argv[0]. If that fails, abort. */
|
| +
|
| +static void find_as(u8* argv0) {
|
| +
|
| + u8 *afl_path = getenv("AFL_PATH");
|
| + u8 *slash, *tmp;
|
| +
|
| + if (afl_path) {
|
| +
|
| + tmp = alloc_printf("%s/as", afl_path);
|
| +
|
| + if (!access(tmp, X_OK)) {
|
| + as_path = afl_path;
|
| + ck_free(tmp);
|
| + return;
|
| + }
|
| +
|
| + ck_free(tmp);
|
| +
|
| + }
|
| +
|
| + slash = strrchr(argv0, '/');
|
| +
|
| + if (slash) {
|
| +
|
| + u8 *dir;
|
| +
|
| + *slash = 0;
|
| + dir = ck_strdup(argv0);
|
| + *slash = '/';
|
| +
|
| + tmp = alloc_printf("%s/afl-as", dir);
|
| +
|
| + if (!access(tmp, X_OK)) {
|
| + as_path = dir;
|
| + ck_free(tmp);
|
| + return;
|
| + }
|
| +
|
| + ck_free(tmp);
|
| + ck_free(dir);
|
| +
|
| + }
|
| +
|
| + if (!access(AFL_PATH "/as", X_OK)) {
|
| + as_path = AFL_PATH;
|
| + return;
|
| + }
|
| +
|
| + FATAL("Unable to find AFL wrapper binary for 'as'. Please set AFL_PATH");
|
| +
|
| +}
|
| +
|
| +
|
| +/* Copy argv to cc_params, making the necessary edits. */
|
| +
|
| +static void edit_params(u32 argc, char** argv) {
|
| +
|
| + u8 fortify_set = 0, asan_set = 0;
|
| + u8 *name;
|
| +
|
| +#if defined(__FreeBSD__) && defined(__x86_64__)
|
| + u8 m32_set = 0;
|
| +#endif
|
| +
|
| + cc_params = ck_alloc((argc + 64) * sizeof(u8*));
|
| +
|
| + name = strrchr(argv[0], '/');
|
| + if (!name) name = argv[0]; else name++;
|
| +
|
| + if (!strncmp(name, "afl-clang", 9)) {
|
| +
|
| + clang_mode = 1;
|
| +
|
| + setenv(CLANG_ENV_VAR, "1", 1);
|
| +
|
| + if (!strcmp(name, "afl-clang++")) {
|
| + u8* alt_cxx = getenv("AFL_CXX");
|
| + cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";
|
| + } else {
|
| + u8* alt_cc = getenv("AFL_CC");
|
| + cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";
|
| + }
|
| +
|
| + } else {
|
| +
|
| + /* With GCJ and Eclipse installed, you can actually compile Java! The
|
| + instrumentation will work (amazingly). Alas, unhandled exceptions do
|
| + not call abort(), so afl-fuzz would need to be modified to equate
|
| + non-zero exit codes with crash conditions when working with Java
|
| + binaries. Meh. */
|
| +
|
| +#ifdef __APPLE__
|
| +
|
| + if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX");
|
| + else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ");
|
| + else cc_params[0] = getenv("AFL_CC");
|
| +
|
| + if (!cc_params[0]) {
|
| +
|
| + SAYF("\n" cLRD "[-] " cRST
|
| + "On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n"
|
| + " 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n"
|
| + " set AFL_CC or AFL_CXX to specify the correct path to that compiler.\n");
|
| +
|
| + FATAL("AFL_CC or AFL_CXX required on MacOS X");
|
| +
|
| + }
|
| +
|
| +#else
|
| +
|
| + if (!strcmp(name, "afl-g++")) {
|
| + u8* alt_cxx = getenv("AFL_CXX");
|
| + cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++";
|
| + } else if (!strcmp(name, "afl-gcj")) {
|
| + u8* alt_cc = getenv("AFL_GCJ");
|
| + cc_params[0] = alt_cc ? alt_cc : (u8*)"gcj";
|
| + } else {
|
| + u8* alt_cc = getenv("AFL_CC");
|
| + cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc";
|
| + }
|
| +
|
| +#endif /* __APPLE__ */
|
| +
|
| + }
|
| +
|
| + while (--argc) {
|
| + u8* cur = *(++argv);
|
| +
|
| + if (!strncmp(cur, "-B", 2)) {
|
| +
|
| + if (!be_quiet) WARNF("-B is already set, overriding");
|
| +
|
| + if (!cur[2] && argc > 1) { argc--; argv++; }
|
| + continue;
|
| +
|
| + }
|
| +
|
| + if (!strcmp(cur, "-integrated-as")) continue;
|
| +
|
| + if (!strcmp(cur, "-pipe")) continue;
|
| +
|
| +#if defined(__FreeBSD__) && defined(__x86_64__)
|
| + if (!strcmp(cur, "-m32")) m32_set = 1;
|
| +#endif
|
| +
|
| + if (!strcmp(cur, "-fsanitize=address") ||
|
| + !strcmp(cur, "-fsanitize=memory")) asan_set = 1;
|
| +
|
| + if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
|
| +
|
| + cc_params[cc_par_cnt++] = cur;
|
| +
|
| + }
|
| +
|
| + cc_params[cc_par_cnt++] = "-B";
|
| + cc_params[cc_par_cnt++] = as_path;
|
| +
|
| + if (clang_mode)
|
| + cc_params[cc_par_cnt++] = "-no-integrated-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 (asan_set) {
|
| +
|
| + /* Pass this on to afl-as to adjust map density. */
|
| +
|
| + setenv("AFL_USE_ASAN", "1", 1);
|
| +
|
| + } else if (getenv("AFL_USE_ASAN")) {
|
| +
|
| + cc_params[cc_par_cnt++] = "-fsanitize=address";
|
| +
|
| + if (getenv("AFL_USE_MSAN"))
|
| + FATAL("ASAN and MSAN are mutually exclusive");
|
| +
|
| + } else if (getenv("AFL_USE_MSAN")) {
|
| +
|
| + cc_params[cc_par_cnt++] = "-fsanitize=memory";
|
| +
|
| + if (getenv("AFL_USE_ASAN"))
|
| + FATAL("ASAN and MSAN are mutually exclusive");
|
| +
|
| + }
|
| +
|
| + if (!getenv("AFL_DONT_OPTIMIZE")) {
|
| +
|
| +#if defined(__FreeBSD__) && defined(__x86_64__)
|
| +
|
| + /* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself
|
| + works OK. This has nothing to do with us, but let's avoid triggering
|
| + that bug. */
|
| +
|
| + if (!clang_mode || !m32_set)
|
| + cc_params[cc_par_cnt++] = "-g";
|
| +
|
| +#else
|
| +
|
| + cc_params[cc_par_cnt++] = "-g";
|
| +
|
| +#endif
|
| +
|
| + cc_params[cc_par_cnt++] = "-O3";
|
| + cc_params[cc_par_cnt++] = "-funroll-loops";
|
| +
|
| + /* Two indicators that you're building for fuzzing; one of them is
|
| + AFL-specific, the other is shared with libfuzzer. */
|
| +
|
| + cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
|
| + cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
|
| +
|
| + }
|
| +
|
| + cc_params[cc_par_cnt] = NULL;
|
| +
|
| +}
|
| +
|
| +
|
| +/* Main entry point */
|
| +
|
| +int main(int argc, char** argv) {
|
| +
|
| + if (isatty(2) && !getenv("AFL_QUIET")) {
|
| +
|
| + SAYF(cCYA "afl-cc " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
|
| +
|
| + } else be_quiet = 1;
|
| +
|
| + if (argc < 2) {
|
| +
|
| + SAYF("\n"
|
| + "This is a helper application for afl-fuzz. It serves as a drop-in replacement\n"
|
| + "for gcc or clang, letting you recompile third-party code with the required\n"
|
| + "runtime instrumentation. A common use pattern would be one of the following:\n\n"
|
| +
|
| + " CC=%s/afl-gcc ./configure\n"
|
| + " CXX=%s/afl-g++ ./configure\n\n"
|
| +
|
| + "You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS.\n"
|
| + "Setting AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
|
| + BIN_PATH, BIN_PATH);
|
| +
|
| + exit(1);
|
| +
|
| + }
|
| +
|
| +
|
| + find_as(argv[0]);
|
| +
|
| + edit_params(argc, argv);
|
| +
|
| + execvp(cc_params[0], (char**)cc_params);
|
| +
|
| + FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
|
| +
|
| + return 0;
|
| +
|
| +}
|
|
|