• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LLVMFuzzerInitialize(int * argc HF_ATTR_UNUSED,char *** argv HF_ATTR_UNUSED)25 __attribute__((weak)) int LLVMFuzzerInitialize(
26     int* argc HF_ATTR_UNUSED, char*** argv HF_ATTR_UNUSED) {
27     return 1;
28 }
29 
LLVMFuzzerMutate(uint8_t * Data HF_ATTR_UNUSED,size_t Size HF_ATTR_UNUSED,size_t MaxSize HF_ATTR_UNUSED)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 
LLVMFuzzerTestOneInput(const uint8_t * buf HF_ATTR_UNUSED,size_t len HF_ATTR_UNUSED)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;
initializePersistent(void)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 
HF_ITER(const uint8_t ** buf_ptr,size_t * len_ptr)55 void HF_ITER(const uint8_t** buf_ptr, size_t* len_ptr) {
56     HonggfuzzFetchData(buf_ptr, len_ptr);
57 }
58 
HonggfuzzRunOneInput(const uint8_t * buf,size_t len)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 
HonggfuzzPersistentLoop(void)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 
HonggfuzzRunFromFile(int argc,char ** argv)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 
HonggfuzzMain(int argc,char ** argv)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__) */
main(int argc,char ** argv)123 int main(int argc, char** argv) {
124     return HonggfuzzMain(argc, argv);
125 }
126