1 /*
2 american fuzzy lop++ - stats 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 "envs.h"
28 #include <limits.h>
29
30 /* Write fuzzer setup file */
31
write_setup_file(afl_state_t * afl,u32 argc,char ** argv)32 void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
33
34 u8 fn[PATH_MAX];
35 snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir);
36 FILE *f = create_ffile(fn);
37 u32 i;
38
39 fprintf(f, "# environment variables:\n");
40 u32 s_afl_env = (u32)sizeof(afl_environment_variables) /
41 sizeof(afl_environment_variables[0]) -
42 1U;
43
44 for (i = 0; i < s_afl_env; ++i) {
45
46 char *val;
47 if ((val = getenv(afl_environment_variables[i])) != NULL) {
48
49 fprintf(f, "%s=%s\n", afl_environment_variables[i], val);
50
51 }
52
53 }
54
55 fprintf(f, "# command line:\n");
56
57 size_t j;
58 for (i = 0; i < argc; ++i) {
59
60 if (i) fprintf(f, " ");
61 #ifdef __ANDROID__
62 if (memchr(argv[i], '\'', sizeof(argv[i]))) {
63
64 #else
65 if (index(argv[i], '\'')) {
66
67 #endif
68
69 fprintf(f, "'");
70 for (j = 0; j < strlen(argv[i]); j++)
71 if (argv[i][j] == '\'')
72 fprintf(f, "'\"'\"'");
73 else
74 fprintf(f, "%c", argv[i][j]);
75 fprintf(f, "'");
76
77 } else {
78
79 fprintf(f, "'%s'", argv[i]);
80
81 }
82
83 }
84
85 fprintf(f, "\n");
86
87 fclose(f);
88 (void)(afl_environment_deprecated);
89
90 }
91
92 /* load some of the existing stats file when resuming.*/
93 void load_stats_file(afl_state_t *afl) {
94
95 FILE *f;
96 u8 buf[MAX_LINE];
97 u8 * lptr;
98 u8 fn[PATH_MAX];
99 u32 lineno = 0;
100 snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
101 f = fopen(fn, "r");
102 if (!f) {
103
104 WARNF("Unable to load stats file '%s'", fn);
105 return;
106
107 }
108
109 while ((lptr = fgets(buf, MAX_LINE, f))) {
110
111 lineno++;
112 u8 *lstartptr = lptr;
113 u8 *rptr = lptr + strlen(lptr) - 1;
114 u8 keystring[MAX_LINE];
115 while (*lptr != ':' && lptr < rptr) {
116
117 lptr++;
118
119 }
120
121 if (*lptr == '\n' || !*lptr) {
122
123 WARNF("Unable to read line %d of stats file", lineno);
124 continue;
125
126 }
127
128 if (*lptr == ':') {
129
130 *lptr = 0;
131 strcpy(keystring, lstartptr);
132 lptr++;
133 char *nptr;
134 switch (lineno) {
135
136 case 3:
137 if (!strcmp(keystring, "run_time "))
138 afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
139 break;
140 case 5:
141 if (!strcmp(keystring, "cycles_done "))
142 afl->queue_cycle =
143 strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
144 break;
145 case 7:
146 if (!strcmp(keystring, "execs_done "))
147 afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
148 break;
149 case 10:
150 if (!strcmp(keystring, "corpus_count ")) {
151
152 u32 corpus_count = strtoul(lptr, &nptr, 10);
153 if (corpus_count != afl->queued_items) {
154
155 WARNF(
156 "queue/ has been modified -- things might not work, you're "
157 "on your own!");
158
159 }
160
161 }
162
163 break;
164 case 12:
165 if (!strcmp(keystring, "corpus_found "))
166 afl->queued_discovered = strtoul(lptr, &nptr, 10);
167 break;
168 case 13:
169 if (!strcmp(keystring, "corpus_imported "))
170 afl->queued_imported = strtoul(lptr, &nptr, 10);
171 break;
172 case 14:
173 if (!strcmp(keystring, "max_depth "))
174 afl->max_depth = strtoul(lptr, &nptr, 10);
175 break;
176 case 21:
177 if (!strcmp(keystring, "saved_crashes "))
178 afl->saved_crashes = strtoull(lptr, &nptr, 10);
179 break;
180 case 22:
181 if (!strcmp(keystring, "saved_hangs "))
182 afl->saved_hangs = strtoull(lptr, &nptr, 10);
183 break;
184 default:
185 break;
186
187 }
188
189 }
190
191 }
192
193 if (afl->saved_crashes) { write_crash_readme(afl); }
194
195 return;
196
197 }
198
199 /* Update stats file for unattended monitoring. */
200
201 void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
202 double stability, double eps) {
203
204 #ifndef __HAIKU__
205 struct rusage rus;
206 #endif
207
208 u64 cur_time = get_cur_time();
209 u8 fn[PATH_MAX];
210 FILE *f;
211
212 snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
213 f = create_ffile(fn);
214
215 /* Keep last values in case we're called from another context
216 where exec/sec stats and such are not readily available. */
217
218 if (!bitmap_cvg && !stability && !eps) {
219
220 bitmap_cvg = afl->last_bitmap_cvg;
221 stability = afl->last_stability;
222
223 } else {
224
225 afl->last_bitmap_cvg = bitmap_cvg;
226 afl->last_stability = stability;
227 afl->last_eps = eps;
228
229 }
230
231 if ((unlikely(!afl->last_avg_exec_update ||
232 cur_time - afl->last_avg_exec_update >= 60000))) {
233
234 afl->last_avg_execs_saved =
235 (double)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) /
236 (double)(cur_time - afl->last_avg_exec_update);
237 afl->last_avg_execs = afl->fsrv.total_execs;
238 afl->last_avg_exec_update = cur_time;
239
240 }
241
242 #ifndef __HAIKU__
243 if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
244 #endif
245
246 fprintf(
247 f,
248 "start_time : %llu\n"
249 "last_update : %llu\n"
250 "run_time : %llu\n"
251 "fuzzer_pid : %u\n"
252 "cycles_done : %llu\n"
253 "cycles_wo_finds : %llu\n"
254 "execs_done : %llu\n"
255 "execs_per_sec : %0.02f\n"
256 "execs_ps_last_min : %0.02f\n"
257 "corpus_count : %u\n"
258 "corpus_favored : %u\n"
259 "corpus_found : %u\n"
260 "corpus_imported : %u\n"
261 "corpus_variable : %u\n"
262 "max_depth : %u\n"
263 "cur_item : %u\n"
264 "pending_favs : %u\n"
265 "pending_total : %u\n"
266 "stability : %0.02f%%\n"
267 "bitmap_cvg : %0.02f%%\n"
268 "saved_crashes : %llu\n"
269 "saved_hangs : %llu\n"
270 "last_find : %llu\n"
271 "last_crash : %llu\n"
272 "last_hang : %llu\n"
273 "execs_since_crash : %llu\n"
274 "exec_timeout : %u\n"
275 "slowest_exec_ms : %u\n"
276 "peak_rss_mb : %lu\n"
277 "cpu_affinity : %d\n"
278 "edges_found : %u\n"
279 "total_edges : %u\n"
280 "var_byte_count : %u\n"
281 "havoc_expansion : %u\n"
282 "auto_dict_entries : %u\n"
283 "testcache_size : %llu\n"
284 "testcache_count : %u\n"
285 "testcache_evict : %u\n"
286 "afl_banner : %s\n"
287 "afl_version : " VERSION
288 "\n"
289 "target_mode : %s%s%s%s%s%s%s%s%s%s\n"
290 "command_line : %s\n",
291 (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
292 (afl->prev_run_time + cur_time - afl->start_time) / 1000, (u32)getpid(),
293 afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
294 afl->fsrv.total_execs,
295 afl->fsrv.total_execs /
296 ((double)(afl->prev_run_time + get_cur_time() - afl->start_time) /
297 1000),
298 afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
299 afl->queued_discovered, afl->queued_imported, afl->queued_variable,
300 afl->max_depth, afl->current_entry, afl->pending_favored,
301 afl->pending_not_fuzzed, stability, bitmap_cvg, afl->saved_crashes,
302 afl->saved_hangs, afl->last_find_time / 1000, afl->last_crash_time / 1000,
303 afl->last_hang_time / 1000, afl->fsrv.total_execs - afl->last_crash_execs,
304 afl->fsrv.exec_tmout, afl->slowest_exec_ms,
305 #ifndef __HAIKU__
306 #ifdef __APPLE__
307 (unsigned long int)(rus.ru_maxrss >> 20),
308 #else
309 (unsigned long int)(rus.ru_maxrss >> 10),
310 #endif
311 #else
312 -1UL,
313 #endif
314 #ifdef HAVE_AFFINITY
315 afl->cpu_aff,
316 #else
317 -1,
318 #endif
319 t_bytes, afl->fsrv.real_map_size, afl->var_byte_count, afl->expand_havoc,
320 afl->a_extras_cnt, afl->q_testcase_cache_size,
321 afl->q_testcase_cache_count, afl->q_testcase_evictions, afl->use_banner,
322 afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "",
323 afl->fsrv.cs_mode ? "coresight" : "",
324 afl->non_instrumented_mode ? " non_instrumented " : "",
325 afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
326 afl->persistent_mode ? "persistent " : "",
327 afl->shmem_testcase_mode ? "shmem_testcase " : "",
328 afl->deferred_mode ? "deferred " : "",
329 (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->fsrv.cs_mode ||
330 afl->non_instrumented_mode || afl->no_forkserver || afl->crash_mode ||
331 afl->persistent_mode || afl->deferred_mode)
332 ? ""
333 : "default",
334 afl->orig_cmdline);
335
336 /* ignore errors */
337
338 if (afl->debug) {
339
340 u32 i = 0;
341 fprintf(f, "virgin_bytes :");
342 for (i = 0; i < afl->fsrv.real_map_size; i++) {
343
344 if (afl->virgin_bits[i] != 0xff) {
345
346 fprintf(f, " %u[%02x]", i, afl->virgin_bits[i]);
347
348 }
349
350 }
351
352 fprintf(f, "\n");
353 fprintf(f, "var_bytes :");
354 for (i = 0; i < afl->fsrv.real_map_size; i++) {
355
356 if (afl->var_bytes[i]) { fprintf(f, " %u", i); }
357
358 }
359
360 fprintf(f, "\n");
361
362 }
363
364 fclose(f);
365
366 }
367
368 /* Update the plot file if there is a reason to. */
369
370 void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
371 double eps) {
372
373 if (unlikely(!afl->force_ui_update &&
374 (afl->stop_soon ||
375 (afl->plot_prev_qp == afl->queued_items &&
376 afl->plot_prev_pf == afl->pending_favored &&
377 afl->plot_prev_pnf == afl->pending_not_fuzzed &&
378 afl->plot_prev_ce == afl->current_entry &&
379 afl->plot_prev_qc == afl->queue_cycle &&
380 afl->plot_prev_uc == afl->saved_crashes &&
381 afl->plot_prev_uh == afl->saved_hangs &&
382 afl->plot_prev_md == afl->max_depth &&
383 afl->plot_prev_ed == afl->fsrv.total_execs) ||
384 !afl->queue_cycle ||
385 get_cur_time() - afl->start_time <= 60000))) {
386
387 return;
388
389 }
390
391 afl->plot_prev_qp = afl->queued_items;
392 afl->plot_prev_pf = afl->pending_favored;
393 afl->plot_prev_pnf = afl->pending_not_fuzzed;
394 afl->plot_prev_ce = afl->current_entry;
395 afl->plot_prev_qc = afl->queue_cycle;
396 afl->plot_prev_uc = afl->saved_crashes;
397 afl->plot_prev_uh = afl->saved_hangs;
398 afl->plot_prev_md = afl->max_depth;
399 afl->plot_prev_ed = afl->fsrv.total_execs;
400
401 /* Fields in the file:
402
403 relative_time, afl->cycles_done, cur_item, corpus_count, corpus_not_fuzzed,
404 favored_not_fuzzed, saved_crashes, saved_hangs, max_depth,
405 execs_per_sec, edges_found */
406
407 fprintf(afl->fsrv.plot_file,
408 "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
409 "%u\n",
410 ((afl->prev_run_time + get_cur_time() - afl->start_time) / 1000),
411 afl->queue_cycle - 1, afl->current_entry, afl->queued_items,
412 afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg,
413 afl->saved_crashes, afl->saved_hangs, afl->max_depth, eps,
414 afl->plot_prev_ed, t_bytes); /* ignore errors */
415
416 fflush(afl->fsrv.plot_file);
417
418 }
419
420 /* Check terminal dimensions after resize. */
421
422 static void check_term_size(afl_state_t *afl) {
423
424 struct winsize ws;
425
426 afl->term_too_small = 0;
427
428 if (ioctl(1, TIOCGWINSZ, &ws)) { return; }
429
430 if (ws.ws_row == 0 || ws.ws_col == 0) { return; }
431 if (ws.ws_row < 24 || ws.ws_col < 79) { afl->term_too_small = 1; }
432
433 }
434
435 /* A spiffy retro stats screen! This is called every afl->stats_update_freq
436 execve() calls, plus in several other circumstances. */
437
438 void show_stats(afl_state_t *afl) {
439
440 if (afl->pizza_is_served) {
441
442 show_stats_pizza(afl);
443
444 } else {
445
446 show_stats_normal(afl);
447
448 }
449
450 }
451
452 void show_stats_normal(afl_state_t *afl) {
453
454 double t_byte_ratio, stab_ratio;
455
456 u64 cur_ms;
457 u32 t_bytes, t_bits;
458
459 static u8 banner[128];
460 u32 banner_len, banner_pad;
461 u8 tmp[256];
462 u8 time_tmp[64];
463
464 u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
465 #define IB(i) (val_buf[(i)])
466
467 cur_ms = get_cur_time();
468
469 if (afl->most_time_key) {
470
471 if (afl->most_time * 1000 < cur_ms - afl->start_time) {
472
473 afl->most_time_key = 2;
474 afl->stop_soon = 2;
475
476 }
477
478 }
479
480 if (afl->most_execs_key == 1) {
481
482 if (afl->most_execs <= afl->fsrv.total_execs) {
483
484 afl->most_execs_key = 2;
485 afl->stop_soon = 2;
486
487 }
488
489 }
490
491 /* If not enough time has passed since last UI update, bail out. */
492
493 if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ &&
494 !afl->force_ui_update) {
495
496 return;
497
498 }
499
500 /* Check if we're past the 10 minute mark. */
501
502 if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; }
503
504 /* Calculate smoothed exec speed stats. */
505
506 if (unlikely(!afl->stats_last_execs)) {
507
508 if (likely(cur_ms != afl->start_time)) {
509
510 afl->stats_avg_exec = ((double)afl->fsrv.total_execs) * 1000 /
511 (afl->prev_run_time + cur_ms - afl->start_time);
512
513 }
514
515 } else {
516
517 if (likely(cur_ms != afl->stats_last_ms)) {
518
519 double cur_avg =
520 ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * 1000 /
521 (cur_ms - afl->stats_last_ms);
522
523 /* If there is a dramatic (5x+) jump in speed, reset the indicator
524 more quickly. */
525
526 if (cur_avg * 5 < afl->stats_avg_exec ||
527 cur_avg / 5 > afl->stats_avg_exec) {
528
529 afl->stats_avg_exec = cur_avg;
530
531 }
532
533 afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
534 cur_avg * (1.0 / AVG_SMOOTHING);
535
536 }
537
538 }
539
540 afl->stats_last_ms = cur_ms;
541 afl->stats_last_execs = afl->fsrv.total_execs;
542
543 /* Tell the callers when to contact us (as measured in execs). */
544
545 afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10);
546 if (!afl->stats_update_freq) { afl->stats_update_freq = 1; }
547
548 /* Do some bitmap stats. */
549
550 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
551 t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.real_map_size;
552
553 if (unlikely(t_bytes > afl->fsrv.real_map_size)) {
554
555 if (unlikely(!afl->afl_env.afl_ignore_problems)) {
556
557 FATAL(
558 "Incorrect fuzzing setup detected. Your target seems to have loaded "
559 "incorrectly instrumented shared libraries (%u of %u/%u). If you use "
560 "LTO mode "
561 "please see instrumentation/README.lto.md. To ignore this problem "
562 "and continue fuzzing just set 'AFL_IGNORE_PROBLEMS=1'.\n",
563 t_bytes, afl->fsrv.real_map_size, afl->fsrv.map_size);
564
565 }
566
567 }
568
569 if (likely(t_bytes) && unlikely(afl->var_byte_count)) {
570
571 stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes);
572
573 } else {
574
575 stab_ratio = 100;
576
577 }
578
579 /* Roughly every minute, update fuzzer stats and save auto tokens. */
580
581 if (unlikely(!afl->non_instrumented_mode &&
582 (afl->force_ui_update ||
583 cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) {
584
585 afl->stats_last_stats_ms = cur_ms;
586 write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
587 afl->stats_avg_exec);
588 save_auto(afl);
589 write_bitmap(afl);
590
591 }
592
593 if (unlikely(afl->afl_env.afl_statsd)) {
594
595 if (unlikely(afl->force_ui_update || cur_ms - afl->statsd_last_send_ms >
596 STATSD_UPDATE_SEC * 1000)) {
597
598 /* reset counter, even if send failed. */
599 afl->statsd_last_send_ms = cur_ms;
600 if (statsd_send_metric(afl)) { WARNF("could not send statsd metric."); }
601
602 }
603
604 }
605
606 /* Every now and then, write plot data. */
607
608 if (unlikely(afl->force_ui_update ||
609 cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000)) {
610
611 afl->stats_last_plot_ms = cur_ms;
612 maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec);
613
614 }
615
616 /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
617
618 if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
619 !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)) {
620
621 afl->stop_soon = 2;
622
623 }
624
625 /* AFL_EXIT_ON_TIME. */
626
627 if (unlikely(afl->last_find_time && !afl->non_instrumented_mode &&
628 afl->afl_env.afl_exit_on_time &&
629 (cur_ms - afl->last_find_time) > afl->exit_on_time)) {
630
631 afl->stop_soon = 2;
632
633 }
634
635 if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) {
636
637 afl->stop_soon = 2;
638
639 }
640
641 /* If we're not on TTY, bail out. */
642
643 if (afl->not_on_tty) { return; }
644
645 /* If we haven't started doing things, bail out. */
646
647 if (unlikely(!afl->queue_cur)) { return; }
648
649 /* Compute some mildly useful bitmap stats. */
650
651 t_bits = (afl->fsrv.map_size << 3) - count_bits(afl, afl->virgin_bits);
652
653 /* Now, for the visuals... */
654
655 if (afl->clear_screen) {
656
657 SAYF(TERM_CLEAR CURSOR_HIDE);
658 afl->clear_screen = 0;
659
660 check_term_size(afl);
661
662 }
663
664 SAYF(TERM_HOME);
665
666 if (unlikely(afl->term_too_small)) {
667
668 SAYF(cBRI
669 "Your terminal is too small to display the UI.\n"
670 "Please resize terminal window to at least 79x24.\n" cRST);
671
672 return;
673
674 }
675
676 /* Let's start by drawing a centered banner. */
677 if (unlikely(!banner[0])) {
678
679 char *si = "";
680 if (afl->sync_id) { si = afl->sync_id; }
681 memset(banner, 0, sizeof(banner));
682 banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
683 strlen(afl->power_name) + 4 + 6;
684
685 if (strlen(afl->use_banner) + banner_len > 75) {
686
687 afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76;
688 memset(afl->use_banner, '.', 3);
689
690 }
691
692 banner_len += strlen(afl->use_banner);
693 banner_pad = (79 - banner_len) / 2;
694 memset(banner, ' ', banner_pad);
695
696 #ifdef __linux__
697 if (afl->fsrv.nyx_mode) {
698
699 sprintf(banner + banner_pad,
700 "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
701 afl->crash_mode ? cPIN "peruvian were-rabbit"
702 : cYEL "american fuzzy lop",
703 si, afl->use_banner, afl->power_name);
704
705 } else {
706
707 #endif
708 sprintf(banner + banner_pad,
709 "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
710 afl->crash_mode ? cPIN "peruvian were-rabbit"
711 : cYEL "american fuzzy lop",
712 si, afl->use_banner, afl->power_name);
713
714 #ifdef __linux__
715
716 }
717
718 #endif
719
720 }
721
722 SAYF("\n%s\n", banner);
723
724 /* "Handy" shortcuts for drawing boxes... */
725
726 #define bSTG bSTART cGRA
727 #define bH2 bH bH
728 #define bH5 bH2 bH2 bH
729 #define bH10 bH5 bH5
730 #define bH20 bH10 bH10
731 #define bH30 bH20 bH10
732 #define SP5 " "
733 #define SP10 SP5 SP5
734 #define SP20 SP10 SP10
735
736 /* Since `total_crashes` does not get reloaded from disk on restart,
737 it indicates if we found crashes this round already -> paint red.
738 If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */
739 char *crash_color = afl->total_crashes ? cLRD
740 : afl->saved_crashes ? cYEL
741 : cRST;
742
743 /* Lord, forgive me this. */
744
745 SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
746 " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA
747 " overall results " bSTG bH2 bH2 bRT "\n");
748
749 if (afl->non_instrumented_mode) {
750
751 strcpy(tmp, cRST);
752
753 } else {
754
755 u64 min_wo_finds = (cur_ms - afl->last_find_time) / 1000 / 60;
756
757 /* First queue cycle: don't stop now! */
758 if (afl->queue_cycle == 1 || min_wo_finds < 15) {
759
760 strcpy(tmp, cMGN);
761
762 } else
763
764 /* Subsequent cycles, but we're still making finds. */
765 if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) {
766
767 strcpy(tmp, cYEL);
768
769 } else
770
771 /* No finds for a long time and no test cases to try. */
772 if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed &&
773 min_wo_finds > 120) {
774
775 strcpy(tmp, cLGN);
776
777 /* Default: cautiously OK to stop? */
778
779 } else {
780
781 strcpy(tmp, cLBL);
782
783 }
784
785 }
786
787 u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time);
788 SAYF(bV bSTOP " run time : " cRST "%-33s " bSTG bV bSTOP
789 " cycles done : %s%-5s " bSTG bV "\n",
790 time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1));
791
792 /* We want to warn people about not seeing new paths after a full cycle,
793 except when resuming fuzzing or running in non-instrumented mode. */
794
795 if (!afl->non_instrumented_mode &&
796 (afl->last_find_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
797 afl->in_bitmap || afl->crash_mode)) {
798
799 u_stringify_time_diff(time_tmp, cur_ms, afl->last_find_time);
800 SAYF(bV bSTOP " last new find : " cRST "%-33s ", time_tmp);
801
802 } else {
803
804 if (afl->non_instrumented_mode) {
805
806 SAYF(bV bSTOP " last new find : " cPIN "n/a" cRST
807 " (non-instrumented mode) ");
808
809 } else {
810
811 SAYF(bV bSTOP " last new find : " cRST "none yet " cLRD
812 "(odd, check syntax!) ");
813
814 }
815
816 }
817
818 SAYF(bSTG bV bSTOP " corpus count : " cRST "%-5s " bSTG bV "\n",
819 u_stringify_int(IB(0), afl->queued_items));
820
821 /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH
822 limit with a '+' appended to the count. */
823
824 sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_crashes),
825 (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
826
827 u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time);
828 SAYF(bV bSTOP "last saved crash : " cRST "%-33s " bSTG bV bSTOP
829 "saved crashes : %s%-6s" bSTG bV "\n",
830 time_tmp, crash_color, tmp);
831
832 sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_hangs),
833 (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
834
835 u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time);
836 SAYF(bV bSTOP " last saved hang : " cRST "%-33s " bSTG bV bSTOP
837 " saved hangs : " cRST "%-6s" bSTG bV "\n",
838 time_tmp, tmp);
839
840 SAYF(bVR bH bSTOP cCYA
841 " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA
842 " map coverage" bSTG bHT bH20 bH2 bVL "\n");
843
844 /* This gets funny because we want to print several variable-length variables
845 together, but then cram them into a fixed-width field - so we need to
846 put them in a temporary buffer first. */
847
848 sprintf(tmp, "%s%s%u (%0.01f%%)", u_stringify_int(IB(0), afl->current_entry),
849 afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level,
850 ((double)afl->current_entry * 100) / afl->queued_items);
851
852 SAYF(bV bSTOP " now processing : " cRST "%-18s " bSTG bV bSTOP, tmp);
853
854 sprintf(tmp, "%0.02f%% / %0.02f%%",
855 ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.real_map_size,
856 t_byte_ratio);
857
858 SAYF(" map density : %s%-19s" bSTG bV "\n",
859 t_byte_ratio > 70
860 ? cLRD
861 : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST),
862 tmp);
863
864 sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_items),
865 ((double)afl->cur_skipped_items * 100) / afl->queued_items);
866
867 SAYF(bV bSTOP " runs timed out : " cRST "%-18s " bSTG bV, tmp);
868
869 sprintf(tmp, "%0.02f bits/tuple", t_bytes ? (((double)t_bits) / t_bytes) : 0);
870
871 SAYF(bSTOP " count coverage : " cRST "%-19s" bSTG bV "\n", tmp);
872
873 SAYF(bVR bH bSTOP cCYA
874 " stage progress " bSTG bH10 bH5 bH2 bH2 bH2 bX bH bSTOP cCYA
875 " findings in depth " bSTG bH10 bH5 bH2 bVL "\n");
876
877 sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
878 ((double)afl->queued_favored) * 100 / afl->queued_items);
879
880 /* Yeah... it's still going on... halp? */
881
882 SAYF(bV bSTOP " now trying : " cRST "%-22s " bSTG bV bSTOP
883 " favored items : " cRST "%-20s" bSTG bV "\n",
884 afl->stage_name, tmp);
885
886 if (!afl->stage_max) {
887
888 sprintf(tmp, "%s/-", u_stringify_int(IB(0), afl->stage_cur));
889
890 } else {
891
892 sprintf(tmp, "%s/%s (%0.02f%%)", u_stringify_int(IB(0), afl->stage_cur),
893 u_stringify_int(IB(1), afl->stage_max),
894 ((double)afl->stage_cur) * 100 / afl->stage_max);
895
896 }
897
898 SAYF(bV bSTOP " stage execs : " cRST "%-23s" bSTG bV bSTOP, tmp);
899
900 sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov),
901 ((double)afl->queued_with_cov) * 100 / afl->queued_items);
902
903 SAYF(" new edges on : " cRST "%-20s" bSTG bV "\n", tmp);
904
905 sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_crashes),
906 u_stringify_int(IB(1), afl->saved_crashes),
907 (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
908
909 if (afl->crash_mode) {
910
911 SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP
912 " new crashes : %s%-20s" bSTG bV "\n",
913 u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp);
914
915 } else {
916
917 SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP
918 " total crashes : %s%-20s" bSTG bV "\n",
919 u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp);
920
921 }
922
923 /* Show a warning about slow execution. */
924
925 if (afl->stats_avg_exec < 100) {
926
927 sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
928 afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
929
930 SAYF(bV bSTOP " exec speed : " cLRD "%-22s ", tmp);
931
932 } else {
933
934 sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec));
935 SAYF(bV bSTOP " exec speed : " cRST "%-22s ", tmp);
936
937 }
938
939 sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts),
940 u_stringify_int(IB(1), afl->saved_tmouts),
941 (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
942
943 SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-20s" bSTG bV "\n", tmp);
944
945 /* Aaaalmost there... hold on! */
946
947 SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH2 bHT bH10 bH2
948 bH bHB bH bSTOP cCYA " item geometry " bSTG bH5 bH2 bVL "\n");
949
950 if (unlikely(afl->custom_only)) {
951
952 strcpy(tmp, "disabled (custom-mutator-only mode)");
953
954 } else if (likely(afl->skip_deterministic)) {
955
956 strcpy(tmp, "disabled (default, enable with -D)");
957
958 } else {
959
960 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
961 u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
962 u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
963 u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
964 u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
965 u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]),
966 u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
967
968 }
969
970 SAYF(bV bSTOP " bit flips : " cRST "%-36s " bSTG bV bSTOP
971 " levels : " cRST "%-10s" bSTG bV "\n",
972 tmp, u_stringify_int(IB(0), afl->max_depth));
973
974 if (unlikely(!afl->skip_deterministic)) {
975
976 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
977 u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
978 u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
979 u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
980 u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
981 u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
982 u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
983
984 }
985
986 SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP
987 " pending : " cRST "%-10s" bSTG bV "\n",
988 tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
989
990 if (unlikely(!afl->skip_deterministic)) {
991
992 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
993 u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
994 u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
995 u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
996 u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
997 u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
998 u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
999
1000 }
1001
1002 SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
1003 " pend fav : " cRST "%-10s" bSTG bV "\n",
1004 tmp, u_stringify_int(IB(0), afl->pending_favored));
1005
1006 if (unlikely(!afl->skip_deterministic)) {
1007
1008 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
1009 u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
1010 u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]),
1011 u_stringify_int(IB(2), afl->stage_finds[STAGE_INTEREST16]),
1012 u_stringify_int(IB(3), afl->stage_cycles[STAGE_INTEREST16]),
1013 u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]),
1014 u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32]));
1015
1016 }
1017
1018 SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP
1019 " own finds : " cRST "%-10s" bSTG bV "\n",
1020 tmp, u_stringify_int(IB(0), afl->queued_discovered));
1021
1022 if (unlikely(!afl->skip_deterministic)) {
1023
1024 sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
1025 u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
1026 u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
1027 u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
1028 u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
1029 u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
1030 u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]),
1031 u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]),
1032 u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI]));
1033
1034 } else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
1035
1036 strcpy(tmp, "n/a");
1037
1038 } else {
1039
1040 strcpy(tmp, "havoc mode");
1041
1042 }
1043
1044 SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP
1045 " imported : " cRST "%-10s" bSTG bV "\n",
1046 tmp,
1047 afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported)
1048 : (u8 *)"n/a");
1049
1050 sprintf(tmp, "%s/%s, %s/%s",
1051 u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
1052 u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
1053 u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
1054 u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]));
1055
1056 SAYF(bV bSTOP "havoc/splice : " cRST "%-36s " bSTG bV bSTOP, tmp);
1057
1058 if (t_bytes) {
1059
1060 sprintf(tmp, "%0.02f%%", stab_ratio);
1061
1062 } else {
1063
1064 strcpy(tmp, "n/a");
1065
1066 }
1067
1068 SAYF(" stability : %s%-10s" bSTG bV "\n",
1069 (stab_ratio < 85 && afl->var_byte_count > 40)
1070 ? cLRD
1071 : ((afl->queued_variable &&
1072 (!afl->persistent_mode || afl->var_byte_count > 20))
1073 ? cMGN
1074 : cRST),
1075 tmp);
1076
1077 if (unlikely(afl->afl_env.afl_python_module)) {
1078
1079 sprintf(tmp, "%s/%s,",
1080 u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
1081 u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]));
1082
1083 } else {
1084
1085 strcpy(tmp, "unused,");
1086
1087 }
1088
1089 if (unlikely(afl->afl_env.afl_custom_mutator_library)) {
1090
1091 strcat(tmp, " ");
1092 strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]));
1093 strcat(tmp, "/");
1094 strcat(tmp,
1095 u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
1096 strcat(tmp, ",");
1097
1098 } else {
1099
1100 strcat(tmp, " unused,");
1101
1102 }
1103
1104 if (unlikely(afl->shm.cmplog_mode)) {
1105
1106 strcat(tmp, " ");
1107 strcat(tmp, u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]));
1108 strcat(tmp, "/");
1109 strcat(tmp, u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]));
1110 strcat(tmp, ", ");
1111 strcat(tmp, u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]));
1112 strcat(tmp, "/");
1113 strcat(tmp, u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
1114
1115 } else {
1116
1117 strcat(tmp, " unused, unused");
1118
1119 }
1120
1121 SAYF(bV bSTOP "py/custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
1122 tmp);
1123
1124 if (likely(afl->disable_trim)) {
1125
1126 sprintf(tmp, "disabled, ");
1127
1128 } else if (unlikely(!afl->bytes_trim_out)) {
1129
1130 sprintf(tmp, "n/a, ");
1131
1132 } else {
1133
1134 sprintf(tmp, "%0.02f%%/%s, ",
1135 ((double)(afl->bytes_trim_in - afl->bytes_trim_out)) * 100 /
1136 afl->bytes_trim_in,
1137 u_stringify_int(IB(0), afl->trim_execs));
1138
1139 }
1140
1141 if (likely(afl->skip_deterministic)) {
1142
1143 strcat(tmp, "disabled");
1144
1145 } else if (unlikely(!afl->blocks_eff_total)) {
1146
1147 strcat(tmp, "n/a");
1148
1149 } else {
1150
1151 u8 tmp2[128];
1152
1153 sprintf(tmp2, "%0.02f%%",
1154 ((double)(afl->blocks_eff_total - afl->blocks_eff_select)) * 100 /
1155 afl->blocks_eff_total);
1156
1157 strcat(tmp, tmp2);
1158
1159 }
1160
1161 // if (afl->custom_mutators_count) {
1162
1163 //
1164 // sprintf(tmp, "%s/%s",
1165 // u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
1166 // u_stringify_int(IB(1), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
1167 // SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp);
1168 //
1169 //} else {
1170
1171 SAYF(bV bSTOP " trim/eff : " cRST "%-36s " bSTG bV RESET_G1, tmp);
1172
1173 //}
1174
1175 /* Provide some CPU utilization stats. */
1176
1177 if (afl->cpu_core_count) {
1178
1179 char *spacing = SP10, snap[24] = " " cLGN "snapshot" cRST " ";
1180
1181 double cur_runnable = get_runnable_processes();
1182 u32 cur_utilization = cur_runnable * 100 / afl->cpu_core_count;
1183
1184 u8 *cpu_color = cCYA;
1185
1186 /* If we could still run one or more processes, use green. */
1187
1188 if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) {
1189
1190 cpu_color = cLGN;
1191
1192 }
1193
1194 /* If we're clearly oversubscribed, use red. */
1195
1196 if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; }
1197
1198 if (afl->fsrv.snapshot) { spacing = snap; }
1199
1200 #ifdef HAVE_AFFINITY
1201
1202 if (afl->cpu_aff >= 0) {
1203
1204 SAYF("%s" cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, spacing,
1205 MIN(afl->cpu_aff, 999), cpu_color, MIN(cur_utilization, (u32)999));
1206
1207 } else {
1208
1209 SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color,
1210 MIN(cur_utilization, (u32)999));
1211
1212 }
1213
1214 #else
1215
1216 SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color,
1217 MIN(cur_utilization, (u32)999));
1218
1219 #endif /* ^HAVE_AFFINITY */
1220
1221 } else {
1222
1223 SAYF("\r");
1224
1225 }
1226
1227 /* Last line */
1228 SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
1229
1230 #undef IB
1231
1232 /* Hallelujah! */
1233
1234 fflush(0);
1235
1236 }
1237
1238 void show_stats_pizza(afl_state_t *afl) {
1239
1240 double t_byte_ratio, stab_ratio;
1241
1242 u64 cur_ms;
1243 u32 t_bytes, t_bits;
1244
1245 static u8 banner[128];
1246 u32 banner_len, banner_pad;
1247 u8 tmp[256];
1248 u8 time_tmp[64];
1249
1250 u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
1251 #define IB(i) (val_buf[(i)])
1252
1253 cur_ms = get_cur_time();
1254
1255 if (afl->most_time_key) {
1256
1257 if (afl->most_time * 1000 < cur_ms - afl->start_time) {
1258
1259 afl->most_time_key = 2;
1260 afl->stop_soon = 2;
1261
1262 }
1263
1264 }
1265
1266 if (afl->most_execs_key == 1) {
1267
1268 if (afl->most_execs <= afl->fsrv.total_execs) {
1269
1270 afl->most_execs_key = 2;
1271 afl->stop_soon = 2;
1272
1273 }
1274
1275 }
1276
1277 /* If not enough time has passed since last UI update, bail out. */
1278
1279 if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ &&
1280 !afl->force_ui_update) {
1281
1282 return;
1283
1284 }
1285
1286 /* Check if we're past the 10 minute mark. */
1287
1288 if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; }
1289
1290 /* Calculate smoothed exec speed stats. */
1291
1292 if (unlikely(!afl->stats_last_execs)) {
1293
1294 if (likely(cur_ms != afl->start_time)) {
1295
1296 afl->stats_avg_exec = ((double)afl->fsrv.total_execs) * 1000 /
1297 (afl->prev_run_time + cur_ms - afl->start_time);
1298
1299 }
1300
1301 } else {
1302
1303 if (likely(cur_ms != afl->stats_last_ms)) {
1304
1305 double cur_avg =
1306 ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * 1000 /
1307 (cur_ms - afl->stats_last_ms);
1308
1309 /* If there is a dramatic (5x+) jump in speed, reset the indicator
1310 more quickly. */
1311
1312 if (cur_avg * 5 < afl->stats_avg_exec ||
1313 cur_avg / 5 > afl->stats_avg_exec) {
1314
1315 afl->stats_avg_exec = cur_avg;
1316
1317 }
1318
1319 afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) +
1320 cur_avg * (1.0 / AVG_SMOOTHING);
1321
1322 }
1323
1324 }
1325
1326 afl->stats_last_ms = cur_ms;
1327 afl->stats_last_execs = afl->fsrv.total_execs;
1328
1329 /* Tell the callers when to contact us (as measured in execs). */
1330
1331 afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10);
1332 if (!afl->stats_update_freq) { afl->stats_update_freq = 1; }
1333
1334 /* Do some bitmap stats. */
1335
1336 t_bytes = count_non_255_bytes(afl, afl->virgin_bits);
1337 t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.real_map_size;
1338
1339 if (unlikely(t_bytes > afl->fsrv.real_map_size)) {
1340
1341 if (unlikely(!afl->afl_env.afl_ignore_problems)) {
1342
1343 FATAL(
1344 "This is what happens when you speak italian to the rabbit "
1345 "Don't speak italian to the rabbit");
1346
1347 }
1348
1349 }
1350
1351 if (likely(t_bytes) && unlikely(afl->var_byte_count)) {
1352
1353 stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes);
1354
1355 } else {
1356
1357 stab_ratio = 100;
1358
1359 }
1360
1361 /* Roughly every minute, update fuzzer stats and save auto tokens. */
1362
1363 if (unlikely(!afl->non_instrumented_mode &&
1364 (afl->force_ui_update ||
1365 cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) {
1366
1367 afl->stats_last_stats_ms = cur_ms;
1368 write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
1369 afl->stats_avg_exec);
1370 save_auto(afl);
1371 write_bitmap(afl);
1372
1373 }
1374
1375 if (unlikely(afl->afl_env.afl_statsd)) {
1376
1377 if (unlikely(afl->force_ui_update || cur_ms - afl->statsd_last_send_ms >
1378 STATSD_UPDATE_SEC * 1000)) {
1379
1380 /* reset counter, even if send failed. */
1381 afl->statsd_last_send_ms = cur_ms;
1382 if (statsd_send_metric(afl)) {
1383
1384 WARNF("Could not order tomato sauce from statsd.");
1385
1386 }
1387
1388 }
1389
1390 }
1391
1392 /* Every now and then, write plot data. */
1393
1394 if (unlikely(afl->force_ui_update ||
1395 cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000)) {
1396
1397 afl->stats_last_plot_ms = cur_ms;
1398 maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec);
1399
1400 }
1401
1402 /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
1403
1404 if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
1405 !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)) {
1406
1407 afl->stop_soon = 2;
1408
1409 }
1410
1411 /* AFL_EXIT_ON_TIME. */
1412
1413 if (unlikely(afl->last_find_time && !afl->non_instrumented_mode &&
1414 afl->afl_env.afl_exit_on_time &&
1415 (cur_ms - afl->last_find_time) > afl->exit_on_time)) {
1416
1417 afl->stop_soon = 2;
1418
1419 }
1420
1421 if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) {
1422
1423 afl->stop_soon = 2;
1424
1425 }
1426
1427 /* If we're not on TTY, bail out. */
1428
1429 if (afl->not_on_tty) { return; }
1430
1431 /* If we haven't started doing things, bail out. */
1432
1433 if (unlikely(!afl->queue_cur)) { return; }
1434
1435 /* Compute some mildly useful bitmap stats. */
1436
1437 t_bits = (afl->fsrv.map_size << 3) - count_bits(afl, afl->virgin_bits);
1438
1439 /* Now, for the visuals... */
1440
1441 if (afl->clear_screen) {
1442
1443 SAYF(TERM_CLEAR CURSOR_HIDE);
1444 afl->clear_screen = 0;
1445
1446 check_term_size(afl);
1447
1448 }
1449
1450 SAYF(TERM_HOME);
1451
1452 if (unlikely(afl->term_too_small)) {
1453
1454 SAYF(cBRI
1455 "Our pizzeria can't host this many guests.\n"
1456 "Please call Pizzeria Caravaggio. They have tables of at least "
1457 "79x24.\n" cRST);
1458
1459 return;
1460
1461 }
1462
1463 /* Let's start by drawing a centered banner. */
1464 if (unlikely(!banner[0])) {
1465
1466 char *si = "";
1467 if (afl->sync_id) { si = afl->sync_id; }
1468 memset(banner, 0, sizeof(banner));
1469 banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
1470 strlen(afl->power_name) + 4 + 6;
1471
1472 if (strlen(afl->use_banner) + banner_len > 75) {
1473
1474 afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76;
1475 memset(afl->use_banner, '.', 3);
1476
1477 }
1478
1479 banner_len += strlen(afl->use_banner);
1480 banner_pad = (79 - banner_len) / 2;
1481 memset(banner, ' ', banner_pad);
1482
1483 #ifdef __linux__
1484 if (afl->fsrv.nyx_mode) {
1485
1486 sprintf(banner + banner_pad,
1487 "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
1488 afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
1489 : cYEL "Mozzarbella Pizzeria management system",
1490 si, afl->use_banner, afl->power_name);
1491
1492 } else {
1493
1494 #endif
1495 sprintf(banner + banner_pad,
1496 "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
1497 afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
1498 : cYEL "Mozzarbella Pizzeria management system",
1499 si, afl->use_banner, afl->power_name);
1500
1501 #ifdef __linux__
1502
1503 }
1504
1505 #endif
1506
1507 }
1508
1509 SAYF("\n%s\n", banner);
1510
1511 /* "Handy" shortcuts for drawing boxes... */
1512
1513 #define bSTG bSTART cGRA
1514 #define bH2 bH bH
1515 #define bH5 bH2 bH2 bH
1516 #define bH10 bH5 bH5
1517 #define bH20 bH10 bH10
1518 #define bH30 bH20 bH10
1519 #define SP5 " "
1520 #define SP10 SP5 SP5
1521 #define SP20 SP10 SP10
1522
1523 /* Since `total_crashes` does not get reloaded from disk on restart,
1524 it indicates if we found crashes this round already -> paint red.
1525 If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */
1526 char *crash_color = afl->total_crashes ? cLRD
1527 : afl->saved_crashes ? cYEL
1528 : cRST;
1529
1530 /* Lord, forgive me this. */
1531
1532 SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
1533 " Mozzarbella has been proudly serving pizzas since " bSTG bH20 bH bH bH
1534 bHB bH bSTOP cCYA " In this time, we served " bSTG bH30 bRT "\n");
1535
1536 if (afl->non_instrumented_mode) {
1537
1538 strcpy(tmp, cRST);
1539
1540 } else {
1541
1542 u64 min_wo_finds = (cur_ms - afl->last_find_time) / 1000 / 60;
1543
1544 /* First queue cycle: don't stop now! */
1545 if (afl->queue_cycle == 1 || min_wo_finds < 15) {
1546
1547 strcpy(tmp, cMGN);
1548
1549 } else
1550
1551 /* Subsequent cycles, but we're still making finds. */
1552 if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) {
1553
1554 strcpy(tmp, cYEL);
1555
1556 } else
1557
1558 /* No finds for a long time and no test cases to try. */
1559 if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed &&
1560 min_wo_finds > 120) {
1561
1562 strcpy(tmp, cLGN);
1563
1564 /* Default: cautiously OK to stop? */
1565
1566 } else {
1567
1568 strcpy(tmp, cLBL);
1569
1570 }
1571
1572 }
1573
1574 u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time);
1575 SAYF(bV bSTOP
1576 " open time : " cRST "%-37s " bSTG bV bSTOP
1577 " seasons done : %s%-5s " bSTG bV "\n",
1578 time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1));
1579
1580 /* We want to warn people about not seeing new paths after a full cycle,
1581 except when resuming fuzzing or running in non-instrumented mode. */
1582
1583 if (!afl->non_instrumented_mode &&
1584 (afl->last_find_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
1585 afl->in_bitmap || afl->crash_mode)) {
1586
1587 u_stringify_time_diff(time_tmp, cur_ms, afl->last_find_time);
1588 SAYF(bV bSTOP " last pizza baked : " cRST "%-37s ",
1589 time_tmp);
1590
1591 } else {
1592
1593 if (afl->non_instrumented_mode) {
1594
1595 SAYF(bV bSTOP " last pizza baked : " cPIN "n/a" cRST
1596 " (non-instrumented mode) ");
1597
1598 } else {
1599
1600 SAYF(bV bSTOP " last pizza baked : " cRST
1601 "none yet " cLRD
1602 "(odd, check Gennarino, he might be slacking!) ");
1603
1604 }
1605
1606 }
1607
1608 SAYF(bSTG bV bSTOP " pizzas on the menu : " cRST
1609 "%-5s " bSTG bV "\n",
1610 u_stringify_int(IB(0), afl->queued_items));
1611
1612 /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH
1613 limit with a '+' appended to the count. */
1614
1615 sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_crashes),
1616 (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
1617
1618 u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time);
1619 SAYF(bV bSTOP
1620 " last ordered pizza : " cRST "%-33s " bSTG bV bSTOP
1621 " at table : %s%-6s " bSTG bV "\n",
1622 time_tmp, crash_color, tmp);
1623
1624 sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_hangs),
1625 (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
1626
1627 u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time);
1628 SAYF(bV bSTOP
1629 " last conversation with customers : " cRST "%-33s " bSTG bV bSTOP
1630 " number of Peroni : " cRST "%-6s " bSTG bV
1631 "\n",
1632 time_tmp, tmp);
1633
1634 SAYF(bVR bH bSTOP cCYA
1635 " Baking progress " bSTG bH30 bH20 bH5 bH bX bH bSTOP cCYA
1636 " Pizzeria busyness" bSTG bH30 bH5 bH bH bVL "\n");
1637
1638 /* This gets funny because we want to print several variable-length variables
1639 together, but then cram them into a fixed-width field - so we need to
1640 put them in a temporary buffer first. */
1641
1642 sprintf(tmp, "%s%s%u (%0.01f%%)", u_stringify_int(IB(0), afl->current_entry),
1643 afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level,
1644 ((double)afl->current_entry * 100) / afl->queued_items);
1645
1646 SAYF(bV bSTOP " now baking : " cRST
1647 "%-18s " bSTG bV bSTOP,
1648 tmp);
1649
1650 sprintf(tmp, "%0.02f%% / %0.02f%%",
1651 ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.real_map_size,
1652 t_byte_ratio);
1653
1654 SAYF(" table full : %s%-19s " bSTG bV "\n",
1655 t_byte_ratio > 70
1656 ? cLRD
1657 : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST),
1658 tmp);
1659
1660 sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_items),
1661 ((double)afl->cur_skipped_items * 100) / afl->queued_items);
1662
1663 SAYF(bV bSTOP " burned pizzas : " cRST
1664 "%-18s " bSTG bV,
1665 tmp);
1666
1667 sprintf(tmp, "%0.02f bits/tuple", t_bytes ? (((double)t_bits) / t_bytes) : 0);
1668
1669 SAYF(bSTOP " count coverage : " cRST "%-19s " bSTG bV "\n",
1670 tmp);
1671
1672 SAYF(bVR bH bSTOP cCYA
1673 " Pizzas almost ready " bSTG bH30 bH20 bH2 bH bX bH bSTOP cCYA
1674 " Types of pizzas cooking " bSTG bH10 bH5 bH2 bH10 bH2 bH bVL "\n");
1675
1676 sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored),
1677 ((double)afl->queued_favored) * 100 / afl->queued_items);
1678
1679 /* Yeah... it's still going on... halp? */
1680
1681 SAYF(bV bSTOP " now preparing : " cRST
1682 "%-22s " bSTG bV bSTOP
1683 " favourite topping : " cRST "%-20s" bSTG bV
1684 "\n",
1685 afl->stage_name, tmp);
1686
1687 if (!afl->stage_max) {
1688
1689 sprintf(tmp, "%s/-", u_stringify_int(IB(0), afl->stage_cur));
1690
1691 } else {
1692
1693 sprintf(tmp, "%s/%s (%0.02f%%)", u_stringify_int(IB(0), afl->stage_cur),
1694 u_stringify_int(IB(1), afl->stage_max),
1695 ((double)afl->stage_cur) * 100 / afl->stage_max);
1696
1697 }
1698
1699 SAYF(bV bSTOP " number of pizzas : " cRST
1700 "%-23s " bSTG bV bSTOP,
1701 tmp);
1702
1703 sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov),
1704 ((double)afl->queued_with_cov) * 100 / afl->queued_items);
1705
1706 SAYF(" new pizza type seen on Instagram : " cRST "%-20s" bSTG bV "\n", tmp);
1707
1708 sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_crashes),
1709 u_stringify_int(IB(1), afl->saved_crashes),
1710 (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : "");
1711
1712 if (afl->crash_mode) {
1713
1714 SAYF(bV bSTOP " total pizzas : " cRST
1715 "%-22s " bSTG bV bSTOP
1716 " pizzas with pineapple : %s%-20s" bSTG bV "\n",
1717 u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp);
1718
1719 } else {
1720
1721 SAYF(bV bSTOP " total pizzas : " cRST
1722 "%-22s " bSTG bV bSTOP
1723 " total pizzas with pineapple : %s%-20s" bSTG bV "\n",
1724 u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp);
1725
1726 }
1727
1728 /* Show a warning about slow execution. */
1729
1730 if (afl->stats_avg_exec < 100) {
1731
1732 sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
1733 afl->stats_avg_exec < 20 ? "zzzz..." : "Gennarino is at it again!");
1734
1735 SAYF(bV bSTOP " pizza making speed : " cLRD
1736 "%-22s ",
1737 tmp);
1738
1739 } else {
1740
1741 sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec));
1742 SAYF(bV bSTOP " pizza making speed : " cRST
1743 "%-22s ",
1744 tmp);
1745
1746 }
1747
1748 sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts),
1749 u_stringify_int(IB(1), afl->saved_tmouts),
1750 (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
1751
1752 SAYF(bSTG bV bSTOP " burned pizzas : " cRST "%-20s" bSTG bV
1753 "\n",
1754 tmp);
1755
1756 /* Aaaalmost there... hold on! */
1757
1758 SAYF(bVR bH cCYA bSTOP " Promotional campaign on TikTok yields " bSTG bH30 bH2
1759 bH bH2 bX bH bSTOP cCYA
1760 " Customer type " bSTG bH5 bH2 bH30 bH2 bH bVL "\n");
1761
1762 if (unlikely(afl->custom_only)) {
1763
1764 strcpy(tmp, "oven off (custom-mutator-only mode)");
1765
1766 } else if (likely(afl->skip_deterministic)) {
1767
1768 strcpy(tmp, "oven off (default, enable with -D)");
1769
1770 } else {
1771
1772 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
1773 u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
1774 u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
1775 u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
1776 u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
1777 u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]),
1778 u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
1779
1780 }
1781
1782 SAYF(bV bSTOP
1783 " pizzas for celiac : " cRST "%-36s " bSTG bV bSTOP
1784 " levels : " cRST "%-10s " bSTG bV
1785 "\n",
1786 tmp, u_stringify_int(IB(0), afl->max_depth));
1787
1788 if (unlikely(!afl->skip_deterministic)) {
1789
1790 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
1791 u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
1792 u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
1793 u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
1794 u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
1795 u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
1796 u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
1797
1798 }
1799
1800 SAYF(bV bSTOP
1801 " pizzas for kids : " cRST "%-36s " bSTG bV bSTOP
1802 " pizzas to make : " cRST "%-10s " bSTG bV
1803 "\n",
1804 tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed));
1805
1806 if (unlikely(!afl->skip_deterministic)) {
1807
1808 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
1809 u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
1810 u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
1811 u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
1812 u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
1813 u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
1814 u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
1815
1816 }
1817
1818 SAYF(bV bSTOP
1819 " pizza bianca : " cRST "%-36s " bSTG bV bSTOP
1820 " nice table : " cRST "%-10s " bSTG bV
1821 "\n",
1822 tmp, u_stringify_int(IB(0), afl->pending_favored));
1823
1824 if (unlikely(!afl->skip_deterministic)) {
1825
1826 sprintf(tmp, "%s/%s, %s/%s, %s/%s",
1827 u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]),
1828 u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]),
1829 u_stringify_int(IB(2), afl->stage_finds[STAGE_INTEREST16]),
1830 u_stringify_int(IB(3), afl->stage_cycles[STAGE_INTEREST16]),
1831 u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]),
1832 u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32]));
1833
1834 }
1835
1836 SAYF(bV bSTOP
1837 " recurring customers : " cRST "%-36s " bSTG bV bSTOP
1838 " new customers : " cRST "%-10s " bSTG bV
1839 "\n",
1840 tmp, u_stringify_int(IB(0), afl->queued_discovered));
1841
1842 if (unlikely(!afl->skip_deterministic)) {
1843
1844 sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
1845 u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
1846 u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
1847 u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
1848 u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
1849 u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
1850 u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]),
1851 u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]),
1852 u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI]));
1853
1854 } else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
1855
1856 strcpy(tmp, "n/a");
1857
1858 } else {
1859
1860 strcpy(tmp, "18 year aniversary mode");
1861
1862 }
1863
1864 SAYF(bV bSTOP
1865 " dictionary : " cRST "%-36s " bSTG bV bSTOP
1866 " patrons from old resturant : " cRST "%-10s " bSTG bV
1867 "\n",
1868 tmp,
1869 afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported)
1870 : (u8 *)"n/a");
1871
1872 sprintf(tmp, "%s/%s, %s/%s",
1873 u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
1874 u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
1875 u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
1876 u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]));
1877
1878 SAYF(bV bSTOP " 18 year anniversary mode/cleaning : " cRST
1879 "%-36s " bSTG bV bSTOP,
1880 tmp);
1881
1882 if (t_bytes) {
1883
1884 sprintf(tmp, "%0.02f%%", stab_ratio);
1885
1886 } else {
1887
1888 strcpy(tmp, "n/a");
1889
1890 }
1891
1892 SAYF(" oven flameout : %s%-10s " bSTG bV "\n",
1893 (stab_ratio < 85 && afl->var_byte_count > 40)
1894 ? cLRD
1895 : ((afl->queued_variable &&
1896 (!afl->persistent_mode || afl->var_byte_count > 20))
1897 ? cMGN
1898 : cRST),
1899 tmp);
1900
1901 if (unlikely(afl->afl_env.afl_python_module)) {
1902
1903 sprintf(tmp, "%s/%s,",
1904 u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
1905 u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]));
1906
1907 } else {
1908
1909 strcpy(tmp, "unused,");
1910
1911 }
1912
1913 if (unlikely(afl->afl_env.afl_custom_mutator_library)) {
1914
1915 strcat(tmp, " ");
1916 strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]));
1917 strcat(tmp, "/");
1918 strcat(tmp,
1919 u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
1920 strcat(tmp, ",");
1921
1922 } else {
1923
1924 strcat(tmp, " unused,");
1925
1926 }
1927
1928 if (unlikely(afl->shm.cmplog_mode)) {
1929
1930 strcat(tmp, " ");
1931 strcat(tmp, u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]));
1932 strcat(tmp, "/");
1933 strcat(tmp, u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]));
1934 strcat(tmp, ", ");
1935 strcat(tmp, u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]));
1936 strcat(tmp, "/");
1937 strcat(tmp, u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
1938
1939 } else {
1940
1941 strcat(tmp, " unused, unused");
1942
1943 }
1944
1945 SAYF(bV bSTOP " py/custom/rq : " cRST
1946 "%-36s " bSTG bVR bH20 bH2 bH30 bH2 bH bH bRB "\n",
1947 tmp);
1948
1949 if (likely(afl->disable_trim)) {
1950
1951 sprintf(tmp, "disabled, ");
1952
1953 } else if (unlikely(!afl->bytes_trim_out)) {
1954
1955 sprintf(tmp, "n/a, ");
1956
1957 } else {
1958
1959 sprintf(tmp, "%0.02f%%/%s, ",
1960 ((double)(afl->bytes_trim_in - afl->bytes_trim_out)) * 100 /
1961 afl->bytes_trim_in,
1962 u_stringify_int(IB(0), afl->trim_execs));
1963
1964 }
1965
1966 if (likely(afl->skip_deterministic)) {
1967
1968 strcat(tmp, "disabled");
1969
1970 } else if (unlikely(!afl->blocks_eff_total)) {
1971
1972 strcat(tmp, "n/a");
1973
1974 } else {
1975
1976 u8 tmp2[128];
1977
1978 sprintf(tmp2, "%0.02f%%",
1979 ((double)(afl->blocks_eff_total - afl->blocks_eff_select)) * 100 /
1980 afl->blocks_eff_total);
1981
1982 strcat(tmp, tmp2);
1983
1984 }
1985
1986 // if (afl->custom_mutators_count) {
1987
1988 //
1989 // sprintf(tmp, "%s/%s",
1990 // u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
1991 // u_stringify_int(IB(1), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
1992 // SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp);
1993 //
1994 //} else {
1995
1996 SAYF(bV bSTOP " toilets clogged : " cRST
1997 "%-36s " bSTG bV RESET_G1,
1998 tmp);
1999
2000 //}
2001
2002 /* Provide some CPU utilization stats. */
2003
2004 if (afl->cpu_core_count) {
2005
2006 char *spacing = SP10, snap[80] = " " cLGN "Pizzaioli's busyness " cRST " ";
2007
2008 double cur_runnable = get_runnable_processes();
2009 u32 cur_utilization = cur_runnable * 100 / afl->cpu_core_count;
2010
2011 u8 *cpu_color = cCYA;
2012
2013 /* If we could still run one or more processes, use green. */
2014
2015 if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) {
2016
2017 cpu_color = cLGN;
2018
2019 }
2020
2021 /* If we're clearly oversubscribed, use red. */
2022
2023 if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; }
2024
2025 if (afl->fsrv.snapshot) { spacing = snap; }
2026
2027 #ifdef HAVE_AFFINITY
2028
2029 if (afl->cpu_aff >= 0) {
2030
2031 SAYF("%s" cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, spacing,
2032 MIN(afl->cpu_aff, 999), cpu_color, MIN(cur_utilization, (u32)999));
2033
2034 } else {
2035
2036 SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color,
2037 MIN(cur_utilization, (u32)999));
2038
2039 }
2040
2041 #else
2042
2043 SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color,
2044 MIN(cur_utilization, (u32)999));
2045
2046 #endif /* ^HAVE_AFFINITY */
2047
2048 } else {
2049
2050 SAYF("\r");
2051
2052 }
2053
2054 /* Last line */
2055 SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bH20 bH2 bH bRB bSTOP cRST RESET_G1);
2056
2057 #undef IB
2058
2059 /* Hallelujah! */
2060
2061 fflush(0);
2062
2063 }
2064
2065 /* Display quick statistics at the end of processing the input directory,
2066 plus a bunch of warnings. Some calibration stuff also ended up here,
2067 along with several hardcoded constants. Maybe clean up eventually. */
2068
2069 void show_init_stats(afl_state_t *afl) {
2070
2071 struct queue_entry *q;
2072 u32 min_bits = 0, max_bits = 0, max_len = 0, count = 0, i;
2073 u64 min_us = 0, max_us = 0;
2074 u64 avg_us = 0;
2075
2076 u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX];
2077 #define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)])
2078
2079 if (afl->total_cal_cycles) {
2080
2081 avg_us = afl->total_cal_us / afl->total_cal_cycles;
2082
2083 }
2084
2085 for (i = 0; i < afl->queued_items; i++) {
2086
2087 q = afl->queue_buf[i];
2088 if (unlikely(q->disabled)) { continue; }
2089
2090 if (!min_us || q->exec_us < min_us) { min_us = q->exec_us; }
2091 if (q->exec_us > max_us) { max_us = q->exec_us; }
2092
2093 if (!min_bits || q->bitmap_size < min_bits) { min_bits = q->bitmap_size; }
2094 if (q->bitmap_size > max_bits) { max_bits = q->bitmap_size; }
2095
2096 if (q->len > max_len) { max_len = q->len; }
2097
2098 ++count;
2099
2100 }
2101
2102 // SAYF("\n");
2103
2104 if (avg_us > ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->unicorn_mode)
2105 ? 50000
2106 : 10000)) {
2107
2108 WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
2109 doc_path);
2110
2111 }
2112
2113 /* Let's keep things moving with slow binaries. */
2114
2115 if (unlikely(afl->fixed_seed)) {
2116
2117 afl->havoc_div = 1;
2118
2119 } else if (avg_us > 50000) {
2120
2121 afl->havoc_div = 10; /* 0-19 execs/sec */
2122
2123 } else if (avg_us > 20000) {
2124
2125 afl->havoc_div = 5; /* 20-49 execs/sec */
2126
2127 } else if (avg_us > 10000) {
2128
2129 afl->havoc_div = 2; /* 50-100 execs/sec */
2130
2131 }
2132
2133 if (!afl->resuming_fuzz) {
2134
2135 if (max_len > 50 * 1024) {
2136
2137 WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!",
2138 stringify_mem_size(IB(0), max_len), doc_path);
2139
2140 } else if (max_len > 10 * 1024) {
2141
2142 WARNF("Some test cases are big (%s) - see %s/perf_tips.md.",
2143 stringify_mem_size(IB(0), max_len), doc_path);
2144
2145 }
2146
2147 if (afl->useless_at_start && !afl->in_bitmap) {
2148
2149 WARNF(cLRD "Some test cases look useless. Consider using a smaller set.");
2150
2151 }
2152
2153 if (afl->queued_items > 100) {
2154
2155 WARNF(cLRD
2156 "You probably have far too many input files! Consider trimming "
2157 "down.");
2158
2159 } else if (afl->queued_items > 20) {
2160
2161 WARNF("You have lots of input files; try starting small.");
2162
2163 }
2164
2165 }
2166
2167 OKF("Here are some useful stats:\n\n"
2168
2169 cGRA " Test case count : " cRST
2170 "%u favored, %u variable, %u ignored, %u total\n" cGRA
2171 " Bitmap range : " cRST
2172 "%u to %u bits (average: %0.02f bits)\n" cGRA
2173 " Exec timing : " cRST "%s to %s us (average: %s us)\n",
2174 afl->queued_favored, afl->queued_variable, afl->queued_items - count,
2175 afl->queued_items, min_bits, max_bits,
2176 ((double)afl->total_bitmap_size) /
2177 (afl->total_bitmap_entries ? afl->total_bitmap_entries : 1),
2178 stringify_int(IB(0), min_us), stringify_int(IB(1), max_us),
2179 stringify_int(IB(2), avg_us));
2180
2181 if (afl->timeout_given != 1) {
2182
2183 /* Figure out the appropriate timeout. The basic idea is: 5x average or
2184 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second.
2185
2186 If the program is slow, the multiplier is lowered to 2x or 3x, because
2187 random scheduler jitter is less likely to have any impact, and because
2188 our patience is wearing thin =) */
2189
2190 if (unlikely(afl->fixed_seed)) {
2191
2192 afl->fsrv.exec_tmout = avg_us * 5 / 1000;
2193
2194 } else if (avg_us > 50000) {
2195
2196 afl->fsrv.exec_tmout = avg_us * 2 / 1000;
2197
2198 } else if (avg_us > 10000) {
2199
2200 afl->fsrv.exec_tmout = avg_us * 3 / 1000;
2201
2202 } else {
2203
2204 afl->fsrv.exec_tmout = avg_us * 5 / 1000;
2205
2206 }
2207
2208 afl->fsrv.exec_tmout = MAX(afl->fsrv.exec_tmout, max_us / 1000);
2209 afl->fsrv.exec_tmout =
2210 (afl->fsrv.exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND;
2211
2212 if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) {
2213
2214 afl->fsrv.exec_tmout = EXEC_TIMEOUT;
2215
2216 }
2217
2218 ACTF("No -t option specified, so I'll use an exec timeout of %u ms.",
2219 afl->fsrv.exec_tmout);
2220
2221 afl->timeout_given = 1;
2222
2223 } else if (afl->timeout_given == 3) {
2224
2225 ACTF("Applying timeout settings from resumed session (%u ms).",
2226 afl->fsrv.exec_tmout);
2227
2228 } else {
2229
2230 ACTF("-t option specified. We'll use an exec timeout of %u ms.",
2231 afl->fsrv.exec_tmout);
2232
2233 }
2234
2235 /* In non-instrumented mode, re-running every timing out test case with a
2236 generous time
2237 limit is very expensive, so let's select a more conservative default. */
2238
2239 if (afl->non_instrumented_mode && !(afl->afl_env.afl_hang_tmout)) {
2240
2241 afl->hang_tmout = MIN((u32)EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100);
2242
2243 }
2244
2245 OKF("All set and ready to roll!");
2246 #undef IB
2247
2248 }
2249
2250