blob: 080be8a339e27b580176a64516507ef746025cec [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +00003 * honggfuzz - the main file
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com8531f692015-02-17 12:25:36 +00006 * Author:
7 * Robert Swiecki <swiecki@google.com>
8 * Felix Gröbert <groebert@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000010 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000011 *
12 * Licensed under the Apache License, Version 2.0 (the "License"); you may
13 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000017 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000018 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
21 * implied. See the License for the specific language governing
22 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000023 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000024 */
robert.swiecki3bb518c2010-10-14 00:48:24 +000025
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000026#include <getopt.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000027#include <stdio.h>
28#include <stdlib.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000029#include <string.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000030#include <time.h>
31#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000032
33#include "common.h"
34#include "log.h"
35#include "files.h"
36#include "fuzz.h"
37#include "util.h"
38
robert.swiecki3d505e22010-10-14 01:17:17 +000039#define AB ANSI_BOLD
40#define AC ANSI_CLEAR
41#define ANSI_BOLD "\033[1m"
42#define ANSI_CLEAR "\033[0m"
43
robert.swiecki3bb518c2010-10-14 00:48:24 +000044static bool checkFor_FILE_PLACEHOLDER(char **args)
45{
46 for (int x = 0; args[x]; x++) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000047 if (!strcmp(args[x], _HF_FILE_PLACEHOLDER))
robert.swiecki3bb518c2010-10-14 00:48:24 +000048 return true;
49 }
50 return false;
51}
52
groebert@google.com76afff92013-06-20 14:43:41 +000053static void usage(bool exit_success)
robert.swiecki3bb518c2010-10-14 00:48:24 +000054{
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000055 /* *INDENT-OFF* */
robert.swiecki3bb518c2010-10-14 00:48:24 +000056 printf("%s",
robert.swiecki@gmail.comcdf18f92015-02-11 22:22:18 +000057 " <" AB "-f val" AC "> : directory with input files (or a path to a single input file)\n"
58 " [" AB "-h" AC "] : this help\n"
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +000059 " [" AB "-q" AC "] : null-ify children's stdin, stdout, stderr; make them quiet\n"
60 " (default: " AB "false" AC ")\n"
61 " [" AB "-s" AC "] : provide fuzzing input on STDIN, instead a file argument\n"
62 " (default: " AB "false" AC ")\n"
robert.swiecki@gmail.comcdf18f92015-02-11 22:22:18 +000063 " [" AB "-u" AC "] : save unique test-cases only, otherwise (if not used) append\n"
64 " current timestamp to the output filenames (default: " AB "false" AC ")\n"
65 " [" AB "-d val" AC "] : debug level (0 - FATAL ... 4 - DEBUG), (default: '" AB "3" AC
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000066 "' [INFO])\n"
robert.swiecki@gmail.comcdf18f92015-02-11 22:22:18 +000067 " [" AB "-e val" AC "] : file extension (e.g swf), (default: '" AB "fuzz" AC "')\n"
68 " [" AB "-r val" AC "] : flip rate, (default: '" AB "0.001" AC "')\n"
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +000069 " [" AB "-c val" AC "] : external command modifying the input corpus of files,\n"
70 " instead of -r/-m (default: " AB "none" AC "\n"
robert.swiecki@gmail.comcdf18f92015-02-11 22:22:18 +000071 " [" AB "-t val" AC "] : timeout (in secs), (default: '" AB "3" AC "' [0 - no timeout])\n"
72 " [" AB "-a val" AC "] : address limit (from si.si_addr) below which crashes\n"
73 " are not reported, (default: '" AB "0" AC "' [suggested: 65535])\n"
74 " [" AB "-n val" AC "] : number of concurrent fuzzing processes, (default: '" AB "5" AC "')\n"
75 " [" AB "-N val" AC "] : number of fuzzing mutations, (default: '" AB "0" AC "' [infinte])\n"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000076 " [" AB "-l val" AC "] : per process memory limit in MiB, (default: '" AB "0" AC "' [no limit])\n"
77 " [" AB "-R val" AC "] : write report to this file, (default: '" AB _HF_REPORT_FILE AC "')\n"
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +000078#if _HF_ARCH == LINUX
79 " [" AB "-p val" AC "] : [Linux] attach to a pid (and its group thread), instead of \n"
80 " monitoring previously created process, default: '" AB "0" AC "' (none)\n"
81 " [" AB "-D val" AC "] : [Linux] create a file dynamically with Linux perf counters,\n"
82 " can be used with or without the '-f' flag (initial file contents)\n"
83 " (default: " AB " none " AC ")\n"
84 " Available counters: \n"
85 " " AB "'i' " AC "- PERF_COUNT_HW_INSTRUCTIONS\n"
86 " " AB "'b' " AC "- PERF_COUNT_HW_BRANCH_INSTRUCTIONS\n"
robert.swiecki@gmail.com34c18fe2015-02-19 18:36:54 +000087 " " AB "'a' " AC "- PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_BRANCH_ANY\n"
88 " " AB "'c' " AC "- PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_BRANCH_ANY_CALL\n"
89 " " AB "'r' " AC "- PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_BRANCH_ANY_RETURN\n"
robert.swiecki@gmail.comc63e1d52015-02-19 18:48:38 +000090 " " AB "'n' " AC "- PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_BRANCH_IND_CALL\n"
robert.swiecki@gmail.com2e11b342015-02-20 17:48:25 +000091 " " AB "'o' " AC "- PERF_SAMPLE_BRANCH_STACK/PERF_SAMPLE_BRANCH_COND\n"
robert.swiecki@gmail.comcd74cfc2015-02-19 16:37:49 +000092 " [" AB "-F val" AC "] : [Linux] Maximal size of a dynamic file (-D)\n"
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +000093#endif /* _HF_ARCH == "LINUX" */
robert.swiecki@gmail.com34a40702015-02-02 20:43:27 +000094 "Usage:"
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000095 AB " " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER AC "\n");
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000096 /* *INDENT-ON* */
groebert@google.com76afff92013-06-20 14:43:41 +000097
98 if (exit_success) {
robert.swiecki@gmail.comc6d28752014-01-08 12:02:37 +000099 exit(EXIT_SUCCESS);
groebert@google.com76afff92013-06-20 14:43:41 +0000100 } else {
robert.swiecki@gmail.comc6d28752014-01-08 12:02:37 +0000101 exit(EXIT_FAILURE);
groebert@google.com76afff92013-06-20 14:43:41 +0000102 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000103}
104
105int main(int argc, char **argv)
106{
robert.swiecki@gmail.com5b935792011-06-01 16:30:09 +0000107 int c;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000108 int ll = l_INFO;
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000109 honggfuzz_t hfuzz = {
robert.swiecki@gmail.com5f6b2e72015-02-02 22:17:37 +0000110 .cmdline = NULL,
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000111 .inputFile = NULL,
112 .nullifyStdio = false,
113 .fuzzStdin = false,
114 .saveUnique = false,
115 .fileExtn = "fuzz",
116 .flipRate = 0.001f,
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000117 .externalCommand = NULL,
robert.swiecki@gmail.com4da86bf2015-02-22 14:24:58 +0000118 .maxFileSz = (1024 * 1024 * 32),
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000119 .tmOut = 3,
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000120 .mutationsMax = 0,
121 .mutationsCnt = 0,
122 .threadsMax = 5,
robert.swiecki@gmail.com5f6b2e72015-02-02 22:17:37 +0000123 .ignoreAddr = NULL,
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000124 .reportFile = _HF_REPORT_FILE,
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000125 .asLimit = 0UL,
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000126 .files = NULL,
robert.swiecki@gmail.com5f6b2e72015-02-02 22:17:37 +0000127 .fileCnt = 0,
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +0000128 .pid = 0,
robert.swiecki@gmail.comcac22fd2015-02-19 14:03:28 +0000129 .dynFileMethod = _HF_DYNFILE_NONE,
robert.swiecki@gmail.com4da86bf2015-02-22 14:24:58 +0000130 .dynamicFileBest = alloca(1),
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000131 .dynamicFileBestSz = 1,
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000132 .branchBestCnt = 0,
robert.swiecki@gmail.com85a0a952015-02-19 01:58:39 +0000133 .branchBestCntIni = 0,
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +0000134 .dynamicFile_mutex = PTHREAD_MUTEX_INITIALIZER,
robert.swiecki@gmail.com327f7502015-02-02 21:10:55 +0000135 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000136
robert.swiecki@gmail.come68a71c2015-02-01 16:13:00 +0000137 printf(AB PROG_NAME " version " PROG_VERSION " by " PROG_AUTHORS AC "\n");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000138 if (argc < 2) {
groebert@google.com76afff92013-06-20 14:43:41 +0000139 usage(true);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000140 }
141
142 for (;;) {
robert.swiecki@gmail.com4da86bf2015-02-22 14:24:58 +0000143 c = getopt(argc, argv, "?hqsuf:d:e:r:c:F:D:t:a:R:n:N:l:p:b:");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000144 if (c < 0)
145 break;
146
147 switch (c) {
148 case 'f':
149 hfuzz.inputFile = optarg;
150 break;
151 case 'h':
robert.swiecki@gmail.comd7aed312015-02-03 21:26:37 +0000152 case '?':
groebert@google.com76afff92013-06-20 14:43:41 +0000153 usage(true);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000154 break;
155 case 'q':
156 hfuzz.nullifyStdio = true;
157 break;
158 case 's':
159 hfuzz.fuzzStdin = true;
160 break;
161 case 'u':
162 hfuzz.saveUnique = true;
163 break;
164 case 'd':
165 ll = atoi(optarg);
166 break;
167 case 'e':
168 hfuzz.fileExtn = optarg;
169 break;
170 case 'r':
171 hfuzz.flipRate = atof(optarg);
172 break;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000173 case 'c':
174 hfuzz.externalCommand = optarg;
175 break;
robert.swiecki@gmail.com4da86bf2015-02-22 14:24:58 +0000176 case 'F':
177 hfuzz.maxFileSz = strtoul(optarg, NULL, 0);
178 break;
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000179 case 'D':
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +0000180 switch (optarg[0]) {
181 case 'i':
robert.swiecki@gmail.comcac22fd2015-02-19 14:03:28 +0000182 hfuzz.dynFileMethod = _HF_DYNFILE_INSTR_COUNT;
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +0000183 break;
184 case 'b':
robert.swiecki@gmail.comcac22fd2015-02-19 14:03:28 +0000185 hfuzz.dynFileMethod = _HF_DYNFILE_BRANCH_COUNT;
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +0000186 break;
robert.swiecki@gmail.com34c18fe2015-02-19 18:36:54 +0000187 case 'a':
188 hfuzz.dynFileMethod = _HF_DYNFILE_EDGE_ANY_COUNT;
189 break;
190 case 'c':
191 hfuzz.dynFileMethod = _HF_DYNFILE_EDGE_CALL_COUNT;
192 break;
193 case 'r':
194 hfuzz.dynFileMethod = _HF_DYNFILE_EDGE_RETURN_COUNT;
195 break;
196 case 'n':
197 hfuzz.dynFileMethod = _HF_DYNFILE_EDGE_IND_COUNT;
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +0000198 break;
robert.swiecki@gmail.com2e11b342015-02-20 17:48:25 +0000199 case 'o':
200 hfuzz.dynFileMethod = _HF_DYNFILE_EDGE_COND_COUNT;
201 break;
robert.swiecki@gmail.com341dd122015-02-18 13:05:20 +0000202 default:
203 usage(EXIT_FAILURE);
204 break;
205 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000206 case 't':
207 hfuzz.tmOut = atol(optarg);
208 break;
209 case 'a':
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +0000210 hfuzz.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000211 break;
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000212 case 'R':
213 hfuzz.reportFile = optarg;
214 break;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000215 case 'n':
216 hfuzz.threadsMax = atol(optarg);
217 break;
groebert@google.com8e2f44a2013-03-15 13:54:18 +0000218 case 'N':
219 hfuzz.mutationsMax = atol(optarg);
220 break;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000221 case 'l':
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +0000222 hfuzz.asLimit = strtoul(optarg, NULL, 0);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000223 break;
robert.swiecki28cba5c2011-06-22 01:38:55 +0000224 case 'p':
225 hfuzz.pid = atoi(optarg);
226 break;
robert.swiecki@gmail.com85a0a952015-02-19 01:58:39 +0000227 case 'b':
228 hfuzz.branchBestCntIni = atoi(optarg);
229 break;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000230 default:
231 break;
232 }
233 }
234 hfuzz.cmdline = &argv[optind];
235
robert.swiecki3bb518c2010-10-14 00:48:24 +0000236 log_setMinLevel(ll);
237
238 if (!hfuzz.cmdline[0]) {
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +0000239 LOGMSG(l_FATAL, "Please specify a binary to fuzz");
groebert@google.com76afff92013-06-20 14:43:41 +0000240 usage(false);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000241 }
242
243 if (!hfuzz.fuzzStdin && !checkFor_FILE_PLACEHOLDER(hfuzz.cmdline)) {
244 LOGMSG(l_FATAL,
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000245 "You must specify '" _HF_FILE_PLACEHOLDER
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000246 "' when the -s (stdin fuzzing) option is not set");
groebert@google.com76afff92013-06-20 14:43:41 +0000247 usage(false);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000248 }
249
250 if (strchr(hfuzz.fileExtn, '/')) {
251 LOGMSG(l_FATAL, "The file extension contains the '/' character: '%s'", hfuzz.fileExtn);
groebert@google.com76afff92013-06-20 14:43:41 +0000252 usage(false);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000253 }
254
255 LOGMSG(l_INFO,
256 "debugLevel: %d, inputFile '%s', nullifyStdio: %d, fuzzStdin: %d, saveUnique: %d, flipRate: %lf, "
robert.swiecki@gmail.com4da86bf2015-02-22 14:24:58 +0000257 "externalCommand: '%s', tmOut: %ld, mutationsMax: %ld, threadsMax: %ld, fileExtn '%s', ignoreAddr: %p, "
robert.swiecki28cba5c2011-06-22 01:38:55 +0000258 "memoryLimit: %lu (MiB), fuzzExe: '%s', fuzzedPid: %d",
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000259 ll, hfuzz.inputFile, hfuzz.nullifyStdio ? 1 : 0,
260 hfuzz.fuzzStdin ? 1 : 0, hfuzz.saveUnique ? 1 : 0,
robert.swiecki@gmail.com4da86bf2015-02-22 14:24:58 +0000261 hfuzz.flipRate,
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000262 hfuzz.externalCommand == NULL ? "NULL" : hfuzz.externalCommand,
263 hfuzz.tmOut, hfuzz.mutationsMax, hfuzz.threadsMax,
264 hfuzz.fileExtn, hfuzz.ignoreAddr, hfuzz.asLimit, hfuzz.cmdline[0], hfuzz.pid);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000265
robert.swiecki3bb518c2010-10-14 00:48:24 +0000266 if (!files_init(&hfuzz)) {
267 LOGMSG(l_FATAL, "Couldn't load input files");
268 exit(EXIT_FAILURE);
269 }
270
271 /*
272 * So far so good
273 */
274 fuzz_main(&hfuzz);
275
276 abort(); /* NOTREACHED */
277 return EXIT_SUCCESS;
278}