blob: 4ac427290e90f334f52948be997c0bb49bcaa554 [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);
Jaggere848cc72016-09-19 02:28:52 +020082 LOG_HELP(" Use compile-time instrumentation (libhfuzz/instrument.c):");
83 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -z -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
84 LOG_HELP(" Use persistent mode (libhfuzz/persistent.c):");
85 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -- /usr/bin/tiffinfo_persistent");
Robert Swieckia88f96f2015-10-09 16:47:39 +020086#if defined(_HF_ARCH_LINUX)
Jagger32127372015-10-09 23:07:38 +020087 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
Jagger72f258b2015-10-09 23:09:01 +020088 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_instr -- /usr/bin/tiffinfo -D "
89 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020090 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of branches:");
Jagger72f258b2015-10-09 23:09:01 +020091 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
92 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020093 LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks (coverage):");
94 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ip -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
95 LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges):");
Jagger72f258b2015-10-09 23:09:01 +020096 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ip_addr -- /usr/bin/tiffinfo -D "
97 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020098 LOG_HELP(" Run the binary over a dynamic file, maximize custom counters (experimental):");
Jagger72f258b2015-10-09 23:09:01 +020099 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_custom -- /usr/bin/tiffinfo -D "
100 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200101#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200102}
103
104static void cmdlineUsage(const char *pname, struct custom_option *opts)
105{
106 cmdlineHelp(pname, opts);
107 exit(0);
108}
109
Robert Swieckia88f96f2015-10-09 16:47:39 +0200110rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
111{
112 struct rlimit cur;
113 if (getrlimit(res, &cur) == -1) {
114 PLOG_F("getrlimit(%d)", res);
115 }
116 if (strcasecmp(optarg, "max") == 0) {
117 return cur.rlim_max;
118 }
119 if (strcasecmp(optarg, "def") == 0) {
120 return cur.rlim_cur;
121 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200122 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200123 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
124 }
125 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200126 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200127 PLOG_F("strtoul('%s', 0)", optarg);
128 }
129 return val;
130}
131
132bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
133{
134 /* *INDENT-OFF* */
135 (*hfuzz) = (honggfuzz_t) {
136 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100137 .cmdline_txt[0] = '\0',
Jagger1b2d4822016-09-25 16:19:45 +0200138 .inputDir = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200139 .nullifyStdio = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200140 .fuzzStdin = false,
141 .saveUnique = true,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100142 .useScreen = true,
143 .useVerifier = false,
144 .timeStart = time(NULL),
Robert Swieckia88f96f2015-10-09 16:47:39 +0200145 .fileExtn = "fuzz",
146 .workDir = ".",
Jagger1b2d4822016-09-25 16:19:45 +0200147 .covDir = NULL,
Robert Swieckia96d78d2016-03-14 16:50:50 +0100148 .origFlipRate = 0.001f,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200149 .externalCommand = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200150 .blacklistFile = NULL,
151 .blacklistCnt = 0,
152 .blacklist = NULL,
Jaggerf4a60562016-09-25 15:40:23 +0200153 .maxFileSz = 0UL,
Jaggerba92b4b2016-03-16 02:24:17 +0100154 .tmOut = 10,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200155 .mutationsMax = 0,
156 .threadsFinished = 0,
157 .threadsMax = 2,
158 .reportFile = NULL,
159 .asLimit = 0ULL,
160 .files = NULL,
161 .fileCnt = 0,
Robert Swiecki05354ca2016-03-15 19:10:23 +0100162 .lastFileIndex = 0,
163 .doneFileIndex = 0,
Jagger80041fe2016-03-10 21:32:35 +0100164 .clearEnv = false,
Jaggerab26e702016-03-22 04:28:00 +0100165 .envs = {
166 [0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,
167 },
Robert Swiecki0f937af2016-03-30 18:19:16 +0200168 .persistent = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200169
Robert Swiecki531438a2016-09-13 19:05:11 +0200170 .dictionaryFile = NULL,
171 .dictionaryCnt = 0,
172
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100173 .state = _HF_STATE_UNSET,
Jaggerb7fa3ee2016-08-21 19:46:26 +0200174 .feedback = NULL,
Robert Swieckibc7532e2016-08-20 00:34:17 +0200175 .bbFd = -1,
Robert Swieckie586c1f2016-03-14 18:46:03 +0100176 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100177 .dynfileqCnt = 0U,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100178
Robert Swieckia88f96f2015-10-09 16:47:39 +0200179 .mutationsCnt = 0,
180 .crashesCnt = 0,
181 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200182 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200183 .blCrashesCnt = 0,
184 .timeoutedCnt = 0,
185
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100186 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200187 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100188 .hitBBCnt = 0ULL,
189 .totalBBCnt = 0ULL,
190 .dsoCnt = 0ULL,
191 .iDsoCnt = 0ULL,
192 .newBBCnt = 0ULL,
193 .crashesCnt = 0ULL,
194 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200195
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200196 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100197 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100198 .asanOpts = NULL,
199 .msanOpts = NULL,
200 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200201 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100202 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100203 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100204 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100205
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700206 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
207
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100208 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200209 .linux = {
Jaggerab26e702016-03-22 04:28:00 +0100210 .hwCnts = {
211 .cpuInstrCnt = 0ULL,
212 .cpuBranchCnt = 0ULL,
213 .customCnt = 0ULL,
214 .bbCnt = 0ULL,
215 .newBBCnt = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200216 .softCntPc = 0ULL,
217 .softCntCmp = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100218 },
219 .dynamicCutOffAddr = ~(0ULL),
220 .disableRandomization = true,
221 .ignoreAddr = NULL,
222 .numMajorFrames = 7,
223 .pid = 0,
224 .pidFile = NULL,
225 .pidCmd = NULL,
226 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200227 };
228 /* *INDENT-ON* */
229
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100230 TAILQ_INIT(&hfuzz->dynfileq);
Robert Swiecki531438a2016-09-13 19:05:11 +0200231 TAILQ_INIT(&hfuzz->dictionaryq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100232
Robert Swieckia88f96f2015-10-09 16:47:39 +0200233 /* *INDENT-OFF* */
234 struct custom_option custom_opts[] = {
235 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
Jagger1b2d4822016-09-25 16:19:45 +0200236 {{"input", required_argument, NULL, 'f'}, "Path to a directory containing initial file corpus"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200237 {{"nullify_stdio", no_argument, NULL, 'q'}, "Null-ify children's stdin, stdout, stderr; make them quiet"},
Jagger54c96a22016-03-30 23:13:30 +0200238 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
239 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: '2')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200240 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200241 {{"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 +0200242 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200243 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100244 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200245 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
246 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300247 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Jagger1b2d4822016-09-25 16:19:45 +0200248 {{"covdir", required_argument, NULL, 0x103}, "New coverage is written to a separate directory (default: append new coverage only)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200249 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
250 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300251 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command providing fuzz files, instead of mutating the input corpus"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200252 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200253 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100254 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200255 {{"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 +0100256 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200257 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger54c96a22016-03-30 23:13:30 +0200258 {{"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 +0100259 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Jagger6aba6372016-08-28 17:36:48 +0200260 {{"instr", no_argument, NULL, 'z'}, "Enable compile-time instrumentation (see libraries/instrument_func.c)"},
Jagger7ff92fa2016-03-22 04:13:50 +0100261 {{"msan_report_umrs", no_argument, NULL, 0x102}, "Report MSAN's UMRS (uninitialized memory access)"},
Jaggere91b6dc2016-05-07 00:50:11 +0200262 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (link with libraries/persistent.mode.main.o)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200263
264#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200265 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
Robert Swieckifab69162016-03-31 15:41:36 +0200266 {{"linux_file_pid", required_argument, NULL, 0x502}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200267 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
268 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
Jaggerae6a4452015-10-14 17:34:43 +0200269 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200270 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
271 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100272 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
273 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
274 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks"},
Jagger2bd7cd02016-09-11 15:49:19 +0200275 {{"linux_perf_custom", no_argument, NULL, 0x520}, "Custom counter (based on GS register for x86_64)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200276#endif // defined(_HF_ARCH_LINUX)
277 {{0, 0, 0, 0}, NULL},
278 };
279 /* *INDENT-ON* */
280
281 struct option opts[ARRAYSIZE(custom_opts)];
282 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
283 opts[i] = custom_opts[i].opt;
284 }
285
286 enum llevel_t ll = INFO;
287 const char *logfile = NULL;
288 int opt_index = 0;
289 for (;;) {
Jagger4aac9fe2016-08-28 17:35:48 +0200290 int c = getopt_long(argc, argv, "-?hqvVsuPf:d:e:W:r:c:F:t:R:n:N:l:p:g:E:w:B:Cz", opts,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200291 &opt_index);
292 if (c < 0)
293 break;
294
295 switch (c) {
296 case 'h':
297 case '?':
298 cmdlineUsage(argv[0], custom_opts);
299 break;
300 case 'f':
Jagger1b2d4822016-09-25 16:19:45 +0200301 hfuzz->inputDir = optarg;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200302 break;
303 case 'q':
304 hfuzz->nullifyStdio = true;
305 break;
306 case 'v':
307 hfuzz->useScreen = false;
308 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700309 case 'V':
310 hfuzz->useVerifier = true;
311 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200312 case 's':
313 hfuzz->fuzzStdin = true;
314 break;
315 case 'u':
316 hfuzz->saveUnique = false;
317 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200318 case 'l':
319 logfile = optarg;
320 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200321 case 'd':
322 ll = atoi(optarg);
323 break;
324 case 'e':
325 hfuzz->fileExtn = optarg;
326 break;
327 case 'W':
328 hfuzz->workDir = optarg;
329 break;
330 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100331 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200332 break;
333 case 'c':
334 hfuzz->externalCommand = optarg;
335 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200336 case 'C':
337 hfuzz->useSanCov = true;
338 break;
Jagger4aac9fe2016-08-28 17:35:48 +0200339 case 'z':
340 hfuzz->dynFileMethod |= _HF_DYNFILE_SOFT;
341 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200342 case 'F':
343 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
344 break;
345 case 't':
346 hfuzz->tmOut = atol(optarg);
347 break;
348 case 'R':
349 hfuzz->reportFile = optarg;
350 break;
351 case 'n':
352 hfuzz->threadsMax = atol(optarg);
353 break;
354 case 'N':
355 hfuzz->mutationsMax = atol(optarg);
356 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200357 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200358 hfuzz->asLimit = strtoull(optarg, NULL, 0);
359 break;
Jagger80041fe2016-03-10 21:32:35 +0100360 case 0x101:
361 hfuzz->clearEnv = true;
362 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100363 case 0x102:
364 hfuzz->msanReportUMRS = true;
365 break;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200366 case 0x103:
Jagger1b2d4822016-09-25 16:19:45 +0200367 hfuzz->covDir = optarg;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200368 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200369 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200370 hfuzz->persistent = true;
371 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200372 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200373 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200374 LOG_E("-p '%s' is not a number", optarg);
375 return false;
376 }
Jagger247c3b42016-03-21 23:24:05 +0100377 hfuzz->linux.pid = atoi(optarg);
378 if (hfuzz->linux.pid < 1) {
379 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200380 return false;
381 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200382 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200383 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100384 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200385 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200386 case 'E':
387 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
388 if (hfuzz->envs[i] == NULL) {
389 hfuzz->envs[i] = optarg;
390 break;
391 }
392 }
393 break;
394 case 'w':
395 hfuzz->dictionaryFile = optarg;
396 break;
397 case 'B':
398 hfuzz->blacklistFile = optarg;
399 break;
400 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100401 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200402 break;
403 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100404 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200405 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200406 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100407 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200408 break;
409 case 0x510:
410 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
411 break;
412 case 0x511:
413 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
414 break;
415 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100416 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200417 break;
418 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100419 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200420 break;
421 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100422 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
423 break;
Jagger39bd2b02016-02-04 01:16:15 +0100424 case 0x520:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200425 hfuzz->dynFileMethod |= _HF_DYNFILE_CUSTOM;
426 break;
427 default:
428 cmdlineUsage(argv[0], custom_opts);
429 return false;
430 break;
431 }
432 }
Jagger72f258b2015-10-09 23:09:01 +0200433
Robert Swieckia88f96f2015-10-09 16:47:39 +0200434 if (logInitLogFile(logfile, ll) == false) {
435 return false;
436 }
437
438 hfuzz->cmdline = &argv[optind];
439 if (hfuzz->cmdline[0] == NULL) {
440 LOG_E("No fuzz command provided");
441 cmdlineUsage(argv[0], custom_opts);
442 return false;
443 }
444
Robert Swiecki0f937af2016-03-30 18:19:16 +0200445 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200446 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200447 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200448 return false;
449 }
450
Robert Swiecki71b73722016-09-05 15:18:25 +0200451 if (hfuzz->threadsMax >= _HF_THREAD_MAX) {
452 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", hfuzz->threadsMax,
453 _HF_THREAD_MAX);
454 return false;
455 }
456
Robert Swieckia88f96f2015-10-09 16:47:39 +0200457 if (strchr(hfuzz->fileExtn, '/')) {
458 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
459 return false;
460 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200461
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200462 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200463 if (!files_exists(hfuzz->workDir)) {
464 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
465 return false;
466 }
467 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200468
Jagger247c3b42016-03-21 23:24:05 +0100469 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
470 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
471 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200472 hfuzz->threadsMax = 1;
473 }
474
Robert Swieckia96d78d2016-03-14 16:50:50 +0100475 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200476 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200477 }
478
Jagger1b2d4822016-09-25 16:19:45 +0200479 LOG_I("inputDir '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Jagger247c3b42016-03-21 23:24:05 +0100480 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn '%s', "
Robert Swieckia88f96f2015-10-09 16:47:39 +0200481 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d",
Jagger1b2d4822016-09-25 16:19:45 +0200482 hfuzz->inputDir,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200483 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100484 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200485 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
Jagger247c3b42016-03-21 23:24:05 +0100486 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn,
487 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200488
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100489 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100490 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
491 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
492 }
493
Robert Swieckia88f96f2015-10-09 16:47:39 +0200494 return true;
495}