• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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