blob: 68350b4c8917bc7555374d1103938e6054109886 [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);
Robert Swieckia2d5be32016-10-11 22:52:42 +020084 LOG_HELP(" Use persistent mode (libhfuzz/persistent.c):");
Jaggere848cc72016-09-19 02:28:52 +020085 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);
Robert Swiecki349cb9e2016-10-14 21:36:42 +020093 LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks via BTS:");
94 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_block -- /usr/bin/tiffinfo -D "
95 _HF_FILE_PLACEHOLDER);
96 LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges) via BTS:");
97 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_edge -- /usr/bin/tiffinfo -D ");
98 LOG_HELP
99 (" Run the binary over a dynamic file, maximize unique code blocks via Intel Processor Trace:");
100 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ipt_block -- /usr/bin/tiffinfo -D "
Jagger72f258b2015-10-09 23:09:01 +0200101 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +0200102 LOG_HELP(" Run the binary over a dynamic file, maximize custom counters (experimental):");
Jagger72f258b2015-10-09 23:09:01 +0200103 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_custom -- /usr/bin/tiffinfo -D "
104 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200105#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200106}
107
108static void cmdlineUsage(const char *pname, struct custom_option *opts)
109{
110 cmdlineHelp(pname, opts);
111 exit(0);
112}
113
Robert Swieckia88f96f2015-10-09 16:47:39 +0200114rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
115{
116 struct rlimit cur;
117 if (getrlimit(res, &cur) == -1) {
118 PLOG_F("getrlimit(%d)", res);
119 }
120 if (strcasecmp(optarg, "max") == 0) {
121 return cur.rlim_max;
122 }
123 if (strcasecmp(optarg, "def") == 0) {
124 return cur.rlim_cur;
125 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200126 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200127 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
128 }
129 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200130 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200131 PLOG_F("strtoul('%s', 0)", optarg);
132 }
133 return val;
134}
135
136bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
137{
138 /* *INDENT-OFF* */
139 (*hfuzz) = (honggfuzz_t) {
140 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100141 .cmdline_txt[0] = '\0',
Jagger1b2d4822016-09-25 16:19:45 +0200142 .inputDir = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200143 .nullifyStdio = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200144 .fuzzStdin = false,
145 .saveUnique = true,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100146 .useScreen = true,
147 .useVerifier = false,
148 .timeStart = time(NULL),
Robert Swieckia88f96f2015-10-09 16:47:39 +0200149 .fileExtn = "fuzz",
150 .workDir = ".",
Jagger1b2d4822016-09-25 16:19:45 +0200151 .covDir = NULL,
Robert Swieckia96d78d2016-03-14 16:50:50 +0100152 .origFlipRate = 0.001f,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200153 .externalCommand = NULL,
Robert Swieckiee266ac2016-10-03 02:25:59 +0200154 .postExternalCommand = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200155 .blacklistFile = NULL,
156 .blacklistCnt = 0,
157 .blacklist = NULL,
Jaggerf4a60562016-09-25 15:40:23 +0200158 .maxFileSz = 0UL,
Jaggerba92b4b2016-03-16 02:24:17 +0100159 .tmOut = 10,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200160 .mutationsMax = 0,
161 .threadsFinished = 0,
Jagger2664f542016-09-28 14:37:00 +0200162 .threadsMax = (sysconf(_SC_NPROCESSORS_ONLN) <= 1) ? 1 : sysconf(_SC_NPROCESSORS_ONLN) / 2,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200163 .reportFile = NULL,
164 .asLimit = 0ULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200165 .fileCnt = 0,
Robert Swiecki05354ca2016-03-15 19:10:23 +0100166 .lastFileIndex = 0,
167 .doneFileIndex = 0,
Jagger80041fe2016-03-10 21:32:35 +0100168 .clearEnv = false,
Jaggerab26e702016-03-22 04:28:00 +0100169 .envs = {
170 [0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,
171 },
Robert Swiecki0f937af2016-03-30 18:19:16 +0200172 .persistent = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200173
Robert Swiecki531438a2016-09-13 19:05:11 +0200174 .dictionaryFile = NULL,
175 .dictionaryCnt = 0,
176
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100177 .state = _HF_STATE_UNSET,
Jaggerb7fa3ee2016-08-21 19:46:26 +0200178 .feedback = NULL,
Robert Swieckibc7532e2016-08-20 00:34:17 +0200179 .bbFd = -1,
Robert Swieckie586c1f2016-03-14 18:46:03 +0100180 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100181 .dynfileqCnt = 0U,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100182
Robert Swieckia88f96f2015-10-09 16:47:39 +0200183 .mutationsCnt = 0,
184 .crashesCnt = 0,
185 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200186 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200187 .blCrashesCnt = 0,
188 .timeoutedCnt = 0,
189
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100190 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200191 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100192 .hitBBCnt = 0ULL,
193 .totalBBCnt = 0ULL,
194 .dsoCnt = 0ULL,
195 .iDsoCnt = 0ULL,
196 .newBBCnt = 0ULL,
197 .crashesCnt = 0ULL,
198 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200199
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200200 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100201 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100202 .asanOpts = NULL,
203 .msanOpts = NULL,
204 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200205 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100206 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100207 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100208 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100209
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700210 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
211
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100212 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200213 .linux = {
Jaggerab26e702016-03-22 04:28:00 +0100214 .hwCnts = {
215 .cpuInstrCnt = 0ULL,
216 .cpuBranchCnt = 0ULL,
217 .customCnt = 0ULL,
218 .bbCnt = 0ULL,
219 .newBBCnt = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200220 .softCntPc = 0ULL,
221 .softCntCmp = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100222 },
223 .dynamicCutOffAddr = ~(0ULL),
224 .disableRandomization = true,
225 .ignoreAddr = NULL,
226 .numMajorFrames = 7,
227 .pid = 0,
228 .pidFile = NULL,
229 .pidCmd = NULL,
230 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200231 };
232 /* *INDENT-ON* */
233
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100234 TAILQ_INIT(&hfuzz->dynfileq);
Robert Swiecki3a572262016-10-04 01:48:34 +0200235 TAILQ_INIT(&hfuzz->dictq);
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200236 TAILQ_INIT(&hfuzz->fileq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100237
Robert Swieckia88f96f2015-10-09 16:47:39 +0200238 /* *INDENT-OFF* */
239 struct custom_option custom_opts[] = {
240 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
Jagger1b2d4822016-09-25 16:19:45 +0200241 {{"input", required_argument, NULL, 'f'}, "Path to a directory containing initial file corpus"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200242 {{"nullify_stdio", no_argument, NULL, 'q'}, "Null-ify children's stdin, stdout, stderr; make them quiet"},
Jagger54c96a22016-03-30 23:13:30 +0200243 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
Jagger2664f542016-09-28 14:37:00 +0200244 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: number of CPUs / 2)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200245 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200246 {{"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 +0200247 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200248 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100249 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200250 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
251 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300252 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Robert Swieckid32018f2016-10-11 22:58:22 +0200253 {{"covdir", required_argument, NULL, 0x103}, "New coverage is written to a separate directory (default: use the input directory)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200254 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
255 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Robert Swieckiee266ac2016-10-03 02:25:59 +0200256 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command producing fuzz files (instead of internal mutators)"},
257 {{"pprocess_cmd", required_argument, NULL, 0x104}, "External command postprocessing files produced by internal mutators"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200258 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200259 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100260 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200261 {{"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 +0100262 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200263 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger54c96a22016-03-30 23:13:30 +0200264 {{"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 +0100265 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Robert Swieckia2d5be32016-10-11 22:52:42 +0200266 {{"instrument", no_argument, NULL, 'z'}, "Enable compile-time instrumentation (link with libraries/instrument.a)"},
Jagger7ff92fa2016-03-22 04:13:50 +0100267 {{"msan_report_umrs", no_argument, NULL, 0x102}, "Report MSAN's UMRS (uninitialized memory access)"},
Robert Swiecki116213b2016-10-11 22:54:03 +0200268 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (link with libraries/persistent.c)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200269
270#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200271 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
Robert Swieckifab69162016-03-31 15:41:36 +0200272 {{"linux_file_pid", required_argument, NULL, 0x502}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200273 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
274 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
Jaggerae6a4452015-10-14 17:34:43 +0200275 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200276 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
277 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100278 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
279 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
280 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks"},
Jagger2bd7cd02016-09-11 15:49:19 +0200281 {{"linux_perf_custom", no_argument, NULL, 0x520}, "Custom counter (based on GS register for x86_64)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200282#endif // defined(_HF_ARCH_LINUX)
283 {{0, 0, 0, 0}, NULL},
284 };
285 /* *INDENT-ON* */
286
287 struct option opts[ARRAYSIZE(custom_opts)];
288 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
289 opts[i] = custom_opts[i].opt;
290 }
291
292 enum llevel_t ll = INFO;
293 const char *logfile = NULL;
294 int opt_index = 0;
295 for (;;) {
Jagger4aac9fe2016-08-28 17:35:48 +0200296 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 +0200297 &opt_index);
298 if (c < 0)
299 break;
300
301 switch (c) {
302 case 'h':
303 case '?':
304 cmdlineUsage(argv[0], custom_opts);
305 break;
306 case 'f':
Jagger1b2d4822016-09-25 16:19:45 +0200307 hfuzz->inputDir = optarg;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200308 break;
309 case 'q':
310 hfuzz->nullifyStdio = true;
311 break;
312 case 'v':
313 hfuzz->useScreen = false;
314 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700315 case 'V':
316 hfuzz->useVerifier = true;
317 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200318 case 's':
319 hfuzz->fuzzStdin = true;
320 break;
321 case 'u':
322 hfuzz->saveUnique = false;
323 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200324 case 'l':
325 logfile = optarg;
326 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200327 case 'd':
328 ll = atoi(optarg);
329 break;
330 case 'e':
331 hfuzz->fileExtn = optarg;
332 break;
333 case 'W':
334 hfuzz->workDir = optarg;
335 break;
336 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100337 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200338 break;
339 case 'c':
340 hfuzz->externalCommand = optarg;
341 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200342 case 'C':
343 hfuzz->useSanCov = true;
344 break;
Jagger4aac9fe2016-08-28 17:35:48 +0200345 case 'z':
346 hfuzz->dynFileMethod |= _HF_DYNFILE_SOFT;
347 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200348 case 'F':
349 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
350 break;
351 case 't':
352 hfuzz->tmOut = atol(optarg);
353 break;
354 case 'R':
355 hfuzz->reportFile = optarg;
356 break;
357 case 'n':
358 hfuzz->threadsMax = atol(optarg);
359 break;
360 case 'N':
361 hfuzz->mutationsMax = atol(optarg);
362 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200363 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200364 hfuzz->asLimit = strtoull(optarg, NULL, 0);
365 break;
Jagger80041fe2016-03-10 21:32:35 +0100366 case 0x101:
367 hfuzz->clearEnv = true;
368 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100369 case 0x102:
370 hfuzz->msanReportUMRS = true;
371 break;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200372 case 0x103:
Jagger1b2d4822016-09-25 16:19:45 +0200373 hfuzz->covDir = optarg;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200374 break;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200375 case 0x104:
376 hfuzz->postExternalCommand = optarg;
377 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200378 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200379 hfuzz->persistent = true;
380 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200381 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200382 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200383 LOG_E("-p '%s' is not a number", optarg);
384 return false;
385 }
Jagger247c3b42016-03-21 23:24:05 +0100386 hfuzz->linux.pid = atoi(optarg);
387 if (hfuzz->linux.pid < 1) {
388 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200389 return false;
390 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200391 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200392 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100393 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200394 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200395 case 'E':
396 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
397 if (hfuzz->envs[i] == NULL) {
398 hfuzz->envs[i] = optarg;
399 break;
400 }
401 }
402 break;
403 case 'w':
404 hfuzz->dictionaryFile = optarg;
405 break;
406 case 'B':
407 hfuzz->blacklistFile = optarg;
408 break;
409 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100410 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200411 break;
412 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100413 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200414 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200415 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100416 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200417 break;
418 case 0x510:
419 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
420 break;
421 case 0x511:
422 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
423 break;
424 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100425 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200426 break;
427 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100428 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200429 break;
430 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100431 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
432 break;
Jagger39bd2b02016-02-04 01:16:15 +0100433 case 0x520:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200434 hfuzz->dynFileMethod |= _HF_DYNFILE_CUSTOM;
435 break;
436 default:
437 cmdlineUsage(argv[0], custom_opts);
438 return false;
439 break;
440 }
441 }
Jagger72f258b2015-10-09 23:09:01 +0200442
Robert Swieckia88f96f2015-10-09 16:47:39 +0200443 if (logInitLogFile(logfile, ll) == false) {
444 return false;
445 }
446
447 hfuzz->cmdline = &argv[optind];
448 if (hfuzz->cmdline[0] == NULL) {
449 LOG_E("No fuzz command provided");
450 cmdlineUsage(argv[0], custom_opts);
451 return false;
452 }
453
Robert Swiecki0f937af2016-03-30 18:19:16 +0200454 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200455 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200456 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200457 return false;
458 }
459
Robert Swiecki71b73722016-09-05 15:18:25 +0200460 if (hfuzz->threadsMax >= _HF_THREAD_MAX) {
461 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", hfuzz->threadsMax,
462 _HF_THREAD_MAX);
463 return false;
464 }
465
Robert Swieckia88f96f2015-10-09 16:47:39 +0200466 if (strchr(hfuzz->fileExtn, '/')) {
467 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
468 return false;
469 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200470
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200471 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200472 if (!files_exists(hfuzz->workDir)) {
473 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
474 return false;
475 }
476 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200477
Jagger247c3b42016-03-21 23:24:05 +0100478 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
479 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
480 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200481 hfuzz->threadsMax = 1;
482 }
483
Robert Swieckia96d78d2016-03-14 16:50:50 +0100484 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200485 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200486 }
487
Jagger1b2d4822016-09-25 16:19:45 +0200488 LOG_I("inputDir '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Jagger247c3b42016-03-21 23:24:05 +0100489 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn '%s', "
Robert Swieckia88f96f2015-10-09 16:47:39 +0200490 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d",
Jagger1b2d4822016-09-25 16:19:45 +0200491 hfuzz->inputDir,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200492 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100493 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200494 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
Jagger247c3b42016-03-21 23:24:05 +0100495 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn,
496 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200497
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100498 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100499 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
500 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
501 }
502
Robert Swieckia88f96f2015-10-09 16:47:39 +0200503 return true;
504}