1 /*
2 * Copyright(c) 2017-2018 Tim Ruehsen
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *
22 * This file is part of libpsl.
23 */
24
25 #include <config.h>
26
27 #include <stdio.h>
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include <stdlib.h>
34
35 #ifdef HAVE_STDINT_H
36 #include <stdint.h>
37 #endif
38
39 #include <string.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 #include <sys/stat.h>
43
44 #if defined (_MSC_VER) && ! defined (ssize_t)
45 #include <basetsd.h>
46 typedef SSIZE_T ssize_t;
47 #endif
48
49 #include "fuzzer.h"
50
51 #if defined (TEST_RUN) && defined (HAVE_FMEMOPEN) && defined (HAVE_DIRENT_H)
52
53 #include <dirent.h>
54
test_all_from(const char * dirname)55 static void test_all_from(const char *dirname)
56 {
57 DIR *dirp;
58 struct dirent *dp;
59
60 if ((dirp = opendir(dirname))) {
61 while ((dp = readdir(dirp))) {
62 char fname[1024];
63 int fd;
64 struct stat st;
65 uint8_t *data;
66 ssize_t n;
67
68 if (*dp->d_name == '.') continue;
69
70 snprintf(fname, sizeof(fname), "%s/%s", dirname, dp->d_name);
71
72 if ((fd = open(fname, O_RDONLY)) == -1) {
73 fprintf(stderr, "Failed to open %s (%d)\n", fname, errno);
74 continue;
75 }
76
77 if (fstat(fd, &st) != 0) {
78 fprintf(stderr, "Failed to stat %d (%d)\n", fd, errno);
79 close(fd);
80 continue;
81 }
82
83 data = malloc(st.st_size);
84 if ((n = read(fd, data, st.st_size)) == st.st_size) {
85 printf("testing %d bytes from '%s'\n", (int) n, fname);
86 LLVMFuzzerTestOneInput(data, st.st_size);
87 } else
88 fprintf(stderr, "Failed to read %d bytes from %s (%d), got %d\n", (int) st.st_size, fname, errno, (int) n);
89
90 free(data);
91 close(fd);
92 }
93 closedir(dirp);
94 }
95 }
96
main(int argc,char ** argv)97 int main(int argc, char **argv)
98 {
99 /* if VALGRIND testing is enabled, we have to call ourselves with valgrind checking */
100 if (argc == 1) {
101 const char *valgrind = getenv("TESTS_VALGRIND");
102
103 if (valgrind && *valgrind) {
104 char cmd[1024];
105
106 snprintf(cmd, sizeof(cmd), "TESTS_VALGRIND="" %s %s", valgrind, argv[0]);
107 return system(cmd) != 0;
108 }
109 }
110
111 const char *target = strrchr(argv[0], '/');
112 target = target ? target + 1 : argv[0];
113
114 char corporadir[1024];
115 snprintf(corporadir, sizeof(corporadir), SRCDIR "/%s.in", target);
116
117 test_all_from(corporadir);
118
119 snprintf(corporadir, sizeof(corporadir), SRCDIR "/%s.repro", target);
120
121 test_all_from(corporadir);
122
123 return 0;
124 }
125
126 #else /* TEST_RUN && HAVE_FMEMOPEN && HAVE_DIRENT_H */
127
128 #ifndef __AFL_LOOP
__AFL_LOOP(int n)129 static int __AFL_LOOP(int n)
130 {
131 static int first = 1;
132
133 if (first) {
134 first = 0;
135 return 1;
136 }
137
138 return 0;
139 }
140 #endif
141
main(int argc,char ** argv)142 int main(int argc, char **argv)
143 {
144 #ifdef HAVE_FMEMOPEN
145 int ret;
146 unsigned char buf[64 * 1024];
147
148 while (__AFL_LOOP(10000)) { /* only works with afl-clang-fast */
149 ret = fread(buf, 1, sizeof(buf), stdin);
150 if (ret < 0)
151 return 0;
152
153 LLVMFuzzerTestOneInput(buf, ret);
154 }
155
156 return 0;
157 #else
158 exit (77);
159 #endif
160 }
161
162 #endif /* TEST_RUN && HAVE_FMEMOPEN && HAVE_DIRENT_H */
163