Home | History | Annotate | Download | only in libhfuzz
      1 #include "libhfuzz/libhfuzz.h"
      2 
      3 #include <errno.h>
      4 #include <fcntl.h>
      5 #include <inttypes.h>
      6 #include <limits.h>
      7 #include <signal.h>
      8 #include <stdbool.h>
      9 #include <stdint.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <sys/mman.h>
     14 #include <sys/stat.h>
     15 #include <sys/types.h>
     16 #include <unistd.h>
     17 
     18 #include "honggfuzz.h"
     19 #include "libhfcommon/common.h"
     20 #include "libhfcommon/files.h"
     21 #include "libhfcommon/log.h"
     22 #include "libhfuzz/fetch.h"
     23 #include "libhfuzz/instrument.h"
     24 
     25 __attribute__((weak)) int LLVMFuzzerInitialize(
     26     int* argc HF_ATTR_UNUSED, char*** argv HF_ATTR_UNUSED) {
     27     return 1;
     28 }
     29 
     30 __attribute__((weak)) size_t LLVMFuzzerMutate(
     31     uint8_t* Data HF_ATTR_UNUSED, size_t Size HF_ATTR_UNUSED, size_t MaxSize HF_ATTR_UNUSED) {
     32     LOG_F("LLVMFuzzerMutate() is not supported in honggfuzz yet");
     33     return 0;
     34 }
     35 
     36 __attribute__((weak)) int LLVMFuzzerTestOneInput(
     37     const uint8_t* buf HF_ATTR_UNUSED, size_t len HF_ATTR_UNUSED) {
     38     LOG_F("Define 'int LLVMFuzzerTestOneInput(uint8_t * buf, size_t len)' in your "
     39           "code to make it work");
     40     return 0;
     41 }
     42 
     43 static const uint8_t* inputFile = NULL;
     44 __attribute__((constructor)) static void initializePersistent(void) {
     45     if (fcntl(_HF_INPUT_FD, F_GETFD) == -1 && errno == EBADF) {
     46         return;
     47     }
     48     if ((inputFile = mmap(NULL, _HF_INPUT_MAX_SIZE, PROT_READ, MAP_SHARED, _HF_INPUT_FD, 0)) ==
     49         MAP_FAILED) {
     50         PLOG_F("mmap(fd=%d, size=%zu) of the input file failed", _HF_INPUT_FD,
     51             (size_t)_HF_INPUT_MAX_SIZE);
     52     }
     53 }
     54 
     55 void HF_ITER(const uint8_t** buf_ptr, size_t* len_ptr) {
     56     HonggfuzzFetchData(buf_ptr, len_ptr);
     57 }
     58 
     59 static void HonggfuzzRunOneInput(const uint8_t* buf, size_t len) {
     60     int ret = LLVMFuzzerTestOneInput(buf, len);
     61     if (ret != 0) {
     62         LOG_F("LLVMFuzzerTestOneInput() returned '%d' instead of '0'", ret);
     63     }
     64 }
     65 
     66 static void HonggfuzzPersistentLoop(void) {
     67     for (;;) {
     68         size_t len;
     69         const uint8_t* buf;
     70 
     71         HonggfuzzFetchData(&buf, &len);
     72         HonggfuzzRunOneInput(buf, len);
     73     }
     74 }
     75 
     76 static int HonggfuzzRunFromFile(int argc, char** argv) {
     77     int in_fd = STDIN_FILENO;
     78     const char* fname = "[STDIN]";
     79     if (argc > 1) {
     80         fname = argv[argc - 1];
     81         if ((in_fd = open(argv[argc - 1], O_RDONLY)) == -1) {
     82             PLOG_W("Cannot open '%s' as input, using stdin", argv[argc - 1]);
     83             in_fd = STDIN_FILENO;
     84             fname = "[STDIN]";
     85         }
     86     }
     87 
     88     LOG_I("Accepting input from '%s'", fname);
     89     LOG_I("Usage for fuzzing: honggfuzz -P [flags] -- %s", argv[0]);
     90 
     91     uint8_t* buf = (uint8_t*)util_Malloc(_HF_INPUT_MAX_SIZE);
     92     ssize_t len = files_readFromFd(in_fd, buf, _HF_INPUT_MAX_SIZE);
     93     if (len < 0) {
     94         LOG_E("Couldn't read data from stdin: %s", strerror(errno));
     95         free(buf);
     96         return -1;
     97     }
     98 
     99     HonggfuzzRunOneInput(buf, len);
    100     free(buf);
    101     return 0;
    102 }
    103 
    104 int HonggfuzzMain(int argc, char** argv) {
    105     LLVMFuzzerInitialize(&argc, &argv);
    106     instrumentClearNewCov();
    107 
    108     if (!fetchIsInputAvailable()) {
    109         return HonggfuzzRunFromFile(argc, argv);
    110     }
    111 
    112     HonggfuzzPersistentLoop();
    113     return 0;
    114 }
    115 
    116 /*
    117  * Declare it 'weak', so it can be safely linked with regular binaries which
    118  * implement their own main()
    119  */
    120 #if !defined(__CYGWIN__)
    121 __attribute__((weak))
    122 #endif /* !defined(__CYGWIN__) */
    123 int main(int argc, char** argv) {
    124     return HonggfuzzMain(argc, argv);
    125 }
    126