blob: c012ea7235d9b01324028ae1eafc385f8a26486d [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 Swiecki3bfc33c2016-03-14 18:12:41 +010033#include <sys/queue.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020034#include <unistd.h>
35
36#include "common.h"
37#include "log.h"
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +020038#include "files.h"
Robert Swiecki72d2bef2016-01-19 14:39:26 +010039#include "util.h"
Robert Swieckia88f96f2015-10-09 16:47:39 +020040
41struct custom_option {
42 struct option opt;
43 const char *descr;
44};
45
46static bool checkFor_FILE_PLACEHOLDER(char **args)
47{
48 for (int x = 0; args[x]; x++) {
49 if (strstr(args[x], _HF_FILE_PLACEHOLDER))
50 return true;
51 }
52 return false;
53}
54
55static const char *cmdlineYesNo(bool yes)
56{
57 return (yes ? "true" : "false");
58}
59
60static void cmdlineHelp(const char *pname, struct custom_option *opts)
61{
62 LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
63 LOG_HELP_BOLD("Options:");
64 for (int i = 0; opts[i].opt.name; i++) {
Robert Swieckif3a5f6a2016-03-16 14:47:30 +010065 if (isprint(opts[i].opt.val) && opts[i].opt.val < 0x80) {
Robert Swieckia88f96f2015-10-09 16:47:39 +020066 LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name,
67 "|-", opts[i].opt.val,
Robert Swieckibf063db2016-02-16 18:42:00 +010068 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020069 } else {
70 LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
Robert Swieckibf063db2016-02-16 18:42:00 +010071 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020072 }
73 LOG_HELP("\t%s", opts[i].descr);
74 }
Jagger32127372015-10-09 23:07:38 +020075 LOG_HELP_BOLD("\nExamples:");
76 LOG_HELP(" Run the binary over a mutated file chosen from the directory");
77 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
78 LOG_HELP(" As above, provide input over STDIN:");
Robert Swiecki72d2bef2016-01-19 14:39:26 +010079 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg");
Jaggerba92b4b2016-03-16 02:24:17 +010080 LOG_HELP(" Use SANCOV to maximize code coverage:");
81 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -C -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +020082#if defined(_HF_ARCH_LINUX)
Jagger32127372015-10-09 23:07:38 +020083 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
Jagger72f258b2015-10-09 23:09:01 +020084 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_instr -- /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 total no. of branches:");
Jagger72f258b2015-10-09 23:09:01 +020087 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
88 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020089 LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks (coverage):");
90 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ip -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
91 LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges):");
Jagger72f258b2015-10-09 23:09:01 +020092 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ip_addr -- /usr/bin/tiffinfo -D "
93 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020094 LOG_HELP(" Run the binary over a dynamic file, maximize custom counters (experimental):");
Jagger72f258b2015-10-09 23:09:01 +020095 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_custom -- /usr/bin/tiffinfo -D "
96 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +020097#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +020098}
99
100static void cmdlineUsage(const char *pname, struct custom_option *opts)
101{
102 cmdlineHelp(pname, opts);
103 exit(0);
104}
105
Robert Swieckia88f96f2015-10-09 16:47:39 +0200106rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
107{
108 struct rlimit cur;
109 if (getrlimit(res, &cur) == -1) {
110 PLOG_F("getrlimit(%d)", res);
111 }
112 if (strcasecmp(optarg, "max") == 0) {
113 return cur.rlim_max;
114 }
115 if (strcasecmp(optarg, "def") == 0) {
116 return cur.rlim_cur;
117 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200118 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200119 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
120 }
121 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200122 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200123 PLOG_F("strtoul('%s', 0)", optarg);
124 }
125 return val;
126}
127
128bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
129{
130 /* *INDENT-OFF* */
131 (*hfuzz) = (honggfuzz_t) {
132 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100133 .cmdline_txt[0] = '\0',
Robert Swieckia88f96f2015-10-09 16:47:39 +0200134 .inputFile = NULL,
135 .nullifyStdio = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200136 .fuzzStdin = false,
137 .saveUnique = true,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100138 .useScreen = true,
139 .useVerifier = false,
140 .timeStart = time(NULL),
Robert Swieckia88f96f2015-10-09 16:47:39 +0200141 .fileExtn = "fuzz",
142 .workDir = ".",
Robert Swieckia96d78d2016-03-14 16:50:50 +0100143 .origFlipRate = 0.001f,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200144 .externalCommand = NULL,
145 .dictionaryFile = NULL,
146 .dictionary = NULL,
147 .dictionaryCnt = 0,
148 .blacklistFile = NULL,
149 .blacklistCnt = 0,
150 .blacklist = NULL,
151 .maxFileSz = (1024 * 1024),
Jaggerba92b4b2016-03-16 02:24:17 +0100152 .tmOut = 10,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200153 .mutationsMax = 0,
154 .threadsFinished = 0,
155 .threadsMax = 2,
156 .reportFile = NULL,
157 .asLimit = 0ULL,
158 .files = NULL,
159 .fileCnt = 0,
Robert Swiecki05354ca2016-03-15 19:10:23 +0100160 .lastFileIndex = 0,
161 .doneFileIndex = 0,
Jaggercdbf6852016-02-07 22:06:02 +0100162 .exeFd = -1,
Jagger80041fe2016-03-10 21:32:35 +0100163 .clearEnv = false,
Jaggerab26e702016-03-22 04:28:00 +0100164 .envs = {
165 [0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,
166 },
Robert Swiecki0f937af2016-03-30 18:19:16 +0200167 .persistent = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200168
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100169 .state = _HF_STATE_UNSET,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100170 .bbMapSz = _HF_PERF_BITMAP_SIZE,
Jagger2c8f7192016-03-19 02:17:22 +0100171 .bbMap = NULL,
Robert Swieckie586c1f2016-03-14 18:46:03 +0100172 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100173 .dynfileqCnt = 0U,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100174
Robert Swieckia88f96f2015-10-09 16:47:39 +0200175 .mutationsCnt = 0,
176 .crashesCnt = 0,
177 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200178 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200179 .blCrashesCnt = 0,
180 .timeoutedCnt = 0,
181
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100182 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200183 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100184 .hitBBCnt = 0ULL,
185 .totalBBCnt = 0ULL,
186 .dsoCnt = 0ULL,
187 .iDsoCnt = 0ULL,
188 .newBBCnt = 0ULL,
189 .crashesCnt = 0ULL,
190 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200191
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200192 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100193 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100194 .asanOpts = NULL,
195 .msanOpts = NULL,
196 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200197 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100198 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100199 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100200 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100201
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700202 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
203
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100204 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200205 .linux = {
Jaggerab26e702016-03-22 04:28:00 +0100206 .hwCnts = {
207 .cpuInstrCnt = 0ULL,
208 .cpuBranchCnt = 0ULL,
209 .customCnt = 0ULL,
210 .bbCnt = 0ULL,
211 .newBBCnt = 0ULL,
212 },
213 .dynamicCutOffAddr = ~(0ULL),
214 .disableRandomization = true,
215 .ignoreAddr = NULL,
216 .numMajorFrames = 7,
217 .pid = 0,
218 .pidFile = NULL,
219 .pidCmd = NULL,
220 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200221 };
222 /* *INDENT-ON* */
223
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100224 TAILQ_INIT(&hfuzz->dynfileq);
225
Robert Swieckia88f96f2015-10-09 16:47:39 +0200226 /* *INDENT-OFF* */
227 struct custom_option custom_opts[] = {
228 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
229 {{"input", required_argument, NULL, 'f'}, "Path to the file corpus (file or a directory)"},
230 {{"nullify_stdio", no_argument, NULL, 'q'}, "Null-ify children's stdin, stdout, stderr; make them quiet"},
Jagger54c96a22016-03-30 23:13:30 +0200231 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
232 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: '2')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200233 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200234 {{"mutation_rate", required_argument, NULL, 'r'}, "Maximal mutation rate in relation to the file size, (default: '0.001')"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200235 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200236 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100237 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200238 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
239 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300240 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200241 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
242 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300243 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command providing fuzz files, instead of mutating the input corpus"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200244 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200245 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100246 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200247 {{"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 +0100248 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200249 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger54c96a22016-03-30 23:13:30 +0200250 {{"save_all", no_argument, NULL, 'u'}, "Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames"},
Jagger3db1d952016-03-10 02:02:46 +0100251 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Jagger7ff92fa2016-03-22 04:13:50 +0100252 {{"msan_report_umrs", no_argument, NULL, 0x102}, "Report MSAN's UMRS (uninitialized memory access)"},
Jaggere91b6dc2016-05-07 00:50:11 +0200253 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (link with libraries/persistent.mode.main.o)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200254
255#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200256 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
Robert Swieckifab69162016-03-31 15:41:36 +0200257 {{"linux_file_pid", required_argument, NULL, 0x502}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200258 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
259 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
Jaggerae6a4452015-10-14 17:34:43 +0200260 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200261 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
262 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100263 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
264 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
265 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks"},
Jaggerad2b3c12016-04-02 00:06:37 +0200266 {{"linux_perf_custom", no_argument, NULL, 0x520}, "Custom counter (see interceptor/stringmem.c)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200267#endif // defined(_HF_ARCH_LINUX)
268 {{0, 0, 0, 0}, NULL},
269 };
270 /* *INDENT-ON* */
271
272 struct option opts[ARRAYSIZE(custom_opts)];
273 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
274 opts[i] = custom_opts[i].opt;
275 }
276
277 enum llevel_t ll = INFO;
278 const char *logfile = NULL;
279 int opt_index = 0;
280 for (;;) {
Robert Swieckifab69162016-03-31 15:41:36 +0200281 int c = getopt_long(argc, argv, "-?hqvVsuPf:d:e:W:r:c:F:t:R:n:N:l:p:g:E:w:B:C", opts,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200282 &opt_index);
283 if (c < 0)
284 break;
285
286 switch (c) {
287 case 'h':
288 case '?':
289 cmdlineUsage(argv[0], custom_opts);
290 break;
291 case 'f':
292 hfuzz->inputFile = optarg;
293 break;
294 case 'q':
295 hfuzz->nullifyStdio = true;
296 break;
297 case 'v':
298 hfuzz->useScreen = false;
299 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700300 case 'V':
301 hfuzz->useVerifier = true;
302 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200303 case 's':
304 hfuzz->fuzzStdin = true;
305 break;
306 case 'u':
307 hfuzz->saveUnique = false;
308 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200309 case 'l':
310 logfile = optarg;
311 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200312 case 'd':
313 ll = atoi(optarg);
314 break;
315 case 'e':
316 hfuzz->fileExtn = optarg;
317 break;
318 case 'W':
319 hfuzz->workDir = optarg;
320 break;
321 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100322 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200323 break;
324 case 'c':
325 hfuzz->externalCommand = optarg;
326 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200327 case 'C':
328 hfuzz->useSanCov = true;
329 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200330 case 'F':
331 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
332 break;
333 case 't':
334 hfuzz->tmOut = atol(optarg);
335 break;
336 case 'R':
337 hfuzz->reportFile = optarg;
338 break;
339 case 'n':
340 hfuzz->threadsMax = atol(optarg);
341 break;
342 case 'N':
343 hfuzz->mutationsMax = atol(optarg);
344 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200345 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200346 hfuzz->asLimit = strtoull(optarg, NULL, 0);
347 break;
Jagger80041fe2016-03-10 21:32:35 +0100348 case 0x101:
349 hfuzz->clearEnv = true;
350 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100351 case 0x102:
352 hfuzz->msanReportUMRS = true;
353 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200354 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200355 hfuzz->persistent = true;
356 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200357 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200358 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200359 LOG_E("-p '%s' is not a number", optarg);
360 return false;
361 }
Jagger247c3b42016-03-21 23:24:05 +0100362 hfuzz->linux.pid = atoi(optarg);
363 if (hfuzz->linux.pid < 1) {
364 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200365 return false;
366 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200367 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200368 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100369 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200370 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200371 case 'E':
372 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
373 if (hfuzz->envs[i] == NULL) {
374 hfuzz->envs[i] = optarg;
375 break;
376 }
377 }
378 break;
379 case 'w':
380 hfuzz->dictionaryFile = optarg;
381 break;
382 case 'B':
383 hfuzz->blacklistFile = optarg;
384 break;
385 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100386 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200387 break;
388 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100389 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200390 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200391 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100392 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200393 break;
394 case 0x510:
395 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
396 break;
397 case 0x511:
398 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
399 break;
400 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100401 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200402 break;
403 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100404 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200405 break;
406 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100407 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
408 break;
Jagger39bd2b02016-02-04 01:16:15 +0100409 case 0x520:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200410 hfuzz->dynFileMethod |= _HF_DYNFILE_CUSTOM;
411 break;
412 default:
413 cmdlineUsage(argv[0], custom_opts);
414 return false;
415 break;
416 }
417 }
Jagger72f258b2015-10-09 23:09:01 +0200418
Robert Swieckia88f96f2015-10-09 16:47:39 +0200419 if (logInitLogFile(logfile, ll) == false) {
420 return false;
421 }
422
423 hfuzz->cmdline = &argv[optind];
424 if (hfuzz->cmdline[0] == NULL) {
425 LOG_E("No fuzz command provided");
426 cmdlineUsage(argv[0], custom_opts);
427 return false;
428 }
429
Robert Swiecki0f937af2016-03-30 18:19:16 +0200430 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200431 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200432 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200433 return false;
434 }
435
Anestis Bechtsoudisbd650542015-12-26 18:10:32 +0200436 /* Sanity checks for timeout. Optimal ranges highly depend on target */
Jaggerba92b4b2016-03-16 02:24:17 +0100437 if (hfuzz->useSanCov && hfuzz->tmOut < 10) {
438 LOG_E("Timeout value (%ld) too small for sanitizer coverage feedback", (long)hfuzz->tmOut);
Anestis Bechtsoudisebea8452015-12-26 18:05:40 +0200439 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
Jagger247c3b42016-03-21 23:24:05 +0100454 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
455 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
456 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200457 hfuzz->threadsMax = 1;
458 }
459
Robert Swieckia96d78d2016-03-14 16:50:50 +0100460 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200461 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200462 }
463
Robert Swieckia88f96f2015-10-09 16:47:39 +0200464 LOG_I("inputFile '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Jagger247c3b42016-03-21 23:24:05 +0100465 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn '%s', "
Robert Swieckia88f96f2015-10-09 16:47:39 +0200466 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d",
467 hfuzz->inputFile,
468 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100469 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200470 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
Jagger247c3b42016-03-21 23:24:05 +0100471 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn,
472 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200473
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100474 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100475 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
476 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
477 }
478
Robert Swieckia88f96f2015-10-09 16:47:39 +0200479 return true;
480}