1 #include "libhfuzz/libhfuzz.h" 2 3 #include <errno.h> 4 #include <fcntl.h> 5 #include <limits.h> 6 #include <signal.h> 7 #include <stdbool.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 #include <unistd.h> 15 16 #include "honggfuzz.h" 17 #include "libcommon/common.h" 18 #include "libcommon/files.h" 19 #include "libcommon/log.h" 20 21 __attribute__((weak)) int LLVMFuzzerTestOneInput(const uint8_t* buf, size_t len); 22 __attribute__((weak)) int LLVMFuzzerInitialize(int* argc UNUSED, char*** argv UNUSED) { return 0; } 23 24 /* FIXME(robertswiecki): Make it call mangle_Mangle() */ 25 __attribute__((weak)) size_t LLVMFuzzerMutate( 26 uint8_t* Data UNUSED, size_t Size UNUSED, size_t MaxSize UNUSED) { 27 LOG_F("LLVMFuzzerMutate() is not supported in honggfuzz yet"); 28 return 0; 29 } 30 31 static uint8_t buf[_HF_PERF_BITMAP_SIZE_16M] = {0}; 32 33 void HF_ITER(const uint8_t** buf_ptr, size_t* len_ptr) { 34 /* 35 * Send the 'done' marker to the parent 36 */ 37 static bool initialized = false; 38 39 if (initialized == true) { 40 static const uint8_t readyTag = 'A'; 41 if (files_writeToFd(_HF_PERSISTENT_FD, &readyTag, sizeof(readyTag)) == false) { 42 LOG_F("writeToFd(size=%zu) failed", sizeof(readyTag)); 43 } 44 } 45 initialized = true; 46 47 uint32_t rlen; 48 if (files_readFromFd(_HF_PERSISTENT_FD, (uint8_t*)&rlen, sizeof(rlen)) != 49 (ssize_t)sizeof(rlen)) { 50 LOG_F("readFromFd(size=%zu) failed", sizeof(rlen)); 51 } 52 size_t len = (size_t)rlen; 53 if (len > _HF_PERF_BITMAP_SIZE_16M) { 54 LOG_F("len (%zu) > buf_size (%zu)\n", len, (size_t)_HF_PERF_BITMAP_SIZE_16M); 55 } 56 57 if (files_readFromFd(_HF_PERSISTENT_FD, buf, len) != (ssize_t)len) { 58 LOG_F("readFromFd(size=%zu) failed", len); 59 } 60 61 *buf_ptr = buf; 62 *len_ptr = len; 63 } 64 65 static void runOneInput(const uint8_t* buf, size_t len) { 66 int ret = LLVMFuzzerTestOneInput(buf, len); 67 if (ret != 0) { 68 LOG_F("LLVMFuzzerTestOneInput() returned '%d' instead of '0'", ret); 69 } 70 } 71 72 /* 73 * Declare it 'weak', so it can be safely linked with regular binaries which 74 * implement their own main() 75 */ 76 #if !defined(__CYGWIN__) 77 __attribute__((weak)) 78 #endif /* !defined(__CYGWIN__) */ 79 int main(int argc, char** argv) { 80 LLVMFuzzerInitialize(&argc, &argv); 81 if (LLVMFuzzerTestOneInput == NULL) { 82 LOG_F( 83 "Define 'int LLVMFuzzerTestOneInput(uint8_t * buf, size_t len)' in your " 84 "code to make it work"); 85 86 extern int hfuzz_module_instrument; 87 extern int hfuzz_module_memorycmp; 88 LOG_F( 89 "This won't be displayed, it's used just to reference other modules in this archive: " 90 "%d", 91 hfuzz_module_instrument + hfuzz_module_memorycmp); 92 } 93 94 if (fcntl(_HF_PERSISTENT_FD, F_GETFD) == -1 && errno == EBADF) { 95 int in_fd = STDIN_FILENO; 96 const char* fname = "[STDIN]"; 97 if (argc > 1) { 98 fname = argv[argc - 1]; 99 if ((in_fd = open(argv[argc - 1], O_RDONLY)) == -1) { 100 PLOG_W("Cannot open '%s' as input, using stdin", argv[argc - 1]); 101 in_fd = STDIN_FILENO; 102 fname = "[STDIN]"; 103 } 104 } 105 106 LOG_I( 107 "Accepting input from '%s'\n" 108 "Usage for fuzzing: honggfuzz -P [flags] -- %s", 109 fname, argv[0]); 110 111 ssize_t len = files_readFromFd(in_fd, buf, sizeof(buf)); 112 if (len < 0) { 113 LOG_E("Couldn't read data from stdin: %s", strerror(errno)); 114 return -1; 115 } 116 117 runOneInput(buf, len); 118 return 0; 119 } 120 121 for (;;) { 122 size_t len; 123 const uint8_t* buf; 124 125 HF_ITER(&buf, &len); 126 runOneInput(buf, len); 127 } 128 } 129