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