xref: /aosp_15_r20/external/AFLplusplus/src/afl-fuzz.c (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1 /*
2    american fuzzy lop++ - fuzzer code
3    --------------------------------
4 
5    Originally written by Michal Zalewski
6 
7    Now maintained by Marc Heuse <[email protected]>,
8                         Heiko Eißfeldt <[email protected]> and
9                         Andrea Fioraldi <[email protected]>
10 
11    Copyright 2016, 2017 Google Inc. All rights reserved.
12    Copyright 2019-2024 AFLplusplus Project. All rights reserved.
13 
14    Licensed under the Apache License, Version 2.0 (the "License");
15    you may not use this file except in compliance with the License.
16    You may obtain a copy of the License at:
17 
18      https://www.apache.org/licenses/LICENSE-2.0
19 
20    This is the real deal: the program takes an instrumented binary and
21    attempts a variety of basic fuzzing tricks, paying close attention to
22    how they affect the execution path.
23 
24  */
25 
26 #include "afl-fuzz.h"
27 #include "cmplog.h"
28 #include "common.h"
29 #include <limits.h>
30 #include <stdlib.h>
31 #ifndef USEMMAP
32   #include <sys/mman.h>
33   #include <sys/stat.h>
34   #include <fcntl.h>
35   #include <sys/ipc.h>
36   #include <sys/shm.h>
37 #endif
38 
39 #ifdef __APPLE__
40   #include <sys/qos.h>
41   #include <pthread/qos.h>
42 #endif
43 
44 #ifdef PROFILING
45 extern u64 time_spent_working;
46 #endif
47 
at_exit()48 static void at_exit() {
49 
50   s32   i, pid1 = 0, pid2 = 0, pgrp = -1;
51   char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL};
52   char *ptr;
53 
54   ptr = getenv("__AFL_TARGET_PID2");
55   if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) {
56 
57     pgrp = getpgid(pid2);
58     if (pgrp > 0) { killpg(pgrp, SIGTERM); }
59     kill(pid2, SIGTERM);
60 
61   }
62 
63   ptr = getenv("__AFL_TARGET_PID1");
64   if (ptr && *ptr && (pid1 = atoi(ptr)) > 0) {
65 
66     pgrp = getpgid(pid1);
67     if (pgrp > 0) { killpg(pgrp, SIGTERM); }
68     kill(pid1, SIGTERM);
69 
70   }
71 
72   ptr = getenv(CPU_AFFINITY_ENV_VAR);
73   if (ptr && *ptr) unlink(ptr);
74 
75   i = 0;
76   while (list[i] != NULL) {
77 
78     ptr = getenv(list[i]);
79     if (ptr && *ptr) {
80 
81 #ifdef USEMMAP
82 
83       shm_unlink(ptr);
84 
85 #else
86 
87       shmctl(atoi(ptr), IPC_RMID, NULL);
88 
89 #endif
90 
91     }
92 
93     i++;
94 
95   }
96 
97   int kill_signal = SIGKILL;
98   /* AFL_KILL_SIGNAL should already be a valid int at this point */
99   if ((ptr = getenv("AFL_KILL_SIGNAL"))) { kill_signal = atoi(ptr); }
100 
101   if (pid1 > 0) {
102 
103     pgrp = getpgid(pid1);
104     if (pgrp > 0) { killpg(pgrp, kill_signal); }
105     kill(pid1, kill_signal);
106 
107   }
108 
109   if (pid2 > 0) {
110 
111     pgrp = getpgid(pid1);
112     if (pgrp > 0) { killpg(pgrp, kill_signal); }
113     kill(pid2, kill_signal);
114 
115   }
116 
117 }
118 
119 /* Display usage hints. */
120 
usage(u8 * argv0,int more_help)121 static void usage(u8 *argv0, int more_help) {
122 
123   SAYF(
124       "\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
125 
126       "Required parameters:\n"
127       "  -i dir        - input directory with test cases (or '-' to resume, "
128       "also see \n"
129       "                  AFL_AUTORESUME)\n"
130       "  -o dir        - output directory for fuzzer findings\n\n"
131 
132       "Execution control settings:\n"
133       "  -P strategy   - set fix mutation strategy: explore (focus on new "
134       "coverage),\n"
135       "                  exploit (focus on triggering crashes). You can also "
136       "set a\n"
137       "                  number of seconds after without any finds it switches "
138       "to\n"
139       "                  exploit mode, and back on new coverage (default: %u)\n"
140       "  -p schedule   - power schedules compute a seed's performance score:\n"
141       "                  explore(default), fast, exploit, seek, rare, mmopt, "
142       "coe, lin\n"
143       "                  quad -- see docs/FAQ.md for more information\n"
144       "  -f file       - location read by the fuzzed program (default: stdin "
145       "or @@)\n"
146       "  -t msec       - timeout for each run (auto-scaled, default %u ms). "
147       "Add a '+'\n"
148       "                  to auto-calculate the timeout, the value being the "
149       "maximum.\n"
150       "  -m megs       - memory limit for child process (%u MB, 0 = no limit "
151       "[default])\n"
152 #if defined(__linux__) && defined(__aarch64__)
153       "  -A            - use binary-only instrumentation (ARM CoreSight mode)\n"
154 #endif
155       "  -O            - use binary-only instrumentation (FRIDA mode)\n"
156 #if defined(__linux__)
157       "  -Q            - use binary-only instrumentation (QEMU mode)\n"
158       "  -U            - use unicorn-based instrumentation (Unicorn mode)\n"
159       "  -W            - use qemu-based instrumentation with Wine (Wine mode)\n"
160 #endif
161 #if defined(__linux__)
162       "  -X            - use VM fuzzing (NYX mode - standalone mode)\n"
163       "  -Y            - use VM fuzzing (NYX mode - multiple instances mode)\n"
164 #endif
165       "\n"
166 
167       "Mutator settings:\n"
168       "  -a type       - target input format, \"text\" or \"binary\" (default: "
169       "generic)\n"
170       "  -g minlength  - set min length of generated fuzz input (default: 1)\n"
171       "  -G maxlength  - set max length of generated fuzz input (default: "
172       "%lu)\n"
173       "  -D            - enable (a new) effective deterministic fuzzing\n"
174       "  -L minutes    - use MOpt(imize) mode and set the time limit for "
175       "entering the\n"
176       "                  pacemaker mode (minutes of no new finds). 0 = "
177       "immediately,\n"
178       "                  -1 = immediately and together with normal mutation.\n"
179       "                  Note: this option is usually not very effective\n"
180       "  -c program    - enable CmpLog by specifying a binary compiled for "
181       "it.\n"
182       "                  if using QEMU/FRIDA or the fuzzing target is "
183       "compiled\n"
184       "                  for CmpLog then use '-c 0'. To disable Cmplog use '-c "
185       "-'.\n"
186       "  -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
187       "                  1=small files, 2=larger files (default), 3=all "
188       "files,\n"
189       "                  A=arithmetic solving, T=transformational solving,\n"
190       "                  X=extreme transform solving, R=random colorization "
191       "bytes.\n\n"
192       "Fuzzing behavior settings:\n"
193       "  -Z            - sequential queue selection instead of weighted "
194       "random\n"
195       "  -N            - do not unlink the fuzzing input file (for devices "
196       "etc.)\n"
197       "  -n            - fuzz without instrumentation (non-instrumented mode)\n"
198       "  -x dict_file  - fuzzer dictionary (see README.md, specify up to 4 "
199       "times)\n\n"
200 
201       "Test settings:\n"
202       "  -s seed       - use a fixed seed for the RNG\n"
203       "  -V seconds    - fuzz for a specified time then terminate\n"
204       "  -E execs      - fuzz for an approx. no. of total executions then "
205       "terminate\n"
206       "                  Note: not precise and can have several more "
207       "executions.\n\n"
208 
209       "Other stuff:\n"
210       "  -M/-S id      - distributed mode (-M sets -Z and disables trimming)\n"
211       "                  see docs/fuzzing_in_depth.md#c-using-multiple-cores\n"
212       "                  for effective recommendations for parallel fuzzing.\n"
213       "  -F path       - sync to a foreign fuzzer queue directory (requires "
214       "-M, can\n"
215       "                  be specified up to %u times)\n"
216       // "  -d            - skip deterministic fuzzing in -M mode\n"
217       "  -T text       - text banner to show on the screen\n"
218       "  -I command    - execute this command/script when a new crash is "
219       "found\n"
220       //"  -B bitmap.txt - mutate a specific test case, use the
221       // out/default/fuzz_bitmap file\n"
222       "  -C            - crash exploration mode (the peruvian rabbit thing)\n"
223       "  -b cpu_id     - bind the fuzzing process to the specified CPU core "
224       "(0-...)\n"
225       "  -e ext        - file extension for the fuzz test input file (if "
226       "needed)\n"
227       "\n",
228       argv0, STRATEGY_SWITCH_TIME, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE,
229       FOREIGN_SYNCS_MAX);
230 
231   if (more_help > 1) {
232 
233 #if defined USE_COLOR && !defined ALWAYS_COLORED
234   #define DYN_COLOR \
235     "AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n"
236 #else
237   #define DYN_COLOR
238 #endif
239 
240 #ifdef AFL_PERSISTENT_RECORD
241   #define PERSISTENT_MSG                                                 \
242     "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \
243     "out/crashes\n"
244 #else
245   #define PERSISTENT_MSG
246 #endif
247 
248     SAYF(
249       "Environment variables used:\n"
250       "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
251       "ASAN_OPTIONS: custom settings for ASAN\n"
252       "              (must contain abort_on_error=1 and symbolize=0)\n"
253       "MSAN_OPTIONS: custom settings for MSAN\n"
254       "              (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
255       "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n"
256       "AFL_BENCH_JUST_ONE: run the target just once\n"
257       "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n"
258       "AFL_CMPLOG_ONLY_NEW: do not run cmplog on initial testcases (good for resumes!)\n"
259       "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
260       "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n"
261       "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
262       "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
263       "AFL_DEBUG: extra debugging output for Python mode trimming\n"
264       "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
265       "AFL_DISABLE_TRIM: disable the trimming of test cases\n"
266       "AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
267       "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
268       "AFL_EXIT_ON_TIME: exit when no new coverage is found within the specified time\n"
269       "AFL_EXIT_ON_SEED_ISSUES: exit on any kind of seed issues\n"
270       "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60\n"
271       "                      minutes and a cycle without finds)\n"
272       "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
273       "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
274       "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in ms)\n"
275       "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
276       "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
277       "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
278       "AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n"
279       "                              ignore those libs for coverage\n"
280       "AFL_IGNORE_SEED_PROBLEMS: skip over crashes and timeouts in the seeds instead of\n"
281       "                          exiting\n"
282       "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
283       "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
284       "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
285       "AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n"
286       "AFL_PIZZA_MODE: 1 - enforce pizza mode, -1 - disable for April 1st,\n"
287       "                0 (default) - activate on April 1st\n"
288       "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n"
289       "                 (default: SIGKILL)\n"
290       "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n"
291       "                             (default: SIGTERM). If unset and AFL_KILL_SIGNAL is\n"
292       "                             set, that value will be used.\n"
293       "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
294       "              the target was compiled for\n"
295       "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
296       "                    then they are randomly selected instead all of them being\n"
297       "                    used. Defaults to 200.\n"
298       "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
299       "AFL_TRY_AFFINITY: try to bind to an unused core, but don't fail if unsuccessful\n"
300       "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
301       "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n"
302       "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
303       "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n"
304       "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n"
305       "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n"
306       "AFL_NO_WARN_INSTABILITY: no warn about instability issues on startup calibration\n"
307       "AFL_NO_UI: switch status screen off\n"
308       "AFL_NYX_AUX_SIZE: size of the Nyx auxiliary buffer. Must be a multiple of 4096.\n"
309       "                  Increase this value in case the crash reports are truncated.\n"
310       "                  Default value is 4096.\n"
311       "AFL_NYX_DISABLE_SNAPSHOT_MODE: disable snapshot mode (must be supported by the agent)\n"
312       "AFL_NYX_LOG: output NYX hprintf messages to another file\n"
313       "AFL_NYX_REUSE_SNAPSHOT: reuse an existing Nyx root snapshot\n"
314       DYN_COLOR
315 
316       "AFL_PATH: path to AFL support binaries\n"
317       "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n"
318       "AFL_QUIET: suppress forkserver status messages\n"
319 
320       PERSISTENT_MSG
321 
322       "AFL_POST_PROCESS_KEEP_ORIGINAL: save the file as it was prior post-processing to\n"
323       "                                the queue, but execute the post-processed one\n"
324       "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
325       "AFL_TARGET_ENV: pass extra environment variables to target\n"
326       "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
327       "AFL_SKIP_BIN_CHECK: skip afl compatibility checks, also disables auto map size\n"
328       "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
329       //"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
330       "AFL_STATSD: enables StatsD metrics collection\n"
331       "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n"
332       "AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
333       "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
334       "                        suported formats: dogstatsd, librato, signalfx, influxdb\n"
335       "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
336       "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n"
337       "AFL_NO_CRASH_README: do not create a README in the crashes directory\n"
338       "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n"
339       "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
340       "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n"
341       "                      afl-clang-lto/afl-gcc-fast target\n"
342       "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib)\n"
343       "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a shared lib)\n"
344       "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in\n"
345       "                                  seconds (default: 60, minimum: 1)\n"
346       "\n"
347     );
348 
349   } else {
350 
351     SAYF(
352         "To view also the supported environment variables of afl-fuzz please "
353         "use \"-hh\".\n\n");
354 
355   }
356 
357 #ifdef USE_PYTHON
358   SAYF("Compiled with %s module support, see docs/custom_mutators.md\n",
359        (char *)PYTHON_VERSION);
360 #else
361   SAYF("Compiled without Python module support.\n");
362 #endif
363 
364 #ifdef AFL_PERSISTENT_RECORD
365   SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n");
366 #else
367   SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n");
368 #endif
369 
370 #ifdef USEMMAP
371   SAYF("Compiled with shm_open support.\n");
372 #else
373   SAYF("Compiled with shmat support.\n");
374 #endif
375 
376 #ifdef ASAN_BUILD
377   SAYF("Compiled with ASAN_BUILD.\n");
378 #endif
379 
380 #ifdef NO_SPLICING
381   SAYF("Compiled with NO_SPLICING.\n");
382 #endif
383 
384 #ifdef FANCY_BOXES_NO_UTF
385   SAYF("Compiled without UTF-8 support for line rendering in status screen.\n");
386 #endif
387 
388 #ifdef PROFILING
389   SAYF("Compiled with PROFILING.\n");
390 #endif
391 
392 #ifdef INTROSPECTION
393   SAYF("Compiled with INTROSPECTION.\n");
394 #endif
395 
396 #ifdef _DEBUG
397   SAYF("Compiled with _DEBUG.\n");
398 #endif
399 
400 #ifdef _AFL_DOCUMENT_MUTATIONS
401   SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
402 #endif
403 
404   SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
405 
406   exit(1);
407 #undef PHYTON_SUPPORT
408 
409 }
410 
411 #ifndef AFL_LIB
412 
stricmp(char const * a,char const * b)413 static int stricmp(char const *a, char const *b) {
414 
415   if (!a || !b) { FATAL("Null reference"); }
416 
417   for (;; ++a, ++b) {
418 
419     int d;
420     d = tolower((int)*a) - tolower((int)*b);
421     if (d != 0 || !*a) { return d; }
422 
423   }
424 
425 }
426 
fasan_check_afl_preload(char * afl_preload)427 static void fasan_check_afl_preload(char *afl_preload) {
428 
429   char   first_preload[PATH_MAX + 1] = {0};
430   char  *separator = strchr(afl_preload, ':');
431   size_t first_preload_len = PATH_MAX;
432   char  *basename;
433   char   clang_runtime_prefix[] = "libclang_rt.asan";
434 
435   if (separator != NULL && (separator - afl_preload) < PATH_MAX) {
436 
437     first_preload_len = separator - afl_preload;
438 
439   }
440 
441   strncpy(first_preload, afl_preload, first_preload_len);
442 
443   basename = strrchr(first_preload, '/');
444   if (basename == NULL) {
445 
446     basename = first_preload;
447 
448   } else {
449 
450     basename = basename + 1;
451 
452   }
453 
454   if (strncmp(basename, clang_runtime_prefix,
455               sizeof(clang_runtime_prefix) - 1) != 0) {
456 
457     FATAL("Address Sanitizer DSO must be the first DSO in AFL_PRELOAD");
458 
459   }
460 
461   if (access(first_preload, R_OK) != 0) {
462 
463     FATAL("Address Sanitizer DSO not found");
464 
465   }
466 
467   OKF("Found ASAN DSO: %s", first_preload);
468 
469 }
470 
471 /* Main entry point */
472 
main(int argc,char ** argv_orig,char ** envp)473 int main(int argc, char **argv_orig, char **envp) {
474 
475   s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;
476   u64 prev_queued = 0;
477   u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1,
478       map_size = get_map_size();
479   u8 *extras_dir[4];
480   u8  mem_limit_given = 0, exit_1 = 0, debug = 0,
481      extras_dir_cnt = 0 /*, have_p = 0*/;
482   char  *afl_preload;
483   char  *frida_afl_preload = NULL;
484   char **use_argv;
485 
486   struct timeval  tv;
487   struct timezone tz;
488 
489   doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH;
490 
491   if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) {
492 
493     printf("afl-fuzz" VERSION "\n");
494     exit(0);
495 
496   }
497 
498   if (argc > 1 && strcmp(argv_orig[1], "--help") == 0) {
499 
500     usage(argv_orig[0], 1);
501     exit(0);
502 
503   }
504 
505   #if defined USE_COLOR && defined ALWAYS_COLORED
506   if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) {
507 
508     WARNF(
509         "Setting AFL_NO_COLOR has no effect (colors are configured on at "
510         "compile time)");
511 
512   }
513 
514   #endif
515 
516   char **argv = argv_cpy_dup(argc, argv_orig);
517 
518   afl_state_t *afl = calloc(1, sizeof(afl_state_t));
519   if (!afl) { FATAL("Could not create afl state"); }
520 
521   if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; }
522 
523   afl_state_init(afl, map_size);
524   afl->debug = debug;
525   afl_fsrv_init(&afl->fsrv);
526   if (debug) { afl->fsrv.debug = true; }
527   read_afl_environment(afl, envp);
528   if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; }
529   exit_1 = !!afl->afl_env.afl_bench_just_one;
530 
531   SAYF(cCYA "afl-fuzz" VERSION cRST
532             " based on afl by Michal Zalewski and a large online community\n");
533 
534   gettimeofday(&tv, &tz);
535   rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid());
536 
537   afl->shmem_testcase_mode = 1;  // we always try to perform shmem fuzzing
538 
539   // still available: HjJkKqruvwz
540   while ((opt = getopt(argc, argv,
541                        "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
542                        "T:UV:WXx:YZ")) > 0) {
543 
544     switch (opt) {
545 
546       case 'a':
547 
548         if (!stricmp(optarg, "text") || !stricmp(optarg, "ascii") ||
549             !stricmp(optarg, "txt") || !stricmp(optarg, "asc")) {
550 
551           afl->input_mode = 1;
552 
553         } else if (!stricmp(optarg, "bin") || !stricmp(optarg, "binary")) {
554 
555           afl->input_mode = 2;
556 
557         } else if (!stricmp(optarg, "def") || !stricmp(optarg, "default")) {
558 
559           afl->input_mode = 0;
560 
561         } else {
562 
563           FATAL("-a input mode needs to be \"text\" or \"binary\".");
564 
565         }
566 
567         break;
568 
569       case 'P':
570         if (!stricmp(optarg, "explore") || !stricmp(optarg, "exploration")) {
571 
572           afl->fuzz_mode = 0;
573           afl->switch_fuzz_mode = 0;
574 
575         } else if (!stricmp(optarg, "exploit") ||
576 
577                    !stricmp(optarg, "exploitation")) {
578 
579           afl->fuzz_mode = 1;
580           afl->switch_fuzz_mode = 0;
581 
582         } else {
583 
584           if ((afl->switch_fuzz_mode = (u32)atoi(optarg)) > INT_MAX) {
585 
586             FATAL(
587                 "Parameter for option -P must be \"explore\", \"exploit\" or a "
588                 "number!");
589 
590           } else {
591 
592             afl->switch_fuzz_mode *= 1000;
593 
594           }
595 
596         }
597 
598         break;
599 
600       case 'g':
601         afl->min_length = atoi(optarg);
602         break;
603 
604       case 'G':
605         afl->max_length = atoi(optarg);
606         break;
607 
608       case 'Z':
609         afl->old_seed_selection = 1;
610         break;
611 
612       case 'I':
613         afl->infoexec = optarg;
614         break;
615 
616       case 'b': {                                          /* bind CPU core */
617 
618         if (afl->cpu_to_bind != -1) FATAL("Multiple -b options not supported");
619 
620         if (sscanf(optarg, "%d", &afl->cpu_to_bind) < 0) {
621 
622           FATAL("Bad syntax used for -b");
623 
624         }
625 
626         break;
627 
628       }
629 
630       case 'c': {
631 
632         if (strcmp(optarg, "-") == 0) {
633 
634           if (afl->shm.cmplog_mode) {
635 
636             ACTF("Disabling cmplog again because of '-c -'.");
637             afl->shm.cmplog_mode = 0;
638             afl->cmplog_binary = NULL;
639 
640           }
641 
642         } else {
643 
644           afl->shm.cmplog_mode = 1;
645           afl->cmplog_binary = ck_strdup(optarg);
646 
647         }
648 
649         break;
650 
651       }
652 
653       case 's': {
654 
655         if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
656         rand_set_seed(afl, strtoul(optarg, 0L, 10));
657         afl->fixed_seed = 1;
658         break;
659 
660       }
661 
662       case 'p':                                           /* Power schedule */
663 
664         if (!stricmp(optarg, "fast")) {
665 
666           afl->schedule = FAST;
667 
668         } else if (!stricmp(optarg, "coe")) {
669 
670           afl->schedule = COE;
671 
672         } else if (!stricmp(optarg, "exploit")) {
673 
674           afl->schedule = EXPLOIT;
675 
676         } else if (!stricmp(optarg, "lin")) {
677 
678           afl->schedule = LIN;
679 
680         } else if (!stricmp(optarg, "quad")) {
681 
682           afl->schedule = QUAD;
683 
684         } else if (!stricmp(optarg, "mopt") || !stricmp(optarg, "mmopt")) {
685 
686           afl->schedule = MMOPT;
687 
688         } else if (!stricmp(optarg, "rare")) {
689 
690           afl->schedule = RARE;
691 
692         } else if (!stricmp(optarg, "explore") || !stricmp(optarg, "afl") ||
693 
694                    !stricmp(optarg, "default") ||
695 
696                    !stricmp(optarg, "normal")) {
697 
698           afl->schedule = EXPLORE;
699 
700         } else if (!stricmp(optarg, "seek")) {
701 
702           afl->schedule = SEEK;
703 
704         } else {
705 
706           FATAL("Unknown -p power schedule");
707 
708         }
709 
710         // have_p = 1;
711 
712         break;
713 
714       case 'e':
715 
716         if (afl->file_extension) { FATAL("Multiple -e options not supported"); }
717 
718         afl->file_extension = optarg;
719 
720         break;
721 
722       case 'i':                                                /* input dir */
723 
724         if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
725         if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
726         afl->in_dir = optarg;
727 
728         if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
729 
730         break;
731 
732       case 'o':                                               /* output dir */
733 
734         if (afl->out_dir) { FATAL("Multiple -o options not supported"); }
735         afl->out_dir = optarg;
736         break;
737 
738       case 'M': {                                           /* main sync ID */
739 
740         u8 *c;
741 
742         if (afl->non_instrumented_mode) {
743 
744           FATAL("-M is not supported in non-instrumented mode");
745 
746         }
747 
748         if (afl->fsrv.cs_mode) {
749 
750           FATAL("-M is not supported in ARM CoreSight mode");
751 
752         }
753 
754         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
755 
756         /* sanity check for argument: should not begin with '-' (possible
757          * option) */
758         if (optarg && *optarg == '-') {
759 
760           FATAL(
761               "argument for -M started with a dash '-', which is used for "
762               "options");
763 
764         }
765 
766         afl->sync_id = ck_strdup(optarg);
767         afl->old_seed_selection = 1;  // force old queue walking seed selection
768         afl->disable_trim = 1;        // disable trimming
769 
770         if ((c = strchr(afl->sync_id, ':'))) {
771 
772           *c = 0;
773 
774           if (sscanf(c + 1, "%u/%u", &afl->main_node_id, &afl->main_node_max) !=
775                   2 ||
776               !afl->main_node_id || !afl->main_node_max ||
777               afl->main_node_id > afl->main_node_max ||
778               afl->main_node_max > 1000000) {
779 
780             FATAL("Bogus main node ID passed to -M");
781 
782           }
783 
784         }
785 
786         afl->is_main_node = 1;
787 
788       }
789 
790       break;
791 
792       case 'S':                                        /* secondary sync id */
793 
794         if (afl->non_instrumented_mode) {
795 
796           FATAL("-S is not supported in non-instrumented mode");
797 
798         }
799 
800         if (afl->fsrv.cs_mode) {
801 
802           FATAL("-S is not supported in ARM CoreSight mode");
803 
804         }
805 
806         if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
807 
808         /* sanity check for argument: should not begin with '-' (possible
809          * option) */
810         if (optarg && *optarg == '-') {
811 
812           FATAL(
813               "argument for -M started with a dash '-', which is used for "
814               "options");
815 
816         }
817 
818         afl->sync_id = ck_strdup(optarg);
819         afl->is_secondary_node = 1;
820         break;
821 
822       case 'F':                                         /* foreign sync dir */
823 
824         if (!optarg) { FATAL("Missing path for -F"); }
825         if (!afl->is_main_node) {
826 
827           FATAL(
828               "Option -F can only be specified after the -M option for the "
829               "main fuzzer of a fuzzing campaign");
830 
831         }
832 
833         if (afl->foreign_sync_cnt >= FOREIGN_SYNCS_MAX) {
834 
835           FATAL("Maximum %u entried of -F option can be specified",
836                 FOREIGN_SYNCS_MAX);
837 
838         }
839 
840         afl->foreign_syncs[afl->foreign_sync_cnt].dir = optarg;
841         while (afl->foreign_syncs[afl->foreign_sync_cnt]
842                    .dir[strlen(afl->foreign_syncs[afl->foreign_sync_cnt].dir) -
843                         1] == '/') {
844 
845           afl->foreign_syncs[afl->foreign_sync_cnt]
846               .dir[strlen(afl->foreign_syncs[afl->foreign_sync_cnt].dir) - 1] =
847               0;
848 
849         }
850 
851         afl->foreign_sync_cnt++;
852         break;
853 
854       case 'f':                                              /* target file */
855 
856         if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); }
857 
858         afl->fsrv.out_file = ck_strdup(optarg);
859         afl->fsrv.use_stdin = 0;
860         default_output = 0;
861         break;
862 
863       case 'x':                                               /* dictionary */
864 
865         if (extras_dir_cnt >= 4) {
866 
867           FATAL("More than four -x options are not supported");
868 
869         }
870 
871         extras_dir[extras_dir_cnt++] = optarg;
872         break;
873 
874       case 't': {                                                /* timeout */
875 
876         u8 suffix = 0;
877 
878         if (afl->timeout_given) { FATAL("Multiple -t options not supported"); }
879 
880         if (!optarg ||
881             sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 ||
882             optarg[0] == '-') {
883 
884           FATAL("Bad syntax used for -t");
885 
886         }
887 
888         if (afl->fsrv.exec_tmout < 5) { FATAL("Dangerously low value of -t"); }
889 
890         if (suffix == '+') {
891 
892           afl->timeout_given = 2;
893 
894         } else {
895 
896           afl->timeout_given = 1;
897 
898         }
899 
900         break;
901 
902       }
903 
904       case 'm': {                                              /* mem limit */
905 
906         u8 suffix = 'M';
907 
908         if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
909         mem_limit_given = 1;
910 
911         if (!optarg) { FATAL("Wrong usage of -m"); }
912 
913         if (!strcmp(optarg, "none")) {
914 
915           afl->fsrv.mem_limit = 0;
916           break;
917 
918         }
919 
920         if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 ||
921             optarg[0] == '-') {
922 
923           FATAL("Bad syntax used for -m");
924 
925         }
926 
927         switch (suffix) {
928 
929           case 'T':
930             afl->fsrv.mem_limit *= 1024 * 1024;
931             break;
932           case 'G':
933             afl->fsrv.mem_limit *= 1024;
934             break;
935           case 'k':
936             afl->fsrv.mem_limit /= 1024;
937             break;
938           case 'M':
939             break;
940 
941           default:
942             FATAL("Unsupported suffix or bad syntax for -m");
943 
944         }
945 
946         if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); }
947 
948         if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) {
949 
950           FATAL("Value of -m out of range on 32-bit systems");
951 
952         }
953 
954       }
955 
956       break;
957 
958       case 'D':                                    /* partial deterministic */
959 
960         afl->skip_deterministic = 0;
961         break;
962 
963       case 'd':                                         /* no deterministic */
964 
965         // this is the default and currently a lot of infrastructure enforces
966         // it (e.g. clusterfuzz, fuzzbench) based on that this feature
967         // originally was bad performance wise. We now have a better
968         // implementation, hence if it is activated, we do not want to
969         // deactivate it by such setups.
970 
971         // afl->skip_deterministic = 1;
972         break;
973 
974       case 'B':                                              /* load bitmap */
975 
976         /* This is a secret undocumented option! It is useful if you find
977            an interesting test case during a normal fuzzing process, and want
978            to mutate it without rediscovering any of the test cases already
979            found during an earlier run.
980 
981            To use this mode, you need to point -B to the fuzz_bitmap produced
982            by an earlier run for the exact same binary... and that's it.
983 
984            I only used this once or twice to get variants of a particular
985            file, so I'm not making this an official setting. */
986 
987         if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); }
988 
989         afl->in_bitmap = optarg;
990         break;
991 
992       case 'C':                                               /* crash mode */
993 
994         if (afl->crash_mode) { FATAL("Multiple -C options not supported"); }
995         afl->crash_mode = FSRV_RUN_CRASH;
996         break;
997 
998       case 'n':                                                /* dumb mode */
999 
1000         if (afl->is_main_node || afl->is_secondary_node) {
1001 
1002           FATAL("Non instrumented mode is not supported with -M / -S");
1003 
1004         }
1005 
1006         if (afl->non_instrumented_mode) {
1007 
1008           FATAL("Multiple -n options not supported");
1009 
1010         }
1011 
1012         if (afl->afl_env.afl_dumb_forksrv) {
1013 
1014           afl->non_instrumented_mode = 2;
1015 
1016         } else {
1017 
1018           afl->non_instrumented_mode = 1;
1019 
1020         }
1021 
1022         break;
1023 
1024       case 'T':                                                   /* banner */
1025 
1026         if (afl->use_banner) { FATAL("Multiple -T options not supported"); }
1027         afl->use_banner = optarg;
1028         break;
1029 
1030   #ifdef __linux__
1031       case 'X':                                                 /* NYX mode */
1032 
1033         if (afl->fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
1034 
1035         afl->fsrv.nyx_parent = true;
1036         afl->fsrv.nyx_standalone = true;
1037         afl->fsrv.nyx_mode = 1;
1038         afl->fsrv.nyx_id = 0;
1039 
1040         break;
1041 
1042       case 'Y':                                     /* NYX distributed mode */
1043         if (afl->fsrv.nyx_mode) { FATAL("Multiple -Y options not supported"); }
1044 
1045         afl->fsrv.nyx_mode = 1;
1046 
1047         break;
1048   #else
1049       case 'X':
1050       case 'Y':
1051         FATAL("Nyx mode is only availabe on linux...");
1052         break;
1053   #endif
1054       case 'A':                                           /* CoreSight mode */
1055 
1056   #if !defined(__aarch64__) || !defined(__linux__)
1057         FATAL("-A option is not supported on this platform");
1058   #endif
1059 
1060         if (afl->is_main_node || afl->is_secondary_node) {
1061 
1062           FATAL("ARM CoreSight mode is not supported with -M / -S");
1063 
1064         }
1065 
1066         if (afl->fsrv.cs_mode) { FATAL("Multiple -A options not supported"); }
1067 
1068         afl->fsrv.cs_mode = 1;
1069 
1070         break;
1071 
1072       case 'O':                                               /* FRIDA mode */
1073 
1074         if (afl->fsrv.frida_mode) {
1075 
1076           FATAL("Multiple -O options not supported");
1077 
1078         }
1079 
1080         afl->fsrv.frida_mode = 1;
1081         if (get_afl_env("AFL_USE_FASAN")) { afl->fsrv.frida_asan = 1; }
1082 
1083         break;
1084 
1085       case 'Q':                                                /* QEMU mode */
1086 
1087         if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); }
1088 
1089         afl->fsrv.qemu_mode = 1;
1090 
1091         if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
1092 
1093         break;
1094 
1095       case 'N':                                             /* Unicorn mode */
1096 
1097         if (afl->no_unlink) { FATAL("Multiple -N options not supported"); }
1098         afl->fsrv.no_unlink = (afl->no_unlink = true);
1099 
1100         break;
1101 
1102       case 'U':                                             /* Unicorn mode */
1103 
1104         if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); }
1105         afl->unicorn_mode = 1;
1106 
1107         if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; }
1108 
1109         break;
1110 
1111       case 'W':                                           /* Wine+QEMU mode */
1112 
1113         if (afl->use_wine) { FATAL("Multiple -W options not supported"); }
1114         afl->fsrv.qemu_mode = 1;
1115         afl->use_wine = 1;
1116 
1117         if (!mem_limit_given) { afl->fsrv.mem_limit = 0; }
1118 
1119         break;
1120 
1121       case 'V': {
1122 
1123         afl->most_time_key = 1;
1124         if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 ||
1125             optarg[0] == '-') {
1126 
1127           FATAL("Bad syntax used for -V");
1128 
1129         }
1130 
1131       } break;
1132 
1133       case 'E': {
1134 
1135         afl->most_execs_key = 1;
1136         if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 ||
1137             optarg[0] == '-') {
1138 
1139           FATAL("Bad syntax used for -E");
1140 
1141         }
1142 
1143       } break;
1144 
1145       case 'l': {
1146 
1147         if (!optarg) { FATAL("missing parameter for 'l'"); }
1148         char *c = optarg;
1149         while (*c) {
1150 
1151           switch (*c) {
1152 
1153             case '0':
1154             case '1':
1155               afl->cmplog_lvl = 1;
1156               break;
1157             case '2':
1158               afl->cmplog_lvl = 2;
1159               break;
1160             case '3':
1161               afl->cmplog_lvl = 3;
1162 
1163               if (!afl->disable_trim) {
1164 
1165                 ACTF("Deactivating trimming due CMPLOG level 3");
1166                 afl->disable_trim = 1;
1167 
1168               }
1169 
1170               break;
1171             case 'a':
1172             case 'A':
1173               afl->cmplog_enable_arith = 1;
1174               break;
1175             case 's':
1176             case 'S':
1177               afl->cmplog_enable_scale = 1;
1178               break;
1179             case 't':
1180             case 'T':
1181               afl->cmplog_enable_transform = 1;
1182               break;
1183             case 'x':
1184             case 'X':
1185               afl->cmplog_enable_xtreme_transform = 1;
1186               break;
1187             case 'r':
1188             case 'R':
1189               afl->cmplog_random_colorization = 1;
1190               break;
1191             default:
1192               FATAL("Unknown option value '%c' in -l %s", *c, optarg);
1193 
1194           }
1195 
1196           ++c;
1197 
1198         }
1199 
1200         if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
1201 
1202           afl->cmplog_max_filesize = MAX_FILE;
1203 
1204         }
1205 
1206       } break;
1207 
1208       case 'L': {                                              /* MOpt mode */
1209 
1210         if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); }
1211 
1212         afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT;
1213 
1214         if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) {
1215 
1216           FATAL("Bad syntax used for -L");
1217 
1218         }
1219 
1220         if (afl->limit_time_puppet == -1) {
1221 
1222           afl->limit_time_sig = -1;
1223           afl->limit_time_puppet = 0;
1224 
1225         } else if (afl->limit_time_puppet < 0) {
1226 
1227           FATAL("-L value must be between 0 and 2000000 or -1");
1228 
1229         } else {
1230 
1231           afl->limit_time_sig = 1;
1232 
1233         }
1234 
1235         u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
1236 
1237         if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
1238 
1239           FATAL("limit_time overflow");
1240 
1241         }
1242 
1243         afl->limit_time_puppet = limit_time_puppet2;
1244         afl->swarm_now = 0;
1245         if (afl->limit_time_puppet == 0) { afl->key_puppet = 1; }
1246 
1247         int j;
1248         int tmp_swarm = 0;
1249 
1250         if (afl->g_now > afl->g_max) { afl->g_now = 0; }
1251         afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) /
1252                          (afl->g_max) +
1253                      afl->w_end;
1254 
1255         for (tmp_swarm = 0; tmp_swarm < swarm_num; ++tmp_swarm) {
1256 
1257           double total_puppet_temp = 0.0;
1258           afl->swarm_fitness[tmp_swarm] = 0.0;
1259 
1260           for (j = 0; j < operator_num; ++j) {
1261 
1262             afl->stage_finds_puppet[tmp_swarm][j] = 0;
1263             afl->probability_now[tmp_swarm][j] = 0.0;
1264             afl->x_now[tmp_swarm][j] =
1265                 ((double)(random() % 7000) * 0.0001 + 0.1);
1266             total_puppet_temp += afl->x_now[tmp_swarm][j];
1267             afl->v_now[tmp_swarm][j] = 0.1;
1268             afl->L_best[tmp_swarm][j] = 0.5;
1269             afl->G_best[j] = 0.5;
1270             afl->eff_best[tmp_swarm][j] = 0.0;
1271 
1272           }
1273 
1274           for (j = 0; j < operator_num; ++j) {
1275 
1276             afl->stage_cycles_puppet_v2[tmp_swarm][j] =
1277                 afl->stage_cycles_puppet[tmp_swarm][j];
1278             afl->stage_finds_puppet_v2[tmp_swarm][j] =
1279                 afl->stage_finds_puppet[tmp_swarm][j];
1280             afl->x_now[tmp_swarm][j] =
1281                 afl->x_now[tmp_swarm][j] / total_puppet_temp;
1282 
1283           }
1284 
1285           double x_temp = 0.0;
1286 
1287           for (j = 0; j < operator_num; ++j) {
1288 
1289             afl->probability_now[tmp_swarm][j] = 0.0;
1290             afl->v_now[tmp_swarm][j] =
1291                 afl->w_now * afl->v_now[tmp_swarm][j] +
1292                 RAND_C *
1293                     (afl->L_best[tmp_swarm][j] - afl->x_now[tmp_swarm][j]) +
1294                 RAND_C * (afl->G_best[j] - afl->x_now[tmp_swarm][j]);
1295 
1296             afl->x_now[tmp_swarm][j] += afl->v_now[tmp_swarm][j];
1297 
1298             if (afl->x_now[tmp_swarm][j] > v_max) {
1299 
1300               afl->x_now[tmp_swarm][j] = v_max;
1301 
1302             } else if (afl->x_now[tmp_swarm][j] < v_min) {
1303 
1304               afl->x_now[tmp_swarm][j] = v_min;
1305 
1306             }
1307 
1308             x_temp += afl->x_now[tmp_swarm][j];
1309 
1310           }
1311 
1312           for (j = 0; j < operator_num; ++j) {
1313 
1314             afl->x_now[tmp_swarm][j] = afl->x_now[tmp_swarm][j] / x_temp;
1315             if (likely(j != 0)) {
1316 
1317               afl->probability_now[tmp_swarm][j] =
1318                   afl->probability_now[tmp_swarm][j - 1] +
1319                   afl->x_now[tmp_swarm][j];
1320 
1321             } else {
1322 
1323               afl->probability_now[tmp_swarm][j] = afl->x_now[tmp_swarm][j];
1324 
1325             }
1326 
1327           }
1328 
1329           if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 ||
1330               afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) {
1331 
1332             FATAL("ERROR probability");
1333 
1334           }
1335 
1336         }
1337 
1338         for (j = 0; j < operator_num; ++j) {
1339 
1340           afl->core_operator_finds_puppet[j] = 0;
1341           afl->core_operator_finds_puppet_v2[j] = 0;
1342           afl->core_operator_cycles_puppet[j] = 0;
1343           afl->core_operator_cycles_puppet_v2[j] = 0;
1344           afl->core_operator_cycles_puppet_v3[j] = 0;
1345 
1346         }
1347 
1348         WARNF(
1349             "Note that the MOpt mode is not maintained and is not as effective "
1350             "as normal havoc mode.");
1351 
1352       } break;
1353 
1354       case 'h':
1355         show_help++;
1356         break;  // not needed
1357 
1358       case 'R':
1359 
1360         FATAL(
1361             "Radamsa is now a custom mutator, please use that "
1362             "(custom_mutators/radamsa/).");
1363 
1364         break;
1365 
1366       default:
1367         if (!show_help) { show_help = 1; }
1368 
1369     }
1370 
1371   }
1372 
1373   if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) {
1374 
1375     FATAL("-M/-S name 'addseeds' is a reserved name, choose something else");
1376 
1377   }
1378 
1379   if (afl->is_main_node == 1 && afl->schedule != FAST &&
1380       afl->schedule != EXPLORE) {
1381 
1382     FATAL("-M is compatible only with fast and explore -p power schedules");
1383 
1384   }
1385 
1386   if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
1387 
1388     usage(argv[0], show_help);
1389 
1390   }
1391 
1392   if (unlikely(afl->afl_env.afl_persistent_record)) {
1393 
1394   #ifdef AFL_PERSISTENT_RECORD
1395 
1396     afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record);
1397 
1398     if (afl->fsrv.persistent_record < 2) {
1399 
1400       FATAL(
1401           "AFL_PERSISTENT_RECORD value must be be at least 2, recommended is "
1402           "100 or 1000.");
1403 
1404     }
1405 
1406   #else
1407 
1408     FATAL(
1409         "afl-fuzz was not compiled with AFL_PERSISTENT_RECORD enabled in "
1410         "config.h!");
1411 
1412   #endif
1413 
1414   }
1415 
1416   if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
1417 
1418   OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
1419       "Fioraldi and Heiko \"hexcoder\" Eißfeldt");
1420   OKF("AFL++ is open source, get it at "
1421       "https://github.com/AFLplusplus/AFLplusplus");
1422   OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
1423 
1424   #ifdef __linux__
1425   if (afl->fsrv.nyx_mode) {
1426 
1427     OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
1428     OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
1429 
1430   }
1431 
1432   #endif
1433 
1434   // silently disable deterministic mutation if custom mutators are used
1435   if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
1436 
1437     afl->skip_deterministic = 1;
1438 
1439   }
1440 
1441   if (afl->fixed_seed) {
1442 
1443     OKF("Running with fixed seed: %u", (u32)afl->init_seed);
1444 
1445   }
1446 
1447   #if defined(__SANITIZE_ADDRESS__)
1448   if (afl->fsrv.mem_limit) {
1449 
1450     WARNF("in the ASAN build we disable all memory limits");
1451     afl->fsrv.mem_limit = 0;
1452 
1453   }
1454 
1455   #endif
1456 
1457   configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal,
1458                              afl->afl_env.afl_fsrv_kill_signal,
1459                              (afl->fsrv.qemu_mode || afl->unicorn_mode
1460   #ifdef __linux__
1461                               || afl->fsrv.nyx_mode
1462   #endif
1463                               )
1464                                  ? SIGKILL
1465                                  : SIGTERM);
1466 
1467   setup_signal_handlers();
1468   check_asan_opts(afl);
1469 
1470   afl->power_name = power_names[afl->schedule];
1471 
1472   if (!afl->non_instrumented_mode && !afl->sync_id) {
1473 
1474     auto_sync = 1;
1475     afl->sync_id = ck_strdup("default");
1476     afl->is_secondary_node = 1;
1477     OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id);
1478 
1479   }
1480 
1481   #ifdef __linux__
1482   if (afl->fsrv.nyx_mode) {
1483 
1484     if (afl->fsrv.nyx_standalone && strcmp(afl->sync_id, "default") != 0) {
1485 
1486       FATAL(
1487           "distributed fuzzing is not supported in this Nyx mode (use -Y "
1488           "instead)");
1489 
1490     }
1491 
1492     if (!afl->fsrv.nyx_standalone) {
1493 
1494       if (afl->is_main_node) {
1495 
1496         if (strcmp("0", afl->sync_id) != 0) {
1497 
1498           FATAL(
1499               "for Nyx -Y mode, the Main (-M) parameter has to be set to 0 (-M "
1500               "0)");
1501 
1502         }
1503 
1504         afl->fsrv.nyx_parent = true;
1505         afl->fsrv.nyx_id = 0;
1506 
1507       }
1508 
1509       if (afl->is_secondary_node) {
1510 
1511         long nyx_id = strtol(afl->sync_id, NULL, 10);
1512 
1513         if (nyx_id == 0 || nyx_id == LONG_MAX) {
1514 
1515           FATAL(
1516               "for Nyx -Y mode, the Secondary (-S) parameter has to be a "
1517               "numeric value and >= 1 (e.g. -S 1)");
1518 
1519         }
1520 
1521         afl->fsrv.nyx_id = nyx_id;
1522 
1523       }
1524 
1525     }
1526 
1527   }
1528 
1529   #endif
1530 
1531   if (afl->sync_id) {
1532 
1533     if (strlen(afl->sync_id) > 50) {
1534 
1535       FATAL("sync_id max length is 50 characters");
1536 
1537     }
1538 
1539     fix_up_sync(afl);
1540 
1541   }
1542 
1543   if (!strcmp(afl->in_dir, afl->out_dir)) {
1544 
1545     FATAL("Input and output directories can't be the same");
1546 
1547   }
1548 
1549   if (afl->non_instrumented_mode) {
1550 
1551     if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
1552     if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
1553     if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
1554     if (afl->fsrv.cs_mode) { FATAL("-A and -n are mutually exclusive"); }
1555     if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
1556 
1557   }
1558 
1559   setenv("__AFL_OUT_DIR", afl->out_dir, 1);
1560 
1561   if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
1562 
1563   if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
1564 
1565     FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive");
1566 
1567   }
1568 
1569   if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
1570 
1571   if (!afl->use_banner) { afl->use_banner = argv[optind]; }
1572 
1573   if (afl->shm.cmplog_mode && strcmp("0", afl->cmplog_binary) == 0) {
1574 
1575     afl->cmplog_binary = strdup(argv[optind]);
1576 
1577   }
1578 
1579   if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
1580 
1581     WARNF(cLRD
1582           "Target binary called without a prefixed path, make sure you are "
1583           "fuzzing the right binary: " cRST "%s",
1584           argv[optind]);
1585 
1586   }
1587 
1588   ACTF("Getting to work...");
1589 
1590   switch (afl->schedule) {
1591 
1592     case FAST:
1593       OKF("Using exponential power schedule (FAST)");
1594       break;
1595     case COE:
1596       OKF("Using cut-off exponential power schedule (COE)");
1597       break;
1598     case EXPLOIT:
1599       OKF("Using exploitation-based constant power schedule (EXPLOIT)");
1600       break;
1601     case LIN:
1602       OKF("Using linear power schedule (LIN)");
1603       break;
1604     case QUAD:
1605       OKF("Using quadratic power schedule (QUAD)");
1606       break;
1607     case MMOPT:
1608       OKF("Using modified MOpt power schedule (MMOPT)");
1609       break;
1610     case RARE:
1611       OKF("Using rare edge focus power schedule (RARE)");
1612       break;
1613     case SEEK:
1614       OKF("Using seek power schedule (SEEK)");
1615       break;
1616     case EXPLORE:
1617       OKF("Using exploration-based constant power schedule (EXPLORE)");
1618       break;
1619     default:
1620       FATAL("Unknown power schedule");
1621       break;
1622 
1623   }
1624 
1625   if (afl->shm.cmplog_mode) { OKF("CmpLog level: %u", afl->cmplog_lvl); }
1626 
1627   /* Dynamically allocate memory for AFLFast schedules */
1628   if (afl->schedule >= FAST && afl->schedule <= RARE) {
1629 
1630     afl->n_fuzz = ck_alloc(N_FUZZ_SIZE * sizeof(u32));
1631 
1632   }
1633 
1634   if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
1635   if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
1636   if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
1637   if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
1638   if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
1639 
1640   if (afl->afl_env.afl_autoresume) {
1641 
1642     afl->autoresume = 1;
1643     if (afl->in_place_resume) {
1644 
1645       SAYF("AFL_AUTORESUME has no effect for '-i -'");
1646 
1647     }
1648 
1649   }
1650 
1651   if (afl->afl_env.afl_hang_tmout) {
1652 
1653     s32 hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
1654     if (hang_tmout < 1) { FATAL("Invalid value for AFL_HANG_TMOUT"); }
1655     afl->hang_tmout = (u32)hang_tmout;
1656 
1657   }
1658 
1659   if (afl->afl_env.afl_exit_on_time) {
1660 
1661     u64 exit_on_time = atoi(afl->afl_env.afl_exit_on_time);
1662     afl->exit_on_time = (u64)exit_on_time * 1000;
1663 
1664   }
1665 
1666   if (afl->afl_env.afl_max_det_extras) {
1667 
1668     s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
1669     if (max_det_extras < 1) { FATAL("Invalid value for AFL_MAX_DET_EXTRAS"); }
1670     afl->max_det_extras = (u32)max_det_extras;
1671 
1672   } else {
1673 
1674     afl->max_det_extras = MAX_DET_EXTRAS;
1675 
1676   }
1677 
1678   if (afl->afl_env.afl_testcache_size) {
1679 
1680     afl->q_testcase_max_cache_size =
1681         (u64)atoi(afl->afl_env.afl_testcache_size) * 1048576;
1682 
1683   }
1684 
1685   if (afl->afl_env.afl_testcache_entries) {
1686 
1687     afl->q_testcase_max_cache_entries =
1688         (u32)atoi(afl->afl_env.afl_testcache_entries);
1689 
1690     // user_set_cache = 1;
1691 
1692   }
1693 
1694   if (!afl->afl_env.afl_testcache_size || !afl->afl_env.afl_testcache_entries) {
1695 
1696     afl->afl_env.afl_testcache_entries = 0;
1697     afl->afl_env.afl_testcache_size = 0;
1698 
1699   }
1700 
1701   if (!afl->q_testcase_max_cache_size) {
1702 
1703     ACTF(
1704         "No testcache was configured. it is recommended to use a testcache, it "
1705         "improves performance: set AFL_TESTCACHE_SIZE=(value in MB)");
1706 
1707   } else if (afl->q_testcase_max_cache_size < 2 * MAX_FILE) {
1708 
1709     FATAL("AFL_TESTCACHE_SIZE must be set to %ld or more, or 0 to disable",
1710           (2 * MAX_FILE) % 1048576 == 0 ? (2 * MAX_FILE) / 1048576
1711                                         : 1 + ((2 * MAX_FILE) / 1048576));
1712 
1713   } else {
1714 
1715     OKF("Enabled testcache with %llu MB",
1716         afl->q_testcase_max_cache_size / 1048576);
1717 
1718   }
1719 
1720   if (afl->afl_env.afl_forksrv_init_tmout) {
1721 
1722     afl->fsrv.init_tmout = atoi(afl->afl_env.afl_forksrv_init_tmout);
1723     if (!afl->fsrv.init_tmout) {
1724 
1725       FATAL("Invalid value of AFL_FORKSRV_INIT_TMOUT");
1726 
1727     }
1728 
1729   } else {
1730 
1731     afl->fsrv.init_tmout = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
1732 
1733   }
1734 
1735   if (afl->afl_env.afl_crash_exitcode) {
1736 
1737     long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10);
1738     if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
1739         exitcode < -127 || exitcode > 128) {
1740 
1741       FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
1742             afl->afl_env.afl_crash_exitcode);
1743 
1744     }
1745 
1746     afl->fsrv.uses_crash_exitcode = true;
1747     // WEXITSTATUS is 8 bit unsigned
1748     afl->fsrv.crash_exitcode = (u8)exitcode;
1749 
1750   }
1751 
1752   if (afl->non_instrumented_mode == 2 && afl->no_forkserver) {
1753 
1754     FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
1755 
1756   }
1757 
1758   // Marker: ADD_TO_INJECTIONS
1759   if (getenv("AFL_LLVM_INJECTIONS_ALL") || getenv("AFL_LLVM_INJECTIONS_SQL") ||
1760       getenv("AFL_LLVM_INJECTIONS_LDAP") || getenv("AFL_LLVM_INJECTIONS_XSS")) {
1761 
1762     OKF("Adding injection tokens to dictionary.");
1763     if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
1764         getenv("AFL_LLVM_INJECTIONS_SQL")) {
1765 
1766       add_extra(afl, "'\"\"'", 4);
1767 
1768     }
1769 
1770     if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
1771         getenv("AFL_LLVM_INJECTIONS_LDAP")) {
1772 
1773       add_extra(afl, "*)(1=*))(|", 10);
1774 
1775     }
1776 
1777     if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
1778         getenv("AFL_LLVM_INJECTIONS_XSS")) {
1779 
1780       add_extra(afl, "1\"><\"", 5);
1781 
1782     }
1783 
1784   }
1785 
1786   OKF("Generating fuzz data with a length of min=%u max=%u", afl->min_length,
1787       afl->max_length);
1788   u32 min_alloc = MAX(64U, afl->min_length);
1789   afl_realloc(AFL_BUF_PARAM(in_scratch), min_alloc);
1790   afl_realloc(AFL_BUF_PARAM(in), min_alloc);
1791   afl_realloc(AFL_BUF_PARAM(out_scratch), min_alloc);
1792   afl_realloc(AFL_BUF_PARAM(out), min_alloc);
1793   afl_realloc(AFL_BUF_PARAM(eff), min_alloc);
1794   afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
1795 
1796   afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
1797 
1798   #ifdef __linux__
1799   if (!afl->fsrv.nyx_mode) {
1800 
1801     check_crash_handling();
1802     check_cpu_governor(afl);
1803 
1804   } else {
1805 
1806     u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
1807     afl->fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
1808     if (afl->fsrv.nyx_handlers == NULL) {
1809 
1810       FATAL("failed to initialize libnyx.so...");
1811 
1812     }
1813 
1814   }
1815 
1816   #else
1817   check_crash_handling();
1818   check_cpu_governor(afl);
1819   #endif
1820 
1821   #ifdef __APPLE__
1822   setenv("DYLD_NO_PIE", "1", 0);
1823   #endif
1824 
1825   if (getenv("LD_PRELOAD")) {
1826 
1827     WARNF(
1828         "LD_PRELOAD is set, are you sure that is what you want to do "
1829         "instead of using AFL_PRELOAD?");
1830 
1831   }
1832 
1833   if (afl->afl_env.afl_preload) {
1834 
1835     if (afl->fsrv.qemu_mode) {
1836 
1837       /* afl-qemu-trace takes care of converting AFL_PRELOAD. */
1838 
1839     } else if (afl->fsrv.frida_mode) {
1840 
1841       afl_preload = getenv("AFL_PRELOAD");
1842       u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1843       OKF("Injecting %s ...", frida_binary);
1844       if (afl_preload) {
1845 
1846         if (afl->fsrv.frida_asan) {
1847 
1848           OKF("Using Frida Address Sanitizer Mode");
1849 
1850           fasan_check_afl_preload(afl_preload);
1851 
1852           setenv("ASAN_OPTIONS", "detect_leaks=false", 1);
1853 
1854         }
1855 
1856         u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1857         OKF("Injecting %s ...", frida_binary);
1858         frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
1859 
1860         ck_free(frida_binary);
1861 
1862         setenv("LD_PRELOAD", frida_afl_preload, 1);
1863         setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
1864 
1865       }
1866 
1867     } else {
1868 
1869       /* CoreSight mode uses the default behavior. */
1870 
1871       setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
1872       setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
1873 
1874     }
1875 
1876   } else if (afl->fsrv.frida_mode) {
1877 
1878     if (afl->fsrv.frida_asan) {
1879 
1880       OKF("Using Frida Address Sanitizer Mode");
1881       FATAL(
1882           "Address Sanitizer DSO must be loaded using AFL_PRELOAD in Frida "
1883           "Address Sanitizer Mode");
1884 
1885     } else {
1886 
1887       u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
1888       OKF("Injecting %s ...", frida_binary);
1889       setenv("LD_PRELOAD", frida_binary, 1);
1890       setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
1891       ck_free(frida_binary);
1892 
1893     }
1894 
1895   }
1896 
1897   if (getenv("AFL_LD_PRELOAD")) {
1898 
1899     FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
1900 
1901   }
1902 
1903   if (afl->afl_env.afl_target_env &&
1904       !extract_and_set_env(afl->afl_env.afl_target_env)) {
1905 
1906     FATAL("Bad value of AFL_TARGET_ENV");
1907 
1908   }
1909 
1910   save_cmdline(afl, argc, argv);
1911   check_if_tty(afl);
1912   if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
1913 
1914   get_core_count(afl);
1915 
1916   atexit(at_exit);
1917 
1918   setup_dirs_fds(afl);
1919 
1920   #ifdef HAVE_AFFINITY
1921   bind_to_free_cpu(afl);
1922   #endif                                                   /* HAVE_AFFINITY */
1923 
1924   #ifdef __linux__
1925   if (afl->fsrv.nyx_mode && afl->fsrv.nyx_bind_cpu_id == 0xFFFFFFFF) {
1926 
1927     afl->fsrv.nyx_bind_cpu_id = 0;
1928 
1929   }
1930 
1931   #endif
1932 
1933   #ifdef __HAIKU__
1934   /* Prioritizes performance over power saving */
1935   set_scheduler_mode(SCHEDULER_MODE_LOW_LATENCY);
1936   #endif
1937 
1938   #ifdef __APPLE__
1939   if (pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0) != 0) {
1940 
1941     WARNF("general thread priority settings failed");
1942 
1943   }
1944 
1945   #endif
1946 
1947   init_count_class16();
1948 
1949   if (afl->is_main_node && check_main_node_exists(afl) == 1) {
1950 
1951     WARNF("it is wasteful to run more than one main node!");
1952     sleep(1);
1953 
1954   } else if (!auto_sync && afl->is_secondary_node &&
1955 
1956              check_main_node_exists(afl) == 0) {
1957 
1958     WARNF(
1959         "no -M main node found. It is recommended to run exactly one main "
1960         "instance.");
1961     sleep(1);
1962 
1963   }
1964 
1965   #ifdef RAND_TEST_VALUES
1966   u32 counter;
1967   for (counter = 0; counter < 100000; counter++)
1968     printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
1969   #endif
1970 
1971   if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
1972 
1973     setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
1974 
1975   }
1976 
1977   if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
1978 
1979     setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
1980 
1981   }
1982 
1983   if (!getenv("AFL_CUSTOM_INFO_PROGRAM_ARGV")) {
1984 
1985     u8 envbuf[8096] = "", tmpbuf[8096] = "";
1986     for (s32 i = optind + 1; i < argc; ++i) {
1987 
1988       strcpy(tmpbuf, envbuf);
1989       if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
1990           !strchr(argv[i], '\'')) {
1991 
1992         if (!strchr(argv[i], '\'')) {
1993 
1994           snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
1995 
1996         } else {
1997 
1998           snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
1999 
2000         }
2001 
2002       } else {
2003 
2004         snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
2005 
2006       }
2007 
2008     }
2009 
2010     setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
2011 
2012   }
2013 
2014   if (!getenv("AFL_CUSTOM_INFO_OUT")) {
2015 
2016     setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1);  // same as __AFL_OUT_DIR
2017 
2018   }
2019 
2020   setup_custom_mutators(afl);
2021 
2022   if (afl->afl_env.afl_custom_mutator_only) {
2023 
2024     if (!afl->custom_mutators_count) {
2025 
2026       if (afl->shm.cmplog_mode) {
2027 
2028         WARNF(
2029             "No custom mutator loaded, using AFL_CUSTOM_MUTATOR_ONLY is "
2030             "pointless and only allowed now to allow experiments with CMPLOG.");
2031 
2032       } else {
2033 
2034         FATAL(
2035             "No custom mutator loaded but AFL_CUSTOM_MUTATOR_ONLY specified.");
2036 
2037       }
2038 
2039     }
2040 
2041     /* This ensures we don't proceed to havoc/splice */
2042     afl->custom_only = 1;
2043 
2044     /* Ensure we also skip all deterministic steps */
2045     afl->skip_deterministic = 1;
2046 
2047   }
2048 
2049   if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
2050 
2051     if (afl->custom_only) {
2052 
2053       FATAL("Custom mutators are incompatible with MOpt (-L)");
2054 
2055     }
2056 
2057     u32 custom_fuzz = 0;
2058     LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
2059 
2060       if (el->afl_custom_fuzz) { custom_fuzz = 1; }
2061 
2062     });
2063 
2064     if (custom_fuzz) {
2065 
2066       WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
2067 
2068     }
2069 
2070   }
2071 
2072   write_setup_file(afl, argc, argv);
2073 
2074   setup_cmdline_file(afl, argv + optind);
2075 
2076   read_testcases(afl, NULL);
2077   // read_foreign_testcases(afl, 1); for the moment dont do this
2078   OKF("Loaded a total of %u seeds.", afl->queued_items);
2079 
2080   pivot_inputs(afl);
2081 
2082   if (!afl->timeout_given) { find_timeout(afl); }  // only for resumes!
2083 
2084   if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
2085       !afl->in_place_resume) {
2086 
2087     char tmpfile[PATH_MAX];
2088 
2089     if (afl->file_extension) {
2090 
2091       snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
2092                afl->file_extension);
2093 
2094     } else {
2095 
2096       snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
2097 
2098     }
2099 
2100     /* there is still a race condition here, but well ... */
2101     if (access(tmpfile, F_OK) != -1) {
2102 
2103       FATAL(
2104           "AFL_TMPDIR already has an existing temporary input file: %s - if "
2105           "this is not from another instance, then just remove the file.",
2106           tmpfile);
2107 
2108     }
2109 
2110   } else {
2111 
2112     afl->tmp_dir = afl->out_dir;
2113 
2114   }
2115 
2116   /* If we don't have a file name chosen yet, use a safe default. */
2117 
2118   if (!afl->fsrv.out_file) {
2119 
2120     u32 j = optind + 1;
2121     while (argv[j]) {
2122 
2123       u8 *aa_loc = strstr(argv[j], "@@");
2124 
2125       if (aa_loc && !afl->fsrv.out_file) {
2126 
2127         afl->fsrv.use_stdin = 0;
2128         default_output = 0;
2129 
2130         if (afl->file_extension) {
2131 
2132           afl->fsrv.out_file = alloc_printf("%s/.cur_input.%s", afl->tmp_dir,
2133                                             afl->file_extension);
2134 
2135         } else {
2136 
2137           afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
2138 
2139         }
2140 
2141         detect_file_args(argv + optind + 1, afl->fsrv.out_file,
2142                          &afl->fsrv.use_stdin);
2143         break;
2144 
2145       }
2146 
2147       ++j;
2148 
2149     }
2150 
2151   }
2152 
2153   if (!afl->fsrv.out_file) { setup_stdio_file(afl); }
2154 
2155   if (afl->cmplog_binary) {
2156 
2157     if (afl->unicorn_mode) {
2158 
2159       FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry");
2160 
2161     }
2162 
2163     if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
2164         !afl->non_instrumented_mode) {
2165 
2166       check_binary(afl, afl->cmplog_binary);
2167 
2168     }
2169 
2170   }
2171 
2172   check_binary(afl, argv[optind]);
2173 
2174   #ifdef AFL_PERSISTENT_RECORD
2175   if (unlikely(afl->fsrv.persistent_record)) {
2176 
2177     if (!getenv(PERSIST_ENV_VAR)) {
2178 
2179       FATAL(
2180           "Target binary is not compiled in persistent mode, "
2181           "AFL_PERSISTENT_RECORD makes no sense.");
2182 
2183     }
2184 
2185     afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
2186 
2187   }
2188 
2189   #endif
2190 
2191   if (afl->shmem_testcase_mode) { setup_testcase_shmem(afl); }
2192 
2193   afl->start_time = get_cur_time();
2194 
2195   if (afl->fsrv.qemu_mode) {
2196 
2197     if (afl->use_wine) {
2198 
2199       use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind,
2200                                argv + optind);
2201 
2202     } else {
2203 
2204       use_argv = get_qemu_argv(argv[0], &afl->fsrv.target_path, argc - optind,
2205                                argv + optind);
2206 
2207     }
2208 
2209   } else if (afl->fsrv.cs_mode) {
2210 
2211     use_argv = get_cs_argv(argv[0], &afl->fsrv.target_path, argc - optind,
2212                            argv + optind);
2213 
2214   } else {
2215 
2216     use_argv = argv + optind;
2217 
2218   }
2219 
2220   if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
2221       afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
2222 
2223     u32 old_map_size = map_size;
2224     map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
2225     afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
2226     afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
2227     afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
2228     afl->var_bytes = ck_realloc(afl->var_bytes, map_size);
2229     afl->top_rated = ck_realloc(afl->top_rated, map_size * sizeof(void *));
2230     afl->clean_trace = ck_realloc(afl->clean_trace, map_size);
2231     afl->clean_trace_custom = ck_realloc(afl->clean_trace_custom, map_size);
2232     afl->first_trace = ck_realloc(afl->first_trace, map_size);
2233     afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
2234 
2235     if (old_map_size < map_size) {
2236 
2237       memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size);
2238       memset(afl->top_rated + old_map_size, 0, map_size - old_map_size);
2239       memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size);
2240       memset(afl->clean_trace_custom + old_map_size, 0,
2241              map_size - old_map_size);
2242       memset(afl->first_trace + old_map_size, 0, map_size - old_map_size);
2243       memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size);
2244 
2245     }
2246 
2247   }
2248 
2249   afl->argv = use_argv;
2250   afl->fsrv.trace_bits =
2251       afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
2252 
2253   if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
2254       !afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode &&
2255       !afl->afl_env.afl_skip_bin_check) {
2256 
2257     if (map_size <= DEFAULT_SHMEM_SIZE) {
2258 
2259       afl->fsrv.map_size = DEFAULT_SHMEM_SIZE;  // dummy temporary value
2260       char vbuf[16];
2261       snprintf(vbuf, sizeof(vbuf), "%u", DEFAULT_SHMEM_SIZE);
2262       setenv("AFL_MAP_SIZE", vbuf, 1);
2263 
2264     }
2265 
2266     u32 new_map_size = afl_fsrv_get_mapsize(
2267         &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child);
2268 
2269     // only reinitialize if the map needs to be larger than what we have.
2270     if (map_size < new_map_size) {
2271 
2272       OKF("Re-initializing maps to %u bytes", new_map_size);
2273 
2274       u32 old_map_size = map_size;
2275       afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
2276       afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
2277       afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
2278       afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
2279       afl->top_rated =
2280           ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
2281       afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
2282       afl->clean_trace_custom =
2283           ck_realloc(afl->clean_trace_custom, new_map_size);
2284       afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
2285       afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
2286 
2287       if (old_map_size < new_map_size) {
2288 
2289         memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
2290         memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
2291         memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
2292         memset(afl->clean_trace_custom + old_map_size, 0,
2293                new_map_size - old_map_size);
2294         memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
2295         memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
2296 
2297       }
2298 
2299       afl_fsrv_kill(&afl->fsrv);
2300       afl_shm_deinit(&afl->shm);
2301       afl->fsrv.map_size = new_map_size;
2302       afl->fsrv.trace_bits =
2303           afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
2304       setenv("AFL_NO_AUTODICT", "1", 1);  // loaded already
2305       afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
2306                      afl->afl_env.afl_debug_child);
2307 
2308       map_size = new_map_size;
2309 
2310     }
2311 
2312   }
2313 
2314   if (afl->cmplog_binary) {
2315 
2316     ACTF("Spawning cmplog forkserver");
2317     afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
2318     // TODO: this is semi-nice
2319     afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
2320     afl->cmplog_fsrv.cs_mode = afl->fsrv.cs_mode;
2321     afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
2322     afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
2323     afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
2324     afl->cmplog_fsrv.target_path = afl->fsrv.target_path;
2325     afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
2326 
2327     if ((map_size <= DEFAULT_SHMEM_SIZE ||
2328          afl->cmplog_fsrv.map_size < map_size) &&
2329         !afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
2330         !afl->fsrv.frida_mode && !afl->unicorn_mode && !afl->fsrv.cs_mode &&
2331         !afl->afl_env.afl_skip_bin_check) {
2332 
2333       afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
2334       char vbuf[16];
2335       snprintf(vbuf, sizeof(vbuf), "%u", afl->cmplog_fsrv.map_size);
2336       setenv("AFL_MAP_SIZE", vbuf, 1);
2337 
2338     }
2339 
2340     u32 new_map_size =
2341         afl_fsrv_get_mapsize(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
2342                              afl->afl_env.afl_debug_child);
2343 
2344     // only reinitialize when it needs to be larger
2345     if (map_size < new_map_size) {
2346 
2347       OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
2348 
2349       u32 old_map_size = map_size;
2350       afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
2351       afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
2352       afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
2353       afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
2354       afl->top_rated =
2355           ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
2356       afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
2357       afl->clean_trace_custom =
2358           ck_realloc(afl->clean_trace_custom, new_map_size);
2359       afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
2360       afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
2361 
2362       if (old_map_size < new_map_size) {
2363 
2364         memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
2365         memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
2366         memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
2367         memset(afl->clean_trace_custom + old_map_size, 0,
2368                new_map_size - old_map_size);
2369         memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
2370         memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
2371 
2372       }
2373 
2374       afl_fsrv_kill(&afl->fsrv);
2375       afl_fsrv_kill(&afl->cmplog_fsrv);
2376       afl_shm_deinit(&afl->shm);
2377 
2378       afl->cmplog_fsrv.map_size = new_map_size;  // non-cmplog stays the same
2379       map_size = new_map_size;
2380 
2381       setenv("AFL_NO_AUTODICT", "1", 1);  // loaded already
2382       afl->fsrv.trace_bits =
2383           afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
2384       afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
2385       afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
2386                      afl->afl_env.afl_debug_child);
2387       afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
2388                      afl->afl_env.afl_debug_child);
2389 
2390     }
2391 
2392     OKF("Cmplog forkserver successfully started");
2393 
2394   }
2395 
2396   load_auto(afl);
2397 
2398   if (extras_dir_cnt) {
2399 
2400     for (u8 i = 0; i < extras_dir_cnt; i++) {
2401 
2402       load_extras(afl, extras_dir[i]);
2403 
2404     }
2405 
2406   }
2407 
2408   if (afl->fsrv.out_file && afl->fsrv.use_shmem_fuzz) {
2409 
2410     unlink(afl->fsrv.out_file);
2411     afl->fsrv.out_file = NULL;
2412     afl->fsrv.use_stdin = 0;
2413     close(afl->fsrv.out_fd);
2414     afl->fsrv.out_fd = -1;
2415 
2416     if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) {
2417 
2418       WARNF(
2419           "You specified -f or @@ on the command line but the target harness "
2420           "specified fuzz cases via shmem, switching to shmem!");
2421 
2422     }
2423 
2424   }
2425 
2426   deunicode_extras(afl);
2427   dedup_extras(afl);
2428   if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
2429 
2430   // after we have the correct bitmap size we can read the bitmap -B option
2431   // and set the virgin maps
2432   if (afl->in_bitmap) {
2433 
2434     read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size);
2435 
2436   } else {
2437 
2438     memset(afl->virgin_bits, 255, map_size);
2439 
2440   }
2441 
2442   memset(afl->virgin_tmout, 255, map_size);
2443   memset(afl->virgin_crash, 255, map_size);
2444 
2445   if (likely(!afl->afl_env.afl_no_startup_calibration)) {
2446 
2447     perform_dry_run(afl);
2448 
2449   } else {
2450 
2451     ACTF("skipping initial seed calibration due option override!");
2452     usleep(1000);
2453 
2454   }
2455 
2456   if (afl->q_testcase_max_cache_entries) {
2457 
2458     afl->q_testcase_cache =
2459         ck_alloc(afl->q_testcase_max_cache_entries * sizeof(size_t));
2460     if (!afl->q_testcase_cache) { PFATAL("malloc failed for cache entries"); }
2461 
2462   }
2463 
2464   cull_queue(afl);
2465 
2466   // ensure we have at least one seed that is not disabled.
2467   u32 entry, valid_seeds = 0;
2468   for (entry = 0; entry < afl->queued_items; ++entry)
2469     if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
2470 
2471   if (!afl->pending_not_fuzzed || !valid_seeds) {
2472 
2473     FATAL("We need at least one valid input seed that does not crash!");
2474 
2475   }
2476 
2477   if (afl->timeout_given == 2) {  // -t ...+ option
2478 
2479     if (valid_seeds == 1) {
2480 
2481       WARNF(
2482           "Only one valid seed is present, auto-calculating the timeout is "
2483           "disabled!");
2484       afl->timeout_given = 1;
2485 
2486     } else {
2487 
2488       u64 max_ms = 0;
2489 
2490       for (entry = 0; entry < afl->queued_items; ++entry)
2491         if (!afl->queue_buf[entry]->disabled)
2492           if (afl->queue_buf[entry]->exec_us > max_ms)
2493             max_ms = afl->queue_buf[entry]->exec_us;
2494 
2495       afl->fsrv.exec_tmout = max_ms;
2496       afl->timeout_given = 1;
2497 
2498     }
2499 
2500   }
2501 
2502   show_init_stats(afl);
2503 
2504   if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl);
2505 
2506   afl->start_time = get_cur_time();
2507   if (afl->in_place_resume || afl->afl_env.afl_autoresume) {
2508 
2509     load_stats_file(afl);
2510 
2511   }
2512 
2513   if (!afl->non_instrumented_mode) { write_stats_file(afl, 0, 0, 0, 0); }
2514   maybe_update_plot_file(afl, 0, 0, 0);
2515   save_auto(afl);
2516 
2517   if (afl->stop_soon) { goto stop_fuzzing; }
2518 
2519   /* Woop woop woop */
2520 
2521   if (!afl->not_on_tty) {
2522 
2523     sleep(1);
2524     if (afl->stop_soon) { goto stop_fuzzing; }
2525 
2526   }
2527 
2528   // (void)nice(-20);  // does not improve the speed
2529   // real start time, we reset, so this works correctly with -V
2530   afl->start_time = get_cur_time();
2531 
2532   #ifdef INTROSPECTION
2533   u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
2534   #endif
2535   u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1;
2536   u8  skipped_fuzz;
2537 
2538   #ifdef INTROSPECTION
2539   char ifn[4096];
2540   snprintf(ifn, sizeof(ifn), "%s/introspection.txt", afl->out_dir);
2541   if ((afl->introspection_file = fopen(ifn, "w")) == NULL) {
2542 
2543     PFATAL("could not create '%s'", ifn);
2544 
2545   }
2546 
2547   setvbuf(afl->introspection_file, NULL, _IONBF, 0);
2548   OKF("Writing mutation introspection to '%s'", ifn);
2549   #endif
2550 
2551   while (likely(!afl->stop_soon)) {
2552 
2553     cull_queue(afl);
2554 
2555     if (unlikely((!afl->old_seed_selection &&
2556                   runs_in_current_cycle > afl->queued_items) ||
2557                  (afl->old_seed_selection && !afl->queue_cur))) {
2558 
2559       if (unlikely((afl->last_sync_cycle < afl->queue_cycle ||
2560                     (!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
2561                    afl->sync_id)) {
2562 
2563         if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
2564 
2565           OKF("Syncing queues from other fuzzer instances first ...");
2566 
2567         }
2568 
2569         sync_fuzzers(afl);
2570 
2571       }
2572 
2573       ++afl->queue_cycle;
2574       runs_in_current_cycle = (u32)-1;
2575       afl->cur_skipped_items = 0;
2576 
2577       // 1st april fool joke - enable pizza mode
2578       // to not waste time on checking the date we only do this when the
2579       // queue is fully cycled.
2580       time_t     cursec = time(NULL);
2581       struct tm *curdate = localtime(&cursec);
2582       if (likely(!afl->afl_env.afl_pizza_mode)) {
2583 
2584         if (unlikely(curdate->tm_mon == 3 && curdate->tm_mday == 1)) {
2585 
2586           afl->pizza_is_served = 1;
2587 
2588         } else {
2589 
2590           afl->pizza_is_served = 0;
2591 
2592         }
2593 
2594       }
2595 
2596       if (unlikely(afl->old_seed_selection)) {
2597 
2598         afl->current_entry = 0;
2599         while (unlikely(afl->current_entry < afl->queued_items &&
2600                         afl->queue_buf[afl->current_entry]->disabled)) {
2601 
2602           ++afl->current_entry;
2603 
2604         }
2605 
2606         if (afl->current_entry >= afl->queued_items) { afl->current_entry = 0; }
2607 
2608         afl->queue_cur = afl->queue_buf[afl->current_entry];
2609 
2610         if (unlikely(seek_to)) {
2611 
2612           if (unlikely(seek_to >= afl->queued_items)) {
2613 
2614             // This should never happen.
2615             FATAL("BUG: seek_to location out of bounds!\n");
2616 
2617           }
2618 
2619           afl->current_entry = seek_to;
2620           afl->queue_cur = afl->queue_buf[seek_to];
2621           seek_to = 0;
2622 
2623         }
2624 
2625       }
2626 
2627       if (unlikely(afl->not_on_tty)) {
2628 
2629         ACTF("Entering queue cycle %llu.", afl->queue_cycle);
2630         fflush(stdout);
2631 
2632       }
2633 
2634       /* If we had a full queue cycle with no new finds, try
2635          recombination strategies next. */
2636 
2637       if (unlikely(afl->queued_items == prev_queued
2638                    /* FIXME TODO BUG: && (get_cur_time() - afl->start_time) >=
2639                       3600 */
2640                    )) {
2641 
2642         if (afl->use_splicing) {
2643 
2644           ++afl->cycles_wo_finds;
2645 
2646           if (unlikely(afl->shm.cmplog_mode &&
2647                        afl->cmplog_max_filesize < MAX_FILE)) {
2648 
2649             afl->cmplog_max_filesize <<= 4;
2650 
2651           }
2652 
2653           switch (afl->expand_havoc) {
2654 
2655             case 0:
2656               // this adds extra splicing mutation options to havoc mode
2657               afl->expand_havoc = 1;
2658               break;
2659             case 1:
2660               // add MOpt mutator
2661               /*
2662               if (afl->limit_time_sig == 0 && !afl->custom_only &&
2663                   !afl->python_only) {
2664 
2665                 afl->limit_time_sig = -1;
2666                 afl->limit_time_puppet = 0;
2667 
2668               }
2669 
2670               */
2671               afl->expand_havoc = 2;
2672               if (afl->cmplog_lvl && afl->cmplog_lvl < 2) afl->cmplog_lvl = 2;
2673               break;
2674             case 2:
2675               // increase havoc mutations per fuzz attempt
2676               afl->havoc_stack_pow2++;
2677               afl->expand_havoc = 3;
2678               break;
2679             case 3:
2680               // further increase havoc mutations per fuzz attempt
2681               afl->havoc_stack_pow2++;
2682               afl->expand_havoc = 4;
2683               break;
2684             case 4:
2685               afl->expand_havoc = 5;
2686               // if (afl->cmplog_lvl && afl->cmplog_lvl < 3) afl->cmplog_lvl =
2687               // 3;
2688               break;
2689             case 5:
2690               // nothing else currently
2691               break;
2692 
2693           }
2694 
2695         } else {
2696 
2697   #ifndef NO_SPLICING
2698           afl->use_splicing = 1;
2699   #else
2700           afl->use_splicing = 0;
2701   #endif
2702 
2703         }
2704 
2705       } else {
2706 
2707         afl->cycles_wo_finds = 0;
2708 
2709       }
2710 
2711   #ifdef INTROSPECTION
2712       {
2713 
2714         u64 cur_time = get_cur_time();
2715         fprintf(afl->introspection_file,
2716                 "CYCLE cycle=%llu cycle_wo_finds=%llu time_wo_finds=%llu "
2717                 "expand_havoc=%u queue=%u\n",
2718                 afl->queue_cycle, afl->cycles_wo_finds,
2719                 afl->longest_find_time > cur_time - afl->last_find_time
2720                     ? afl->longest_find_time / 1000
2721                     : ((afl->start_time == 0 || afl->last_find_time == 0)
2722                            ? 0
2723                            : (cur_time - afl->last_find_time) / 1000),
2724                 afl->expand_havoc, afl->queued_items);
2725 
2726       }
2727 
2728   #endif
2729 
2730       if (afl->cycle_schedules) {
2731 
2732         /* we cannot mix non-AFLfast schedules with others */
2733 
2734         switch (afl->schedule) {
2735 
2736           case EXPLORE:
2737             afl->schedule = EXPLOIT;
2738             break;
2739           case EXPLOIT:
2740             afl->schedule = MMOPT;
2741             break;
2742           case MMOPT:
2743             afl->schedule = SEEK;
2744             break;
2745           case SEEK:
2746             afl->schedule = EXPLORE;
2747             break;
2748           case FAST:
2749             afl->schedule = COE;
2750             break;
2751           case COE:
2752             afl->schedule = LIN;
2753             break;
2754           case LIN:
2755             afl->schedule = QUAD;
2756             break;
2757           case QUAD:
2758             afl->schedule = RARE;
2759             break;
2760           case RARE:
2761             afl->schedule = FAST;
2762             break;
2763 
2764         }
2765 
2766         // we must recalculate the scores of all queue entries
2767         for (u32 i = 0; i < afl->queued_items; i++) {
2768 
2769           if (likely(!afl->queue_buf[i]->disabled)) {
2770 
2771             update_bitmap_score(afl, afl->queue_buf[i]);
2772 
2773           }
2774 
2775         }
2776 
2777       }
2778 
2779       prev_queued = afl->queued_items;
2780 
2781     }
2782 
2783     ++runs_in_current_cycle;
2784 
2785     do {
2786 
2787       if (likely(!afl->old_seed_selection)) {
2788 
2789         if (likely(afl->pending_favored && afl->smallest_favored >= 0)) {
2790 
2791           afl->current_entry = afl->smallest_favored;
2792 
2793           /*
2794 
2795                     } else {
2796 
2797                       for (s32 iter = afl->queued_items - 1; iter >= 0; --iter)
2798              {
2799 
2800                         if (unlikely(afl->queue_buf[iter]->favored &&
2801                                      !afl->queue_buf[iter]->was_fuzzed)) {
2802 
2803                           afl->current_entry = iter;
2804                           break;
2805 
2806                         }
2807 
2808                       }
2809 
2810           */
2811 
2812           afl->queue_cur = afl->queue_buf[afl->current_entry];
2813 
2814         } else {
2815 
2816           if (unlikely(prev_queued_items < afl->queued_items ||
2817                        afl->reinit_table)) {
2818 
2819             // we have new queue entries since the last run, recreate alias
2820             // table
2821             prev_queued_items = afl->queued_items;
2822             create_alias_table(afl);
2823 
2824           }
2825 
2826           do {
2827 
2828             afl->current_entry = select_next_queue_entry(afl);
2829 
2830           } while (unlikely(afl->current_entry >= afl->queued_items));
2831 
2832           afl->queue_cur = afl->queue_buf[afl->current_entry];
2833 
2834         }
2835 
2836       }
2837 
2838       skipped_fuzz = fuzz_one(afl);
2839   #ifdef INTROSPECTION
2840       ++afl->queue_cur->stats_selected;
2841 
2842       if (unlikely(skipped_fuzz)) {
2843 
2844         ++afl->queue_cur->stats_skipped;
2845 
2846       } else {
2847 
2848         if (unlikely(afl->queued_items > prev_queued_items)) {
2849 
2850           afl->queue_cur->stats_finds += afl->queued_items - prev_queued_items;
2851           prev_queued_items = afl->queued_items;
2852 
2853         }
2854 
2855         if (unlikely(afl->saved_crashes > prev_saved_crashes)) {
2856 
2857           afl->queue_cur->stats_crashes +=
2858               afl->saved_crashes - prev_saved_crashes;
2859           prev_saved_crashes = afl->saved_crashes;
2860 
2861         }
2862 
2863         if (unlikely(afl->saved_tmouts > prev_saved_tmouts)) {
2864 
2865           afl->queue_cur->stats_tmouts += afl->saved_tmouts - prev_saved_tmouts;
2866           prev_saved_tmouts = afl->saved_tmouts;
2867 
2868         }
2869 
2870       }
2871 
2872   #endif
2873 
2874       if (unlikely(!afl->stop_soon && exit_1)) { afl->stop_soon = 2; }
2875 
2876       if (unlikely(afl->old_seed_selection)) {
2877 
2878         while (++afl->current_entry < afl->queued_items &&
2879                afl->queue_buf[afl->current_entry]->disabled) {};
2880         if (unlikely(afl->current_entry >= afl->queued_items ||
2881                      afl->queue_buf[afl->current_entry] == NULL ||
2882                      afl->queue_buf[afl->current_entry]->disabled)) {
2883 
2884           afl->queue_cur = NULL;
2885 
2886         } else {
2887 
2888           afl->queue_cur = afl->queue_buf[afl->current_entry];
2889 
2890         }
2891 
2892       }
2893 
2894     } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon);
2895 
2896     u64 cur_time = get_cur_time();
2897 
2898     if (likely(afl->switch_fuzz_mode && afl->fuzz_mode == 0 &&
2899                !afl->non_instrumented_mode) &&
2900         unlikely(cur_time > (likely(afl->last_find_time) ? afl->last_find_time
2901                                                          : afl->start_time) +
2902                                 afl->switch_fuzz_mode)) {
2903 
2904       if (afl->afl_env.afl_no_ui) {
2905 
2906         ACTF(
2907             "No new coverage found for %llu seconds, switching to exploitation "
2908             "strategy.",
2909             afl->switch_fuzz_mode / 1000);
2910 
2911       }
2912 
2913       afl->fuzz_mode = 1;
2914 
2915     }
2916 
2917     if (likely(!afl->stop_soon && afl->sync_id)) {
2918 
2919       if (likely(afl->skip_deterministic)) {
2920 
2921         if (unlikely(afl->is_main_node)) {
2922 
2923           if (unlikely(cur_time >
2924                        (afl->sync_time >> 1) + afl->last_sync_time)) {
2925 
2926             if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
2927 
2928               sync_fuzzers(afl);
2929 
2930             }
2931 
2932           }
2933 
2934         } else {
2935 
2936           if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
2937 
2938             if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
2939 
2940           }
2941 
2942         }
2943 
2944       } else {
2945 
2946         sync_fuzzers(afl);
2947 
2948       }
2949 
2950     }
2951 
2952   }
2953 
2954 stop_fuzzing:
2955 
2956   afl->force_ui_update = 1;  // ensure the screen is reprinted
2957   afl->stop_soon = 1;        // ensure everything is written
2958   show_stats(afl);           // print the screen one last time
2959   write_bitmap(afl);
2960   save_auto(afl);
2961 
2962   if (afl->pizza_is_served) {
2963 
2964     SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST,
2965          afl->stop_soon == 2 ? "programmatically" : "by the chef");
2966 
2967   } else {
2968 
2969     SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST,
2970          afl->stop_soon == 2 ? "programmatically" : "by user");
2971 
2972   }
2973 
2974   if (afl->most_time_key == 2) {
2975 
2976     SAYF(cYEL "[!] " cRST "Time limit was reached\n");
2977 
2978   }
2979 
2980   if (afl->most_execs_key == 2) {
2981 
2982     SAYF(cYEL "[!] " cRST "Execution limit was reached\n");
2983 
2984   }
2985 
2986   /* Running for more than 30 minutes but still doing first cycle? */
2987 
2988   if (afl->queue_cycle == 1 &&
2989       get_cur_time() - afl->start_time > 30 * 60 * 1000) {
2990 
2991     SAYF("\n" cYEL "[!] " cRST
2992          "Stopped during the first cycle, results may be incomplete.\n"
2993          "    (For info on resuming, see %s/README.md)\n",
2994          doc_path);
2995 
2996   }
2997 
2998   if (afl->not_on_tty) {
2999 
3000     u32 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
3001     u8  time_tmp[64];
3002     u_stringify_time_diff(time_tmp, get_cur_time(), afl->start_time);
3003     ACTF(
3004         "Statistics: %u new corpus items found, %.02f%% coverage achieved, "
3005         "%llu crashes saved, %llu timeouts saved, total runtime %s",
3006         afl->queued_discovered,
3007         ((double)t_bytes * 100) / afl->fsrv.real_map_size, afl->saved_crashes,
3008         afl->saved_hangs, time_tmp);
3009 
3010   }
3011 
3012   #ifdef PROFILING
3013   SAYF(cYEL "[!] " cRST
3014             "Profiling information: %llu ms total work, %llu ns/run\n",
3015        time_spent_working / 1000000,
3016        time_spent_working / afl->fsrv.total_execs);
3017   #endif
3018 
3019   if (afl->afl_env.afl_final_sync) {
3020 
3021     SAYF(cYEL "[!] " cRST
3022               "\nPerforming final sync, this make take some time ...\n");
3023     sync_fuzzers(afl);
3024     write_bitmap(afl);
3025     SAYF(cYEL "[!] " cRST "Done!\n\n");
3026 
3027   }
3028 
3029   if (afl->is_main_node) {
3030 
3031     u8 path[PATH_MAX];
3032     sprintf(path, "%s/is_main_node", afl->out_dir);
3033     unlink(path);
3034 
3035   }
3036 
3037   if (frida_afl_preload) { ck_free(frida_afl_preload); }
3038 
3039   fclose(afl->fsrv.plot_file);
3040 
3041   #ifdef INTROSPECTION
3042   fclose(afl->fsrv.det_plot_file);
3043   #endif
3044 
3045   destroy_queue(afl);
3046   destroy_extras(afl);
3047   destroy_custom_mutators(afl);
3048   afl_shm_deinit(&afl->shm);
3049 
3050   if (afl->shm_fuzz) {
3051 
3052     afl_shm_deinit(afl->shm_fuzz);
3053     ck_free(afl->shm_fuzz);
3054 
3055   }
3056 
3057   afl_fsrv_deinit(&afl->fsrv);
3058 
3059   /* remove tmpfile */
3060   if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
3061 
3062     (void)unlink(afl->fsrv.out_file);
3063 
3064   }
3065 
3066   if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
3067   ck_free(afl->fsrv.target_path);
3068   ck_free(afl->fsrv.out_file);
3069   ck_free(afl->sync_id);
3070   if (afl->q_testcase_cache) { ck_free(afl->q_testcase_cache); }
3071   afl_state_deinit(afl);
3072   free(afl);                                                 /* not tracked */
3073 
3074   argv_cpy_free(argv);
3075 
3076   alloc_report();
3077 
3078   OKF("We're done here. Have a nice day!\n");
3079 
3080   exit(0);
3081 
3082 }
3083 
3084 #endif                                                          /* !AFL_LIB */
3085 
3086