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