1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20
21 #include "fuzz.h"
22
23 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
24
25 #include <dirent.h>
26
27 static void
test_one_file(const char * filename)28 test_one_file(const char *filename) {
29 int fd;
30 struct stat st;
31 char *data;
32 ssize_t n;
33
34 if ((fd = open(filename, O_RDONLY)) == -1) {
35 fprintf(stderr, "Failed to open %s: %s\n", filename,
36 strerror(errno));
37 return;
38 }
39
40 if (fstat(fd, &st) != 0) {
41 fprintf(stderr, "Failed to stat %s: %s\n", filename,
42 strerror(errno));
43 goto closefd;
44 }
45
46 data = malloc(st.st_size);
47 n = read(fd, data, st.st_size);
48 if (n == st.st_size) {
49 printf("testing %zd bytes from %s\n", n, filename);
50 fflush(stdout);
51 LLVMFuzzerTestOneInput((const uint8_t *)data, n);
52 fflush(stderr);
53 } else {
54 if (n < 0) {
55 fprintf(stderr,
56 "Failed to read %zd bytes from %s: %s\n",
57 (ssize_t)st.st_size, filename, strerror(errno));
58 } else {
59 fprintf(stderr,
60 "Failed to read %zd bytes from %s, got %zd\n",
61 (ssize_t)st.st_size, filename, n);
62 }
63 }
64 free(data);
65 closefd:
66 close(fd);
67 }
68
69 static void
test_all_from(const char * dirname)70 test_all_from(const char *dirname) {
71 DIR *dirp;
72 struct dirent *dp;
73
74 dirp = opendir(dirname);
75 if (dirp == NULL) {
76 return;
77 }
78
79 while ((dp = readdir(dirp)) != NULL) {
80 char filename[strlen(dirname) + strlen(dp->d_name) + 2];
81
82 if (dp->d_name[0] == '.') {
83 continue;
84 }
85 snprintf(filename, sizeof(filename), "%s/%s", dirname,
86 dp->d_name);
87 test_one_file(filename);
88 }
89
90 closedir(dirp);
91 }
92
93 int
main(int argc,char ** argv)94 main(int argc, char **argv) {
95 char corpusdir[PATH_MAX];
96 const char *target = strrchr(argv[0], '/');
97
98 (void)LLVMFuzzerInitialize(&argc, &argv);
99
100 if (argv[1] != NULL && strcmp(argv[1], "-d") == 0) {
101 debug = true;
102 argv++;
103 argc--;
104 }
105
106 if (argv[1] != NULL) {
107 while (argv[1] != NULL) {
108 test_one_file(argv[1]);
109 argv++;
110 argc--;
111 }
112 POST(argc);
113 return (0);
114 }
115
116 target = (target != NULL) ? target + 1 : argv[0];
117 if (strncmp(target, "lt-", 3) == 0) {
118 target += 3;
119 }
120
121 snprintf(corpusdir, sizeof(corpusdir), FUZZDIR "/%s.in", target);
122
123 test_all_from(corpusdir);
124
125 return (0);
126 }
127
128 #elif __AFL_COMPILER
129
130 int
main(int argc,char ** argv)131 main(int argc, char **argv) {
132 int ret;
133 unsigned char buf[64 * 1024];
134
135 (void)LLVMFuzzerInitialize(&argc, &argv);
136
137 #ifdef __AFL_LOOP
138 while (__AFL_LOOP(10000)) { /* only works with afl-clang-fast */
139 #else /* ifdef __AFL_LOOP */
140 {
141 #endif /* ifdef __AFL_LOOP */
142 ret = fread(buf, 1, sizeof(buf), stdin);
143 if (ret < 0) {
144 return (0);
145 }
146
147 LLVMFuzzerTestOneInput(buf, ret);
148 }
149
150 return (0);
151 }
152
153 #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
154