• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    american fuzzy lop++ - initialization related routines
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 <limits.h>
28 #include "cmplog.h"
29 
30 #ifdef HAVE_AFFINITY
31 
32 /* bind process to a specific cpu. Returns 0 on failure. */
33 
bind_cpu(afl_state_t * afl,s32 cpuid)34 static u8 bind_cpu(afl_state_t *afl, s32 cpuid) {
35 
36   #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
37   cpu_set_t c;
38   #elif defined(__NetBSD__)
39   cpuset_t *c;
40   #elif defined(__sun)
41   psetid_t c;
42   #endif
43 
44   afl->cpu_aff = cpuid;
45 
46   #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
47 
48   CPU_ZERO(&c);
49   CPU_SET(cpuid, &c);
50 
51   #elif defined(__NetBSD__)
52 
53   c = cpuset_create();
54   if (c == NULL) { PFATAL("cpuset_create failed"); }
55   cpuset_set(cpuid, c);
56 
57   #elif defined(__sun)
58 
59   pset_create(&c);
60   if (pset_assign(c, cpuid, NULL)) { PFATAL("pset_assign failed"); }
61 
62   #endif
63 
64   #if defined(__linux__)
65 
66   return (sched_setaffinity(0, sizeof(c), &c) == 0);
67 
68   #elif defined(__FreeBSD__) || defined(__DragonFly__)
69 
70   return (pthread_setaffinity_np(pthread_self(), sizeof(c), &c) == 0);
71 
72   #elif defined(__NetBSD__)
73 
74   if (pthread_setaffinity_np(pthread_self(), cpuset_size(c), c)) {
75 
76     cpuset_destroy(c);
77     return 0;
78 
79   }
80 
81   cpuset_destroy(c);
82   return 1;
83 
84   #elif defined(__sun)
85 
86   if (pset_bind(c, P_PID, getpid(), NULL)) {
87 
88     pset_destroy(c);
89     return 0;
90 
91   }
92 
93   pset_destroy(c);
94   return 1;
95 
96   #else
97 
98   // this will need something for other platforms
99   // TODO: Solaris/Illumos has processor_bind ... might worth a try
100   WARNF("Cannot bind to CPU yet on this platform.");
101   return 1;
102 
103   #endif
104 
105 }
106 
107 /* Build a list of processes bound to specific cores. Returns -1 if nothing
108    can be found. Assumes an upper bound of 4k CPUs. */
109 
bind_to_free_cpu(afl_state_t * afl)110 void bind_to_free_cpu(afl_state_t *afl) {
111 
112   u8  cpu_used[4096] = {0};
113   u8  lockfile[PATH_MAX] = "";
114   s32 i;
115 
116   if (afl->afl_env.afl_no_affinity && !afl->afl_env.afl_try_affinity) {
117 
118     if (afl->cpu_to_bind != -1) {
119 
120       FATAL("-b and AFL_NO_AFFINITY are mututally exclusive.");
121 
122     }
123 
124     WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set).");
125     return;
126 
127   }
128 
129   if (afl->cpu_to_bind != -1) {
130 
131     if (!bind_cpu(afl, afl->cpu_to_bind)) {
132 
133       if (afl->afl_env.afl_try_affinity) {
134 
135         WARNF(
136             "Could not bind to requested CPU %d! Make sure you passed a valid "
137             "-b.",
138             afl->cpu_to_bind);
139 
140       } else {
141 
142         FATAL(
143             "Could not bind to requested CPU %d! Make sure you passed a valid "
144             "-b.",
145             afl->cpu_to_bind);
146 
147       }
148 
149     }
150 
151     return;
152 
153   }
154 
155   if (afl->cpu_core_count < 2) { return; }
156 
157   if (afl->sync_id) {
158 
159     s32 lockfd, first = 1;
160 
161     snprintf(lockfile, sizeof(lockfile), "%s/.affinity_lock", afl->sync_dir);
162     setenv(CPU_AFFINITY_ENV_VAR, lockfile, 1);
163 
164     do {
165 
166       if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL,
167                          DEFAULT_PERMISSION)) < 0) {
168 
169         if (first) {
170 
171           WARNF("CPU affinity lock file present, waiting ...");
172           first = 0;
173 
174         }
175 
176         usleep(1000);
177 
178       }
179 
180     } while (lockfd < 0);
181 
182     close(lockfd);
183 
184   }
185 
186   #if defined(__linux__)
187 
188   DIR *          d;
189   struct dirent *de;
190   d = opendir("/proc");
191 
192   if (!d) {
193 
194     if (lockfile[0]) unlink(lockfile);
195     WARNF("Unable to access /proc - can't scan for free CPU cores.");
196     return;
197 
198   }
199 
200   ACTF("Checking CPU core loadout...");
201 
202   /* Scan all /proc/<pid>/status entries, checking for Cpus_allowed_list.
203      Flag all processes bound to a specific CPU using cpu_used[]. This will
204      fail for some exotic binding setups, but is likely good enough in almost
205      all real-world use cases. */
206 
207   while ((de = readdir(d))) {
208 
209     u8    fn[PATH_MAX];
210     FILE *f;
211     u8    tmp[MAX_LINE];
212     u8    has_vmsize = 0;
213 
214     if (!isdigit(de->d_name[0])) { continue; }
215 
216     snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name);
217 
218     if (!(f = fopen(fn, "r"))) { continue; }
219 
220     while (fgets(tmp, MAX_LINE, f)) {
221 
222       u32 hval;
223 
224       /* Processes without VmSize are probably kernel tasks. */
225 
226       if (!strncmp(tmp, "VmSize:\t", 8)) { has_vmsize = 1; }
227 
228       if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && !strchr(tmp, '-') &&
229           !strchr(tmp, ',') && sscanf(tmp + 19, "%u", &hval) == 1 &&
230           hval < sizeof(cpu_used) && has_vmsize) {
231 
232         cpu_used[hval] = 1;
233         break;
234 
235       }
236 
237     }
238 
239     fclose(f);
240 
241   }
242 
243   closedir(d);
244 
245   #elif defined(__FreeBSD__) || defined(__DragonFly__)
246 
247   struct kinfo_proc *procs;
248   size_t             nprocs;
249   size_t             proccount;
250   int                s_name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
251   size_t             s_name_l = sizeof(s_name) / sizeof(s_name[0]);
252 
253   if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) {
254 
255     if (lockfile[0]) unlink(lockfile);
256     return;
257 
258   }
259 
260   proccount = nprocs / sizeof(*procs);
261   nprocs = nprocs * 4 / 3;
262 
263   procs = ck_alloc(nprocs);
264   if (sysctl(s_name, s_name_l, procs, &nprocs, NULL, 0) != 0) {
265 
266     if (lockfile[0]) unlink(lockfile);
267     ck_free(procs);
268     return;
269 
270   }
271 
272   for (i = 0; i < (s32)proccount; i++) {
273 
274     #if defined(__FreeBSD__)
275 
276     if (!strcmp(procs[i].ki_comm, "idle")) continue;
277 
278     // fix when ki_oncpu = -1
279     s32 oncpu;
280     oncpu = procs[i].ki_oncpu;
281     if (oncpu == -1) oncpu = procs[i].ki_lastcpu;
282 
283     if (oncpu != -1 && oncpu < (s32)sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
284       cpu_used[oncpu] = 1;
285 
286     #elif defined(__DragonFly__)
287 
288     if (procs[i].kp_lwp.kl_cpuid < (s32)sizeof(cpu_used) &&
289         procs[i].kp_lwp.kl_pctcpu > 10)
290       cpu_used[procs[i].kp_lwp.kl_cpuid] = 1;
291 
292     #endif
293 
294   }
295 
296   ck_free(procs);
297 
298   #elif defined(__NetBSD__)
299 
300   struct kinfo_proc2 *procs;
301   size_t              nprocs;
302   size_t              proccount;
303   int                 s_name[] = {
304 
305       CTL_KERN, KERN_PROC2, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), 0};
306   size_t s_name_l = sizeof(s_name) / sizeof(s_name[0]);
307 
308   if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) {
309 
310     if (lockfile[0]) unlink(lockfile);
311     return;
312 
313   }
314 
315   proccount = nprocs / sizeof(struct kinfo_proc2);
316   procs = ck_alloc(nprocs * sizeof(struct kinfo_proc2));
317   s_name[5] = proccount;
318 
319   if (sysctl(s_name, s_name_l, procs, &nprocs, NULL, 0) != 0) {
320 
321     if (lockfile[0]) unlink(lockfile);
322     ck_free(procs);
323     return;
324 
325   }
326 
327   for (i = 0; i < (s32)proccount; i++) {
328 
329     if (procs[i].p_cpuid < sizeof(cpu_used) && procs[i].p_pctcpu > 0)
330       cpu_used[procs[i].p_cpuid] = 1;
331 
332   }
333 
334   ck_free(procs);
335 
336   #elif defined(__sun)
337 
338   kstat_named_t *n;
339   kstat_ctl_t *  m;
340   kstat_t *      k;
341   cpu_stat_t     cs;
342   u32            ncpus;
343 
344   m = kstat_open();
345 
346   if (!m) FATAL("kstat_open failed");
347 
348   k = kstat_lookup(m, "unix", 0, "system_misc");
349 
350   if (!k) {
351 
352     if (lockfile[0]) unlink(lockfile);
353     kstat_close(m);
354     return;
355 
356   }
357 
358   if (kstat_read(m, k, NULL)) {
359 
360     if (lockfile[0]) unlink(lockfile);
361     kstat_close(m);
362     return;
363 
364   }
365 
366   n = kstat_data_lookup(k, "ncpus");
367   ncpus = n->value.i32;
368 
369   if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
370 
371   for (i = 0; i < (s32)ncpus; i++) {
372 
373     k = kstat_lookup(m, "cpu_stat", i, NULL);
374     if (kstat_read(m, k, &cs)) {
375 
376       if (lockfile[0]) unlink(lockfile);
377       kstat_close(m);
378       return;
379 
380     }
381 
382     if (cs.cpu_sysinfo.cpu[CPU_IDLE] > 0) continue;
383 
384     if (cs.cpu_sysinfo.cpu[CPU_USER] > 0 || cs.cpu_sysinfo.cpu[CPU_KERNEL] > 0)
385       cpu_used[i] = 1;
386 
387   }
388 
389   kstat_close(m);
390 
391   #else
392     #warning \
393         "For this platform we do not have free CPU binding code yet. If possible, please supply a PR to https://github.com/AFLplusplus/AFLplusplus"
394   #endif
395 
396   #if !defined(__aarch64__) && !defined(__arm__) && !defined(__arm64__)
397 
398   for (i = 0; i < afl->cpu_core_count; i++) {
399 
400   #else
401 
402   /* many ARM devices have performance and efficiency cores, the slower
403      efficiency cores seem to always come first */
404 
405   for (i = afl->cpu_core_count - 1; i > -1; i--) {
406 
407   #endif
408 
409     if (cpu_used[i]) { continue; }
410 
411     OKF("Found a free CPU core, try binding to #%u.", i);
412 
413     if (bind_cpu(afl, i)) {
414 
415   #ifdef __linux__
416       if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = i; }
417   #endif
418       /* Success :) */
419       break;
420 
421     }
422 
423     WARNF("setaffinity failed to CPU %d, trying next CPU", i);
424 
425   }
426 
427   if (lockfile[0]) unlink(lockfile);
428 
429   if (i == afl->cpu_core_count || i == -1) {
430 
431     SAYF("\n" cLRD "[-] " cRST
432          "Uh-oh, looks like all %d CPU cores on your system are allocated to\n"
433          "    other instances of afl-fuzz (or similar CPU-locked tasks). "
434          "Starting\n"
435          "    another fuzzer on this machine is probably a bad plan.\n"
436          "%s",
437          afl->cpu_core_count,
438          afl->afl_env.afl_try_affinity ? ""
439                                        : "    If you are sure, you can set "
440                                          "AFL_NO_AFFINITY and try again.\n");
441 
442     if (!afl->afl_env.afl_try_affinity) { FATAL("No more free CPU cores"); }
443 
444   }
445 
446 }
447 
448 #endif                                                     /* HAVE_AFFINITY */
449 
450 /* Shuffle an array of pointers. Might be slightly biased. */
451 
452 static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
453 
454   u32 i;
455 
456   for (i = 0; i < cnt - 2; ++i) {
457 
458     u32   j = i + rand_below(afl, cnt - i);
459     void *s = ptrs[i];
460     ptrs[i] = ptrs[j];
461     ptrs[j] = s;
462 
463   }
464 
465 }
466 
467 /* Read all testcases from foreign input directories, then queue them for
468    testing. Called at startup and at sync intervals.
469    Does not descend into subdirectories! */
470 
471 void read_foreign_testcases(afl_state_t *afl, int first) {
472 
473   if (!afl->foreign_sync_cnt) return;
474 
475   struct dirent **nl;
476   s32             nl_cnt;
477   u32             i, iter;
478 
479   u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
480   u8 foreign_name[16];
481 
482   for (iter = 0; iter < afl->foreign_sync_cnt; iter++) {
483 
484     if (afl->foreign_syncs[iter].dir && afl->foreign_syncs[iter].dir[0]) {
485 
486       if (first) ACTF("Scanning '%s'...", afl->foreign_syncs[iter].dir);
487       time_t mtime_max = 0;
488 
489       u8 *name = strrchr(afl->foreign_syncs[iter].dir, '/');
490       if (!name) {
491 
492         name = afl->foreign_syncs[iter].dir;
493 
494       } else {
495 
496         ++name;
497 
498       }
499 
500       if (!strcmp(name, "queue") || !strcmp(name, "out") ||
501           !strcmp(name, "default")) {
502 
503         snprintf(foreign_name, sizeof(foreign_name), "foreign_%u", iter);
504 
505       } else {
506 
507         snprintf(foreign_name, sizeof(foreign_name), "%s_%u", name, iter);
508 
509       }
510 
511       /* We do not use sorting yet and do a more expensive mtime check instead.
512          a mtimesort() implementation would be better though. */
513 
514       nl_cnt = scandir(afl->foreign_syncs[iter].dir, &nl, NULL, NULL);
515 
516       if (nl_cnt < 0) {
517 
518         if (first) {
519 
520           WARNF("Unable to open directory '%s'", afl->foreign_syncs[iter].dir);
521           sleep(1);
522 
523         }
524 
525         continue;
526 
527       }
528 
529       if (nl_cnt == 0) {
530 
531         if (first) {
532 
533           WARNF("directory %s is currently empty",
534                 afl->foreign_syncs[iter].dir);
535 
536         }
537 
538         continue;
539 
540       }
541 
542       /* Show stats */
543 
544       snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "foreign sync %u", iter);
545 
546       afl->stage_name = afl->stage_name_buf;
547       afl->stage_cur = 0;
548       afl->stage_max = 0;
549 
550       for (i = 0; i < (u32)nl_cnt; ++i) {
551 
552         struct stat st;
553 
554         u8 *fn2 =
555             alloc_printf("%s/%s", afl->foreign_syncs[iter].dir, nl[i]->d_name);
556 
557         free(nl[i]);                                         /* not tracked */
558 
559         if (unlikely(lstat(fn2, &st) || access(fn2, R_OK))) {
560 
561           if (first) PFATAL("Unable to access '%s'", fn2);
562           continue;
563 
564         }
565 
566         /* we detect new files by their mtime */
567         if (likely(st.st_mtime <= afl->foreign_syncs[iter].mtime)) {
568 
569           ck_free(fn2);
570           continue;
571 
572         }
573 
574         /* This also takes care of . and .. */
575 
576         if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
577 
578           ck_free(fn2);
579           continue;
580 
581         }
582 
583         if (st.st_size > MAX_FILE) {
584 
585           if (first) {
586 
587             WARNF(
588                 "Test case '%s' is too big (%s, limit is %s), skipping", fn2,
589                 stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
590                 stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
591 
592           }
593 
594           ck_free(fn2);
595           continue;
596 
597         }
598 
599         // lets do not use add_to_queue(afl, fn2, st.st_size, 0);
600         // as this could add duplicates of the startup input corpus
601 
602         int fd = open(fn2, O_RDONLY);
603         if (fd < 0) {
604 
605           ck_free(fn2);
606           continue;
607 
608         }
609 
610         u8  fault;
611         u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
612 
613         if (mem == MAP_FAILED) {
614 
615           ck_free(fn2);
616           continue;
617 
618         }
619 
620         u32 len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
621         fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
622         afl->syncing_party = foreign_name;
623         afl->queued_imported += save_if_interesting(afl, mem, len, fault);
624         afl->syncing_party = 0;
625         munmap(mem, st.st_size);
626         close(fd);
627 
628         if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
629 
630       }
631 
632       afl->foreign_syncs[iter].mtime = mtime_max;
633       free(nl);                                              /* not tracked */
634 
635     }
636 
637   }
638 
639   if (first) {
640 
641     afl->last_find_time = 0;
642     afl->queued_at_start = afl->queued_items;
643 
644   }
645 
646 }
647 
648 /* Read all testcases from the input directory, then queue them for testing.
649    Called at startup. */
650 
651 void read_testcases(afl_state_t *afl, u8 *directory) {
652 
653   struct dirent **nl;
654   s32             nl_cnt, subdirs = 1;
655   u32             i;
656   u8 *            fn1, *dir = directory;
657   u8              val_buf[2][STRINGIFY_VAL_SIZE_MAX];
658 
659   /* Auto-detect non-in-place resumption attempts. */
660 
661   if (dir == NULL) {
662 
663     fn1 = alloc_printf("%s/queue", afl->in_dir);
664     if (!access(fn1, F_OK)) {
665 
666       afl->in_dir = fn1;
667       subdirs = 0;
668 
669     } else {
670 
671       ck_free(fn1);
672 
673     }
674 
675     dir = afl->in_dir;
676 
677   }
678 
679   ACTF("Scanning '%s'...", dir);
680 
681   /* We use scandir() + alphasort() rather than readdir() because otherwise,
682      the ordering of test cases would vary somewhat randomly and would be
683      difficult to control. */
684 
685   nl_cnt = scandir(dir, &nl, NULL, alphasort);
686 
687   if (nl_cnt < 0 && directory == NULL) {
688 
689     if (errno == ENOENT || errno == ENOTDIR) {
690 
691       SAYF("\n" cLRD "[-] " cRST
692            "The input directory does not seem to be valid - try again. The "
693            "fuzzer needs\n"
694            "    one or more test case to start with - ideally, a small file "
695            "under 1 kB\n"
696            "    or so. The cases must be stored as regular files directly in "
697            "the input\n"
698            "    directory.\n");
699 
700     }
701 
702     PFATAL("Unable to open '%s'", dir);
703 
704   }
705 
706   if (unlikely(afl->old_seed_selection && afl->shuffle_queue && nl_cnt > 1)) {
707 
708     ACTF("Shuffling queue...");
709     shuffle_ptrs(afl, (void **)nl, nl_cnt);
710 
711   }
712 
713   if (nl_cnt) {
714 
715     i = nl_cnt;
716     do {
717 
718       --i;
719 
720       struct stat st;
721       u8          dfn[PATH_MAX];
722       snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
723                nl[i]->d_name);
724       u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
725 
726       u8 passed_det = 0;
727 
728       if (lstat(fn2, &st) || access(fn2, R_OK)) {
729 
730         PFATAL("Unable to access '%s'", fn2);
731 
732       }
733 
734       /* obviously we want to skip "descending" into . and .. directories,
735          however it is a good idea to skip also directories that start with
736          a dot */
737       if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
738 
739         free(nl[i]);                                         /* not tracked */
740         read_testcases(afl, fn2);
741         ck_free(fn2);
742         continue;
743 
744       }
745 
746       free(nl[i]);
747 
748       if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
749 
750         ck_free(fn2);
751         continue;
752 
753       }
754 
755       if (st.st_size > MAX_FILE) {
756 
757         WARNF("Test case '%s' is too big (%s, limit is %s), partial reading",
758               fn2,
759               stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
760               stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
761 
762       }
763 
764       /* Check for metadata that indicates that deterministic fuzzing
765          is complete for this entry. We don't want to repeat deterministic
766          fuzzing when resuming aborted scans, because it would be pointless
767          and probably very time-consuming. */
768 
769       if (!access(dfn, F_OK)) { passed_det = 1; }
770 
771       add_to_queue(afl, fn2, st.st_size >= MAX_FILE ? MAX_FILE : st.st_size,
772                    passed_det);
773 
774       if (unlikely(afl->shm.cmplog_mode)) {
775 
776         if (afl->cmplog_lvl == 1) {
777 
778           if (!afl->cmplog_max_filesize ||
779               afl->cmplog_max_filesize < st.st_size) {
780 
781             afl->cmplog_max_filesize = st.st_size;
782 
783           }
784 
785         } else if (afl->cmplog_lvl == 2) {
786 
787           if (!afl->cmplog_max_filesize ||
788               afl->cmplog_max_filesize > st.st_size) {
789 
790             afl->cmplog_max_filesize = st.st_size;
791 
792           }
793 
794         }
795 
796       }
797 
798       /*
799           if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
800 
801             u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size,
802          HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
803             afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
804 
805           }
806 
807       */
808 
809     } while (i > 0);
810 
811   }
812 
813   free(nl);                                                  /* not tracked */
814 
815   if (!afl->queued_items && directory == NULL) {
816 
817     SAYF("\n" cLRD "[-] " cRST
818          "Looks like there are no valid test cases in the input directory! The "
819          "fuzzer\n"
820          "    needs one or more test case to start with - ideally, a small "
821          "file under\n"
822          "    1 kB or so. The cases must be stored as regular files directly "
823          "in the\n"
824          "    input directory.\n");
825 
826     FATAL("No usable test cases in '%s'", afl->in_dir);
827 
828   }
829 
830   if (unlikely(afl->shm.cmplog_mode)) {
831 
832     if (afl->cmplog_max_filesize < 1024) {
833 
834       afl->cmplog_max_filesize = 1024;
835 
836     } else {
837 
838       afl->cmplog_max_filesize = (((afl->cmplog_max_filesize >> 10) + 1) << 10);
839 
840     }
841 
842   }
843 
844   afl->last_find_time = 0;
845   afl->queued_at_start = afl->queued_items;
846 
847 }
848 
849 /* Perform dry run of all test cases to confirm that the app is working as
850    expected. This is done only for the initial inputs, and only once. */
851 
852 void perform_dry_run(afl_state_t *afl) {
853 
854   struct queue_entry *q;
855   u32                 cal_failures = 0, idx;
856   u8 *                use_mem;
857 
858   for (idx = 0; idx < afl->queued_items; idx++) {
859 
860     q = afl->queue_buf[idx];
861     if (unlikely(!q || q->disabled)) { continue; }
862 
863     u8  res;
864     s32 fd;
865 
866     if (unlikely(!q->len)) {
867 
868       WARNF("Skipping 0-sized entry in queue (%s)", q->fname);
869       continue;
870 
871     }
872 
873     if (afl->afl_env.afl_cmplog_only_new) { q->colorized = CMPLOG_LVL_MAX; }
874 
875     u8 *fn = strrchr(q->fname, '/') + 1;
876 
877     ACTF("Attempting dry run with '%s'...", fn);
878 
879     fd = open(q->fname, O_RDONLY);
880     if (fd < 0) { PFATAL("Unable to open '%s'", q->fname); }
881 
882     u32 read_len = MIN(q->len, (u32)MAX_FILE);
883     use_mem = afl_realloc(AFL_BUF_PARAM(in), read_len);
884     ck_read(fd, use_mem, read_len, q->fname);
885 
886     close(fd);
887 
888     res = calibrate_case(afl, q, use_mem, 0, 1);
889 
890     if (afl->stop_soon) { return; }
891 
892     if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
893 
894       SAYF(cGRA "    len = %u, map size = %u, exec speed = %llu us\n" cRST,
895            q->len, q->bitmap_size, q->exec_us);
896 
897     }
898 
899     switch (res) {
900 
901       case FSRV_RUN_OK:
902 
903         if (afl->crash_mode) { FATAL("Test case '%s' does *NOT* crash", fn); }
904 
905         break;
906 
907       case FSRV_RUN_TMOUT:
908 
909         if (afl->timeout_given && !afl->afl_env.afl_exit_on_seed_issues) {
910 
911           /* if we have a timeout but a timeout value was given then always
912              skip. The '+' meaning has been changed! */
913           WARNF("Test case results in a timeout (skipping)");
914           ++cal_failures;
915           q->cal_failed = CAL_CHANCES;
916           q->disabled = 1;
917           q->perf_score = 0;
918 
919           if (!q->was_fuzzed) {
920 
921             q->was_fuzzed = 1;
922             --afl->pending_not_fuzzed;
923             --afl->active_items;
924 
925           }
926 
927           break;
928 
929         } else {
930 
931           SAYF("\n" cLRD "[-] " cRST
932                "The program took more than %u ms to process one of the initial "
933                "test cases.\n"
934                "    This is bad news; raising the limit with the -t option is "
935                "possible, but\n"
936                "    will probably make the fuzzing process extremely slow.\n\n"
937 
938                "    If this test case is just a fluke, the other option is to "
939                "just avoid it\n"
940                "    altogether, and find one that is less of a CPU hog.\n",
941                afl->fsrv.exec_tmout);
942 
943           FATAL("Test case '%s' results in a timeout", fn);
944 
945         }
946 
947       case FSRV_RUN_CRASH:
948 
949         if (afl->crash_mode) { break; }
950 
951         if (afl->fsrv.mem_limit) {
952 
953           u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
954 
955           SAYF("\n" cLRD "[-] " cRST
956                "Oops, the program crashed with one of the test cases provided. "
957                "There are\n"
958                "    several possible explanations:\n\n"
959 
960                "    - The test case causes known crashes under normal working "
961                "conditions. If\n"
962                "      so, please remove it. The fuzzer should be seeded with "
963                "interesting\n"
964                "      inputs - but not ones that cause an outright crash.\n\n"
965 
966                "    - The current memory limit (%s) is too low for this "
967                "program, causing\n"
968                "      it to die due to OOM when parsing valid files. To fix "
969                "this, try\n"
970                "      bumping it up with the -m setting in the command line. "
971                "If in doubt,\n"
972                "      try something along the lines of:\n\n"
973 
974                MSG_ULIMIT_USAGE
975                " /path/to/binary [...] <testcase )\n\n"
976 
977                "      Tip: you can use https://jwilk.net/software/recidivm to\n"
978                "      estimate the required amount of virtual memory for the "
979                "binary. Also,\n"
980                "      if you are using ASAN, set '-m 0'.\n\n"
981 
982                "    - In QEMU persistent mode the selected address(es) for the "
983                "loop are not\n"
984                "      properly cleaning up variables and memory. Try adding\n"
985                "      AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in "
986                "the binary.\n\n"
987 
988                MSG_FORK_ON_APPLE
989 
990                "    - Least likely, there is a horrible bug in the fuzzer. If "
991                "other options\n"
992                "      fail, poke <afl-users@googlegroups.com> for "
993                "troubleshooting tips.\n",
994                stringify_mem_size(val_buf, sizeof(val_buf),
995                                   afl->fsrv.mem_limit << 20),
996                afl->fsrv.mem_limit - 1);
997 
998         } else {
999 
1000           SAYF("\n" cLRD "[-] " cRST
1001                "Oops, the program crashed with one of the test cases provided. "
1002                "There are\n"
1003                "    several possible explanations:\n\n"
1004 
1005                "    - The test case causes known crashes under normal working "
1006                "conditions. If\n"
1007                "      so, please remove it. The fuzzer should be seeded with "
1008                "interesting\n"
1009                "      inputs - but not ones that cause an outright crash.\n\n"
1010 
1011                "    - In QEMU persistent mode the selected address(es) for the "
1012                "loop are not\n"
1013                "      properly cleaning up variables and memory. Try adding\n"
1014                "      AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in "
1015                "the binary.\n\n"
1016 
1017                MSG_FORK_ON_APPLE
1018 
1019                "    - Least likely, there is a horrible bug in the fuzzer. If "
1020                "other options\n"
1021                "      fail, poke <afl-users@googlegroups.com> for "
1022                "troubleshooting tips.\n");
1023 
1024         }
1025 
1026 #undef MSG_ULIMIT_USAGE
1027 #undef MSG_FORK_ON_APPLE
1028 
1029         if (afl->fsrv.uses_crash_exitcode) {
1030 
1031           WARNF(
1032               "Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, "
1033               "skipping",
1034               fn, (int)(s8)afl->fsrv.crash_exitcode);
1035 
1036         } else {
1037 
1038           WARNF("Test case '%s' results in a crash, skipping", fn);
1039 
1040         }
1041 
1042         if (afl->afl_env.afl_exit_on_seed_issues) {
1043 
1044           FATAL("As AFL_EXIT_ON_SEED_ISSUES is set, afl-fuzz exits.");
1045 
1046         }
1047 
1048         /* Remove from fuzzing queue but keep for splicing */
1049 
1050         if (!q->was_fuzzed) {
1051 
1052           q->was_fuzzed = 1;
1053           --afl->pending_not_fuzzed;
1054           --afl->active_items;
1055 
1056         }
1057 
1058         q->disabled = 1;
1059         q->perf_score = 0;
1060 
1061         u32 i = 0;
1062         while (unlikely(i < afl->queued_items && afl->queue_buf[i] &&
1063                         afl->queue_buf[i]->disabled)) {
1064 
1065           ++i;
1066 
1067         }
1068 
1069         if (i < afl->queued_items && afl->queue_buf[i]) {
1070 
1071           afl->queue = afl->queue_buf[i];
1072 
1073         } else {
1074 
1075           afl->queue = afl->queue_buf[0];
1076 
1077         }
1078 
1079         afl->max_depth = 0;
1080         for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) {
1081 
1082           if (!afl->queue_buf[i]->disabled &&
1083               afl->queue_buf[i]->depth > afl->max_depth)
1084             afl->max_depth = afl->queue_buf[i]->depth;
1085 
1086         }
1087 
1088         break;
1089 
1090       case FSRV_RUN_ERROR:
1091 
1092         FATAL("Unable to execute target application ('%s')", afl->argv[0]);
1093 
1094       case FSRV_RUN_NOINST:
1095 #ifdef __linux__
1096         if (afl->fsrv.nyx_mode && afl->fsrv.nyx_runner != NULL) {
1097 
1098           afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner);
1099 
1100         }
1101 
1102 #endif
1103         FATAL("No instrumentation detected");
1104 
1105       case FSRV_RUN_NOBITS:
1106 
1107         ++afl->useless_at_start;
1108 
1109         if (!afl->in_bitmap && !afl->shuffle_queue) {
1110 
1111           WARNF("No new instrumentation output, test case may be useless.");
1112 
1113         }
1114 
1115         break;
1116 
1117     }
1118 
1119     if (q->var_behavior) {
1120 
1121       WARNF("Instrumentation output varies across runs.");
1122 
1123     }
1124 
1125   }
1126 
1127   if (cal_failures) {
1128 
1129     if (cal_failures == afl->queued_items) {
1130 
1131       FATAL("All test cases time out or crash, giving up!");
1132 
1133     }
1134 
1135     WARNF("Skipped %u test cases (%0.02f%%) due to timeouts or crashes.",
1136           cal_failures, ((double)cal_failures) * 100 / afl->queued_items);
1137 
1138     if (cal_failures * 5 > afl->queued_items) {
1139 
1140       WARNF(cLRD "High percentage of rejected test cases, check settings!");
1141 
1142     }
1143 
1144   }
1145 
1146   /* Now we remove all entries from the queue that have a duplicate trace map */
1147 
1148   u32 duplicates = 0, i;
1149 
1150   for (idx = 0; idx < afl->queued_items; idx++) {
1151 
1152     q = afl->queue_buf[idx];
1153     if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
1154 
1155     u32 done = 0;
1156     for (i = idx + 1;
1157          i < afl->queued_items && !done && likely(afl->queue_buf[i]); i++) {
1158 
1159       struct queue_entry *p = afl->queue_buf[i];
1160       if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
1161 
1162       if (p->exec_cksum == q->exec_cksum) {
1163 
1164         duplicates = 1;
1165 
1166         // we keep the shorter file
1167         if (p->len >= q->len) {
1168 
1169           if (!p->was_fuzzed) {
1170 
1171             p->was_fuzzed = 1;
1172             --afl->pending_not_fuzzed;
1173             --afl->active_items;
1174 
1175           }
1176 
1177           p->disabled = 1;
1178           p->perf_score = 0;
1179 
1180         } else {
1181 
1182           if (!q->was_fuzzed) {
1183 
1184             q->was_fuzzed = 1;
1185             --afl->pending_not_fuzzed;
1186             --afl->active_items;
1187 
1188           }
1189 
1190           q->disabled = 1;
1191           q->perf_score = 0;
1192 
1193           done = 1;
1194 
1195         }
1196 
1197       }
1198 
1199     }
1200 
1201   }
1202 
1203   if (duplicates) {
1204 
1205     afl->max_depth = 0;
1206 
1207     for (idx = 0; idx < afl->queued_items; idx++) {
1208 
1209       if (afl->queue_buf[idx] && !afl->queue_buf[idx]->disabled &&
1210           afl->queue_buf[idx]->depth > afl->max_depth)
1211         afl->max_depth = afl->queue_buf[idx]->depth;
1212 
1213     }
1214 
1215     afl->queue_top = afl->queue;
1216 
1217   }
1218 
1219   OKF("All test cases processed.");
1220 
1221 }
1222 
1223 /* Helper function: link() if possible, copy otherwise. */
1224 
1225 static void link_or_copy(u8 *old_path, u8 *new_path) {
1226 
1227   s32 i = link(old_path, new_path);
1228   s32 sfd, dfd;
1229   u8 *tmp;
1230 
1231   if (!i) { return; }
1232 
1233   sfd = open(old_path, O_RDONLY);
1234   if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
1235 
1236   dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
1237   if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); }
1238 
1239   tmp = ck_alloc(64 * 1024);
1240 
1241   while ((i = read(sfd, tmp, 64 * 1024)) > 0) {
1242 
1243     ck_write(dfd, tmp, i, new_path);
1244 
1245   }
1246 
1247   if (i < 0) { PFATAL("read() failed"); }
1248 
1249   ck_free(tmp);
1250   close(sfd);
1251   close(dfd);
1252 
1253 }
1254 
1255 /* Create hard links for input test cases in the output directory, choosing
1256    good names and pivoting accordingly. */
1257 
1258 void pivot_inputs(afl_state_t *afl) {
1259 
1260   struct queue_entry *q;
1261   u32                 id = 0, i;
1262 
1263   ACTF("Creating hard links for all input files...");
1264 
1265   for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) {
1266 
1267     q = afl->queue_buf[i];
1268 
1269     if (unlikely(q->disabled)) { continue; }
1270 
1271     u8 *nfn, *rsl = strrchr(q->fname, '/');
1272     u32 orig_id;
1273 
1274     if (!rsl) {
1275 
1276       rsl = q->fname;
1277 
1278     } else {
1279 
1280       ++rsl;
1281 
1282     }
1283 
1284     /* If the original file name conforms to the syntax and the recorded
1285        ID matches the one we'd assign, just use the original file name.
1286        This is valuable for resuming fuzzing runs. */
1287 
1288     if (!strncmp(rsl, CASE_PREFIX, 3) &&
1289         sscanf(rsl + 3, "%06u", &orig_id) == 1 && orig_id == id) {
1290 
1291       u8 *src_str;
1292       u32 src_id;
1293 
1294       afl->resuming_fuzz = 1;
1295       nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
1296 
1297       /* Since we're at it, let's also get the parent and figure out the
1298          appropriate depth for this entry. */
1299 
1300       src_str = strchr(rsl + 3, ':');
1301 
1302       if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) {
1303 
1304         if (src_id < afl->queued_items) {
1305 
1306           struct queue_entry *s = afl->queue_buf[src_id];
1307 
1308           if (s) { q->depth = s->depth + 1; }
1309 
1310         }
1311 
1312         if (afl->max_depth < q->depth) { afl->max_depth = q->depth; }
1313 
1314       }
1315 
1316     } else {
1317 
1318       /* No dice - invent a new name, capturing the original one as a
1319          substring. */
1320 
1321 #ifndef SIMPLE_FILES
1322 
1323       u8 *use_name = strstr(rsl, ",orig:");
1324 
1325       if (use_name) {
1326 
1327         use_name += 6;
1328 
1329       } else {
1330 
1331         use_name = rsl;
1332 
1333       }
1334 
1335       nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
1336                          afl->out_dir, id, afl->fsrv.total_execs, use_name);
1337 
1338 #else
1339 
1340       nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id);
1341 
1342 #endif                                                    /* ^!SIMPLE_FILES */
1343 
1344     }
1345 
1346     /* Pivot to the new queue entry. */
1347 
1348     link_or_copy(q->fname, nfn);
1349     ck_free(q->fname);
1350     q->fname = nfn;
1351 
1352     /* Make sure that the passed_det value carries over, too. */
1353 
1354     if (q->passed_det) { mark_as_det_done(afl, q); }
1355 
1356     if (afl->custom_mutators_count) {
1357 
1358       run_afl_custom_queue_new_entry(afl, q, q->fname, NULL);
1359 
1360     }
1361 
1362     ++id;
1363 
1364   }
1365 
1366   if (afl->in_place_resume) { nuke_resume_dir(afl); }
1367 
1368 }
1369 
1370 /* When resuming, try to find the queue position to start from. This makes sense
1371    only when resuming, and when we can find the original fuzzer_stats. */
1372 
1373 u32 find_start_position(afl_state_t *afl) {
1374 
1375   u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
1376 
1377   u8 *fn, *off;
1378   s32 fd, i;
1379   u32 ret;
1380 
1381   if (!afl->resuming_fuzz) { return 0; }
1382 
1383   if (afl->in_place_resume) {
1384 
1385     fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1386 
1387   } else {
1388 
1389     fn = alloc_printf("%s/../fuzzer_stats", afl->in_dir);
1390 
1391   }
1392 
1393   fd = open(fn, O_RDONLY);
1394   ck_free(fn);
1395 
1396   if (fd < 0) { return 0; }
1397 
1398   i = read(fd, tmp, sizeof(tmp) - 1);
1399   (void)i;                                                 /* Ignore errors */
1400   close(fd);
1401 
1402   off = strstr(tmp, "cur_item          : ");
1403   if (!off) { return 0; }
1404 
1405   ret = atoi(off + 20);
1406   if (ret >= afl->queued_items) { ret = 0; }
1407   return ret;
1408 
1409 }
1410 
1411 /* The same, but for timeouts. The idea is that when resuming sessions without
1412    -t given, we don't want to keep auto-scaling the timeout over and over
1413    again to prevent it from growing due to random flukes. */
1414 
1415 void find_timeout(afl_state_t *afl) {
1416 
1417   u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
1418 
1419   u8 *fn, *off;
1420   s32 fd, i;
1421   u32 ret;
1422 
1423   if (!afl->resuming_fuzz) { return; }
1424 
1425   if (afl->in_place_resume) {
1426 
1427     fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1428 
1429   } else {
1430 
1431     fn = alloc_printf("%s/../fuzzer_stats", afl->in_dir);
1432 
1433   }
1434 
1435   fd = open(fn, O_RDONLY);
1436   ck_free(fn);
1437 
1438   if (fd < 0) { return; }
1439 
1440   i = read(fd, tmp, sizeof(tmp) - 1);
1441   (void)i;                                                 /* Ignore errors */
1442   close(fd);
1443 
1444   off = strstr(tmp, "exec_timeout      : ");
1445   if (!off) { return; }
1446 
1447   ret = atoi(off + 20);
1448   if (ret <= 4) { return; }
1449 
1450   afl->fsrv.exec_tmout = ret;
1451   afl->timeout_given = 3;
1452 
1453 }
1454 
1455 /* A helper function for handle_existing_out_dir(), deleting all prefixed
1456    files in a directory. */
1457 
1458 static u8 delete_files(u8 *path, u8 *prefix) {
1459 
1460   DIR *          d;
1461   struct dirent *d_ent;
1462 
1463   d = opendir(path);
1464 
1465   if (!d) { return 0; }
1466 
1467   while ((d_ent = readdir(d))) {
1468 
1469     if (d_ent->d_name[0] != '.' &&
1470         (!prefix || !strncmp(d_ent->d_name, prefix, strlen(prefix)))) {
1471 
1472       u8 *fname = alloc_printf("%s/%s", path, d_ent->d_name);
1473       if (unlink(fname)) { PFATAL("Unable to delete '%s'", fname); }
1474       ck_free(fname);
1475 
1476     }
1477 
1478   }
1479 
1480   closedir(d);
1481 
1482   return !!rmdir(path);
1483 
1484 }
1485 
1486 /* Get the number of runnable processes, with some simple smoothing. */
1487 
1488 double get_runnable_processes(void) {
1489 
1490   double res = 0;
1491 
1492 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
1493     defined(__NetBSD__) || defined(__DragonFly__)
1494 
1495   /* I don't see any portable sysctl or so that would quickly give us the
1496      number of runnable processes; the 1-minute load average can be a
1497      semi-decent approximation, though. */
1498 
1499   if (getloadavg(&res, 1) != 1) return 0;
1500 
1501 #else
1502 
1503   /* On Linux, /proc/stat is probably the best way; load averages are
1504      computed in funny ways and sometimes don't reflect extremely short-lived
1505      processes well. */
1506 
1507   FILE *f = fopen("/proc/stat", "r");
1508   u8 tmp[1024];
1509   u32 val = 0;
1510 
1511   if (!f) { return 0; }
1512 
1513   while (fgets(tmp, sizeof(tmp), f)) {
1514 
1515     if (!strncmp(tmp, "procs_running ", 14) ||
1516         !strncmp(tmp, "procs_blocked ", 14)) {
1517 
1518       val += atoi(tmp + 14);
1519 
1520     }
1521 
1522   }
1523 
1524   fclose(f);
1525 
1526   if (!res) {
1527 
1528     res = val;
1529 
1530   } else {
1531 
1532     res = res * (1.0 - 1.0 / AVG_SMOOTHING) +
1533           ((double)val) * (1.0 / AVG_SMOOTHING);
1534 
1535   }
1536 
1537 #endif          /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__ || __NetBSD__) */
1538 
1539   return res;
1540 
1541 }
1542 
1543 /* Delete the temporary directory used for in-place session resume. */
1544 
1545 void nuke_resume_dir(afl_state_t *afl) {
1546 
1547   u8 *fn;
1548 
1549   fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
1550   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1551   ck_free(fn);
1552 
1553   fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
1554   if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; }
1555   ck_free(fn);
1556 
1557   fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
1558   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1559   ck_free(fn);
1560 
1561   fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
1562   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1563   ck_free(fn);
1564 
1565   fn = alloc_printf("%s/_resume/.state", afl->out_dir);
1566   if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1567   ck_free(fn);
1568 
1569   fn = alloc_printf("%s/_resume", afl->out_dir);
1570   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1571   ck_free(fn);
1572 
1573   return;
1574 
1575 dir_cleanup_failed:
1576 
1577   FATAL("_resume directory cleanup failed");
1578 
1579 }
1580 
1581 /* Delete fuzzer output directory if we recognize it as ours, if the fuzzer
1582    is not currently running, and if the last run time isn't too great.
1583    Resume fuzzing if `-` is set as in_dir or if AFL_AUTORESUME is set */
1584 
1585 static void handle_existing_out_dir(afl_state_t *afl) {
1586 
1587   FILE *f;
1588   u8 *  fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1589 
1590   /* See if the output directory is locked. If yes, bail out. If not,
1591      create a lock that will persist for the lifetime of the process
1592      (this requires leaving the descriptor open).*/
1593 
1594   afl->fsrv.out_dir_fd = open(afl->out_dir, O_RDONLY);
1595   if (afl->fsrv.out_dir_fd < 0) { PFATAL("Unable to open '%s'", afl->out_dir); }
1596 
1597 #ifndef __sun
1598 
1599   if (flock(afl->fsrv.out_dir_fd, LOCK_EX | LOCK_NB) && errno == EWOULDBLOCK) {
1600 
1601     SAYF("\n" cLRD "[-] " cRST
1602          "Looks like the job output directory is being actively used by "
1603          "another\n"
1604          "    instance of afl-fuzz. You will need to choose a different %s\n"
1605          "    or stop the other process first.\n",
1606          afl->sync_id ? "fuzzer ID" : "output location");
1607 
1608     FATAL("Directory '%s' is in use", afl->out_dir);
1609 
1610   }
1611 
1612 #endif                                                            /* !__sun */
1613 
1614   f = fopen(fn, "r");
1615 
1616   if (f) {
1617 
1618     u64 start_time2, last_update;
1619 
1620     if (fscanf(f,
1621                "start_time     : %llu\n"
1622                "last_update    : %llu\n",
1623                &start_time2, &last_update) != 2) {
1624 
1625       FATAL("Malformed data in '%s'", fn);
1626 
1627     }
1628 
1629     fclose(f);
1630 
1631     /* Autoresume treats a normal run as in_place_resume if a valid out dir
1632      * already exists */
1633 
1634     if (!afl->in_place_resume && afl->autoresume) {
1635 
1636       OKF("Detected prior run with AFL_AUTORESUME set. Resuming.");
1637       afl->in_place_resume = 1;
1638 
1639     }
1640 
1641     /* Let's see how much work is at stake. */
1642 
1643     if (!afl->in_place_resume && last_update > start_time2 &&
1644         last_update - start_time2 > OUTPUT_GRACE * 60) {
1645 
1646       SAYF("\n" cLRD "[-] " cRST
1647            "The job output directory already exists and contains the results "
1648            "of more\n"
1649            "    than %d minutes worth of fuzzing. To avoid data loss, afl-fuzz "
1650            "will *NOT*\n"
1651            "    automatically delete this data for you.\n\n"
1652 
1653            "    If you wish to start a new session, remove or rename the "
1654            "directory manually,\n"
1655            "    or specify a different output location for this job. To resume "
1656            "the old\n"
1657            "    session, pass '-' as input directory in the command line ('-i "
1658            "-')\n"
1659            "    or set the 'AFL_AUTORESUME=1' env variable and try again.\n",
1660            OUTPUT_GRACE);
1661 
1662       FATAL("At-risk data found in '%s'", afl->out_dir);
1663 
1664     }
1665 
1666   }
1667 
1668   ck_free(fn);
1669 
1670   /* The idea for in-place resume is pretty simple: we temporarily move the old
1671      queue/ to a new location that gets deleted once import to the new queue/
1672      is finished. If _resume/ already exists, the current queue/ may be
1673      incomplete due to an earlier abort, so we want to use the old _resume/
1674      dir instead, and we let rename() fail silently. */
1675 
1676   if (afl->in_place_resume) {
1677 
1678     u8 *orig_q = alloc_printf("%s/queue", afl->out_dir);
1679 
1680     afl->in_dir = alloc_printf("%s/_resume", afl->out_dir);
1681 
1682     rename(orig_q, afl->in_dir);                           /* Ignore errors */
1683 
1684     OKF("Output directory exists, will attempt session resume.");
1685 
1686     ck_free(orig_q);
1687 
1688   } else {
1689 
1690     OKF("Output directory exists but deemed OK to reuse.");
1691 
1692   }
1693 
1694   ACTF("Deleting old session data...");
1695 
1696   /* Okay, let's get the ball rolling! First, we need to get rid of the entries
1697      in <afl->out_dir>/.synced/.../id:*, if any are present. */
1698 
1699   if (!afl->in_place_resume) {
1700 
1701     fn = alloc_printf("%s/.synced", afl->out_dir);
1702     if (delete_files(fn, NULL)) { goto dir_cleanup_failed; }
1703     ck_free(fn);
1704 
1705   }
1706 
1707   /* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
1708 
1709   fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
1710   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1711   ck_free(fn);
1712 
1713   fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
1714   if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; }
1715   ck_free(fn);
1716 
1717   fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
1718   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1719   ck_free(fn);
1720 
1721   fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
1722   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1723   ck_free(fn);
1724 
1725   /* Then, get rid of the .state subdirectory itself (should be empty by now)
1726      and everything matching <afl->out_dir>/queue/id:*. */
1727 
1728   fn = alloc_printf("%s/queue/.state", afl->out_dir);
1729   if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1730   ck_free(fn);
1731 
1732   fn = alloc_printf("%s/queue", afl->out_dir);
1733   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1734   ck_free(fn);
1735 
1736   /* All right, let's do <afl->out_dir>/crashes/id:* and
1737    * <afl->out_dir>/hangs/id:*. */
1738 
1739   if (!afl->in_place_resume) {
1740 
1741     fn = alloc_printf("%s/crashes/README.txt", afl->out_dir);
1742     unlink(fn);                                            /* Ignore errors */
1743     ck_free(fn);
1744 
1745   }
1746 
1747   fn = alloc_printf("%s/crashes", afl->out_dir);
1748 
1749   /* Make backup of the crashes directory if it's not empty and if we're
1750      doing in-place resume. */
1751 
1752   if (afl->in_place_resume && rmdir(fn)) {
1753 
1754     time_t    cur_t = time(0);
1755     struct tm t;
1756     localtime_r(&cur_t, &t);
1757 
1758 #ifndef SIMPLE_FILES
1759 
1760     u8 *nfn =
1761         alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, t.tm_year + 1900,
1762                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1763 
1764 #else
1765 
1766     u8 *nfn =
1767         alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t.tm_year + 1900,
1768                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1769 
1770 #endif                                                    /* ^!SIMPLE_FILES */
1771 
1772     rename(fn, nfn);                                      /* Ignore errors. */
1773     ck_free(nfn);
1774 
1775   }
1776 
1777   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1778   ck_free(fn);
1779 
1780   fn = alloc_printf("%s/hangs", afl->out_dir);
1781 
1782   /* Backup hangs, too. */
1783 
1784   if (afl->in_place_resume && rmdir(fn)) {
1785 
1786     time_t    cur_t = time(0);
1787     struct tm t;
1788     localtime_r(&cur_t, &t);
1789 
1790 #ifndef SIMPLE_FILES
1791 
1792     u8 *nfn =
1793         alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, t.tm_year + 1900,
1794                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1795 
1796 #else
1797 
1798     u8 *nfn =
1799         alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t.tm_year + 1900,
1800                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1801 
1802 #endif                                                    /* ^!SIMPLE_FILES */
1803 
1804     rename(fn, nfn);                                      /* Ignore errors. */
1805     ck_free(nfn);
1806 
1807   }
1808 
1809   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1810   ck_free(fn);
1811 
1812   /* And now, for some finishing touches. */
1813 
1814   if (afl->file_extension) {
1815 
1816     fn = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
1817 
1818   } else {
1819 
1820     fn = alloc_printf("%s/.cur_input", afl->tmp_dir);
1821 
1822   }
1823 
1824   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1825   ck_free(fn);
1826 
1827   fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
1828   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1829   ck_free(fn);
1830 
1831   if (!afl->in_place_resume) {
1832 
1833     fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1834     if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1835     ck_free(fn);
1836 
1837   }
1838 
1839   if (!afl->in_place_resume) {
1840 
1841     fn = alloc_printf("%s/plot_data", afl->out_dir);
1842     if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1843     ck_free(fn);
1844 
1845   }
1846 
1847   fn = alloc_printf("%s/cmdline", afl->out_dir);
1848   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1849   ck_free(fn);
1850 
1851   OKF("Output dir cleanup successful.");
1852 
1853   /* Wow... is that all? If yes, celebrate! */
1854 
1855   return;
1856 
1857 dir_cleanup_failed:
1858 
1859   SAYF("\n" cLRD "[-] " cRST
1860        "Whoops, the fuzzer tried to reuse your output directory, but bumped "
1861        "into\n"
1862        "    some files that shouldn't be there or that couldn't be removed - "
1863        "so it\n"
1864        "    decided to abort! This happened while processing this path:\n\n"
1865 
1866        "    %s\n\n"
1867        "    Please examine and manually delete the files, or specify a "
1868        "different\n"
1869        "    output location for the tool.\n",
1870        fn);
1871 
1872   FATAL("Output directory cleanup failed");
1873 
1874 }
1875 
1876 /* If this is a -S secondary node, ensure a -M main node is running,
1877   if a main node is running when another main is started, then warn */
1878 
1879 int check_main_node_exists(afl_state_t *afl) {
1880 
1881   DIR *          sd;
1882   struct dirent *sd_ent;
1883   u8 *           fn;
1884 
1885   sd = opendir(afl->sync_dir);
1886   if (!sd) { return 0; }
1887 
1888   while ((sd_ent = readdir(sd))) {
1889 
1890     /* Skip dot files and our own output directory. */
1891 
1892     if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) {
1893 
1894       continue;
1895 
1896     }
1897 
1898     fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name);
1899     int res = access(fn, F_OK);
1900     free(fn);
1901     if (res == 0) return 1;
1902 
1903   }
1904 
1905   return 0;
1906 
1907 }
1908 
1909 /* Prepare output directories and fds. */
1910 
1911 void setup_dirs_fds(afl_state_t *afl) {
1912 
1913   u8 *tmp;
1914 
1915   ACTF("Setting up output directories...");
1916 
1917   if (afl->sync_id && mkdir(afl->sync_dir, 0700) && errno != EEXIST) {
1918 
1919     PFATAL("Unable to create '%s'", afl->sync_dir);
1920 
1921   }
1922 
1923   if (mkdir(afl->out_dir, 0700)) {
1924 
1925     if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); }
1926 
1927     handle_existing_out_dir(afl);
1928 
1929   } else {
1930 
1931     if (afl->in_place_resume) {
1932 
1933       FATAL("Resume attempted but old output directory not found");
1934 
1935     }
1936 
1937     afl->fsrv.out_dir_fd = open(afl->out_dir, O_RDONLY);
1938 
1939 #ifndef __sun
1940 
1941     if (afl->fsrv.out_dir_fd < 0 ||
1942         flock(afl->fsrv.out_dir_fd, LOCK_EX | LOCK_NB)) {
1943 
1944       PFATAL("Unable to flock() output directory.");
1945 
1946     }
1947 
1948 #endif                                                            /* !__sun */
1949 
1950   }
1951 
1952   if (afl->is_main_node) {
1953 
1954     u8 *x = alloc_printf("%s/is_main_node", afl->out_dir);
1955     int fd = open(x, O_CREAT | O_RDWR, 0644);
1956     if (fd < 0) FATAL("cannot create %s", x);
1957     free(x);
1958     close(fd);
1959 
1960   }
1961 
1962   /* Queue directory for any starting & discovered paths. */
1963 
1964   tmp = alloc_printf("%s/queue", afl->out_dir);
1965   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
1966   ck_free(tmp);
1967 
1968   /* Top-level directory for queue metadata used for session
1969      resume and related tasks. */
1970 
1971   tmp = alloc_printf("%s/queue/.state/", afl->out_dir);
1972   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
1973   ck_free(tmp);
1974 
1975   /* Directory for flagging queue entries that went through
1976      deterministic fuzzing in the past. */
1977 
1978   tmp = alloc_printf("%s/queue/.state/deterministic_done/", afl->out_dir);
1979   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
1980   ck_free(tmp);
1981 
1982   /* Directory with the auto-selected dictionary entries. */
1983 
1984   tmp = alloc_printf("%s/queue/.state/auto_extras/", afl->out_dir);
1985   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
1986   ck_free(tmp);
1987 
1988   /* The set of paths currently deemed redundant. */
1989 
1990   tmp = alloc_printf("%s/queue/.state/redundant_edges/", afl->out_dir);
1991   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
1992   ck_free(tmp);
1993 
1994   /* The set of paths showing variable behavior. */
1995 
1996   tmp = alloc_printf("%s/queue/.state/variable_behavior/", afl->out_dir);
1997   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
1998   ck_free(tmp);
1999 
2000   /* Sync directory for keeping track of cooperating fuzzers. */
2001 
2002   if (afl->sync_id) {
2003 
2004     tmp = alloc_printf("%s/.synced/", afl->out_dir);
2005 
2006     if (mkdir(tmp, 0700) && (!afl->in_place_resume || errno != EEXIST)) {
2007 
2008       PFATAL("Unable to create '%s'", tmp);
2009 
2010     }
2011 
2012     ck_free(tmp);
2013 
2014   }
2015 
2016   /* All recorded crashes. */
2017 
2018   tmp = alloc_printf("%s/crashes", afl->out_dir);
2019   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2020   ck_free(tmp);
2021 
2022   /* All recorded hangs. */
2023 
2024   tmp = alloc_printf("%s/hangs", afl->out_dir);
2025   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2026   ck_free(tmp);
2027 
2028   /* Generally useful file descriptors. */
2029 
2030   afl->fsrv.dev_null_fd = open("/dev/null", O_RDWR);
2031   if (afl->fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
2032 
2033   afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
2034   if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
2035 
2036   /* Gnuplot output file. */
2037 
2038   tmp = alloc_printf("%s/plot_data", afl->out_dir);
2039 
2040   if (!afl->in_place_resume) {
2041 
2042     int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
2043     if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2044     ck_free(tmp);
2045 
2046     afl->fsrv.plot_file = fdopen(fd, "w");
2047     if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
2048 
2049     fprintf(
2050         afl->fsrv.plot_file,
2051         "# relative_time, cycles_done, cur_item, corpus_count, "
2052         "pending_total, pending_favs, map_size, saved_crashes, "
2053         "saved_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
2054 
2055   } else {
2056 
2057     int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION);
2058     if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2059     ck_free(tmp);
2060 
2061     afl->fsrv.plot_file = fdopen(fd, "w");
2062     if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
2063 
2064     fseek(afl->fsrv.plot_file, 0, SEEK_END);
2065 
2066   }
2067 
2068   fflush(afl->fsrv.plot_file);
2069 
2070   /* ignore errors */
2071 
2072 }
2073 
2074 void setup_cmdline_file(afl_state_t *afl, char **argv) {
2075 
2076   u8 *tmp;
2077   s32 fd;
2078   u32 i = 0;
2079 
2080   FILE *cmdline_file = NULL;
2081 
2082   /* Store the command line to reproduce our findings */
2083   tmp = alloc_printf("%s/cmdline", afl->out_dir);
2084   fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
2085   if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2086   ck_free(tmp);
2087 
2088   cmdline_file = fdopen(fd, "w");
2089   if (!cmdline_file) { PFATAL("fdopen() failed"); }
2090 
2091   while (argv[i]) {
2092 
2093     fprintf(cmdline_file, "%s\n", argv[i]);
2094     ++i;
2095 
2096   }
2097 
2098   fclose(cmdline_file);
2099 
2100 }
2101 
2102 /* Setup the output file for fuzzed data, if not using -f. */
2103 
2104 void setup_stdio_file(afl_state_t *afl) {
2105 
2106   if (afl->file_extension) {
2107 
2108     afl->fsrv.out_file =
2109         alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
2110 
2111   } else {
2112 
2113     afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
2114 
2115   }
2116 
2117   unlink(afl->fsrv.out_file);                              /* Ignore errors */
2118 
2119   afl->fsrv.out_fd =
2120       open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
2121 
2122   if (afl->fsrv.out_fd < 0) {
2123 
2124     PFATAL("Unable to create '%s'", afl->fsrv.out_file);
2125 
2126   }
2127 
2128 }
2129 
2130 /* Make sure that core dumps don't go to a program. */
2131 
2132 void check_crash_handling(void) {
2133 
2134 #ifdef __APPLE__
2135 
2136   /* Yuck! There appears to be no simple C API to query for the state of
2137      loaded daemons on MacOS X, and I'm a bit hesitant to do something
2138      more sophisticated, such as disabling crash reporting via Mach ports,
2139      until I get a box to test the code. So, for now, we check for crash
2140      reporting the awful way. */
2141 
2142   #if !TARGET_OS_IPHONE
2143   if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return;
2144 
2145   SAYF(
2146       "\n" cLRD "[-] " cRST
2147       "Whoops, your system is configured to forward crash notifications to an\n"
2148       "    external crash reporting utility. This will cause issues due to "
2149       "the\n"
2150       "    extended delay between the fuzzed binary malfunctioning and this "
2151       "fact\n"
2152       "    being relayed to the fuzzer via the standard waitpid() API.\n\n"
2153       "    To avoid having crashes misinterpreted as timeouts, please run the\n"
2154       "    following commands:\n\n"
2155 
2156       "    SL=/System/Library; PL=com.apple.ReportCrash\n"
2157       "    launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n"
2158       "    sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n");
2159 
2160   #endif
2161   if (!get_afl_env("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))
2162     FATAL("Crash reporter detected");
2163 
2164 #else
2165 
2166   /* This is Linux specific, but I don't think there's anything equivalent on
2167    *BSD, so we can just let it slide for now. */
2168 
2169   s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY);
2170   u8 fchar;
2171 
2172   if (fd < 0) { return; }
2173 
2174   ACTF("Checking core_pattern...");
2175 
2176   if (read(fd, &fchar, 1) == 1 && fchar == '|') {
2177 
2178     SAYF(
2179         "\n" cLRD "[-] " cRST
2180         "Hmm, your system is configured to send core dump notifications to an\n"
2181         "    external utility. This will cause issues: there will be an "
2182         "extended delay\n"
2183         "    between stumbling upon a crash and having this information "
2184         "relayed to the\n"
2185         "    fuzzer via the standard waitpid() API.\n"
2186         "    If you're just testing, set "
2187         "'AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1'.\n\n"
2188 
2189         "    To avoid having crashes misinterpreted as timeouts, please log in "
2190         "as root\n"
2191         "    and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n"
2192 
2193         "    echo core >/proc/sys/kernel/core_pattern\n");
2194 
2195     if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) {
2196 
2197       FATAL("Pipe at the beginning of 'core_pattern'");
2198 
2199     }
2200 
2201   }
2202 
2203   close(fd);
2204 
2205 #endif                                                        /* ^__APPLE__ */
2206 
2207 }
2208 
2209 /* Check CPU governor. */
2210 
2211 void check_cpu_governor(afl_state_t *afl) {
2212 
2213 #ifdef __linux__
2214   FILE *f;
2215   u8    tmp[128];
2216   u64   min = 0, max = 0;
2217 
2218   if (afl->afl_env.afl_skip_cpufreq) { return; }
2219 
2220   if (afl->cpu_aff > 0) {
2221 
2222     snprintf(tmp, sizeof(tmp), "%s%d%s", "/sys/devices/system/cpu/cpu",
2223              afl->cpu_aff, "/cpufreq/scaling_governor");
2224 
2225   } else {
2226 
2227     snprintf(tmp, sizeof(tmp), "%s",
2228              "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
2229 
2230   }
2231 
2232   f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r");
2233   if (!f) {
2234 
2235     if (afl->cpu_aff > 0) {
2236 
2237       snprintf(tmp, sizeof(tmp), "%s%d%s",
2238                "/sys/devices/system/cpu/cpufreq/policy", afl->cpu_aff,
2239                "/scaling_governor");
2240 
2241     } else {
2242 
2243       snprintf(tmp, sizeof(tmp), "%s",
2244                "/sys/devices/system/cpu/cpufreq/policy0/scaling_governor");
2245 
2246     }
2247 
2248     f = fopen(tmp, "r");
2249 
2250   }
2251 
2252   if (!f) {
2253 
2254     WARNF("Could not check CPU scaling governor");
2255     return;
2256 
2257   }
2258 
2259   ACTF("Checking CPU scaling governor...");
2260 
2261   if (!fgets(tmp, 128, f)) { PFATAL("fgets() failed"); }
2262 
2263   fclose(f);
2264 
2265   if (!strncmp(tmp, "perf", 4)) { return; }
2266 
2267   f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r");
2268 
2269   if (f) {
2270 
2271     if (fscanf(f, "%llu", &min) != 1) { min = 0; }
2272     fclose(f);
2273 
2274   }
2275 
2276   f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r");
2277 
2278   if (f) {
2279 
2280     if (fscanf(f, "%llu", &max) != 1) { max = 0; }
2281     fclose(f);
2282 
2283   }
2284 
2285   if (min == max) { return; }
2286 
2287   SAYF("\n" cLRD "[-] " cRST
2288        "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n"
2289        "    between %llu and %llu MHz. Unfortunately, the scaling algorithm in "
2290        "the\n"
2291        "    kernel is imperfect and can miss the short-lived processes spawned "
2292        "by\n"
2293        "    afl-fuzz. To keep things moving, run these commands as root:\n\n"
2294 
2295        "    cd /sys/devices/system/cpu\n"
2296        "    echo performance | tee cpu*/cpufreq/scaling_governor\n\n"
2297 
2298        "    You can later go back to the original state by replacing "
2299        "'performance'\n"
2300        "    with 'ondemand' or 'powersave'. If you don't want to change the "
2301        "settings,\n"
2302        "    set AFL_SKIP_CPUFREQ to make afl-fuzz skip this check - but expect "
2303        "some\n"
2304        "    performance drop.\n",
2305        min / 1024, max / 1024);
2306   FATAL("Suboptimal CPU scaling governor");
2307 
2308 #elif defined __APPLE__
2309   u64 min = 0, max = 0;
2310   size_t mlen = sizeof(min);
2311   if (afl->afl_env.afl_skip_cpufreq) return;
2312 
2313   ACTF("Checking CPU scaling governor...");
2314 
2315   if (sysctlbyname("hw.cpufrequency_min", &min, &mlen, NULL, 0) == -1) {
2316 
2317     WARNF("Could not check CPU min frequency");
2318     return;
2319 
2320   }
2321 
2322   if (sysctlbyname("hw.cpufrequency_max", &max, &mlen, NULL, 0) == -1) {
2323 
2324     WARNF("Could not check CPU max frequency");
2325     return;
2326 
2327   }
2328 
2329   if (min == max) return;
2330 
2331   SAYF("\n" cLRD "[-] " cRST
2332        "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n"
2333        "    between %llu and %llu MHz.\n"
2334        "    If you don't want to check those settings, set "
2335        "AFL_SKIP_CPUFREQ\n"
2336        "    to make afl-fuzz skip this check - but expect some performance "
2337        "drop.\n",
2338        min / 1024, max / 1024);
2339   FATAL("Suboptimal CPU scaling governor");
2340 #else
2341   (void)afl;
2342 #endif
2343 
2344 }
2345 
2346 /* Count the number of logical CPU cores. */
2347 
2348 void get_core_count(afl_state_t *afl) {
2349 
2350 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
2351     defined(__DragonFly__)
2352 
2353   size_t s = sizeof(afl->cpu_core_count);
2354 
2355   /* On *BSD systems, we can just use a sysctl to get the number of CPUs. */
2356 
2357   #ifdef __APPLE__
2358 
2359   if (sysctlbyname("hw.logicalcpu", &afl->cpu_core_count, &s, NULL, 0) < 0)
2360     return;
2361 
2362   #else
2363 
2364   int s_name[2] = {CTL_HW, HW_NCPU};
2365 
2366   if (sysctl(s_name, 2, &afl->cpu_core_count, &s, NULL, 0) < 0) return;
2367 
2368   #endif                                                      /* ^__APPLE__ */
2369 
2370 #else
2371 
2372   #ifdef HAVE_AFFINITY
2373 
2374   afl->cpu_core_count = sysconf(_SC_NPROCESSORS_ONLN);
2375 
2376   #else
2377 
2378   FILE *f = fopen("/proc/stat", "r");
2379   u8    tmp[1024];
2380 
2381   if (!f) return;
2382 
2383   while (fgets(tmp, sizeof(tmp), f))
2384     if (!strncmp(tmp, "cpu", 3) && isdigit(tmp[3])) ++afl->cpu_core_count;
2385 
2386   fclose(f);
2387 
2388   #endif                                                  /* ^HAVE_AFFINITY */
2389 
2390 #endif                        /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */
2391 
2392   if (afl->cpu_core_count > 0) {
2393 
2394     u32 cur_runnable = 0;
2395 
2396     cur_runnable = (u32)get_runnable_processes();
2397 
2398 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
2399     defined(__DragonFly__)
2400 
2401     /* Add ourselves, since the 1-minute average doesn't include that yet. */
2402 
2403     ++cur_runnable;
2404 
2405 #endif                           /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
2406 
2407     OKF("You have %d CPU core%s and %u runnable tasks (utilization: %0.0f%%).",
2408         afl->cpu_core_count, afl->cpu_core_count > 1 ? "s" : "", cur_runnable,
2409         cur_runnable * 100.0 / afl->cpu_core_count);
2410 
2411     if (afl->cpu_core_count > 1) {
2412 
2413       if (cur_runnable > afl->cpu_core_count * 1.5) {
2414 
2415         WARNF("System under apparent load, performance may be spotty.");
2416 
2417       } else if ((s64)cur_runnable + 1 <= (s64)afl->cpu_core_count) {
2418 
2419         OKF("Try parallel jobs - see %s/parallel_fuzzing.md.", doc_path);
2420 
2421       }
2422 
2423     }
2424 
2425   } else {
2426 
2427     afl->cpu_core_count = 0;
2428     WARNF("Unable to figure out the number of CPU cores.");
2429 
2430   }
2431 
2432 }
2433 
2434 /* Validate and fix up afl->out_dir and sync_dir when using -S. */
2435 
2436 void fix_up_sync(afl_state_t *afl) {
2437 
2438   u8 *x = afl->sync_id;
2439 
2440   while (*x) {
2441 
2442     if (!isalnum(*x) && *x != '_' && *x != '-') {
2443 
2444       FATAL("Non-alphanumeric fuzzer ID specified via -S or -M");
2445 
2446     }
2447 
2448     ++x;
2449 
2450   }
2451 
2452   if (strlen(afl->sync_id) > 32) { FATAL("Fuzzer ID too long"); }
2453 
2454   x = alloc_printf("%s/%s", afl->out_dir, afl->sync_id);
2455 
2456 #ifdef __linux__
2457   if (afl->fsrv.nyx_mode) { afl->fsrv.out_dir_path = afl->out_dir; }
2458 #endif
2459   afl->sync_dir = afl->out_dir;
2460   afl->out_dir = x;
2461 
2462 }
2463 
2464 /* Handle screen resize (SIGWINCH). */
2465 
2466 static void handle_resize(int sig) {
2467 
2468   (void)sig;
2469   afl_states_clear_screen();
2470 
2471 }
2472 
2473 /* Check ASAN options. */
2474 
2475 void check_asan_opts(afl_state_t *afl) {
2476 
2477   u8 *x = get_afl_env("ASAN_OPTIONS");
2478 
2479   (void)(afl);
2480 
2481   if (x) {
2482 
2483     if (!strstr(x, "abort_on_error=1")) {
2484 
2485       FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
2486 
2487     }
2488 
2489 #ifndef ASAN_BUILD
2490     if (!afl->debug && !strstr(x, "symbolize=0")) {
2491 
2492       FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
2493 
2494     }
2495 
2496 #endif
2497 
2498   }
2499 
2500   x = get_afl_env("MSAN_OPTIONS");
2501 
2502   if (x) {
2503 
2504     if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) {
2505 
2506       FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY(
2507           MSAN_ERROR) " - please fix!");
2508 
2509     }
2510 
2511     if (!afl->debug && !strstr(x, "symbolize=0")) {
2512 
2513       FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
2514 
2515     }
2516 
2517   }
2518 
2519   x = get_afl_env("LSAN_OPTIONS");
2520 
2521   if (x) {
2522 
2523     if (!strstr(x, "symbolize=0")) {
2524 
2525       FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
2526 
2527     }
2528 
2529   }
2530 
2531 }
2532 
2533 /* Handle stop signal (Ctrl-C, etc). */
2534 
2535 static void handle_stop_sig(int sig) {
2536 
2537   (void)sig;
2538   afl_states_stop();
2539 
2540 }
2541 
2542 /* Handle skip request (SIGUSR1). */
2543 
2544 static void handle_skipreq(int sig) {
2545 
2546   (void)sig;
2547   afl_states_request_skip();
2548 
2549 }
2550 
2551 /* Setup shared map for fuzzing with input via sharedmem */
2552 
2553 void setup_testcase_shmem(afl_state_t *afl) {
2554 
2555   afl->shm_fuzz = ck_alloc(sizeof(sharedmem_t));
2556 
2557   // we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR
2558   u8 *map = afl_shm_init(afl->shm_fuzz, MAX_FILE + sizeof(u32), 1);
2559   afl->shm_fuzz->shmemfuzz_mode = 1;
2560 
2561   if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
2562 
2563 #ifdef USEMMAP
2564   setenv(SHM_FUZZ_ENV_VAR, afl->shm_fuzz->g_shm_file_path, 1);
2565 #else
2566   u8 *shm_str = alloc_printf("%d", afl->shm_fuzz->shm_id);
2567   setenv(SHM_FUZZ_ENV_VAR, shm_str, 1);
2568   ck_free(shm_str);
2569 #endif
2570   afl->fsrv.support_shmem_fuzz = 1;
2571   afl->fsrv.shmem_fuzz_len = (u32 *)map;
2572   afl->fsrv.shmem_fuzz = map + sizeof(u32);
2573 
2574 }
2575 
2576 /* Do a PATH search and find target binary to see that it exists and
2577    isn't a shell script - a common and painful mistake. We also check for
2578    a valid ELF header and for evidence of AFL instrumentation. */
2579 
2580 void check_binary(afl_state_t *afl, u8 *fname) {
2581 
2582   if (unlikely(!fname)) { FATAL("BUG: Binary name is NULL"); }
2583 
2584   u8 *        env_path = 0;
2585   struct stat st;
2586 
2587   s32 fd;
2588   u8 *f_data;
2589   u32 f_len = 0;
2590 
2591   ACTF("Validating target binary...");
2592 
2593   if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
2594 
2595     afl->fsrv.target_path = ck_strdup(fname);
2596 #ifdef __linux__
2597     if (afl->fsrv.nyx_mode) {
2598 
2599       /* check if target_path is a nyx sharedir */
2600       if (stat(afl->fsrv.target_path, &st) || S_ISDIR(st.st_mode)) {
2601 
2602         char *tmp = alloc_printf("%s/config.ron", afl->fsrv.target_path);
2603         if (stat(tmp, &st) || S_ISREG(st.st_mode)) {
2604 
2605           free(tmp);
2606           return;
2607 
2608         }
2609 
2610       }
2611 
2612       FATAL("Directory '%s' not found or is not a nyx share directory",
2613             afl->fsrv.target_path);
2614 
2615     }
2616 
2617 #endif
2618     if (stat(afl->fsrv.target_path, &st) || !S_ISREG(st.st_mode) ||
2619         !(st.st_mode & 0111) || (f_len = st.st_size) < 4) {
2620 
2621       FATAL("Program '%s' not found or not executable", fname);
2622 
2623     }
2624 
2625   } else {
2626 
2627     while (env_path) {
2628 
2629       u8 *cur_elem, *delim = strchr(env_path, ':');
2630 
2631       if (delim) {
2632 
2633         cur_elem = ck_alloc(delim - env_path + 1);
2634         if (unlikely(!cur_elem)) { FATAL("Unexpected large PATH"); }
2635         memcpy(cur_elem, env_path, delim - env_path);
2636         ++delim;
2637 
2638       } else {
2639 
2640         cur_elem = ck_strdup(env_path);
2641 
2642       }
2643 
2644       env_path = delim;
2645 
2646       if (cur_elem[0]) {
2647 
2648         afl->fsrv.target_path = alloc_printf("%s/%s", cur_elem, fname);
2649 
2650       } else {
2651 
2652         afl->fsrv.target_path = ck_strdup(fname);
2653 
2654       }
2655 
2656       ck_free(cur_elem);
2657 
2658       if (!stat(afl->fsrv.target_path, &st) && S_ISREG(st.st_mode) &&
2659           (st.st_mode & 0111) && (f_len = st.st_size) >= 4) {
2660 
2661         break;
2662 
2663       }
2664 
2665       ck_free(afl->fsrv.target_path);
2666       afl->fsrv.target_path = 0;
2667 
2668     }
2669 
2670     if (!afl->fsrv.target_path) {
2671 
2672       FATAL("Program '%s' not found or not executable", fname);
2673 
2674     }
2675 
2676   }
2677 
2678   if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
2679       (afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
2680       (afl->fsrv.cs_mode && getenv("AFL_CS_CUSTOM_BIN")) ||
2681       afl->non_instrumented_mode) {
2682 
2683     return;
2684 
2685   }
2686 
2687   /* Check for blatant user errors. */
2688 
2689   /*  disabled. not a real-worl scenario where this is a problem.
2690     if ((!strncmp(afl->fsrv.target_path, "/tmp/", 5) &&
2691          !strchr(afl->fsrv.target_path + 5, '/')) ||
2692         (!strncmp(afl->fsrv.target_path, "/var/tmp/", 9) &&
2693          !strchr(afl->fsrv.target_path + 9, '/'))) {
2694 
2695       FATAL("Please don't keep binaries in /tmp or /var/tmp");
2696 
2697     }
2698 
2699   */
2700 
2701   fd = open(afl->fsrv.target_path, O_RDONLY);
2702 
2703   if (fd < 0) { PFATAL("Unable to open '%s'", afl->fsrv.target_path); }
2704 
2705   f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
2706 
2707   if (f_data == MAP_FAILED) {
2708 
2709     PFATAL("Unable to mmap file '%s'", afl->fsrv.target_path);
2710 
2711   }
2712 
2713   close(fd);
2714 
2715   if (f_data[0] == '#' && f_data[1] == '!') {
2716 
2717     SAYF("\n" cLRD "[-] " cRST
2718          "Oops, the target binary looks like a shell script. Some build "
2719          "systems will\n"
2720          "    sometimes generate shell stubs for dynamically linked programs; "
2721          "try static\n"
2722          "    library mode (./configure --disable-shared) if that's the "
2723          "case.\n\n"
2724 
2725          "    Another possible cause is that you are actually trying to use a "
2726          "shell\n"
2727          "    wrapper around the fuzzed component. Invoking shell can slow "
2728          "down the\n"
2729          "    fuzzing process by a factor of 20x or more; it's best to write "
2730          "the wrapper\n"
2731          "    in a compiled language instead.\n");
2732 
2733     FATAL("Program '%s' is a shell script", afl->fsrv.target_path);
2734 
2735   }
2736 
2737 #ifndef __APPLE__
2738 
2739   if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) {
2740 
2741     FATAL("Program '%s' is not an ELF binary", afl->fsrv.target_path);
2742 
2743   }
2744 
2745 #else
2746 
2747   #if !defined(__arm__) && !defined(__arm64__)
2748   if ((f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) &&
2749       (f_data[0] != 0xCA || f_data[1] != 0xFE || f_data[2] != 0xBA))
2750     FATAL("Program '%s' is not a 64-bit or universal Mach-O binary",
2751           afl->fsrv.target_path);
2752   #endif
2753 
2754 #endif                                                       /* ^!__APPLE__ */
2755 
2756   if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode &&
2757 #ifdef __linux__
2758       !afl->fsrv.nyx_mode &&
2759 #endif
2760       !afl->fsrv.cs_mode && !afl->non_instrumented_mode &&
2761       !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
2762 
2763     SAYF("\n" cLRD "[-] " cRST
2764          "Looks like the target binary is not instrumented! The fuzzer depends "
2765          "on\n"
2766          "    compile-time instrumentation to isolate interesting test cases "
2767          "while\n"
2768          "    mutating the input data. For more information, and for tips on "
2769          "how to\n"
2770          "    instrument binaries, please see %s/README.md.\n\n"
2771 
2772          "    When source code is not available, you may be able to leverage "
2773          "QEMU\n"
2774          "    mode support. Consult the README.md for tips on how to enable "
2775          "this.\n\n"
2776 
2777          "    If your target is an instrumented binary (e.g. with zafl, "
2778          "retrowrite,\n"
2779          "    etc.) then set 'AFL_SKIP_BIN_CHECK=1'\n\n"
2780 
2781          "    (It is also possible to use afl-fuzz as a traditional, "
2782          "non-instrumented\n"
2783          "    fuzzer. For that use the -n option - but expect much worse "
2784          "results.)\n",
2785          doc_path);
2786 
2787     FATAL("No instrumentation detected");
2788 
2789   }
2790 
2791   if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
2792       memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
2793 
2794     SAYF("\n" cLRD "[-] " cRST
2795          "This program appears to be instrumented with afl-gcc, but is being "
2796          "run in\n"
2797          "    QEMU mode (-Q). This is probably not what you "
2798          "want -\n"
2799          "    this setup will be slow and offer no practical benefits.\n");
2800 
2801     FATAL("Instrumentation found in -Q mode");
2802 
2803   }
2804 
2805   if (memmem(f_data, f_len, "__asan_init", 11) ||
2806       memmem(f_data, f_len, "__msan_init", 11) ||
2807       memmem(f_data, f_len, "__lsan_init", 11)) {
2808 
2809     afl->fsrv.uses_asan = 1;
2810 
2811   }
2812 
2813   /* Detect persistent & deferred init signatures in the binary. */
2814 
2815   if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
2816 
2817     OKF(cPIN "Persistent mode binary detected.");
2818     setenv(PERSIST_ENV_VAR, "1", 1);
2819     afl->persistent_mode = 1;
2820     afl->fsrv.persistent_mode = 1;
2821     afl->shmem_testcase_mode = 1;
2822 
2823   } else if (getenv("AFL_PERSISTENT")) {
2824 
2825     OKF(cPIN "Persistent mode enforced.");
2826     setenv(PERSIST_ENV_VAR, "1", 1);
2827     afl->persistent_mode = 1;
2828     afl->fsrv.persistent_mode = 1;
2829     afl->shmem_testcase_mode = 1;
2830 
2831   } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
2832 
2833     OKF("FRIDA Persistent mode configuration options detected.");
2834     setenv(PERSIST_ENV_VAR, "1", 1);
2835     afl->persistent_mode = 1;
2836     afl->fsrv.persistent_mode = 1;
2837     afl->shmem_testcase_mode = 1;
2838 
2839   }
2840 
2841   if (afl->fsrv.frida_mode ||
2842       memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
2843 
2844     OKF(cPIN "Deferred forkserver binary detected.");
2845     setenv(DEFER_ENV_VAR, "1", 1);
2846     afl->deferred_mode = 1;
2847 
2848   } else if (getenv("AFL_DEFER_FORKSRV")) {
2849 
2850     OKF(cPIN "Deferred forkserver enforced.");
2851     setenv(DEFER_ENV_VAR, "1", 1);
2852     afl->deferred_mode = 1;
2853 
2854   }
2855 
2856   if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
2857 
2858 }
2859 
2860 /* Check if we're on TTY. */
2861 
2862 void check_if_tty(afl_state_t *afl) {
2863 
2864   struct winsize ws;
2865 
2866   if (afl->afl_env.afl_no_ui) {
2867 
2868     OKF("Disabling the UI because AFL_NO_UI is set.");
2869     afl->not_on_tty = 1;
2870     return;
2871 
2872   }
2873 
2874   if (ioctl(1, TIOCGWINSZ, &ws)) {
2875 
2876     if (errno == ENOTTY) {
2877 
2878       OKF("Looks like we're not running on a tty, so I'll be a bit less "
2879           "verbose.");
2880       afl->not_on_tty = 1;
2881 
2882     }
2883 
2884     return;
2885 
2886   }
2887 
2888 }
2889 
2890 /* Set up signal handlers. More complicated that needs to be, because libc on
2891    Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call
2892    siginterrupt(), and does other stupid things. */
2893 
2894 void setup_signal_handlers(void) {
2895 
2896   struct sigaction sa;
2897 
2898   sa.sa_handler = NULL;
2899   sa.sa_flags = SA_RESTART;
2900   sa.sa_sigaction = NULL;
2901 
2902   sigemptyset(&sa.sa_mask);
2903 
2904   /* Various ways of saying "stop". */
2905 
2906   sa.sa_handler = handle_stop_sig;
2907   sigaction(SIGHUP, &sa, NULL);
2908   sigaction(SIGINT, &sa, NULL);
2909   sigaction(SIGTERM, &sa, NULL);
2910 
2911   /* Window resize */
2912 
2913   sa.sa_handler = handle_resize;
2914   sigaction(SIGWINCH, &sa, NULL);
2915 
2916   /* SIGUSR1: skip entry */
2917 
2918   sa.sa_handler = handle_skipreq;
2919   sigaction(SIGUSR1, &sa, NULL);
2920 
2921   /* Things we don't care about. */
2922 
2923   sa.sa_handler = SIG_IGN;
2924   sigaction(SIGTSTP, &sa, NULL);
2925   sigaction(SIGPIPE, &sa, NULL);
2926 
2927 }
2928 
2929 /* Make a copy of the current command line. */
2930 
2931 void save_cmdline(afl_state_t *afl, u32 argc, char **argv) {
2932 
2933   u32 len = 1, i;
2934   u8 *buf;
2935 
2936   for (i = 0; i < argc; ++i) {
2937 
2938     len += strlen(argv[i]) + 1;
2939 
2940   }
2941 
2942   buf = afl->orig_cmdline = ck_alloc(len);
2943 
2944   for (i = 0; i < argc; ++i) {
2945 
2946     u32 l = strlen(argv[i]);
2947 
2948     if (!argv[i] || !buf) { FATAL("null deref detected"); }
2949 
2950     memcpy(buf, argv[i], l);
2951     buf += l;
2952 
2953     if (i != argc - 1) { *(buf++) = ' '; }
2954 
2955   }
2956 
2957   *buf = 0;
2958 
2959 }
2960 
2961