diff options
Diffstat (limited to 'hfuzz_cc/hfuzz-cc.c')
-rw-r--r-- | hfuzz_cc/hfuzz-cc.c | 532 |
1 files changed, 0 insertions, 532 deletions
diff --git a/hfuzz_cc/hfuzz-cc.c b/hfuzz_cc/hfuzz-cc.c deleted file mode 100644 index 5957d4d1..00000000 --- a/hfuzz_cc/hfuzz-cc.c +++ /dev/null @@ -1,532 +0,0 @@ -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <libgen.h> -#include <limits.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "honggfuzz.h" -#include "libhfcommon/common.h" -#include "libhfcommon/files.h" -#include "libhfcommon/log.h" -#include "libhfcommon/util.h" - -#define ARGS_MAX 4096 - -static bool isCXX = false; -static bool isGCC = false; -static bool usePCGuard = true; -static bool hasCmdLineFSanitizeFuzzer = false; - -/* Embed libhf/.a inside this binary */ -__asm__("\n" - " .global lhfuzz_start\n" - " .global lhfuzz_end\n" - "lhfuzz_start:\n" - " .incbin \"libhfuzz/libhfuzz.a\"\n" - "lhfuzz_end:\n" - "\n" - " .global lhfnetdriver_start\n" - " .global lhfnetdriver_end\n" - "lhfnetdriver_start:\n" - " .incbin \"libhfnetdriver/libhfnetdriver.a\"\n" - "lhfnetdriver_end:\n" - "\n" - " .global lhfcommon_start\n" - " .global lhfcommon_end\n" - "lhfcommon_start:\n" - " .incbin \"libhfcommon/libhfcommon.a\"\n" - "lhfcommon_end:\n" - "\n"); - -static const char* _basename(const char* path) { - static __thread char fname[PATH_MAX]; - /* basename() can modify the argument (sic!) */ - snprintf(fname, sizeof(fname), "%s", path); - return basename(fname); -} - -static bool useASAN() { - if (getenv("HFUZZ_CC_ASAN")) { - return true; - } - return false; -} - -static bool useMSAN() { - if (getenv("HFUZZ_CC_MSAN")) { - return true; - } - return false; -} - -static bool useUBSAN() { - if (getenv("HFUZZ_CC_UBSAN")) { - return true; - } - return false; -} - -static bool useM32() { - if (getenv("HFUZZ_FORCE_M32")) { - return true; - } - return false; -} - -static bool useBelowGCC8() { - if (getenv("HFUZZ_CC_USE_GCC_BELOW_8")) { - return true; - } - return false; -} - -static bool isLDMode(int argc, char** argv) { - for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "--version") == 0) { - return false; - } - if (strcmp(argv[i], "--target-help") == 0) { - return false; - } - if (strcmp(argv[i], "-c") == 0) { - return false; - } - if (strcmp(argv[i], "-E") == 0) { - return false; - } - if (strcmp(argv[i], "-S") == 0) { - return false; - } - } - return true; -} - -static bool hasFSanitizeFuzzer(int argc, char** argv) { - for (int i = 1; i < argc; i++) { - if (util_strStartsWith(argv[i], "-fsanitize=") && strstr(argv[i], "fuzzer")) { - return true; - } - } - return false; -} - -static int hf_execvp(const char* file, char** argv) { - argv[0] = (char*)file; - return execvp(file, argv); -} - -static int execCC(int argc, char** argv) { - if (useASAN()) { - argv[argc++] = "-fsanitize=address"; - } - if (useMSAN()) { - argv[argc++] = "-fsanitize=memory"; - } - if (useUBSAN()) { - argv[argc++] = "-fsanitize=undefined"; - } - argv[argc] = NULL; - - if (isCXX) { - const char* cxx_path = getenv("HFUZZ_CXX_PATH"); - if (cxx_path != NULL) { - hf_execvp(cxx_path, argv); - PLOG_E("execvp('%s')", cxx_path); - return EXIT_FAILURE; - } - } else { - const char* cc_path = getenv("HFUZZ_CC_PATH"); - if (cc_path != NULL) { - hf_execvp(cc_path, argv); - PLOG_E("execvp('%s')", cc_path); - return EXIT_FAILURE; - } - } - - if (isGCC) { - if (isCXX) { - hf_execvp("g++", argv); - hf_execvp("gcc", argv); - } else { - hf_execvp("gcc", argv); - } - } else { - if (isCXX) { - /* Try the default one, then the newest ones (hopefully) in order */ - hf_execvp("clang++", argv); - hf_execvp("clang++-11.0", argv); - hf_execvp("clang++-11", argv); - hf_execvp("clang++11", argv); - hf_execvp("clang++-10.0", argv); - hf_execvp("clang++-10", argv); - hf_execvp("clang++10", argv); - hf_execvp("clang++-9.0", argv); - hf_execvp("clang++-9", argv); - hf_execvp("clang++9", argv); - hf_execvp("clang++-8.0", argv); - hf_execvp("clang++-8", argv); - hf_execvp("clang++8", argv); - hf_execvp("clang++-7.0", argv); - hf_execvp("clang++-7", argv); - hf_execvp("clang++7", argv); - hf_execvp("clang", argv); - } else { - /* Try the default one, then the newest ones (hopefully) in order */ - hf_execvp("clang", argv); - hf_execvp("clang-11.0", argv); - hf_execvp("clang-11", argv); - hf_execvp("clang11", argv); - hf_execvp("clang-10.0", argv); - hf_execvp("clang-10", argv); - hf_execvp("clang10", argv); - hf_execvp("clang-9.0", argv); - hf_execvp("clang-9", argv); - hf_execvp("clang9", argv); - hf_execvp("clang-8.0", argv); - hf_execvp("clang-8", argv); - hf_execvp("clang8", argv); - hf_execvp("clang-7.0", argv); - hf_execvp("clang-7", argv); - hf_execvp("clang7", argv); - } - } - - PLOG_F("execvp('%s')", argv[0]); - return EXIT_FAILURE; -} - -/* It'll point back to the libhfuzz's source tree */ -char* getIncPaths(void) { -#if !defined(_HFUZZ_INC_PATH) -#error \ - "You need to define _HFUZZ_INC_PATH to a directory with the directory called 'includes', containing honggfuzz's lib* includes. Typically it'd be the build/sources dir" -#endif - - static char path[PATH_MAX]; - snprintf(path, sizeof(path), "-I%s/includes/", HF_XSTR(_HFUZZ_INC_PATH)); - return path; -} - -static bool getLibPath( - const char* name, const char* env, const uint8_t* start, const uint8_t* end, char* path) { - const char* libEnvLoc = getenv(env); - if (libEnvLoc) { - snprintf(path, PATH_MAX, "%s", libEnvLoc); - return true; - } - - ptrdiff_t len = (uintptr_t)end - (uintptr_t)start; - uint64_t crc64 = util_CRC64(start, len); - snprintf(path, PATH_MAX, "/tmp/%s.%d.%" PRIx64 ".a", name, geteuid(), crc64); - - /* Does the library exist, belongs to the user, and is of expected size? */ - struct stat st; - if (stat(path, &st) != -1 && st.st_size == len && st.st_uid == geteuid()) { - return true; - } - - /* If not, create it with atomic rename() */ - char template[] = "/tmp/lib.honggfuzz.a.XXXXXX"; - int fd = TEMP_FAILURE_RETRY(mkostemp(template, O_CLOEXEC)); - if (fd == -1) { - PLOG_E("mkostemp('%s')", template); - return false; - } - defer { - close(fd); - }; - - if (!files_writeToFd(fd, start, len)) { - PLOG_E("Couldn't write to '%s'", template); - unlink(template); - return false; - } - - if (TEMP_FAILURE_RETRY(rename(template, path)) == -1) { - PLOG_E("Couldn't rename('%s', '%s')", template, path); - unlink(template); - return false; - } - - return true; -} - -static char* getLibHFuzzPath() { - extern uint8_t lhfuzz_start __asm__("lhfuzz_start"); - extern uint8_t lhfuzz_end __asm__("lhfuzz_end"); - - static char path[PATH_MAX] = {}; - if (path[0]) { - return path; - } - if (!getLibPath("libhfuzz", "HFUZZ_LHFUZZ_PATH", &lhfuzz_start, &lhfuzz_end, path)) { - LOG_F("Couldn't create the temporary libhfuzz.a"); - } - return path; -} - -static char* getLibHFNetDriverPath() { - extern uint8_t lhfnetdriver_start __asm__("lhfnetdriver_start"); - extern uint8_t lhfnetdriver_end __asm__("lhfnetdriver_end"); - - static char path[PATH_MAX] = {}; - if (path[0]) { - return path; - } - if (!getLibPath("libhfnetdriver", "HFUZZ_LHFNETDRIVER_PATH", &lhfnetdriver_start, - &lhfnetdriver_end, path)) { - LOG_F("Couldn't create the temporary libhfnetdriver.a"); - } - return path; -} - -static char* getLibHFCommonPath() { - extern uint8_t lhfcommon_start __asm__("lhfcommon_start"); - extern uint8_t lhfcommon_end __asm__("lhfcommon_end"); - - static char path[PATH_MAX] = {}; - if (path[0]) { - return path; - } - if (!getLibPath("libhfuzz", "HFUZZ_LHFCOMMON_PATH", &lhfcommon_start, &lhfcommon_end, path)) { - LOG_F("Couldn't create the temporary libhcommon.a"); - } - return path; -} - -static void commonPreOpts(int* j, char** args) { - args[(*j)++] = getIncPaths(); - - if (!isGCC) { - args[(*j)++] = "-Wno-unused-command-line-argument"; - } - - /* - * Make the execution flow more explicit, allowing for more code blocks - * (and better code coverage estimates) - */ - if (isGCC) { - args[(*j)++] = "-finline-limit=4000"; - } else { - args[(*j)++] = "-mllvm"; - args[(*j)++] = "-inline-threshold=2000"; - } - args[(*j)++] = "-fno-builtin"; - args[(*j)++] = "-fno-omit-frame-pointer"; - args[(*j)++] = "-D__NO_STRING_INLINES"; - - /* Make it possible to use the libhfnetdriver */ - args[(*j)++] = "-DHFND_FUZZING_ENTRY_FUNCTION_CXX(x,y)=" - "extern const char* LIBHFNETDRIVER_module_netdriver;" - "const char** LIBHFNETDRIVER_tmp1 = &LIBHFNETDRIVER_module_netdriver;" - "extern \"C\" int HonggfuzzNetDriver_main(x,y);" - "int HonggfuzzNetDriver_main(x,y)"; - args[(*j)++] = "-DHFND_FUZZING_ENTRY_FUNCTION(x,y)=" - "extern const char* LIBHFNETDRIVER_module_netdriver;" - "const char** LIBHFNETDRIVER_tmp1 = &LIBHFNETDRIVER_module_netdriver;" - "int HonggfuzzNetDriver_main(x,y);" - "int HonggfuzzNetDriver_main(x,y)"; - - if (useM32()) { - args[(*j)++] = "-m32"; - } -} - -static void commonPostOpts(int* j, char** args) { - if (isGCC) { - if (useBelowGCC8()) { - /* trace-pc is the best that gcc-6/7 currently offers */ - args[(*j)++] = "-fsanitize-coverage=trace-pc"; - } else { - /* gcc-8+ offers trace-cmp as well, but it's not that widely used yet */ - args[(*j)++] = "-fsanitize-coverage=trace-pc,trace-cmp"; - } - } else { - if (usePCGuard) { - if (hasCmdLineFSanitizeFuzzer) { - args[(*j)++] = "-fno-sanitize=fuzzer"; - args[(*j)++] = "-fno-sanitize=fuzzer-no-link"; - } - args[(*j)++] = "-fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div,indirect-calls"; - } else { - args[(*j)++] = "-fno-sanitize-coverage=trace-pc-guard"; - args[(*j)++] = "-fno-sanitize=fuzzer"; - args[(*j)++] = "-fsanitize=fuzzer-no-link"; - args[(*j)++] = "-fsanitize-coverage=trace-cmp,trace-div,indirect-calls"; - } - } -} - -static int ccMode(int argc, char** argv) { - char* args[ARGS_MAX]; - - int j = 0; - if (isCXX) { - args[j++] = "c++"; - } else { - args[j++] = "cc"; - } - - commonPreOpts(&j, args); - - for (int i = 1; i < argc; i++) { - args[j++] = argv[i]; - } - - commonPostOpts(&j, args); - - return execCC(j, args); -} - -static int ldMode(int argc, char** argv) { - char* args[ARGS_MAX]; - - int j = 0; - if (isCXX) { - args[j++] = "c++"; - } else { - args[j++] = "cc"; - } - - commonPreOpts(&j, args); - -/* MacOS X linker doesn't like those */ -#ifndef _HF_ARCH_DARWIN - /* Intercept common *cmp functions */ - args[j++] = "-Wl,--wrap=strcmp"; - args[j++] = "-Wl,--wrap=strcasecmp"; - args[j++] = "-Wl,--wrap=stricmp"; - args[j++] = "-Wl,--wrap=strncmp"; - args[j++] = "-Wl,--wrap=strncasecmp"; - args[j++] = "-Wl,--wrap=strnicmp"; - args[j++] = "-Wl,--wrap=strstr"; - args[j++] = "-Wl,--wrap=strcasestr"; - args[j++] = "-Wl,--wrap=memcmp"; - args[j++] = "-Wl,--wrap=bcmp"; - args[j++] = "-Wl,--wrap=memmem"; - args[j++] = "-Wl,--wrap=strcpy"; - /* Apache httpd */ - args[j++] = "-Wl,--wrap=ap_cstr_casecmp"; - args[j++] = "-Wl,--wrap=ap_cstr_casecmpn"; - args[j++] = "-Wl,--wrap=ap_strcasestr"; - args[j++] = "-Wl,--wrap=apr_cstr_casecmp"; - args[j++] = "-Wl,--wrap=apr_cstr_casecmpn"; - /* *SSL */ - args[j++] = "-Wl,--wrap=CRYPTO_memcmp"; - args[j++] = "-Wl,--wrap=OPENSSL_memcmp"; - args[j++] = "-Wl,--wrap=OPENSSL_strcasecmp"; - args[j++] = "-Wl,--wrap=OPENSSL_strncasecmp"; - args[j++] = "-Wl,--wrap=memcmpct"; - /* libXML2 */ - args[j++] = "-Wl,--wrap=xmlStrncmp"; - args[j++] = "-Wl,--wrap=xmlStrcmp"; - args[j++] = "-Wl,--wrap=xmlStrEqual"; - args[j++] = "-Wl,--wrap=xmlStrcasecmp"; - args[j++] = "-Wl,--wrap=xmlStrncasecmp"; - args[j++] = "-Wl,--wrap=xmlStrstr"; - args[j++] = "-Wl,--wrap=xmlStrcasestr"; - /* Samba */ - args[j++] = "-Wl,--wrap=memcmp_const_time"; - args[j++] = "-Wl,--wrap=strcsequal"; - /* LittleCMS */ - args[j++] = "-Wl,--wrap=cmsstrcasecmp"; - /* GLib */ - args[j++] = "-Wl,--wrap=g_strcmp0"; - args[j++] = "-Wl,--wrap=g_strcasecmp"; - args[j++] = "-Wl,--wrap=g_strncasecmp"; - args[j++] = "-Wl,--wrap=g_strstr_len"; - args[j++] = "-Wl,--wrap=g_ascii_strcasecmp"; - args[j++] = "-Wl,--wrap=g_ascii_strncasecmp"; - args[j++] = "-Wl,--wrap=g_str_has_prefix"; - args[j++] = "-Wl,--wrap=g_str_has_suffix"; - /* CUrl */ - args[j++] = "-Wl,--wrap=Curl_strcasecompare"; - args[j++] = "-Wl,--wrap=curl_strequal"; - args[j++] = "-Wl,--wrap=Curl_safe_strcasecompare"; - args[j++] = "-Wl,--wrap=Curl_strncasecompare"; - args[j++] = "-Wl,--wrap=curl_strnequal"; -#endif /* _HF_ARCH_DARWIN */ - - /* Pull modules defining the following symbols (if they exist) */ -#ifdef _HF_ARCH_DARWIN - args[j++] = "-Wl,-U,_HonggfuzzNetDriver_main"; - args[j++] = "-Wl,-U,_LIBHFUZZ_module_instrument"; - args[j++] = "-Wl,-U,_LIBHFUZZ_module_memorycmp"; -#else /* _HF_ARCH_DARWIN */ - args[j++] = "-Wl,-u,HonggfuzzNetDriver_main"; - args[j++] = "-Wl,-u,LIBHFUZZ_module_instrument"; - args[j++] = "-Wl,-u,LIBHFUZZ_module_memorycmp"; -#endif /* _HF_ARCH_DARWIN */ - - for (int i = 1; i < argc; i++) { - args[j++] = argv[i]; - } - - /* Reference standard honggfuzz libraries first (libhfuzz, libhfcommon and libhfnetdriver) */ - args[j++] = getLibHFNetDriverPath(); - args[j++] = getLibHFuzzPath(); - args[j++] = getLibHFCommonPath(); - - /* Needed by libhfcommon */ - args[j++] = "-pthread"; -#if !defined(__NetBSD__) - args[j++] = "-ldl"; -#endif /* !defined(__NetBSD__) */ -#if !defined(_HF_ARCH_DARWIN) && !defined(__OpenBSD__) - args[j++] = "-lrt"; -#endif /* !defined(_HF_ARCH_DARWIN) && !defined(__OpenBSD__) */ -#if defined(__ANDROID__) - args[j++] = "-latomic"; -#endif - - commonPostOpts(&j, args); - - return execCC(j, args); -} - -static bool baseNameContains(const char* path, const char* str) { - if (strstr(_basename(path), str)) { - return true; - } - return false; -} - -int main(int argc, char** argv) { - if (baseNameContains(argv[0], "++")) { - isCXX = true; - } - if (baseNameContains(argv[0], "-gcc")) { - isGCC = true; - } - if (baseNameContains(argv[0], "-g++")) { - isGCC = true; - } - if (baseNameContains(argv[0], "-pcguard-")) { - usePCGuard = true; - } - if (baseNameContains(argv[0], "-8bitcnt-")) { - usePCGuard = false; - } - hasCmdLineFSanitizeFuzzer = hasFSanitizeFuzzer(argc, argv); - - if (argc <= 1) { - return execCC(argc, argv); - } - if (argc > (ARGS_MAX - 128)) { - LOG_F("'%s': Too many positional arguments: %d", argv[0], argc); - return EXIT_FAILURE; - } - - if (isLDMode(argc, argv)) { - return ldMode(argc, argv); - } - return ccMode(argc, argv); -} |