blob: 79b00381a54e56bb5ea809b8182ad09a2e140936 [file] [log] [blame]
Robert Swieckia88f96f2015-10-09 16:47:39 +02001/*
2
3 honggfuzz - cmdline parsing
4
5 -----------------------------------------
6
7 Copyright 2014 Google Inc. All Rights Reserved.
8
9 Licensed under the Apache License, Version 2.0 (the "License");
10 you may not use this file except in compliance with the License.
11 You may obtain a copy of the License at
12
13 http://www.apache.org/licenses/LICENSE-2.0
14
15 Unless required by applicable law or agreed to in writing, software
16 distributed under the License is distributed on an "AS IS" BASIS,
17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 See the License for the specific language governing permissions and
19 limitations under the License.
20
21*/
22
23#include "cmdline.h"
24
25#include <ctype.h>
26#include <errno.h>
27#include <getopt.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020028#include <inttypes.h>
29#include <limits.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020030#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020033#include <unistd.h>
34
35#include "common.h"
36#include "log.h"
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +020037#include "files.h"
Robert Swiecki72d2bef2016-01-19 14:39:26 +010038#include "util.h"
Robert Swieckia88f96f2015-10-09 16:47:39 +020039
40struct custom_option {
41 struct option opt;
42 const char *descr;
43};
44
45static bool checkFor_FILE_PLACEHOLDER(char **args)
46{
47 for (int x = 0; args[x]; x++) {
48 if (strstr(args[x], _HF_FILE_PLACEHOLDER))
49 return true;
50 }
51 return false;
52}
53
54static const char *cmdlineYesNo(bool yes)
55{
56 return (yes ? "true" : "false");
57}
58
59static void cmdlineHelp(const char *pname, struct custom_option *opts)
60{
61 LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
62 LOG_HELP_BOLD("Options:");
63 for (int i = 0; opts[i].opt.name; i++) {
64 if (isprint(opts[i].opt.val)) {
65 LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name,
66 "|-", opts[i].opt.val,
Robert Swieckibf063db2016-02-16 18:42:00 +010067 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020068 } else {
69 LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
Robert Swieckibf063db2016-02-16 18:42:00 +010070 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020071 }
72 LOG_HELP("\t%s", opts[i].descr);
73 }
Jagger32127372015-10-09 23:07:38 +020074 LOG_HELP_BOLD("\nExamples:");
75 LOG_HELP(" Run the binary over a mutated file chosen from the directory");
76 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
77 LOG_HELP(" As above, provide input over STDIN:");
Robert Swiecki72d2bef2016-01-19 14:39:26 +010078 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg");
Robert Swieckia88f96f2015-10-09 16:47:39 +020079#if defined(_HF_ARCH_LINUX)
Jagger32127372015-10-09 23:07:38 +020080 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
Jagger72f258b2015-10-09 23:09:01 +020081 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_instr -- /usr/bin/tiffinfo -D "
82 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020083 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of branches:");
Jagger72f258b2015-10-09 23:09:01 +020084 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
85 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020086 LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks (coverage):");
87 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ip -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
88 LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges):");
Jagger72f258b2015-10-09 23:09:01 +020089 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ip_addr -- /usr/bin/tiffinfo -D "
90 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020091 LOG_HELP(" Run the binary over a dynamic file, maximize custom counters (experimental):");
Jagger72f258b2015-10-09 23:09:01 +020092 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_custom -- /usr/bin/tiffinfo -D "
93 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +020094#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +020095}
96
97static void cmdlineUsage(const char *pname, struct custom_option *opts)
98{
99 cmdlineHelp(pname, opts);
100 exit(0);
101}
102
Robert Swieckia88f96f2015-10-09 16:47:39 +0200103rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
104{
105 struct rlimit cur;
106 if (getrlimit(res, &cur) == -1) {
107 PLOG_F("getrlimit(%d)", res);
108 }
109 if (strcasecmp(optarg, "max") == 0) {
110 return cur.rlim_max;
111 }
112 if (strcasecmp(optarg, "def") == 0) {
113 return cur.rlim_cur;
114 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200115 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200116 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
117 }
118 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200119 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200120 PLOG_F("strtoul('%s', 0)", optarg);
121 }
122 return val;
123}
124
125bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
126{
127 /* *INDENT-OFF* */
128 (*hfuzz) = (honggfuzz_t) {
129 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100130 .cmdline_txt[0] = '\0',
Robert Swieckia88f96f2015-10-09 16:47:39 +0200131 .inputFile = NULL,
132 .nullifyStdio = false,
133 .useScreen = true,
134 .fuzzStdin = false,
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700135 .useVerifier = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200136 .saveUnique = true,
137 .fileExtn = "fuzz",
138 .workDir = ".",
139 .flipRate = 0.001f,
140 .externalCommand = NULL,
141 .dictionaryFile = NULL,
142 .dictionary = NULL,
143 .dictionaryCnt = 0,
144 .blacklistFile = NULL,
145 .blacklistCnt = 0,
146 .blacklist = NULL,
147 .maxFileSz = (1024 * 1024),
148 .tmOut = 3,
149 .mutationsMax = 0,
150 .threadsFinished = 0,
151 .threadsMax = 2,
152 .reportFile = NULL,
153 .asLimit = 0ULL,
154 .files = NULL,
155 .fileCnt = 0,
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200156 .lastCheckedFileIndex = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200157 .pid = 0,
Jaggercdbf6852016-02-07 22:06:02 +0100158 .exeFd = -1,
Jagger80041fe2016-03-10 21:32:35 +0100159 .clearEnv = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200160 .envs = {[0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,},
161
162 .timeStart = time(NULL),
163 .mutationsCnt = 0,
164 .crashesCnt = 0,
165 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200166 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200167 .blCrashesCnt = 0,
168 .timeoutedCnt = 0,
169
170 .dynFileMethod = _HF_DYNFILE_NONE,
171 .dynamicFileBest = NULL,
172 .dynamicFileBestSz = 1,
173 .hwCnts = {
174 .cpuInstrCnt = 0ULL,
175 .cpuBranchCnt = 0ULL,
Jagger39bd2b02016-02-04 01:16:15 +0100176 .cpuBtsBlockCnt = 0ULL,
177 .cpuBtsEdgeCnt = 0ULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200178 .customCnt = 0ULL,
179 },
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200180 .sanCovCnts = {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200181 .hitBBCnt = 0ULL,
182 .totalBBCnt = 0ULL,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200183 .dsoCnt = 0ULL,
184 .iDsoCnt = 0ULL,
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200185 .newBBCnt = 0ULL,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200186 .crashesCnt = 0ULL,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200187 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200188 .dynamicCutOffAddr = ~(0ULL),
189 .dynamicFile_mutex = PTHREAD_MUTEX_INITIALIZER,
190
191 .disableRandomization = true,
192 .msanReportUMRS = false,
193 .ignoreAddr = NULL,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200194 .useSanCov = false,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200195 .covMetadata = NULL,
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200196 .clearCovMetadata = false,
Anestis Bechtsoudis02b99be2015-12-27 11:53:01 +0200197 .dynFileIterExpire = _HF_MAX_DYNFILE_ITER,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200198 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Anestis Bechtsoudisac054802016-01-07 23:48:06 +0200199 .workersBlock_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100200 .sanOpts = {
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200201 .asanOpts = NULL,
202 .msanOpts = NULL,
203 .ubsanOpts = NULL,
204 },
205 .numMajorFrames = 7,
Anestis Bechtsoudisa1f8a032016-01-14 16:45:30 +0200206 .isDynFileLocked = false,
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200207 .pidFile = NULL,
Anestis Bechtsoudis7c88d7a2016-02-09 17:55:38 +0200208 .pidCmd = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200209 };
210 /* *INDENT-ON* */
211
212 /* *INDENT-OFF* */
213 struct custom_option custom_opts[] = {
214 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
215 {{"input", required_argument, NULL, 'f'}, "Path to the file corpus (file or a directory)"},
216 {{"nullify_stdio", no_argument, NULL, 'q'}, "Null-ify children's stdin, stdout, stderr; make them quiet"},
217 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
218 {{"save_all", no_argument, NULL, 'u'}, "Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200219 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200220 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Anestis Bechtsoudis4a3c8e82015-11-07 18:59:14 +0200221#if defined(_HF_ARCH_LINUX) || defined(_HF_ARCH_DARWIN)
Jagger5ff08ac2016-02-09 22:15:58 +0100222 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700223#endif
Robert Swieckia88f96f2015-10-09 16:47:39 +0200224 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
225 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
226 {{"wokspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
227 {{"flip_rate", required_argument, NULL, 'r'}, "Maximal flip rate, (default: '0.001')"},
228 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
229 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
230 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command modifying the input corpus of files, instead of -r/-m parameters"},
231 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '3')"},
232 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: '2')"},
233 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200234 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100235 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200236 {{"max_file_size", required_argument, NULL, 'F'}, "Maximal size of files processed by the fuzzer in bytes (default: '1048576')"},
Jagger80041fe2016-03-10 21:32:35 +0100237 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200238 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger3db1d952016-03-10 02:02:46 +0100239 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200240
241#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200242 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
243 {{"linux_file_pid", required_argument, NULL, 'P'}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200244 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
245 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
246 {{"linux_report_msan_umrs", no_argument, NULL, 0x502}, "Report MSAN's UMRS (uninitialized memory access)"},
Jaggerae6a4452015-10-14 17:34:43 +0200247 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200248 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
249 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100250 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
251 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
252 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks"},
Jagger39bd2b02016-02-04 01:16:15 +0100253 {{"linux_perf_custom", no_argument, NULL, 0x520}, "Custom counter (see the interceptor/ directory for examples)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200254#endif // defined(_HF_ARCH_LINUX)
255 {{0, 0, 0, 0}, NULL},
256 };
257 /* *INDENT-ON* */
258
259 struct option opts[ARRAYSIZE(custom_opts)];
260 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
261 opts[i] = custom_opts[i].opt;
262 }
263
264 enum llevel_t ll = INFO;
265 const char *logfile = NULL;
266 int opt_index = 0;
267 for (;;) {
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200268 int c = getopt_long(argc, argv, "-?hqvVsuf:d:e:W:r:c:F:t:R:n:N:l:p:P:g:E:w:B:C", opts,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200269 &opt_index);
270 if (c < 0)
271 break;
272
273 switch (c) {
274 case 'h':
275 case '?':
276 cmdlineUsage(argv[0], custom_opts);
277 break;
278 case 'f':
279 hfuzz->inputFile = optarg;
280 break;
281 case 'q':
282 hfuzz->nullifyStdio = true;
283 break;
284 case 'v':
285 hfuzz->useScreen = false;
286 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700287 case 'V':
288 hfuzz->useVerifier = true;
289 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200290 case 's':
291 hfuzz->fuzzStdin = true;
292 break;
293 case 'u':
294 hfuzz->saveUnique = false;
295 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200296 case 'l':
297 logfile = optarg;
298 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200299 case 'd':
300 ll = atoi(optarg);
301 break;
302 case 'e':
303 hfuzz->fileExtn = optarg;
304 break;
305 case 'W':
306 hfuzz->workDir = optarg;
307 break;
308 case 'r':
309 hfuzz->flipRate = strtod(optarg, NULL);
310 break;
311 case 'c':
312 hfuzz->externalCommand = optarg;
313 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200314 case 'C':
315 hfuzz->useSanCov = true;
316 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200317 case 'F':
318 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
319 break;
320 case 't':
321 hfuzz->tmOut = atol(optarg);
322 break;
323 case 'R':
324 hfuzz->reportFile = optarg;
325 break;
326 case 'n':
327 hfuzz->threadsMax = atol(optarg);
328 break;
329 case 'N':
330 hfuzz->mutationsMax = atol(optarg);
331 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200332 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200333 hfuzz->asLimit = strtoull(optarg, NULL, 0);
334 break;
Jagger80041fe2016-03-10 21:32:35 +0100335 case 0x101:
336 hfuzz->clearEnv = true;
337 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200338 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200339 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200340 LOG_E("-p '%s' is not a number", optarg);
341 return false;
342 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200343 hfuzz->pid = atoi(optarg);
Jagger9c4d1622015-10-16 01:40:17 +0200344 if (hfuzz->pid < 1) {
345 LOG_E("-p '%d' is invalid", hfuzz->pid);
346 return false;
347 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200348 break;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200349 case 'P':
350 hfuzz->pidFile = optarg;
351 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200352 case 'E':
353 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
354 if (hfuzz->envs[i] == NULL) {
355 hfuzz->envs[i] = optarg;
356 break;
357 }
358 }
359 break;
360 case 'w':
361 hfuzz->dictionaryFile = optarg;
362 break;
363 case 'B':
364 hfuzz->blacklistFile = optarg;
365 break;
366 case 0x500:
367 hfuzz->ignoreAddr = (void *)strtoul(optarg, NULL, 0);
368 break;
369 case 0x501:
370 hfuzz->disableRandomization = false;
371 break;
372 case 0x502:
373 hfuzz->msanReportUMRS = true;
374 break;
375 case 0x503:
Jagger0b21ebb2015-10-14 17:39:15 +0200376 hfuzz->dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200377 break;
378 case 0x510:
379 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
380 break;
381 case 0x511:
382 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
383 break;
384 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100385 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200386 break;
387 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100388 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200389 break;
390 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100391 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
392 break;
Jagger39bd2b02016-02-04 01:16:15 +0100393 case 0x520:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200394 hfuzz->dynFileMethod |= _HF_DYNFILE_CUSTOM;
395 break;
396 default:
397 cmdlineUsage(argv[0], custom_opts);
398 return false;
399 break;
400 }
401 }
Jagger72f258b2015-10-09 23:09:01 +0200402
Robert Swieckia88f96f2015-10-09 16:47:39 +0200403 if (logInitLogFile(logfile, ll) == false) {
404 return false;
405 }
406
407 hfuzz->cmdline = &argv[optind];
408 if (hfuzz->cmdline[0] == NULL) {
409 LOG_E("No fuzz command provided");
410 cmdlineUsage(argv[0], custom_opts);
411 return false;
412 }
413
414 if (hfuzz->dynamicFileBestSz > hfuzz->maxFileSz) {
415 LOG_E("Initial dynamic file size cannot be larger than maximum file size (%zu > %zu)",
416 hfuzz->dynamicFileBestSz, hfuzz->maxFileSz);
417 return false;
418 }
419
420 if ((hfuzz->dynamicFileBest = malloc(hfuzz->maxFileSz)) == NULL) {
421 LOG_E("malloc(%zu) failed", hfuzz->maxFileSz);
422 return false;
423 }
424
425 if (!hfuzz->fuzzStdin && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
426 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
427 "' when the -s (stdin fuzzing) option is not set");
428 return false;
429 }
430
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200431 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE && hfuzz->useSanCov) {
432 LOG_E("You cannot enable sanitizer coverage & perf feedback at the same time");
433 return false;
434 }
435
Anestis Bechtsoudisbd650542015-12-26 18:10:32 +0200436 /* Sanity checks for timeout. Optimal ranges highly depend on target */
437 if (hfuzz->useSanCov && hfuzz->tmOut < 15) {
Anestis Bechtsoudisebea8452015-12-26 18:05:40 +0200438 LOG_E("Timeout value (%ld) too small for sanitizer coverage feedback", hfuzz->tmOut);
439 return false;
440 }
441
Robert Swieckia88f96f2015-10-09 16:47:39 +0200442 if (strchr(hfuzz->fileExtn, '/')) {
443 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
444 return false;
445 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200446
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200447 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200448 if (!files_exists(hfuzz->workDir)) {
449 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
450 return false;
451 }
452 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200453
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200454 if (hfuzz->pid > 0 || hfuzz->pidFile) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200455 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1", hfuzz->pid);
456 hfuzz->threadsMax = 1;
457 }
458
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200459 if (hfuzz->flipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200460 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200461 }
462
Robert Swieckia88f96f2015-10-09 16:47:39 +0200463 LOG_I("inputFile '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Anestis Bechtsoudisc9473322015-10-09 12:59:17 -0700464 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn '%s', ignoreAddr: %p, "
Robert Swieckia88f96f2015-10-09 16:47:39 +0200465 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d",
466 hfuzz->inputFile,
467 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
468 cmdlineYesNo(hfuzz->saveUnique), hfuzz->flipRate,
469 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
470 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn, hfuzz->ignoreAddr,
471 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->pid);
472
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100473 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100474 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
475 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
476 }
477
Robert Swieckia88f96f2015-10-09 16:47:39 +0200478 return true;
479}