1 /*
2 american fuzzy lop++ - common 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 Gather some functions common to multiple executables
21
22 - detect_file_args
23
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #define _GNU_SOURCE
29 #define __USE_GNU
30 #include <string.h>
31 #include <strings.h>
32 #include <math.h>
33 #include <sys/mman.h>
34
35 #include "debug.h"
36 #include "alloc-inl.h"
37 #include "envs.h"
38 #include "common.h"
39
40 /* Detect @@ in args. */
41 #include <unistd.h>
42 #include <limits.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46
47 u8 be_quiet = 0;
48 u8 *doc_path = "";
49 u8 last_intr = 0;
50
51 #ifndef AFL_PATH
52 #define AFL_PATH "/usr/local/lib/afl/"
53 #endif
54
check_binary_signatures(u8 * fn)55 u32 check_binary_signatures(u8 *fn) {
56
57 int ret = 0, fd = open(fn, O_RDONLY);
58 if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
59 struct stat st;
60 if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
61 u32 f_len = st.st_size;
62 u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
63 if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
64 close(fd);
65
66 if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
67
68 if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); }
69 setenv(PERSIST_ENV_VAR, "1", 1);
70 ret = 1;
71
72 } else if (getenv("AFL_PERSISTENT")) {
73
74 if (!be_quiet) { OKF(cPIN "Persistent mode enforced."); }
75 setenv(PERSIST_ENV_VAR, "1", 1);
76 ret = 1;
77
78 } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
79
80 if (!be_quiet) {
81
82 OKF("FRIDA Persistent mode configuration options detected.");
83
84 }
85
86 setenv(PERSIST_ENV_VAR, "1", 1);
87 ret = 1;
88
89 }
90
91 if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
92
93 if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); }
94 setenv(DEFER_ENV_VAR, "1", 1);
95 ret += 2;
96
97 } else if (getenv("AFL_DEFER_FORKSRV")) {
98
99 if (!be_quiet) { OKF(cPIN "Deferred forkserver enforced."); }
100 setenv(DEFER_ENV_VAR, "1", 1);
101 ret += 2;
102
103 }
104
105 if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
106
107 return ret;
108
109 }
110
detect_file_args(char ** argv,u8 * prog_in,bool * use_stdin)111 void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
112
113 u32 i = 0;
114 u8 cwd[PATH_MAX];
115 if (getcwd(cwd, (size_t)sizeof(cwd)) == NULL) { PFATAL("getcwd() failed"); }
116
117 /* we are working with libc-heap-allocated argvs. So do not mix them with
118 * other allocation APIs like ck_alloc. That would disturb the free() calls.
119 */
120 while (argv[i]) {
121
122 u8 *aa_loc = strstr(argv[i], "@@");
123
124 if (aa_loc) {
125
126 if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
127
128 *use_stdin = false;
129
130 /* Be sure that we're always using fully-qualified paths. */
131
132 *aa_loc = 0;
133
134 /* Construct a replacement argv value. */
135 u8 *n_arg;
136
137 if (prog_in[0] == '/') {
138
139 n_arg = alloc_printf("%s%s%s", argv[i], prog_in, aa_loc + 2);
140
141 } else {
142
143 n_arg = alloc_printf("%s%s/%s%s", argv[i], cwd, prog_in, aa_loc + 2);
144
145 }
146
147 ck_free(argv[i]);
148 argv[i] = n_arg;
149
150 }
151
152 i++;
153
154 }
155
156 /* argvs are automatically freed at exit. */
157
158 }
159
160 /* duplicate the system argv so that
161 we can edit (and free!) it later */
162
argv_cpy_dup(int argc,char ** argv)163 char **argv_cpy_dup(int argc, char **argv) {
164
165 int i = 0;
166
167 char **ret = ck_alloc((argc + 1) * sizeof(char *));
168 if (unlikely(!ret)) { FATAL("Amount of arguments specified is too high"); }
169
170 for (i = 0; i < argc; i++) {
171
172 ret[i] = ck_strdup(argv[i]);
173
174 }
175
176 ret[i] = NULL;
177
178 return ret;
179
180 }
181
182 /* frees all args in the given argv,
183 previously created by argv_cpy_dup */
184
argv_cpy_free(char ** argv)185 void argv_cpy_free(char **argv) {
186
187 u32 i = 0;
188 while (argv[i]) {
189
190 ck_free(argv[i]);
191 argv[i] = NULL;
192 i++;
193
194 }
195
196 ck_free(argv);
197
198 }
199
200 /* Rewrite argv for CoreSight process tracer. */
201
get_cs_argv(u8 * own_loc,u8 ** target_path_p,int argc,char ** argv)202 char **get_cs_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
203
204 if (unlikely(getenv("AFL_CS_CUSTOM_BIN"))) {
205
206 WARNF(
207 "AFL_CS_CUSTOM_BIN is enabled. "
208 "You must run your target under afl-cs-proxy on your own!");
209 return argv;
210
211 }
212
213 char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
214 if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
215
216 memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
217 new_argv[argc + 3] = NULL;
218
219 new_argv[2] = *target_path_p;
220 new_argv[1] = "--";
221
222 /* Now we need to actually find the cs-proxy binary to put in argv[0]. */
223
224 *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-cs-proxy");
225 return new_argv;
226
227 }
228
229 /* Rewrite argv for QEMU. */
230
get_qemu_argv(u8 * own_loc,u8 ** target_path_p,int argc,char ** argv)231 char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
232
233 if (unlikely(getenv("AFL_QEMU_CUSTOM_BIN"))) {
234
235 WARNF(
236 "AFL_QEMU_CUSTOM_BIN is enabled. "
237 "You must run your target under afl-qemu-trace on your own!");
238 return argv;
239
240 }
241
242 char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
243 if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
244
245 memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
246
247 new_argv[2] = *target_path_p;
248 new_argv[1] = "--";
249
250 /* Now we need to actually find the QEMU binary to put in argv[0]. */
251
252 *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-qemu-trace");
253 return new_argv;
254
255 }
256
257 /* Rewrite argv for Wine+QEMU. */
258
get_wine_argv(u8 * own_loc,u8 ** target_path_p,int argc,char ** argv)259 char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
260
261 char **new_argv = ck_alloc(sizeof(char *) * (argc + 2));
262 if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
263
264 memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
265
266 new_argv[1] = *target_path_p;
267
268 /* Now we need to actually find the QEMU binary to put in argv[0]. */
269
270 u8 *tmp = find_afl_binary(own_loc, "afl-qemu-trace");
271 ck_free(tmp);
272 *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-wine-trace");
273 return new_argv;
274
275 }
276
277 /* Find binary, used by analyze, showmap, tmin
278 @returns the path, allocating the string */
279
find_binary(u8 * fname)280 u8 *find_binary(u8 *fname) {
281
282 // TODO: Merge this function with check_binary of afl-fuzz-init.c
283
284 u8 *env_path = NULL;
285 u8 *target_path = NULL;
286
287 struct stat st;
288
289 if (unlikely(!fname)) { FATAL("No binary supplied"); }
290
291 if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
292
293 target_path = ck_strdup(fname);
294
295 if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
296 !(st.st_mode & 0111) || st.st_size < 4) {
297
298 ck_free(target_path);
299 FATAL("Program '%s' not found or not executable", fname);
300
301 }
302
303 } else {
304
305 while (env_path) {
306
307 u8 *cur_elem, *delim = strchr(env_path, ':');
308
309 if (delim) {
310
311 cur_elem = ck_alloc(delim - env_path + 1);
312 if (unlikely(!cur_elem)) {
313
314 FATAL(
315 "Unexpected overflow when processing ENV. This should never "
316 "happend.");
317
318 }
319
320 memcpy(cur_elem, env_path, delim - env_path);
321 delim++;
322
323 } else {
324
325 cur_elem = ck_strdup(env_path);
326
327 }
328
329 env_path = delim;
330
331 if (cur_elem[0]) {
332
333 target_path = alloc_printf("%s/%s", cur_elem, fname);
334
335 } else {
336
337 target_path = ck_strdup(fname);
338
339 }
340
341 ck_free(cur_elem);
342
343 if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
344 (st.st_mode & 0111) && st.st_size >= 4) {
345
346 break;
347
348 }
349
350 ck_free(target_path);
351 target_path = NULL;
352
353 }
354
355 if (!target_path) {
356
357 FATAL("Program '%s' not found or not executable", fname);
358
359 }
360
361 }
362
363 return target_path;
364
365 }
366
find_afl_binary(u8 * own_loc,u8 * fname)367 u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
368
369 u8 *afl_path = NULL, *target_path, *own_copy, *tmp;
370 int perm = X_OK;
371
372 if ((tmp = strrchr(fname, '.'))) {
373
374 if (!strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; }
375
376 }
377
378 if ((afl_path = getenv("AFL_PATH"))) {
379
380 target_path = alloc_printf("%s/%s", afl_path, fname);
381 if (!access(target_path, perm)) {
382
383 return target_path;
384
385 } else {
386
387 ck_free(target_path);
388
389 }
390
391 }
392
393 if (own_loc) {
394
395 own_copy = ck_strdup(own_loc);
396 u8 *rsl = strrchr(own_copy, '/');
397
398 if (rsl) {
399
400 *rsl = 0;
401
402 target_path = alloc_printf("%s/%s", own_copy, fname);
403 ck_free(own_copy);
404
405 if (!access(target_path, perm)) {
406
407 return target_path;
408
409 } else {
410
411 ck_free(target_path);
412
413 }
414
415 } else {
416
417 ck_free(own_copy);
418
419 }
420
421 }
422
423 if (perm == X_OK) {
424
425 target_path = alloc_printf("%s/%s", BIN_PATH, fname);
426
427 } else {
428
429 target_path = alloc_printf("%s/%s", AFL_PATH, fname);
430
431 }
432
433 if (!access(target_path, perm)) {
434
435 return target_path;
436
437 } else {
438
439 ck_free(target_path);
440
441 }
442
443 if (perm == X_OK) {
444
445 return find_binary(fname);
446
447 } else {
448
449 FATAL("Library '%s' not found", fname);
450
451 }
452
453 }
454
455 /* Parses the kill signal environment variable, FATALs on error.
456 If the env is not set, sets the env to default_signal for the signal handlers
457 and returns the default_signal. */
parse_afl_kill_signal_env(u8 * afl_kill_signal_env,int default_signal)458 int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) {
459
460 if (afl_kill_signal_env && afl_kill_signal_env[0]) {
461
462 char *endptr;
463 u8 signal_code;
464 signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10);
465 /* Did we manage to parse the full string? */
466 if (*endptr != '\0' || endptr == (char *)afl_kill_signal_env) {
467
468 FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
469 afl_kill_signal_env);
470
471 }
472
473 return signal_code;
474
475 } else {
476
477 char *sigstr = alloc_printf("%d", default_signal);
478 if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
479
480 /* Set the env for signal handler */
481 setenv("AFL_KILL_SIGNAL", sigstr, 1);
482 free(sigstr);
483 return default_signal;
484
485 }
486
487 }
488
helper_min3(unsigned int a,unsigned int b,unsigned int c)489 static inline unsigned int helper_min3(unsigned int a, unsigned int b,
490 unsigned int c) {
491
492 return a < b ? (a < c ? a : c) : (b < c ? b : c);
493
494 }
495
496 // from
497 // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C
string_distance_levenshtein(char * s1,char * s2)498 static int string_distance_levenshtein(char *s1, char *s2) {
499
500 unsigned int s1len, s2len, x, y, lastdiag, olddiag;
501 s1len = strlen(s1);
502 s2len = strlen(s2);
503 unsigned int column[s1len + 1];
504 column[s1len] = 1;
505
506 for (y = 1; y <= s1len; y++)
507 column[y] = y;
508 for (x = 1; x <= s2len; x++) {
509
510 column[0] = x;
511 for (y = 1, lastdiag = x - 1; y <= s1len; y++) {
512
513 olddiag = column[y];
514 column[y] = helper_min3(column[y] + 1, column[y - 1] + 1,
515 lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1));
516 lastdiag = olddiag;
517
518 }
519
520 }
521
522 return column[s1len];
523
524 }
525
526 #define ENV_SIMILARITY_TRESHOLD 3
527
print_suggested_envs(char * mispelled_env)528 void print_suggested_envs(char *mispelled_env) {
529
530 size_t env_name_len =
531 strcspn(mispelled_env, "=") - 4; // remove the AFL_prefix
532 char *env_name = ck_alloc(env_name_len + 1);
533 memcpy(env_name, mispelled_env + 4, env_name_len);
534
535 char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *));
536 int found = 0;
537
538 int j;
539 for (j = 0; afl_environment_variables[j] != NULL; ++j) {
540
541 char *afl_env = afl_environment_variables[j] + 4;
542 int distance = string_distance_levenshtein(afl_env, env_name);
543 if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
544
545 SAYF("Did you mean %s?\n", afl_environment_variables[j]);
546 seen[j] = 1;
547 found = 1;
548
549 }
550
551 }
552
553 if (found) goto cleanup;
554
555 for (j = 0; afl_environment_variables[j] != NULL; ++j) {
556
557 char * afl_env = afl_environment_variables[j] + 4;
558 size_t afl_env_len = strlen(afl_env);
559 char * reduced = ck_alloc(afl_env_len + 1);
560
561 size_t start = 0;
562 while (start < afl_env_len) {
563
564 size_t end = start + strcspn(afl_env + start, "_") + 1;
565 memcpy(reduced, afl_env, start);
566 if (end < afl_env_len) {
567
568 memcpy(reduced + start, afl_env + end, afl_env_len - end);
569
570 }
571
572 if (afl_env_len + start >= end) {
573
574 reduced[afl_env_len - end + start] = 0;
575
576 }
577
578 int distance = string_distance_levenshtein(reduced, env_name);
579 if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
580
581 SAYF("Did you mean %s?\n", afl_environment_variables[j]);
582 seen[j] = 1;
583 found = 1;
584
585 }
586
587 start = end;
588
589 };
590
591 ck_free(reduced);
592
593 }
594
595 if (found) goto cleanup;
596
597 char * reduced = ck_alloc(env_name_len + 1);
598 size_t start = 0;
599 while (start < env_name_len) {
600
601 size_t end = start + strcspn(env_name + start, "_") + 1;
602 memcpy(reduced, env_name, start);
603 if (end < env_name_len)
604 memcpy(reduced + start, env_name + end, env_name_len - end);
605 reduced[env_name_len - end + start] = 0;
606
607 for (j = 0; afl_environment_variables[j] != NULL; ++j) {
608
609 int distance = string_distance_levenshtein(
610 afl_environment_variables[j] + 4, reduced);
611 if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
612
613 SAYF("Did you mean %s?\n", afl_environment_variables[j]);
614 seen[j] = 1;
615
616 }
617
618 }
619
620 start = end;
621
622 };
623
624 ck_free(reduced);
625
626 cleanup:
627 ck_free(env_name);
628 ck_free(seen);
629
630 }
631
check_environment_vars(char ** envp)632 void check_environment_vars(char **envp) {
633
634 if (be_quiet) { return; }
635
636 int index = 0, issue_detected = 0;
637 char *env, *val, *ignore = getenv("AFL_IGNORE_UNKNOWN_ENVS");
638 while ((env = envp[index++]) != NULL) {
639
640 if (strncmp(env, "ALF_", 4) == 0 || strncmp(env, "_ALF", 4) == 0 ||
641 strncmp(env, "__ALF", 5) == 0 || strncmp(env, "_AFL", 4) == 0 ||
642 strncmp(env, "__AFL", 5) == 0) {
643
644 WARNF("Potentially mistyped AFL environment variable: %s", env);
645 issue_detected = 1;
646
647 } else if (strncmp(env, "AFL_", 4) == 0) {
648
649 int i = 0, match = 0;
650 while (match == 0 && afl_environment_variables[i] != NULL) {
651
652 if (strncmp(env, afl_environment_variables[i],
653 strlen(afl_environment_variables[i])) == 0 &&
654 env[strlen(afl_environment_variables[i])] == '=') {
655
656 match = 1;
657
658 if ((val = getenv(afl_environment_variables[i])) && !*val) {
659
660 WARNF(
661 "AFL environment variable %s defined but is empty, this can "
662 "lead to unexpected consequences",
663 afl_environment_variables[i]);
664 issue_detected = 1;
665
666 }
667
668 } else {
669
670 i++;
671
672 }
673
674 }
675
676 i = 0;
677 while (match == 0 && afl_environment_deprecated[i] != NULL) {
678
679 if (strncmp(env, afl_environment_deprecated[i],
680 strlen(afl_environment_deprecated[i])) == 0 &&
681 env[strlen(afl_environment_deprecated[i])] == '=') {
682
683 match = 1;
684
685 WARNF("AFL environment variable %s is deprecated!",
686 afl_environment_deprecated[i]);
687 issue_detected = 1;
688
689 } else {
690
691 i++;
692
693 }
694
695 }
696
697 if (match == 0 && !ignore) {
698
699 WARNF("Mistyped AFL environment variable: %s", env);
700 issue_detected = 1;
701
702 print_suggested_envs(env);
703
704 }
705
706 }
707
708 }
709
710 if (issue_detected) { sleep(2); }
711
712 }
713
get_afl_env(char * env)714 char *get_afl_env(char *env) {
715
716 char *val;
717
718 if ((val = getenv(env)) != NULL) {
719
720 if (!be_quiet) {
721
722 OKF("Loaded environment variable %s with value %s", env, val);
723
724 }
725
726 }
727
728 return val;
729
730 }
731
extract_and_set_env(u8 * env_str)732 bool extract_and_set_env(u8 *env_str) {
733
734 if (!env_str) { return false; }
735
736 bool ret = false; // return false by default
737
738 u8 *p = ck_strdup(env_str);
739 u8 *end = p + strlen((char *)p);
740 u8 *rest = p;
741
742 u8 closing_sym = ' ';
743 u8 c;
744
745 size_t num_pairs = 0;
746
747 while (rest < end) {
748
749 while (*rest == ' ') {
750
751 rest++;
752
753 }
754
755 if (rest + 1 >= end) break;
756
757 u8 *key = rest;
758 // env variable names may not start with numbers or '='
759 if (*key == '=' || (*key >= '0' && *key <= '9')) { goto free_and_return; }
760
761 while (rest < end && *rest != '=' && *rest != ' ') {
762
763 c = *rest;
764 // lowercase is bad but we may still allow it
765 if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
766 (c < '0' || c > '9') && c != '_') {
767
768 goto free_and_return;
769
770 }
771
772 rest++;
773
774 }
775
776 if (*rest != '=') { goto free_and_return; }
777
778 *rest = '\0'; // done with variable name
779
780 rest += 1;
781 if (rest >= end || *rest == ' ') { goto free_and_return; }
782
783 u8 *val = rest;
784 if (*val == '\'' || *val == '"') {
785
786 closing_sym = *val;
787 val += 1;
788 rest += 1;
789 if (rest >= end) { goto free_and_return; }
790
791 } else {
792
793 closing_sym = ' ';
794
795 }
796
797 while (rest < end && *rest != closing_sym) {
798
799 rest++;
800
801 }
802
803 if (closing_sym != ' ' && *rest != closing_sym) { goto free_and_return; }
804
805 *rest = '\0'; // done with variable value
806
807 rest += 1;
808 num_pairs++;
809 setenv(key, val, 1);
810
811 }
812
813 if (num_pairs) { ret = true; }
814
815 free_and_return:
816 ck_free(p);
817 return ret;
818
819 }
820
821 /* Read mask bitmap from file. This is for the -B option. */
822
read_bitmap(u8 * fname,u8 * map,size_t len)823 void read_bitmap(u8 *fname, u8 *map, size_t len) {
824
825 s32 fd = open(fname, O_RDONLY);
826
827 if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
828
829 ck_read(fd, map, len, fname);
830
831 close(fd);
832
833 }
834
835 /* Get unix time in milliseconds */
836
get_cur_time(void)837 u64 get_cur_time(void) {
838
839 struct timeval tv;
840 struct timezone tz;
841
842 gettimeofday(&tv, &tz);
843
844 return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
845
846 }
847
848 /* Get unix time in microseconds */
849
get_cur_time_us(void)850 u64 get_cur_time_us(void) {
851
852 struct timeval tv;
853 struct timezone tz;
854
855 gettimeofday(&tv, &tz);
856
857 return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
858
859 }
860
861 /* Describe integer. The buf should be
862 at least 6 bytes to fit all ints we randomly see.
863 Will return buf for convenience. */
864
stringify_int(u8 * buf,size_t len,u64 val)865 u8 *stringify_int(u8 *buf, size_t len, u64 val) {
866 \
867 #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
868 do { \
869 \
870 if (val < (_divisor) * (_limit_mult)) { \
871 \
872 snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
873 return buf; \
874 \
875 } \
876 \
877 } while (0)
878
879 /* 0-9999 */
880 CHK_FORMAT(1, 10000, "%llu", u64);
881
882 /* 10.0k - 99.9k */
883 CHK_FORMAT(1000, 99.95, "%0.01fk", double);
884
885 /* 100k - 999k */
886 CHK_FORMAT(1000, 1000, "%lluk", u64);
887
888 /* 1.00M - 9.99M */
889 CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
890
891 /* 10.0M - 99.9M */
892 CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
893
894 /* 100M - 999M */
895 CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
896
897 /* 1.00G - 9.99G */
898 CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
899
900 /* 10.0G - 99.9G */
901 CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
902
903 /* 100G - 999G */
904 CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
905
906 /* 1.00T - 9.99G */
907 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
908
909 /* 10.0T - 99.9T */
910 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
911
912 /* 100T+ */
913 strncpy(buf, "infty", len);
914 buf[len - 1] = '\0';
915
916 return buf;
917
918 }
919
920 /* Describe float. Similar as int. */
921
stringify_float(u8 * buf,size_t len,double val)922 u8 *stringify_float(u8 *buf, size_t len, double val) {
923
924 if (val < 99.995) {
925
926 snprintf(buf, len, "%0.02f", val);
927
928 } else if (val < 999.95) {
929
930 snprintf(buf, len, "%0.01f", val);
931
932 } else if (unlikely(isnan(val) || isinf(val))) {
933
934 strcpy(buf, "inf");
935
936 } else {
937
938 stringify_int(buf, len, (u64)val);
939
940 }
941
942 return buf;
943
944 }
945
946 /* Describe integer as memory size. */
947
stringify_mem_size(u8 * buf,size_t len,u64 val)948 u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
949
950 /* 0-9999 */
951 CHK_FORMAT(1, 10000, "%llu B", u64);
952
953 /* 10.0k - 99.9k */
954 CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
955
956 /* 100k - 999k */
957 CHK_FORMAT(1024, 1000, "%llu kB", u64);
958
959 /* 1.00M - 9.99M */
960 CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
961
962 /* 10.0M - 99.9M */
963 CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
964
965 /* 100M - 999M */
966 CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
967
968 /* 1.00G - 9.99G */
969 CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
970
971 /* 10.0G - 99.9G */
972 CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
973
974 /* 100G - 999G */
975 CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
976
977 /* 1.00T - 9.99G */
978 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
979
980 /* 10.0T - 99.9T */
981 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
982
983 #undef CHK_FORMAT
984
985 /* 100T+ */
986 strncpy(buf, "infty", len - 1);
987 buf[len - 1] = '\0';
988
989 return buf;
990
991 }
992
993 /* Describe time delta as string.
994 Returns a pointer to buf for convenience. */
995
stringify_time_diff(u8 * buf,size_t len,u64 cur_ms,u64 event_ms)996 u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
997
998 if (!event_ms) {
999
1000 snprintf(buf, len, "none seen yet");
1001
1002 } else {
1003
1004 u64 delta;
1005 s32 t_d, t_h, t_m, t_s;
1006 u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
1007
1008 delta = cur_ms - event_ms;
1009
1010 t_d = delta / 1000 / 60 / 60 / 24;
1011 t_h = (delta / 1000 / 60 / 60) % 24;
1012 t_m = (delta / 1000 / 60) % 60;
1013 t_s = (delta / 1000) % 60;
1014
1015 stringify_int(val_buf, sizeof(val_buf), t_d);
1016 snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
1017 t_s);
1018
1019 }
1020
1021 return buf;
1022
1023 }
1024
1025 /* Unsafe Describe integer. The buf sizes are not checked.
1026 This is unsafe but fast.
1027 Will return buf for convenience. */
1028
u_stringify_int(u8 * buf,u64 val)1029 u8 *u_stringify_int(u8 *buf, u64 val) {
1030 \
1031 #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
1032 do { \
1033 \
1034 if (val < (_divisor) * (_limit_mult)) { \
1035 \
1036 sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \
1037 return buf; \
1038 \
1039 } \
1040 \
1041 } while (0)
1042
1043 /* 0-9999 */
1044 CHK_FORMAT(1, 10000, "%llu", u64);
1045
1046 /* 10.0k - 99.9k */
1047 CHK_FORMAT(1000, 99.95, "%0.01fk", double);
1048
1049 /* 100k - 999k */
1050 CHK_FORMAT(1000, 1000, "%lluk", u64);
1051
1052 /* 1.00M - 9.99M */
1053 CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
1054
1055 /* 10.0M - 99.9M */
1056 CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
1057
1058 /* 100M - 999M */
1059 CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
1060
1061 /* 1.00G - 9.99G */
1062 CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
1063
1064 /* 10.0G - 99.9G */
1065 CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
1066
1067 /* 100G - 999G */
1068 CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
1069
1070 /* 1.00T - 9.99G */
1071 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
1072
1073 /* 10.0T - 99.9T */
1074 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
1075
1076 /* 100T+ */
1077 strcpy(buf, "infty");
1078
1079 return buf;
1080
1081 }
1082
1083 /* Unsafe describe float. Similar as unsafe int. */
1084
u_stringify_float(u8 * buf,double val)1085 u8 *u_stringify_float(u8 *buf, double val) {
1086
1087 if (val < 99.995) {
1088
1089 sprintf(buf, "%0.02f", val);
1090
1091 } else if (val < 999.95) {
1092
1093 sprintf(buf, "%0.01f", val);
1094
1095 } else if (unlikely(isnan(val) || isinf(val))) {
1096
1097 strcpy(buf, "infinite");
1098
1099 } else {
1100
1101 return u_stringify_int(buf, (u64)val);
1102
1103 }
1104
1105 return buf;
1106
1107 }
1108
1109 /* Unsafe describe integer as memory size. */
1110
u_stringify_mem_size(u8 * buf,u64 val)1111 u8 *u_stringify_mem_size(u8 *buf, u64 val) {
1112
1113 /* 0-9999 */
1114 CHK_FORMAT(1, 10000, "%llu B", u64);
1115
1116 /* 10.0k - 99.9k */
1117 CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
1118
1119 /* 100k - 999k */
1120 CHK_FORMAT(1024, 1000, "%llu kB", u64);
1121
1122 /* 1.00M - 9.99M */
1123 CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
1124
1125 /* 10.0M - 99.9M */
1126 CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
1127
1128 /* 100M - 999M */
1129 CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
1130
1131 /* 1.00G - 9.99G */
1132 CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
1133
1134 /* 10.0G - 99.9G */
1135 CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
1136
1137 /* 100G - 999G */
1138 CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
1139
1140 /* 1.00T - 9.99G */
1141 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
1142
1143 /* 10.0T - 99.9T */
1144 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
1145
1146 #undef CHK_FORMAT
1147
1148 /* 100T+ */
1149 strcpy(buf, "infty");
1150
1151 return buf;
1152
1153 }
1154
1155 /* Unsafe describe time delta as string.
1156 Returns a pointer to buf for convenience. */
1157
u_stringify_time_diff(u8 * buf,u64 cur_ms,u64 event_ms)1158 u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
1159
1160 if (!event_ms) {
1161
1162 sprintf(buf, "none seen yet");
1163
1164 } else {
1165
1166 u64 delta;
1167 s32 t_d, t_h, t_m, t_s;
1168 u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
1169
1170 delta = cur_ms - event_ms;
1171
1172 t_d = delta / 1000 / 60 / 60 / 24;
1173 t_h = (delta / 1000 / 60 / 60) % 24;
1174 t_m = (delta / 1000 / 60) % 60;
1175 t_s = (delta / 1000) % 60;
1176
1177 u_stringify_int(val_buf, t_d);
1178 sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
1179
1180 }
1181
1182 return buf;
1183
1184 }
1185
1186 /* Reads the map size from ENV */
get_map_size(void)1187 u32 get_map_size(void) {
1188
1189 uint32_t map_size = DEFAULT_SHMEM_SIZE;
1190 char * ptr;
1191
1192 if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
1193
1194 map_size = atoi(ptr);
1195 if (!map_size || map_size > (1 << 29)) {
1196
1197 FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 64U,
1198 1U << 29);
1199
1200 }
1201
1202 if (map_size % 64) { map_size = (((map_size >> 6) + 1) << 6); }
1203
1204 } else if (getenv("AFL_SKIP_BIN_CHECK")) {
1205
1206 map_size = MAP_SIZE;
1207
1208 }
1209
1210 return map_size;
1211
1212 }
1213
1214 /* Create a stream file */
1215
create_ffile(u8 * fn)1216 FILE *create_ffile(u8 *fn) {
1217
1218 s32 fd;
1219 FILE *f;
1220
1221 fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
1222
1223 if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
1224
1225 f = fdopen(fd, "w");
1226
1227 if (!f) { PFATAL("fdopen() failed"); }
1228
1229 return f;
1230
1231 }
1232
1233 /* Create a file */
1234
create_file(u8 * fn)1235 s32 create_file(u8 *fn) {
1236
1237 s32 fd;
1238
1239 fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
1240
1241 if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
1242
1243 return fd;
1244
1245 }
1246
1247