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