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