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