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