diff --git a/doc/1.docx b/doc/AFL++阅读报告.docx similarity index 65% rename from doc/1.docx rename to doc/AFL++阅读报告.docx index c37eaa2..c85cc82 100644 Binary files a/doc/1.docx and b/doc/AFL++阅读报告.docx differ diff --git a/doc/afl流程源码分析-慕容承霖.docx b/doc/afl流程源码分析-慕容承霖.docx deleted file mode 100644 index d9e4b14..0000000 Binary files a/doc/afl流程源码分析-慕容承霖.docx and /dev/null differ diff --git a/doc/afl流程源码分析-覃业斌.docx b/doc/afl流程源码分析-覃业斌.docx deleted file mode 100644 index 1f83ac9..0000000 Binary files a/doc/afl流程源码分析-覃业斌.docx and /dev/null differ diff --git a/doc/乔成炜源码部分分析.docx b/doc/乔成炜源码部分分析.docx deleted file mode 100644 index f14a3b8..0000000 Binary files a/doc/乔成炜源码部分分析.docx and /dev/null differ diff --git a/doc/李林轩_AFL源码分析_AFLanalyse.c.docx b/doc/李林轩_AFL源码分析_AFLanalyse.c.docx deleted file mode 100644 index 25d56da..0000000 Binary files a/doc/李林轩_AFL源码分析_AFLanalyse.c.docx and /dev/null differ diff --git a/src%2FAFLplusplus-stable%2Fsrc/afl-analyze.c b/src%2FAFLplusplus-stable%2Fsrc/afl-analyze.c deleted file mode 100644 index 7ebf5fc..0000000 --- a/src%2FAFLplusplus-stable%2Fsrc/afl-analyze.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* - american fuzzy lop++ - file format analyzer - ------------------------------------------- - - Originally written by Michal Zalewski - - Now maintained by Marc Heuse , - Heiko Eissfeldt and - Andrea Fioraldi - - Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2024 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - https://www.apache.org/licenses/LICENSE-2.0 - - A nifty utility that grabs an input file and takes a stab at explaining - its structure by observing how changes to it affect the execution path. - - If the output scrolls past the edge of the screen, pipe it to 'less -r'. - - */ - -#define AFL_MAIN - -#include "config.h" -#include "types.h" -#include "debug.h" -#include "alloc-inl.h" -#include "hash.h" -#include "sharedmem.h" -#include "common.h" -#include "forkserver.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifndef USEMMAP - #include -#endif -#include -#include -#include - -static u8 *in_file; /* Analyzer input test case */ - -static u8 *in_data; /* Input data for analysis */ - -static u32 in_len, /* Input data length */ - total_execs, /* Total number of execs */ - exec_hangs, /* Total number of hangs */ - exec_tmout = EXEC_TIMEOUT; /* Exec timeout (ms) */ - -static u64 orig_cksum; /* Original checksum */ - -static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ - -static bool edges_only, /* Ignore hit counts? */ - use_hex_offsets, /* Show hex offsets? */ - use_stdin = true; /* Use stdin for program input? */ - -static volatile u8 stop_soon; /* Ctrl-C pressed? */ - -static u8 *target_path; -static u8 frida_mode; -static u8 qemu_mode; -static u8 cs_mode; -static u32 map_size = MAP_SIZE; - -static afl_forkserver_t fsrv = {0}; /* The forkserver */ - -/* Constants used for describing byte behavior. */ - -#define RESP_NONE 0x00 /* Changing byte is a no-op. */ -#define RESP_MINOR 0x01 /* Some changes have no effect. */ -#define RESP_VARIABLE 0x02 /* Changes produce variable paths. */ -#define RESP_FIXED 0x03 /* Changes produce fixed patterns. */ - -#define RESP_LEN 0x04 /* Potential length field */ -#define RESP_CKSUM 0x05 /* Potential checksum */ -#define RESP_SUSPECT 0x06 /* Potential "suspect" blob */ - -/* Classify tuple counts. This is a slow & naive version, but good enough here. - */ - -//ģԵĴй鲢ڲ̫Ӱ¼㡢 -static u8 count_class_lookup[256] = { - - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 4, - [4 ... 7] = 8, - [8 ... 15] = 16, - [16 ... 31] = 32, - [32 ... 127] = 64, - [128 ... 255] = 128 - -}; - -//ӽ -static void kill_child() { - - if (fsrv.child_pid > 0) { - - //killɱӦpidӽ̣־λΪ1 - kill(fsrv.child_pid, fsrv.child_kill_signal); - //ӽ̵pidΪ-1޷ѡ - fsrv.child_pid = -1; - - } - -} - -//ڴеֽڽз࣬ͨԤcount_class_lookupʵַЧ -static void classify_counts(u8 *mem, u32 mem_size) { - - u32 i = mem_size; - //ֻԱԵ̽ҪֻΪbool - if (edges_only) { - - while (i--) { - - if (*mem) { *mem = 1; } - mem++; - - } - - } else { - - while (i--) { - - *mem = count_class_lookup[*mem]; - mem++; - - } - - } - -} - -/* See if any bytes are set in the bitmap. */ -//bitmapǷֽbitmap汻 -static inline u8 anything_set(void) { - //ʹfsrv.trace_bitsģbitmap - u32 *ptr = (u32 *)fsrv.trace_bits; - //map_sizeĴС4Ϊǰֽڽ - u32 i = (map_size >> 2); - - while (i--) { - - if (*(ptr++)) { return 1; } - - } - - return 0; - -} - -/* Get rid of temp files (atexit handler). */ -//ںʱãɾʱļ -static void at_exit_handler(void) { - - unlink(fsrv.out_file); /* Ignore errors */ - -} - -/* Read initial file. */ -//ȡҪļʼ״̬ -static void read_initial_file(void) { - - struct stat st; - s32 fd = open(in_file, O_RDONLY); - //޷ȡ֧ - if (fd < 0) { PFATAL("Unable to open '%s'", in_file); } - //ȡļΪշ֧ - if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); } - //ȡļݳֵ֧ - if (st.st_size >= TMIN_MAX_FILE) { - - FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024); - - } - - in_len = st.st_size; - in_data = ck_alloc_nozero(in_len); - - ck_read(fd, in_data, in_len, in_file); - - close(fd); - - OKF("Read %u byte%s from '%s'.", in_len, in_len == 1 ? "" : "s", in_file); - -} - -/* Execute target application. Returns exec checksum, or 0 if program - times out. */ -//һĿḷ̌ڲӰʹõǰ¶Գģ -static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) { - //óľַд뵽ջ - afl_fsrv_write_to_testcase(&fsrv, mem, len); - //ʹafl_fsrv_run_targetо̣صfsrv_run_result_t - fsrv_run_result_t ret = afl_fsrv_run_target(&fsrv, exec_tmout, &stop_soon); - - //ʧܷ֧ - if (ret == FSRV_RUN_ERROR) { - - FATAL("Error in forkserver"); - - } - //оȱʧ֧ - else if (ret == FSRV_RUN_NOINST) { - - FATAL("Target not instrumented"); - - } - //б֧ - else if (ret == FSRV_RUN_NOBITS) { - - FATAL("Failed to run target"); - - } - //classify_countsԲԽڴеֽڽз࣬һģ - classify_counts(fsrv.trace_bits, fsrv.map_size); - //ȫֱtotal_execsԲԳм¼ - total_execs++; - - if (stop_soon) { - //û˳Ctrl+C˳ʾ - SAYF(cRST cLRD "\n+++ Analysis aborted by user +++\n" cRST); - exit(1); - - } - - /* Always discard inputs that time out. */ - //гʱȫֱexec_hangsԲԳʱм¼ - if (fsrv.last_run_timed_out) { - - exec_hangs++; - return 0; - - } - //У - u64 cksum = hash64(fsrv.trace_bits, fsrv.map_size, HASH_CONST); - - if (ret == FSRV_RUN_CRASH) { - - /* We don't actually care if the target is crashing or not, - except that when it does, the checksum should be different. */ - //Уȫ1ÿλȡ - cksum ^= 0xffffffff; - - } - //¼ʼУ - if (first_run) { orig_cksum = cksum; } - - return cksum; - -} - -#ifdef USE_COLOR - -/* Helper function to display a human-readable character. */ -//ڴֽڴӡûɶַ -static void show_char(u8 val) { - - switch (val) { - - case 0 ... 32: - case 127 ... 255: - //ͨʽʵ - SAYF("#%02x", val); - break; - - default: - SAYF(" %c ", val); - - } - -} - -/* Show the legend */ -//ڴֽΪͬɫû -static void show_legend(void) { - - SAYF(" " cLGR bgGRA " 01 " cRST " - no-op block " cBLK bgLGN - " 01 " cRST - " - suspected length field\n" - " " cBRI bgGRA " 01 " cRST " - superficial content " cBLK bgYEL - " 01 " cRST - " - suspected cksum or magic int\n" - " " cBLK bgCYA " 01 " cRST " - critical stream " cBLK bgLRD - " 01 " cRST - " - suspected checksummed block\n" - " " cBLK bgMGN " 01 " cRST " - \"magic value\" section\n\n"); - -} - -#endif /* USE_COLOR */ - -/* Interpret and report a pattern in the input file. */ -//16ʽļֽΪ -static void dump_hex(u32 len, u8 *b_data) { - - u32 i; - - for (i = 0; i < len; i++) { - -#ifdef USE_COLOR - u32 rlen = 1, off; -#else - u32 rlen = 1; -#endif /* ^USE_COLOR */ - - u8 rtype = b_data[i] & 0x0f; - - /* Look ahead to determine the length of run. */ - //ȷг - while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) { - - if (rtype < (b_data[i + rlen] & 0x0f)) { - - rtype = b_data[i + rlen] & 0x0f; - - } - - rlen++; - - } - - /* Try to do some further classification based on length & value. */ - //ֽӦͽз - if (rtype == RESP_FIXED) { - - switch (rlen) { - - case 2: { - - u16 val = *(u16 *)(in_data + i); - - /* Small integers may be length fields. */ - - if (val && (val <= in_len || SWAP16(val) <= in_len)) { - //жΪг - rtype = RESP_LEN; - break; - - } - - /* Uniform integers may be checksums. */ - - if (val && abs(in_data[i] - in_data[i + 1]) > 32) { - //жΪУ - rtype = RESP_CKSUM; - break; - - } - - break; - - } - - case 4: { - //ͬ - u32 val = *(u32 *)(in_data + i); - - /* Small integers may be length fields. */ - - if (val && (val <= in_len || SWAP32(val) <= in_len)) { - - rtype = RESP_LEN; - break; - - } - - /* Uniform integers may be checksums. */ - - if (val && (in_data[i] >> 7 != in_data[i + 1] >> 7 || - in_data[i] >> 7 != in_data[i + 2] >> 7 || - in_data[i] >> 7 != in_data[i + 3] >> 7)) { - - rtype = RESP_CKSUM; - break; - - } - - break; - - } - - case 1: - case 3: - case 5 ... MAX_AUTO_EXTRA - 1: - break; - - default: - rtype = RESP_SUSPECT; - - } - - } - - /* Print out the entire run. */ - -#ifdef USE_COLOR - - for (off = 0; off < rlen; off++) { - - /* Every 16 digits, display offset. */ - //ÿ4ֽΪһ - if (!((i + off) % 16)) { - - if (off) { SAYF(cRST cLCY ">"); } - - if (use_hex_offsets) { - // - SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off); - - } else { - // - SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off); - - } - - } - - switch (rtype) { - //rtypeIJͬͣвͬɫû - case RESP_NONE: - SAYF(cLGR bgGRA); - break; - case RESP_MINOR: - SAYF(cBRI bgGRA); - break; - case RESP_VARIABLE: - SAYF(cBLK bgCYA); - break; - case RESP_FIXED: - SAYF(cBLK bgMGN); - break; - case RESP_LEN: - SAYF(cBLK bgLGN); - break; - case RESP_CKSUM: - SAYF(cBLK bgYEL); - break; - case RESP_SUSPECT: - SAYF(cBLK bgLRD); - break; - - } - // - show_char(in_data[i + off]); - - if (off != rlen - 1 && (i + off + 1) % 16) { - // - SAYF(" "); - - } else { - - SAYF(cRST " "); - - } - - } - -#else - //ûǷ16ƽĴ - if (use_hex_offsets) - SAYF(" Offset %x, length %u: ", i, rlen); - else - SAYF(" Offset %u, length %u: ", i, rlen); - - switch (rtype) { - //ԷõϢ - case RESP_NONE: - SAYF("no-op block\n"); - break; - case RESP_MINOR: - SAYF("superficial content\n"); - break; - case RESP_VARIABLE: - SAYF("critical stream\n"); - break; - case RESP_FIXED: - SAYF("\"magic value\" section\n"); - break; - case RESP_LEN: - SAYF("suspected length field\n"); - break; - case RESP_CKSUM: - SAYF("suspected cksum or magic int\n"); - break; - case RESP_SUSPECT: - SAYF("suspected checksummed block\n"); - break; - - } - -#endif /* ^USE_COLOR */ - - i += rlen - 1; - - } - -#ifdef USE_COLOR - SAYF(cRST "\n"); -#endif /* USE_COLOR */ - -} - -/* Actually analyze! */ -// -static void analyze() { - //ʼ - u32 i; - u32 boring_len = 0, prev_xff = 0, prev_x01 = 0, prev_s10 = 0, prev_a10 = 0; - - u8 *b_data = ck_alloc(in_len + 1); - u8 seq_byte = 0; - - b_data[in_len] = 0xff; /* Intentional terminator. */ - - ACTF("Analyzing input file (this may take a while)...\n"); - -#ifdef USE_COLOR - show_legend(); -#endif /* USE_COLOR */ - - for (i = 0; i < in_len; i++) { - //ÿһֽ - u64 xor_ff, xor_01, sub_10, add_10; - u8 xff_orig, x01_orig, s10_orig, a10_orig; - - /* Perform walking byte adjustments across the file. We perform four - operations designed to elicit some response from the underlying - code. */ - //Գÿֽڽ0xff0x010x100x20Ȼз鿴ǷԳвӰ - in_data[i] ^= 0xff; - xor_ff = analyze_run_target(in_data, in_len, 0); - - in_data[i] ^= 0xfe; - xor_01 = analyze_run_target(in_data, in_len, 0); - - in_data[i] = (in_data[i] ^ 0x01) - 0x10; - sub_10 = analyze_run_target(in_data, in_len, 0); - - in_data[i] += 0x20; - add_10 = analyze_run_target(in_data, in_len, 0); - in_data[i] -= 0x10; - - /* Classify current behavior. */ - //¼УͣԹ۲ǷӰ - xff_orig = (xor_ff == orig_cksum); - x01_orig = (xor_01 == orig_cksum); - s10_orig = (sub_10 == orig_cksum); - a10_orig = (add_10 == orig_cksum); - - if (xff_orig && x01_orig && s10_orig && a10_orig) { - //򽫸ֽڱΪ - b_data[i] = RESP_NONE; - boring_len++; - - } else if (xff_orig || x01_orig || s10_orig || a10_orig) { - //Ϊ - b_data[i] = RESP_MINOR; - boring_len++; - - } else if (xor_ff == xor_01 && xor_ff == sub_10 && xor_ff == add_10) { - //ͬʽ޸ĺУȣ򽫸ֽڱΪ޸ - b_data[i] = RESP_FIXED; - - } else { - //򽫸ֽڱΪ - b_data[i] = RESP_VARIABLE; - - } - - /* When all checksums change, flip most significant bit of b_data. */ - //бһֽڵIJԲһͷתλ - if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 && - prev_a10 != add_10) { - - seq_byte ^= 0x80; - - } - - b_data[i] |= seq_byte; - - prev_xff = xor_ff; - prev_x01 = xor_01; - prev_s10 = sub_10; - prev_a10 = add_10; - - } - // - dump_hex(in_len, b_data); - - SAYF("\n"); - - OKF("Analysis complete. Interesting bits: %0.02f%% of the input file.", - 100.0 - ((double)boring_len * 100) / in_len); - - if (exec_hangs) { - - WARNF(cLRD "Encountered %u timeouts - results may be skewed." cRST, - exec_hangs); - - } - - ck_free(b_data); - -} - -/* Handle Ctrl-C and the like. */ -//ûԳֹĴ -static void handle_stop_sig(int sig) { - - (void)sig; - stop_soon = 1; - - afl_fsrv_killall(); - -} - -/* Do basic preparations - persistent fds, filenames, etc. */ -//òԻ -static void set_up_environment(char **argv) { - - u8 *x; - char *afl_preload; - char *frida_afl_preload = NULL; - - fsrv.dev_null_fd = open("/dev/null", O_RDWR); - if (fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } - - if (!fsrv.out_file) { - - u8 *use_dir = "."; - - if (access(use_dir, R_OK | W_OK | X_OK)) { - - use_dir = get_afl_env("TMPDIR"); - if (!use_dir) { use_dir = "/tmp"; } - - } - - fsrv.out_file = - alloc_printf("%s/.afl-analyze-temp-%u", use_dir, (u32)getpid()); - - } - - unlink(fsrv.out_file); - fsrv.out_fd = - open(fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - - if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); } - - /* Set sane defaults... */ - x = get_afl_env("MSAN_OPTIONS"); - - if (x) { - - if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) { - - FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY( - MSAN_ERROR) " - please fix!"); - - } - - } - - set_sanitizer_defaults(); - - if (get_afl_env("AFL_PRELOAD")) { - - if (qemu_mode) { - - /* afl-qemu-trace takes care of converting AFL_PRELOAD. */ - - } else if (frida_mode) { - - afl_preload = getenv("AFL_PRELOAD"); - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - if (afl_preload) { - - frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); - - } else { - - frida_afl_preload = alloc_printf("%s", frida_binary); - - } - - ck_free(frida_binary); - - setenv("LD_PRELOAD", frida_afl_preload, 1); - setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); - - } else { - - /* CoreSight mode uses the default behavior. */ - - setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); - setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); - - } - - } else if (frida_mode) { - - u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); - setenv("LD_PRELOAD", frida_binary, 1); - setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1); - ck_free(frida_binary); - - } - - if (frida_afl_preload) { ck_free(frida_afl_preload); } - -} - -/* Setup signal handlers, duh. */ -//źŴ򣬽гʼ -static void setup_signal_handlers(void) { - - struct sigaction sa; - - sa.sa_handler = NULL; -#ifdef SA_RESTART - sa.sa_flags = SA_RESTART; -#else - sa.sa_flags = 0; -#endif - sa.sa_sigaction = NULL; - - sigemptyset(&sa.sa_mask); - - /* Various ways of saying "stop". */ - - sa.sa_handler = handle_stop_sig; - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - -} - -/* Display usage hints. */ -//û-hʱô˺Ըùߵʹ÷ -static void usage(u8 *argv0) { - - SAYF( - "\n%s [ options ] -- /path/to/target_app [ ... ]\n\n" - - "Required parameters:\n" - - " -i file - input test case to be analyzed by the tool\n\n" - - "Execution control settings:\n" - - " -f file - input file read by the tested program (stdin)\n" - " -t msec - timeout for each run (%u ms)\n" - " -m megs - memory limit for child process (%u MB)\n" -#if defined(__linux__) && defined(__aarch64__) - " -A - use binary-only instrumentation (ARM CoreSight mode)\n" -#endif - " -O - use binary-only instrumentation (FRIDA mode)\n" -#if defined(__linux__) - " -Q - use binary-only instrumentation (QEMU mode)\n" - " -U - use unicorn-based instrumentation (Unicorn mode)\n" - " -W - use qemu-based instrumentation with Wine (Wine " - "mode)\n" - " -X - use Nyx mode\n" -#endif - "\n" - - "Analysis settings:\n" - - " -e - look for edge coverage only, ignore hit counts\n\n" - - "For additional tips, please consult %s/README.md.\n\n" - - "Environment variables used:\n" - "TMPDIR: directory to use for temporary input files\n" - "ASAN_OPTIONS: custom settings for ASAN\n" - " (must contain abort_on_error=1 and symbolize=0)\n" - "MSAN_OPTIONS: custom settings for MSAN\n" - " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" - "AFL_ANALYZE_HEX: print file offsets in hexadecimal instead of decimal\n" - "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n" - " (default: SIGKILL)\n" - "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n" - " (default: SIGTERM). If unset and AFL_KILL_SIGNAL is\n" - " set, that value will be used.\n" - "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" - " the target was compiled for\n" - "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" - "AFL_SKIP_BIN_CHECK: skip checking the location of and the target\n" - , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); - - exit(1); - -} - -/* Main entry point */ -//mainûʹõʵʽӿ -int main(int argc, char **argv_orig, char **envp) { - - s32 opt; - u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; - char **use_argv; - char **argv = argv_cpy_dup(argc, argv_orig); - - doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - - SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n"); - - afl_fsrv_init(&fsrv); - - while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXYh")) > 0) { - - switch (opt) { - - case 'i': - - if (in_file) { FATAL("Multiple -i options not supported"); } - in_file = optarg; - break; - - case 'f': - - if (fsrv.out_file) { FATAL("Multiple -f options not supported"); } - fsrv.use_stdin = 0; - fsrv.out_file = ck_strdup(optarg); - break; - - case 'e': - - if (edges_only) { FATAL("Multiple -e options not supported"); } - edges_only = 1; - break; - - case 'm': { - - u8 suffix = 'M'; - - if (mem_limit_given) { FATAL("Multiple -m options not supported"); } - mem_limit_given = 1; - - if (!optarg) { FATAL("Wrong usage of -m"); } - - if (!strcmp(optarg, "none")) { - - mem_limit = 0; - fsrv.mem_limit = 0; - break; - - } - - if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || - optarg[0] == '-') { - - FATAL("Bad syntax used for -m"); - - } - - switch (suffix) { - - case 'T': - mem_limit *= 1024 * 1024; - break; - case 'G': - mem_limit *= 1024; - break; - case 'k': - mem_limit /= 1024; - break; - case 'M': - break; - - default: - FATAL("Unsupported suffix or bad syntax for -m"); - - } - - if (mem_limit < 5) { FATAL("Dangerously low value of -m"); } - - if (sizeof(rlim_t) == 4 && mem_limit > 2000) { - - FATAL("Value of -m out of range on 32-bit systems"); - - } - - fsrv.mem_limit = mem_limit; - - } - - break; - - case 't': - - if (timeout_given) { FATAL("Multiple -t options not supported"); } - timeout_given = 1; - - if (!optarg) { FATAL("Wrong usage of -t"); } - - exec_tmout = atoi(optarg); - - if (exec_tmout < 10 || optarg[0] == '-') { - - FATAL("Dangerously low value of -t"); - - } - - fsrv.exec_tmout = exec_tmout; - - break; - - case 'A': /* CoreSight mode */ - -#if !defined(__aarch64__) || !defined(__linux__) - FATAL("-A option is not supported on this platform"); -#endif - - if (cs_mode) { FATAL("Multiple -A options not supported"); } - - cs_mode = 1; - fsrv.cs_mode = cs_mode; - break; - - case 'O': /* FRIDA mode */ - - if (frida_mode) { FATAL("Multiple -O options not supported"); } - - frida_mode = 1; - fsrv.frida_mode = frida_mode; - setenv("AFL_FRIDA_INST_SEED", "1", 1); - - break; - - case 'Q': - - if (qemu_mode) { FATAL("Multiple -Q options not supported"); } - if (!mem_limit_given) { mem_limit = MEM_LIMIT_QEMU; } - - qemu_mode = 1; - fsrv.mem_limit = mem_limit; - fsrv.qemu_mode = qemu_mode; - break; - - case 'U': - - if (unicorn_mode) { FATAL("Multiple -U options not supported"); } - if (!mem_limit_given) { mem_limit = MEM_LIMIT_UNICORN; } - - unicorn_mode = 1; - fsrv.mem_limit = mem_limit; - break; - - case 'W': /* Wine+QEMU mode */ - - if (use_wine) { FATAL("Multiple -W options not supported"); } - qemu_mode = 1; - use_wine = 1; - - if (!mem_limit_given) { mem_limit = 0; } - fsrv.qemu_mode = qemu_mode; - fsrv.mem_limit = mem_limit; - - break; - - case 'Y': // fallthough -#ifdef __linux__ - case 'X': /* NYX mode */ - - if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); } - - fsrv.nyx_mode = 1; - fsrv.nyx_parent = true; - fsrv.nyx_standalone = true; - - break; -#else - case 'X': - FATAL("Nyx mode is only availabe on linux..."); - break; -#endif - - case 'h': - usage(argv[0]); - return -1; - break; - - default: - usage(argv[0]); - - } - - } - - if (optind == argc || !in_file) { usage(argv[0]); } - - map_size = get_map_size(); - fsrv.map_size = map_size; - - use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); - - check_environment_vars(envp); - - sharedmem_t shm = {0}; - - /* initialize cmplog_mode */ - shm.cmplog_mode = 0; - - atexit(at_exit_handler); - setup_signal_handlers(); - - set_up_environment(argv); - -#ifdef __linux__ - if (!fsrv.nyx_mode) { - - fsrv.target_path = find_binary(argv[optind]); - - } else { - - fsrv.target_path = ck_strdup(argv[optind]); - - } - -#else - fsrv.target_path = find_binary(argv[optind]); -#endif - - fsrv.trace_bits = afl_shm_init(&shm, map_size, 0); - detect_file_args(argv + optind, fsrv.out_file, &use_stdin); - signal(SIGALRM, kill_child); - - if (qemu_mode) { - - if (use_wine) { - - use_argv = - get_wine_argv(argv[0], &target_path, argc - optind, argv + optind); - - } else { - - use_argv = - get_qemu_argv(argv[0], &target_path, argc - optind, argv + optind); - - } - - } else if (cs_mode) { - - use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind); - -#ifdef __linux__ - - } else if (fsrv.nyx_mode) { - - fsrv.nyx_id = 0; - - u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so"); - fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); - if (fsrv.nyx_handlers == NULL) { - - FATAL("failed to initialize libnyx.so..."); - - } - - fsrv.nyx_use_tmp_workdir = true; - fsrv.nyx_bind_cpu_id = 0; - - use_argv = argv + optind; -#endif - - } else { - - use_argv = argv + optind; - - } - - SAYF("\n"); - - if (getenv("AFL_FORKSRV_INIT_TMOUT")) { - - s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT")); - if (forksrv_init_tmout < 1) { - - FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT"); - - } - - fsrv.init_tmout = (u32)forksrv_init_tmout; - - } - - configure_afl_kill_signals( - &fsrv, NULL, NULL, (fsrv.qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM); - - read_initial_file(); -#ifdef __linux__ - if (!fsrv.nyx_mode) { (void)check_binary_signatures(fsrv.target_path); } -#else - (void)check_binary_signatures(fsrv.target_path); -#endif - - ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", - mem_limit, exec_tmout, edges_only ? ", edges only" : ""); - - afl_fsrv_start(&fsrv, use_argv, &stop_soon, false); - analyze_run_target(in_data, in_len, 1); - - if (fsrv.last_run_timed_out) { - - FATAL("Target binary times out (adjusting -t may help)."); - - } - - if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) { - - FATAL("No instrumentation detected."); - - } - - analyze(); - - OKF("We're done here. Have a nice day!\n"); - - afl_shm_deinit(&shm); - afl_fsrv_deinit(&fsrv); - if (fsrv.target_path) { ck_free(fsrv.target_path); } - if (in_data) { ck_free(in_data); } - - exit(0); - -} - diff --git a/src/AFLplusplus-stable/src/注释代码---afl-fuzz-stats.c b/src/AFLplusplus-stable/src/注释代码---afl-fuzz-stats.c new file mode 100644 index 0000000..8a80b26 --- /dev/null +++ b/src/AFLplusplus-stable/src/注释代码---afl-fuzz-stats.c @@ -0,0 +1,2469 @@ +/* + american fuzzy lop++ - stats related routines + --------------------------------------------- + + Originally written by Michal Zalewski + + Now maintained by Marc Heuse , + Dominik Meier , + Andrea Fioraldi , and + Heiko Eissfeldt + + Copyright 2016, 2017 Google Inc. All rights reserved. + Copyright 2019-2024 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + https://www.apache.org/licenses/LICENSE-2.0 + + This is the real deal: the program takes an instrumented binary and + attempts a variety of basic fuzzing tricks, paying close attention to + how they affect the execution path. + + */ + +#include "afl-fuzz.h" +#include "envs.h" +#include + +// һά飬ڴ洢ģԣfuzzingIJͬ״̬Ϣ +static char fuzzing_state[4][12] = {"started :-)", "in progress", "final phase", + "finished..."}; + +// ڻȡǰģ״̬ +char *get_fuzzing_state(afl_state_t *afl) { + // ȡǰʱ䣨룩 + u64 cur_ms = get_cur_time(); + + // ϴηʱ䡣 + u64 last_find = cur_ms - afl->last_find_time; + + // 㵱ǰڵʱ䡣 + u64 cur_run_time = cur_ms - afl->start_time; + + // ܵʱ䡣 + u64 cur_total_run_time = afl->prev_run_time + cur_run_time; + + // ǷDz׮ģʽ"in progress"״̬ + if (unlikely(afl->non_instrumented_mode)) { + return fuzzing_state[1]; + } else if (unlikely(cur_run_time < + 60 * 3 * 1000 || // ǰС3ӣ + cur_total_run_time < + 60 * 5 * 1000)) { // ʱС5ӣ + // "started :-)"״̬ + return fuzzing_state[0]; + } else { + // һηռǰʱİٷֱȡ + u64 last_find_100 = 100 * last_find; + u64 percent_cur = last_find_100 / cur_run_time; + // һηռʱİٷֱȡ + u64 percent_total = last_find_100 / cur_total_run_time; + + // ǰʱİٷֱȶڵ80%"finished..."״̬ + if (unlikely(percent_cur >= 80 && percent_total >= 80)) { + return fuzzing_state[3]; + // ǰʱİٷֱȶڵ55%"final phase"״̬ + } else if (unlikely(percent_cur >= 55 && percent_total >= 55)) { + return fuzzing_state[2]; + // 򣬷"in progress"״̬ + } else { + return fuzzing_state[1]; + } + } +} + +/* дģļ */ + +// дģļ +void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { + // ڴ洢ļ顣 + u8 fn[PATH_MAX], fn2[PATH_MAX]; + + // Ŀϣļ·ļ + snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir); + FILE *f2 = create_ffile(fn2); + + // LinuxϵͳУnyxģʽĿϣ +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + nyx_load_target_hash(&afl->fsrv); + // 64λĿϣдļ + fprintf(f2, "%llx\n", afl->fsrv.nyx_target_hash64); + } else { + // 򣬼㲢дĿƵĹϣ + fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); + } +#else + // ڷLinuxϵͳУ㲢дĿƵĹϣ + fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); +#endif + // رĿϣļ + fclose(f2); + + // ģļ·ļ + snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); + FILE *f = create_ffile(fn); + u32 i; + + // д뻷ֵı⡣ + fprintf(f, "# environment variables:\n"); + // 㻷ijȡ + u32 s_afl_env = (u32)sizeof(afl_environment_variables) / + sizeof(afl_environment_variables[0]) - + 1U; + + // 顣 + for (i = 0; i < s_afl_env; ++i) { + char *val; + // ãȡֵ + if ((val = getenv(afl_environment_variables[i])) != NULL) { + // ֵдļ + fprintf(f, "%s=%s\n", afl_environment_variables[i], val); + } + } + // رļ + fclose(f); +} + + // двļ +fprintf(f, "# command line:\n"); + +// һ size_t ͵ı jѭ +size_t j; +// вб +for (i = 0; i < argc; ++i) { + // ǵһһոԷָ + if (i) fprintf(f, " "); + + // Android ϵͳУʹ memchr Ƿš +#ifdef __ANDROID__ + if (memchr(argv[i], '\'', strlen(argv[i]))) { +#else + // ڷ Android ϵͳУʹ strchr Ƿš + if (strchr(argv[i], '\'')) { +#endif + + // аţһſʼDz + fprintf(f, "'"); + // ַеÿַ + for (j = 0; j < strlen(argv[i]); j++) + // ַǵţת + if (argv[i][j] == '\'') fprintf(f, "'\"'\"'"); + // ַ + else + fprintf(f, "%c", argv[i][j]); + // ַһŽǡ + fprintf(f, "'"); + + // вţֱ + } else { + fprintf(f, "'%s'", argv[i]); + } +} +// звд롣 +fprintf(f, "\n"); + +// رļ +fclose(f); +// дĿDZ棬ñڵǰδʹá +(void)(afl_environment_deprecated); + +// һڼַ line Ƿ key ͷ +static bool starts_with(char *key, char *line) { + // ʹ strncmp Ƚ key line ǰ strlen(key) ַ + return strncmp(key, line, strlen(key)) == 0; +} + +/* ָģʱеͳļ*/ +void load_stats_file(afl_state_t *afl) { + // ļָ fڶȡͳļ + FILE *f; + // 建 bufڴ洢ļжȡС + u8 buf[MAX_LINE]; + // ָ lptrָ buf еǰС + u8 *lptr; + // ļ fnڴ洢ͳļ· + u8 fn[PATH_MAX]; + // к linenoڼ¼ȡ + u32 lineno = 0; + // ͳļ·Դļ + snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); + f = fopen(fn, "r"); + if (!f) { + // ޷ļϢء + WARNF("Unable to load stats file '%s'", fn); + return; + } + + // ѭȡļеÿһС + while ((lptr = fgets(buf, MAX_LINE, f))) { + // ÿζȡʱкŵ + lineno++; + // ʼָ lstartptr ָǰеĿʼ + u8 *lstartptr = lptr; + // ʼָ rptr ָǰеĽ + u8 *rptr = lptr + strlen(lptr) - 1; + // keystring ڴ洢еļ + u8 keystring[MAX_LINE]; + // ƶ lptr ָ룬еķǼֱ֣ðŻβ + while (*lptr != ':' && lptr < rptr) { + lptr++; + } + + // ǰǿлֻзϢһС + if (*lptr == '\n' || !*lptr) { + WARNF("Unable to read line %d of stats file", lineno); + continue; + } + + // ǰַðţʾһаֵϢ + if (*lptr == ':') { + // ð滻Ϊֵַָ + *lptr = 0; + strcpy(keystring, lstartptr); + // ƶָ뵽ֵĿʼλá + lptr++; + // ָ nptrstrtoullеת + char *nptr; + + // "run_time"ֵתΪ벢洢afl->prev_run_time + if (starts_with("run_time", keystring)) { + afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10); + } + + // "cycles_done"ֵתΪ޷ųͲ洢afl->queue_cycle + if (starts_with("cycles_done", keystring)) { + afl->queue_cycle = + strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0; + } + + // "calibration_time"ֵתΪ΢벢洢afl->calibration_time_us + if (starts_with("calibration_time", keystring)) { + afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } + + // "sync_time"ֵתΪ΢벢洢afl->sync_time_us + if (starts_with("sync_time", keystring)) { + afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } + + // "cmplog_time"ֵתΪ΢벢洢afl->cmplog_time_us + if (starts_with("cmplog_time", keystring)) { + afl->cmplog_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } + + // "trim_time"ֵתΪ΢벢洢afl->trim_time_us + if (starts_with("trim_time", keystring)) { + afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000; + } + + // "execs_done"ֵתΪ޷ųͲ洢afl->fsrv.total_execs + if (starts_with("execs_done", keystring)) { + afl->fsrv.total_execs = strtoull(lptr, &nptr, 10); + } + + // "corpus_count"ֵתΪ޷Ͳ洢afl->queued_items + if (starts_with("corpus_count", keystring)) { + u32 corpus_count = strtoul(lptr, &nptr, 10); + if (corpus_count != afl->queued_items) { + WARNF( + "queue/ has been modified -- things might not work, you're " + "on your own!"); + sleep(3); + } + } + + // "corpus_found"ֵתΪ޷Ͳ洢afl->queued_discovered + if (starts_with("corpus_found", keystring)) { + afl->queued_discovered = strtoul(lptr, &nptr, 10); + } + + // "corpus_imported"ֵתΪ޷Ͳ洢afl->queued_imported + if (starts_with("corpus_imported", keystring)) { + afl->queued_imported = strtoul(lptr, &nptr, 10); + } + + // "max_depth"ֵתΪ޷Ͳ洢afl->max_depth + if (starts_with("max_depth", keystring)) { + afl->max_depth = strtoul(lptr, &nptr, 10); + } + + // "saved_crashes"ֵתΪ޷ųͲ洢afl->saved_crashes + if (starts_with("saved_crashes", keystring)) { + afl->saved_crashes = strtoull(lptr, &nptr, 10); + } + + // "saved_hangs"ֵתΪ޷ųͲ洢afl->saved_hangs + if (starts_with("saved_hangs", keystring)) { + afl->saved_hangs = strtoull(lptr, &nptr, 10); + } + } + + // бıϢдREADMEļ + if (afl->saved_crashes) { write_crash_readme(afl); } + + // + return; + } + /* Update stats file for unattended monitoring. */ + +// д AFL++ ͳϢļ + void write_stats_file(afl_state_t * afl, u32 t_bytes, double bitmap_cvg, + double stability, double eps) { +#ifndef __HAIKU__ + // ڷ Haiku ϵͳУȡӽ̵Դʹ + struct rusage rus; +#endif + + // ȡǰʱ䡣 + u64 cur_time = get_cur_time(); + // ʱյͳļ + u8 fn_tmp[PATH_MAX], fn_final[PATH_MAX]; + // ļָ롣 + FILE *f; + + // ʱͳļ· + snprintf(fn_tmp, PATH_MAX, "%s/.fuzzer_stats_tmp", afl->out_dir); + // ͳļ· + snprintf(fn_final, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); + // ʱͳļ + f = create_ffile(fn_tmp); + + // ûṩ bitmap_cvg, stability, epsʹһεֵ + if (!bitmap_cvg && !stability && !eps) { + bitmap_cvg = afl->last_bitmap_cvg; + stability = afl->last_stability; + } else { + // һεֵ + afl->last_bitmap_cvg = bitmap_cvg; + afl->last_stability = stability; + afl->last_eps = eps; + } + + // ϴθƽִдʱ䳬60룬ǵһθ£ƽִд + if (unlikely(!afl->last_avg_exec_update || + cur_time - afl->last_avg_exec_update >= 60000)) { + afl->last_avg_execs_saved = + (double)(1000 * (afl->fsrv.total_execs - afl->last_avg_execs)) / + (double)(cur_time - afl->last_avg_exec_update); + afl->last_avg_execs = afl->fsrv.total_execs; + afl->last_avg_exec_update = cur_time; + } + +#ifndef __HAIKU__ + // ڷ Haiku + // ϵͳУȡӽ̵ԴʹʧڴʹΪ0 + if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; } +#endif + // ʱ䣨룩 + u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time; + // ܿʱ䣨룩 + u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us + + afl->trim_time_us + afl->cmplog_time_us) / + 1000; + // ʱΪ0Ϊ1Ա0Ĵ + if (!runtime_ms) { runtime_ms = 1; } + + // дͳϢļ + fprintf(f, "start_time : %llu\n" /* ... ͳϢ ... */, + /* б */); + + // Դ󣬼ִС + + // ˵ģʽдĵϢ + if (afl->debug) { + u32 i = 0; + fprintf(f, "virgin_bytes :"); + // virgin_bits 飬д0xffֵ + for (i = 0; i < afl->fsrv.real_map_size; i++) { + if (afl->virgin_bits[i] != 0xff) { + fprintf(f, " %u[%02x]", i, afl->virgin_bits[i]); + } + } + fprintf(f, "\n"); + fprintf(f, "var_bytes :"); + // var_bytes 飬д0ֵ + for (i = 0; i < afl->fsrv.real_map_size; i++) { + if (afl->var_bytes[i]) { fprintf(f, " %u", i); } + } + fprintf(f, "\n"); + } + + // رļ + fclose(f); + // ʱļΪļ + rename(fn_tmp, fn_final); + } + +#ifdef INTROSPECTION + // деͳϢ + void write_queue_stats(afl_state_t * afl) { + FILE *f; + // ļ· + u8 *fn = alloc_printf("%s/queue_data", afl->out_dir); + // Դļ + if ((f = fopen(fn, "w")) != NULL) { + u32 id; + // дб⡣ + fprintf( + f, + "# filename, length, exec_us, selected, skipped, mutations, finds, " + "crashes, timeouts, bitmap_size, perf_score, weight, colorized, " + "favored, disabled\n"); + // еÿĿ + for (id = 0; id < afl->queued_items; ++id) { + struct queue_entry *q = afl->queue_buf[id]; + // дĿͳϢ + fprintf(f, "\"%s\",%u,%llu,%u,%u,%llu,%u,%u,%u,%u,%.3f,%.3f,%u,%u,%u\n", + q->fname, q->len, q->exec_us, q->stats_selected, + q->stats_skipped, q->stats_mutated, q->stats_finds, + q->stats_crashes, q->stats_tmouts, q->bitmap_size, + q->perf_score, q->weight, q->colorized, q->favored, + q->disabled); + } + + // رļ + fclose(f); + } + + // ͷļַڴ档 + ck_free(fn); + } +#endif + +/* Update the plot file if there is a reason to. */ + +// ڸܸ»ͼļ + void maybe_update_plot_file(afl_state_t * afl, u32 t_bytes, double bitmap_cvg, + double eps) { + // ҪUI߳򼴽ֹͣͳûб仯ʱС60룬򲻸»ͼļ + if (unlikely(!afl->force_ui_update && + (afl->stop_soon || + (afl->plot_prev_qp == afl->queued_items && + afl->plot_prev_pf == afl->pending_favored && + afl->plot_prev_pnf == afl->pending_not_fuzzed && + afl->plot_prev_ce == afl->current_entry && + afl->plot_prev_qc == afl->queue_cycle && + afl->plot_prev_uc == afl->saved_crashes && + afl->plot_prev_uh == afl->saved_hangs && + afl->plot_prev_md == afl->max_depth && + afl->plot_prev_ed == afl->fsrv.total_execs) || + !afl->queue_cycle || + get_cur_time() - afl->start_time <= 60000))) { + return; + } + + // »ͼļеһͳݡ + afl->plot_prev_qp = afl->queued_items; + afl->plot_prev_pf = afl->pending_favored; + afl->plot_prev_pnf = afl->pending_not_fuzzed; + afl->plot_prev_ce = afl->current_entry; + afl->plot_prev_qc = afl->queue_cycle; + afl->plot_prev_uc = afl->saved_crashes; + afl->plot_prev_uh = afl->saved_hangs; + afl->plot_prev_md = afl->max_depth; + afl->plot_prev_ed = afl->fsrv.total_execs; + + /* ڻͼļм¼ֶΣ + + relative_time, cycles_done, cur_item, corpus_count, corpus_not_fuzzed, + favored_not_fuzzed, saved_crashes, saved_hangs, max_depth, + execs_per_sec, edges_found */ + + // дͳݵͼļ + fprintf(afl->fsrv.plot_file, + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, " + "%llu, %u\n", + ((afl->prev_run_time + get_cur_time() - afl->start_time) / 1000), + afl->queue_cycle - 1, afl->current_entry, afl->queued_items, + afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg, + afl->saved_crashes, afl->saved_hangs, afl->max_depth, eps, + afl->plot_prev_ed, t_bytes); /* ignore errors */ + + // ȷдļ + fflush(afl->fsrv.plot_file); + } + + /* ¼ȷԽ׶εЧ */ + + // ڼ¼ȷԽ׶εЧݡ + void plot_profile_data(afl_state_t * afl, struct queue_entry * q) { + // ȡǰʱ䣨룩 + u64 current_ms = get_cur_time() - afl->start_time; + + // 㵱ǰı255ֽڣ + u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits); + // ȷԷʡ + double det_finding_rate = (double)afl->havoc_prof->total_det_edge * 100.0 / + (double)current_edges, + det_time_rate = (double)afl->havoc_prof->total_det_time * 100.0 / + (double)current_ms; + + // ʼδȷλ + u32 ndet_bits = 0; + // skipdet_g->virgin_det_bits 飬δȷλ + for (u32 i = 0; i < afl->fsrv.map_size; i++) { + if (afl->skipdet_g->virgin_det_bits[i]) ndet_bits += 1; + } + + // ȷģʡ + double det_fuzzed_rate = (double)ndet_bits * 100.0 / (double)current_edges; + + // дȷԽ׶εЧݵļ + fprintf(afl->fsrv.det_plot_file, + "[%02lld:%02lld:%02lld] fuzz %d (%d), find %d/%d among %d(%02.2f) " + "and spend %lld/%lld(%02.2f), cover %02.2f yet, %d/%d undet bits, " + "continue %d.\n", + current_ms / 1000 / 3600, (current_ms / 1000 / 60) % 60, + (current_ms / 1000) % 60, afl->current_entry, q->fuzz_level, + afl->havoc_prof->edge_det_stage, afl->havoc_prof->edge_havoc_stage, + current_edges, det_finding_rate, + afl->havoc_prof->det_stage_time / 1000, + afl->havoc_prof->havoc_stage_time / 1000, det_time_rate, + det_fuzzed_rate, q->skipdet_e->undet_bits, + afl->skipdet_g->undet_bits_threshold, q->skipdet_e->continue_inf); + + // ȷдļ + fflush(afl->fsrv.det_plot_file); + } + +/* Check terminal dimensions after resize. */ + +static void check_term_size(afl_state_t *afl) { + + struct winsize ws; + + afl->term_too_small = 0; + + if (ioctl(1, TIOCGWINSZ, &ws)) { return; } + + if (ws.ws_row == 0 || ws.ws_col == 0) { return; } + if (ws.ws_row < 24 || ws.ws_col < 79) { afl->term_too_small = 1; } + +} + +/* A spiffy retro stats screen! This is called every afl->stats_update_freq + execve() calls, plus in several other circumstances. */ + +void show_stats(afl_state_t *afl) { + + if (afl->pizza_is_served) { + + show_stats_pizza(afl); + + } else { + + show_stats_normal(afl); + + } + +} + +void show_stats_normal(afl_state_t *afl) { + + double t_byte_ratio, stab_ratio; + + u64 cur_ms; + u32 t_bytes, t_bits; + + static u8 banner[128]; + u32 banner_len, banner_pad; + u8 tmp[256]; + u8 time_tmp[64]; + + u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX]; +#define IB(i) (val_buf[(i)]) + + cur_ms = get_cur_time(); + + if (afl->most_time_key && afl->queue_cycle) { + + if (afl->most_time * 1000 + afl->sync_time_us / 1000 < + cur_ms - afl->start_time) { + + afl->most_time_key = 2; + afl->stop_soon = 2; + + } + + } + + if (afl->most_execs_key == 1 && afl->queue_cycle) { + + if (afl->most_execs <= afl->fsrv.total_execs) { + + afl->most_execs_key = 2; + afl->stop_soon = 2; + + } + + } + + /* If not enough time has passed since last UI update, bail out. */ + + if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ && + !afl->force_ui_update) { + + return; + + } + + /* Check if we're past the 10 minute mark. */ + + if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; } + + /* Calculate smoothed exec speed stats. */ + + if (unlikely(!afl->stats_last_execs)) { + + if (likely(cur_ms != afl->start_time)) { + + afl->stats_avg_exec = ((double)afl->fsrv.total_execs) * 1000 / + (afl->prev_run_time + cur_ms - afl->start_time); + + } + + } else { + + if (likely(cur_ms != afl->stats_last_ms)) { + + double cur_avg = + ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * 1000 / + (cur_ms - afl->stats_last_ms); + + /* If there is a dramatic (5x+) jump in speed, reset the indicator + more quickly. */ + + if (cur_avg * 5 < afl->stats_avg_exec || + cur_avg / 5 > afl->stats_avg_exec) { + + afl->stats_avg_exec = cur_avg; + + } + + afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + + cur_avg * (1.0 / AVG_SMOOTHING); + + } + + } + + afl->stats_last_ms = cur_ms; + afl->stats_last_execs = afl->fsrv.total_execs; + + /* Tell the callers when to contact us (as measured in execs). */ + + afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10); + if (!afl->stats_update_freq) { afl->stats_update_freq = 1; } + + /* Do some bitmap stats. */ + + t_bytes = count_non_255_bytes(afl, afl->virgin_bits); + t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.real_map_size; + + if (unlikely(t_bytes > afl->fsrv.real_map_size)) { + + if (unlikely(!afl->afl_env.afl_ignore_problems)) { + + FATAL( + "Incorrect fuzzing setup detected. Your target seems to have loaded " + "incorrectly instrumented shared libraries (%u of %u/%u). If you use " + "LTO mode " + "please see instrumentation/README.lto.md. To ignore this problem " + "and continue fuzzing just set 'AFL_IGNORE_PROBLEMS=1'.\n", + t_bytes, afl->fsrv.real_map_size, afl->fsrv.map_size); + + } + + } + + if (likely(t_bytes) && unlikely(afl->var_byte_count)) { + + stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes); + + } else { + + stab_ratio = 100; + + } + + /* Roughly every minute, update fuzzer stats and save auto tokens. */ + + if (unlikely( + !afl->non_instrumented_mode && + (afl->force_ui_update || cur_ms - afl->stats_last_stats_ms > + afl->stats_file_update_freq_msecs))) { + + afl->stats_last_stats_ms = cur_ms; + write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio, + afl->stats_avg_exec); + save_auto(afl); + write_bitmap(afl); + + } + + if (unlikely(afl->afl_env.afl_statsd)) { + + if (unlikely(afl->force_ui_update || cur_ms - afl->statsd_last_send_ms > + STATSD_UPDATE_SEC * 1000)) { + + /* reset counter, even if send failed. */ + afl->statsd_last_send_ms = cur_ms; + if (statsd_send_metric(afl)) { WARNF("could not send statsd metric."); } + + } + + } + + /* Every now and then, write plot data. */ + + if (unlikely(afl->force_ui_update || + cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000)) { + + afl->stats_last_plot_ms = cur_ms; + maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec); + + } + + /* Every now and then, write queue data. */ + + if (unlikely(afl->force_ui_update || + cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) { + + afl->stats_last_queue_ms = cur_ms; +#ifdef INTROSPECTION + write_queue_stats(afl); +#endif + + } + + /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ + + if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 && + !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)) { + + afl->stop_soon = 2; + + } + + /* AFL_EXIT_ON_TIME. */ + + /* If no coverage was found yet, check whether run time is greater than + * exit_on_time. */ + + if (unlikely(!afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && + ((afl->last_find_time && + (cur_ms - afl->last_find_time) > afl->exit_on_time) || + (!afl->last_find_time && + (cur_ms - afl->start_time) > afl->exit_on_time)))) { + + afl->stop_soon = 2; + + } + + if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) { + + afl->stop_soon = 2; + + } + + /* If we're not on TTY, bail out. */ + + if (afl->not_on_tty) { return; } + + /* If we haven't started doing things, bail out. */ + + if (unlikely(!afl->queue_cur)) { return; } + + /* Compute some mildly useful bitmap stats. */ + + t_bits = (afl->fsrv.map_size << 3) - count_bits(afl, afl->virgin_bits); + + /* Now, for the visuals... */ + + if (afl->clear_screen) { + + SAYF(TERM_CLEAR CURSOR_HIDE); + afl->clear_screen = 0; + + check_term_size(afl); + + } + + SAYF(TERM_HOME); + + if (unlikely(afl->term_too_small)) { + + SAYF(cBRI + "Your terminal is too small to display the UI.\n" + "Please resize terminal window to at least 79x24.\n" cRST); + + return; + + } + + /* Let's start by drawing a centered banner. */ + if (unlikely(!banner[0])) { + + char *si = ""; + char *fuzzer_name; + + if (afl->sync_id) { si = afl->sync_id; } + memset(banner, 0, sizeof(banner)); + + banner_len = strlen(VERSION) + strlen(si) + strlen(afl->power_name) + 4 + 6; + + if (afl->crash_mode) { + + fuzzer_name = "peruvian were-rabbit"; + + } else { + + fuzzer_name = "american fuzzy lop"; + if (banner_len + strlen(fuzzer_name) + strlen(afl->use_banner) > 75) { + + fuzzer_name = "AFL"; + + } + + } + + banner_len += strlen(fuzzer_name); + + if (strlen(afl->use_banner) + banner_len > 75) { + + afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76; + memset(afl->use_banner, '.', 3); + + } + + banner_len += strlen(afl->use_banner); + banner_pad = (79 - banner_len) / 2; + memset(banner, ' ', banner_pad); + +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN + "[%s] - Nyx", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, + afl->power_name); + + } else { + +#endif + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN : cYEL, fuzzer_name, si, afl->use_banner, + afl->power_name); + +#ifdef __linux__ + + } + +#endif + + if (banner_pad) + for (u32 i = 0; i < banner_pad; ++i) + strcat(banner, " "); + + } + + SAYF("\n%s\n", banner); + + /* "Handy" shortcuts for drawing boxes... */ + +#define bSTG bSTART cGRA +#define bH2 bH bH +#define bH5 bH2 bH2 bH +#define bH10 bH5 bH5 +#define bH20 bH10 bH10 +#define bH30 bH20 bH10 +#define SP5 " " +#define SP10 SP5 SP5 +#define SP20 SP10 SP10 + + /* Since `total_crashes` does not get reloaded from disk on restart, + it indicates if we found crashes this round already -> paint red. + If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */ + char *crash_color = afl->total_crashes ? cLRD + : afl->saved_crashes ? cYEL + : cRST; + + /* Lord, forgive me this. */ + + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA + " overall results " bSTG bH2 bH2 bRT "\n"); + + if (afl->non_instrumented_mode) { + + strcpy(tmp, cRST); + + } else { + + u64 min_wo_finds = (cur_ms - afl->last_find_time) / 1000 / 60; + + /* First queue cycle: don't stop now! */ + if (afl->queue_cycle == 1 || min_wo_finds < 15) { + + strcpy(tmp, cMGN); + + } else + + /* Subsequent cycles, but we're still making finds. */ + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + + strcpy(tmp, cYEL); + + } else + + /* No finds for a long time and no test cases to try. */ + if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && + min_wo_finds > 120) { + + strcpy(tmp, cLGN); + + /* Default: cautiously OK to stop? */ + + } else { + + strcpy(tmp, cLBL); + + } + + } + + u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time); + SAYF(bV bSTOP " run time : " cRST "%-33s " bSTG bV bSTOP + " cycles done : %s%-5s " bSTG bV "\n", + time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1)); + + /* We want to warn people about not seeing new paths after a full cycle, + except when resuming fuzzing or running in non-instrumented mode. */ + + if (!afl->non_instrumented_mode && + (afl->last_find_time || afl->resuming_fuzz || afl->queue_cycle == 1 || + afl->in_bitmap || afl->crash_mode)) { + + u_stringify_time_diff(time_tmp, cur_ms, afl->last_find_time); + SAYF(bV bSTOP " last new find : " cRST "%-33s ", time_tmp); + + } else { + + if (afl->non_instrumented_mode) { + + SAYF(bV bSTOP " last new find : " cPIN "n/a" cRST + " (non-instrumented mode) "); + + } else { + + SAYF(bV bSTOP " last new find : " cRST "none yet " cLRD + "(odd, check syntax!) "); + + } + + } + + SAYF(bSTG bV bSTOP " corpus count : " cRST "%-5s " bSTG bV "\n", + u_stringify_int(IB(0), afl->queued_items)); + + /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH + limit with a '+' appended to the count. */ + + sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_crashes), + (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time); + SAYF(bV bSTOP "last saved crash : " cRST "%-33s " bSTG bV bSTOP + "saved crashes : %s%-6s" bSTG bV "\n", + time_tmp, crash_color, tmp); + + sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_hangs), + (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + + u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time); + SAYF(bV bSTOP " last saved hang : " cRST "%-33s " bSTG bV bSTOP + " saved hangs : " cRST "%-6s" bSTG bV "\n", + time_tmp, tmp); + + SAYF(bVR bH bSTOP cCYA + " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA + " map coverage" bSTG bHT bH20 bH2 bVL "\n"); + + /* This gets funny because we want to print several variable-length variables + together, but then cram them into a fixed-width field - so we need to + put them in a temporary buffer first. */ + + sprintf(tmp, "%s%s%u (%0.01f%%)", u_stringify_int(IB(0), afl->current_entry), + afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level, + ((double)afl->current_entry * 100) / afl->queued_items); + + SAYF(bV bSTOP " now processing : " cRST "%-18s " bSTG bV bSTOP, tmp); + + sprintf(tmp, "%0.02f%% / %0.02f%%", + ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.real_map_size, + t_byte_ratio); + + SAYF(" map density : %s%-19s" bSTG bV "\n", + t_byte_ratio > 70 + ? cLRD + : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST), + tmp); + + sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_items), + ((double)afl->cur_skipped_items * 100) / afl->queued_items); + + SAYF(bV bSTOP " runs timed out : " cRST "%-18s " bSTG bV, tmp); + + sprintf(tmp, "%0.02f bits/tuple", t_bytes ? (((double)t_bits) / t_bytes) : 0); + + SAYF(bSTOP " count coverage : " cRST "%-19s" bSTG bV "\n", tmp); + + SAYF(bVR bH bSTOP cCYA + " stage progress " bSTG bH10 bH5 bH2 bH2 bH2 bX bH bSTOP cCYA + " findings in depth " bSTG bH10 bH5 bH2 bVL "\n"); + + sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), + ((double)afl->queued_favored) * 100 / afl->queued_items); + + /* Yeah... it's still going on... halp? */ + + SAYF(bV bSTOP " now trying : " cRST "%-22s " bSTG bV bSTOP + " favored items : " cRST "%-20s" bSTG bV "\n", + afl->stage_name, tmp); + + if (!afl->stage_max) { + + sprintf(tmp, "%s/-", u_stringify_int(IB(0), afl->stage_cur)); + + } else { + + sprintf(tmp, "%s/%s (%0.02f%%)", u_stringify_int(IB(0), afl->stage_cur), + u_stringify_int(IB(1), afl->stage_max), + ((double)afl->stage_cur) * 100 / afl->stage_max); + + } + + SAYF(bV bSTOP " stage execs : " cRST "%-23s" bSTG bV bSTOP, tmp); + + sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov), + ((double)afl->queued_with_cov) * 100 / afl->queued_items); + + SAYF(" new edges on : " cRST "%-20s" bSTG bV "\n", tmp); + + sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_crashes), + u_stringify_int(IB(1), afl->saved_crashes), + (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + if (afl->crash_mode) { + + SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP + " new crashes : %s%-20s" bSTG bV "\n", + u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); + + } else { + + SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP + " total crashes : %s%-20s" bSTG bV "\n", + u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); + + } + + /* Show a warning about slow execution. */ + + if (afl->stats_avg_exec < 100) { + + sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec), + afl->stats_avg_exec < 20 ? "zzzz..." : "slow!"); + + SAYF(bV bSTOP " exec speed : " cLRD "%-22s ", tmp); + + } else { + + sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec)); + SAYF(bV bSTOP " exec speed : " cRST "%-22s ", tmp); + + } + + sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts), + u_stringify_int(IB(1), afl->saved_tmouts), + (afl->saved_tmouts >= KEEP_UNIQUE_HANG) ? "+" : ""); + + SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-20s" bSTG bV "\n", tmp); + + /* Aaaalmost there... hold on! */ + + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bH2 bHT bH10 bH2 + bH bHB bH bSTOP cCYA " item geometry " bSTG bH5 bH2 bVL "\n"); + + if (unlikely(afl->custom_only)) { + + strcpy(tmp, "disabled (custom-mutator-only mode)"); + + } else if (likely(afl->skip_deterministic)) { + + strcpy(tmp, "disabled (-z switch used)"); + + } else { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4])); + + } + + SAYF(bV bSTOP " bit flips : " cRST "%-36s " bSTG bV bSTOP + " levels : " cRST "%-10s" bSTG bV "\n", + tmp, u_stringify_int(IB(0), afl->max_depth)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32])); + + } + + SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP + " pending : " cRST "%-10s" bSTG bV "\n", + tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32])); + + } + + SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP + " pend fav : " cRST "%-10s" bSTG bV "\n", + tmp, u_stringify_int(IB(0), afl->pending_favored)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_INTEREST16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_INTEREST16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32])); + + } + + SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP + " own finds : " cRST "%-10s" bSTG bV "\n", + tmp, u_stringify_int(IB(0), afl->queued_discovered)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]), + u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]), + u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI])); + + } else if (unlikely(!afl->extras_cnt || afl->custom_only)) { + + strcpy(tmp, "n/a"); + + } else { + + strcpy(tmp, "havoc mode"); + + } + + SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP + " imported : " cRST "%-10s" bSTG bV "\n", + tmp, + afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) + : (u8 *)"n/a"); + + sprintf(tmp, "%s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]), + u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]), + u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]), + u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE])); + + SAYF(bV bSTOP "havoc/splice : " cRST "%-36s " bSTG bV bSTOP, tmp); + + if (t_bytes) { + + sprintf(tmp, "%0.02f%%", stab_ratio); + + } else { + + strcpy(tmp, "n/a"); + + } + + SAYF(" stability : %s%-10s" bSTG bV "\n", + (stab_ratio < 85 && afl->var_byte_count > 40) + ? cLRD + : ((afl->queued_variable && + (!afl->persistent_mode || afl->var_byte_count > 20)) + ? cMGN + : cRST), + tmp); + + if (unlikely(afl->afl_env.afl_python_module)) { + + sprintf(tmp, "%s/%s,", + u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON])); + + } else { + + strcpy(tmp, "unused,"); + + } + + if (unlikely(afl->afl_env.afl_custom_mutator_library)) { + + strcat(tmp, " "); + strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR])); + strcat(tmp, "/"); + strcat(tmp, + u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); + strcat(tmp, ","); + + } else { + + strcat(tmp, " unused,"); + + } + + if (unlikely(afl->shm.cmplog_mode)) { + + strcat(tmp, " "); + strcat(tmp, u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION])); + strcat(tmp, "/"); + strcat(tmp, u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION])); + strcat(tmp, ", "); + strcat(tmp, u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS])); + strcat(tmp, "/"); + strcat(tmp, u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS])); + + } else { + + strcat(tmp, " unused, unused"); + + } + + SAYF(bV bSTOP "py/custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n", + tmp); + + if (likely(afl->disable_trim)) { + + sprintf(tmp, "disabled, "); + + } else if (unlikely(!afl->bytes_trim_out || + + afl->bytes_trim_in <= afl->bytes_trim_out)) { + + sprintf(tmp, "n/a, "); + + } else { + + sprintf(tmp, "%0.02f%%/%s, ", + ((double)(afl->bytes_trim_in - afl->bytes_trim_out)) * 100 / + afl->bytes_trim_in, + u_stringify_int(IB(0), afl->trim_execs)); + + } + + if (likely(afl->skip_deterministic)) { + + strcat(tmp, "disabled"); + + } else if (unlikely(!afl->blocks_eff_total || + + afl->blocks_eff_select >= afl->blocks_eff_total)) { + + strcat(tmp, "n/a"); + + } else { + + u8 tmp2[128]; + + sprintf(tmp2, "%0.02f%%", + ((double)(afl->blocks_eff_total - afl->blocks_eff_select)) * 100 / + afl->blocks_eff_total); + + strcat(tmp, tmp2); + + } + + // if (afl->custom_mutators_count) { + + // + // sprintf(tmp, "%s/%s", + // u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]), + // u_stringify_int(IB(1), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); + // SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp); + // + //} else { + + SAYF(bV bSTOP " trim/eff : " cRST "%-36s " bSTG bV RESET_G1, tmp); + + //} + + /* Provide some CPU utilization stats. */ + + if (afl->cpu_core_count) { + + char *spacing = SP10, snap[24] = " " cLGN "snapshot" cRST " "; + + double cur_runnable = get_runnable_processes(); + u32 cur_utilization = cur_runnable * 100 / afl->cpu_core_count; + + u8 *cpu_color = cCYA; + + /* If we could still run one or more processes, use green. */ + + if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) { + + cpu_color = cLGN; + + } + + /* If we're clearly oversubscribed, use red. */ + + if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; } + + if (afl->fsrv.snapshot) { spacing = snap; } + +#ifdef HAVE_AFFINITY + + if (afl->cpu_aff >= 0) { + + SAYF("%s" cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, spacing, + MIN(afl->cpu_aff, 999), cpu_color, MIN(cur_utilization, (u32)999)); + + } else { + + SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color, + MIN(cur_utilization, (u32)999)); + + } + +#else + + SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color, + MIN(cur_utilization, (u32)999)); + +#endif /* ^HAVE_AFFINITY */ + + } else { + + SAYF("\r"); + + } + + /* Last line */ + + SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP " strategy:" cPIN + " %s " bSTG bH10 cCYA bSTOP " state:" cPIN + " %s " bSTG bH2 bRB bSTOP cRST RESET_G1, + afl->fuzz_mode == 0 ? "explore" : "exploit", get_fuzzing_state(afl)); + +#undef IB + + /* Hallelujah! */ + + fflush(0); + +} + +void show_stats_pizza(afl_state_t *afl) { + + double t_byte_ratio, stab_ratio; + + u64 cur_ms; + u32 t_bytes, t_bits; + + static u8 banner[128]; + u32 banner_len, banner_pad; + u8 tmp[256]; + u8 time_tmp[64]; + + u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX]; +#define IB(i) (val_buf[(i)]) + + cur_ms = get_cur_time(); + + if (afl->most_time_key && afl->queue_cycle) { + + if (afl->most_time * 1000 + afl->sync_time_us / 1000 < + cur_ms - afl->start_time) { + + afl->most_time_key = 2; + afl->stop_soon = 2; + + } + + } + + if (afl->most_execs_key == 1 && afl->queue_cycle) { + + if (afl->most_execs <= afl->fsrv.total_execs) { + + afl->most_execs_key = 2; + afl->stop_soon = 2; + + } + + } + + /* If not enough time has passed since last UI update, bail out. */ + + if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ && + !afl->force_ui_update) { + + return; + + } + + /* Check if we're past the 10 minute mark. */ + + if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; } + + /* Calculate smoothed exec speed stats. */ + + if (unlikely(!afl->stats_last_execs)) { + + if (likely(cur_ms != afl->start_time)) { + + afl->stats_avg_exec = ((double)afl->fsrv.total_execs) * 1000 / + (afl->prev_run_time + cur_ms - afl->start_time); + + } + + } else { + + if (likely(cur_ms != afl->stats_last_ms)) { + + double cur_avg = + ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * 1000 / + (cur_ms - afl->stats_last_ms); + + /* If there is a dramatic (5x+) jump in speed, reset the indicator + more quickly. */ + + if (cur_avg * 5 < afl->stats_avg_exec || + cur_avg / 5 > afl->stats_avg_exec) { + + afl->stats_avg_exec = cur_avg; + + } + + afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + + cur_avg * (1.0 / AVG_SMOOTHING); + + } + + } + + afl->stats_last_ms = cur_ms; + afl->stats_last_execs = afl->fsrv.total_execs; + + /* Tell the callers when to contact us (as measured in execs). */ + + afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10); + if (!afl->stats_update_freq) { afl->stats_update_freq = 1; } + + /* Do some bitmap stats. */ + + t_bytes = count_non_255_bytes(afl, afl->virgin_bits); + t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.real_map_size; + + if (unlikely(t_bytes > afl->fsrv.real_map_size)) { + + if (unlikely(!afl->afl_env.afl_ignore_problems)) { + + FATAL( + "This is what happens when you speak italian to the rabbit " + "Don't speak italian to the rabbit"); + + } + + } + + if (likely(t_bytes) && unlikely(afl->var_byte_count)) { + + stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes); + + } else { + + stab_ratio = 100; + + } + + /* Roughly every minute, update fuzzer stats and save auto tokens. */ + + if (unlikely(!afl->non_instrumented_mode && + (afl->force_ui_update || + cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) { + + afl->stats_last_stats_ms = cur_ms; + write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio, + afl->stats_avg_exec); + save_auto(afl); + write_bitmap(afl); + + } + + if (unlikely(afl->afl_env.afl_statsd)) { + + if (unlikely(afl->force_ui_update || cur_ms - afl->statsd_last_send_ms > + STATSD_UPDATE_SEC * 1000)) { + + /* reset counter, even if send failed. */ + afl->statsd_last_send_ms = cur_ms; + if (statsd_send_metric(afl)) { + + WARNF("Could not order tomato sauce from statsd."); + + } + + } + + } + + /* Every now and then, write plot data. */ + + if (unlikely(afl->force_ui_update || + cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000)) { + + afl->stats_last_plot_ms = cur_ms; + maybe_update_plot_file(afl, t_bytes, t_byte_ratio, afl->stats_avg_exec); + + } + + /* Every now and then, write queue data. */ + + if (unlikely(afl->force_ui_update || + cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) { + + afl->stats_last_queue_ms = cur_ms; +#ifdef INTROSPECTION + write_queue_stats(afl); +#endif + + } + + /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ + + if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 && + !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done)) { + + afl->stop_soon = 2; + + } + + /* AFL_EXIT_ON_TIME. */ + + /* If no coverage was found yet, check whether run time is greater than + * exit_on_time. */ + + if (unlikely(!afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time && + ((afl->last_find_time && + (cur_ms - afl->last_find_time) > afl->exit_on_time) || + (!afl->last_find_time && + (cur_ms - afl->start_time) > afl->exit_on_time)))) { + + afl->stop_soon = 2; + + } + + if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) { + + afl->stop_soon = 2; + + } + + /* If we're not on TTY, bail out. */ + + if (afl->not_on_tty) { return; } + + /* If we haven't started doing things, bail out. */ + + if (unlikely(!afl->queue_cur)) { return; } + + /* Compute some mildly useful bitmap stats. */ + + t_bits = (afl->fsrv.map_size << 3) - count_bits(afl, afl->virgin_bits); + + /* Now, for the visuals... */ + + if (afl->clear_screen) { + + SAYF(TERM_CLEAR CURSOR_HIDE); + afl->clear_screen = 0; + + check_term_size(afl); + + } + + SAYF(TERM_HOME); + + if (unlikely(afl->term_too_small)) { + + SAYF(cBRI + "Our pizzeria can't host this many guests.\n" + "Please call Pizzeria Caravaggio. They have tables of at least " + "79x24.\n" cRST); + + return; + + } + + /* Let's start by drawing a centered banner. */ + if (unlikely(!banner[0])) { + + char *si = ""; + if (afl->sync_id) { si = afl->sync_id; } + memset(banner, 0, sizeof(banner)); + banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) + + strlen(afl->power_name) + 4 + 6; + + if (strlen(afl->use_banner) + banner_len > 75) { + + afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76; + memset(afl->use_banner, '.', 3); + + } + + banner_len += strlen(afl->use_banner); + banner_pad = (79 - banner_len) / 2; + memset(banner, ' ', banner_pad); + +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", + afl->crash_mode ? cPIN + "Mozzarbella Pizzeria table booking system" + : cYEL "Mozzarbella Pizzeria management system", + si, afl->use_banner, afl->power_name); + + } else { + +#endif + snprintf(banner + banner_pad, sizeof(banner) - banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN + "Mozzarbella Pizzeria table booking system" + : cYEL "Mozzarbella Pizzeria management system", + si, afl->use_banner, afl->power_name); + +#ifdef __linux__ + + } + +#endif + + } + + SAYF("\n%s\n", banner); + + /* "Handy" shortcuts for drawing boxes... */ + +#define bSTG bSTART cGRA +#define bH2 bH bH +#define bH5 bH2 bH2 bH +#define bH10 bH5 bH5 +#define bH20 bH10 bH10 +#define bH30 bH20 bH10 +#define SP5 " " +#define SP10 SP5 SP5 +#define SP20 SP10 SP10 + + /* Since `total_crashes` does not get reloaded from disk on restart, + it indicates if we found crashes this round already -> paint red. + If it's 0, but `saved_crashes` is set from a past run, paint in yellow. */ + char *crash_color = afl->total_crashes ? cLRD + : afl->saved_crashes ? cYEL + : cRST; + + /* Lord, forgive me this. */ + + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + " Mozzarbella has been proudly serving pizzas since " bSTG bH20 bH bH bH + bHB bH bSTOP cCYA " In this time, we served " bSTG bH30 bRT "\n"); + + if (afl->non_instrumented_mode) { + + strcpy(tmp, cRST); + + } else { + + u64 min_wo_finds = (cur_ms - afl->last_find_time) / 1000 / 60; + + /* First queue cycle: don't stop now! */ + if (afl->queue_cycle == 1 || min_wo_finds < 15) { + + strcpy(tmp, cMGN); + + } else + + /* Subsequent cycles, but we're still making finds. */ + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + + strcpy(tmp, cYEL); + + } else + + /* No finds for a long time and no test cases to try. */ + if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && + min_wo_finds > 120) { + + strcpy(tmp, cLGN); + + /* Default: cautiously OK to stop? */ + + } else { + + strcpy(tmp, cLBL); + + } + + } + + u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time); + SAYF(bV bSTOP + " open time : " cRST "%-37s " bSTG bV bSTOP + " seasons done : %s%-5s " bSTG bV "\n", + time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1)); + + /* We want to warn people about not seeing new paths after a full cycle, + except when resuming fuzzing or running in non-instrumented mode. */ + + if (!afl->non_instrumented_mode && + (afl->last_find_time || afl->resuming_fuzz || afl->queue_cycle == 1 || + afl->in_bitmap || afl->crash_mode)) { + + u_stringify_time_diff(time_tmp, cur_ms, afl->last_find_time); + SAYF(bV bSTOP " last pizza baked : " cRST "%-37s ", + time_tmp); + + } else { + + if (afl->non_instrumented_mode) { + + SAYF(bV bSTOP " last pizza baked : " cPIN "n/a" cRST + " (non-instrumented mode) "); + + } else { + + SAYF(bV bSTOP " last pizza baked : " cRST + "none yet " cLRD + "(odd, check Gennarino, he might be slacking!) "); + + } + + } + + SAYF(bSTG bV bSTOP " pizzas on the menu : " cRST + "%-5s " bSTG bV "\n", + u_stringify_int(IB(0), afl->queued_items)); + + /* Highlight crashes in red if found, denote going over the KEEP_UNIQUE_CRASH + limit with a '+' appended to the count. */ + + sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_crashes), + (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time); + SAYF(bV bSTOP + " last ordered pizza : " cRST "%-33s " bSTG bV bSTOP + " at table : %s%-6s " bSTG bV "\n", + time_tmp, crash_color, tmp); + + sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_hangs), + (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); + + u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time); + SAYF(bV bSTOP + " last conversation with customers : " cRST "%-33s " bSTG bV bSTOP + " number of Peroni : " cRST "%-6s " bSTG bV + "\n", + time_tmp, tmp); + + SAYF(bVR bH bSTOP cCYA + " Baking progress " bSTG bH30 bH20 bH5 bH bX bH bSTOP cCYA + " Pizzeria busyness" bSTG bH30 bH5 bH bH bVL "\n"); + + /* This gets funny because we want to print several variable-length variables + together, but then cram them into a fixed-width field - so we need to + put them in a temporary buffer first. */ + + sprintf(tmp, "%s%s%u (%0.01f%%)", u_stringify_int(IB(0), afl->current_entry), + afl->queue_cur->favored ? "." : "*", afl->queue_cur->fuzz_level, + ((double)afl->current_entry * 100) / afl->queued_items); + + SAYF(bV bSTOP " now baking : " cRST + "%-18s " bSTG bV bSTOP, + tmp); + + sprintf(tmp, "%0.02f%% / %0.02f%%", + ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.real_map_size, + t_byte_ratio); + + SAYF(" table full : %s%-19s " bSTG bV "\n", + t_byte_ratio > 70 + ? cLRD + : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST), + tmp); + + sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_items), + ((double)afl->cur_skipped_items * 100) / afl->queued_items); + + SAYF(bV bSTOP " burned pizzas : " cRST + "%-18s " bSTG bV, + tmp); + + sprintf(tmp, "%0.02f bits/tuple", t_bytes ? (((double)t_bits) / t_bytes) : 0); + + SAYF(bSTOP " count coverage : " cRST "%-19s " bSTG bV "\n", + tmp); + + SAYF(bVR bH bSTOP cCYA + " Pizzas almost ready " bSTG bH30 bH20 bH2 bH bX bH bSTOP cCYA + " Types of pizzas cooking " bSTG bH10 bH5 bH2 bH10 bH2 bH bVL "\n"); + + sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), + ((double)afl->queued_favored) * 100 / afl->queued_items); + + /* Yeah... it's still going on... halp? */ + + SAYF(bV bSTOP " now preparing : " cRST + "%-22s " bSTG bV bSTOP + " favourite topping : " cRST "%-20s" bSTG bV + "\n", + afl->stage_name, tmp); + + if (!afl->stage_max) { + + sprintf(tmp, "%s/-", u_stringify_int(IB(0), afl->stage_cur)); + + } else { + + sprintf(tmp, "%s/%s (%0.02f%%)", u_stringify_int(IB(0), afl->stage_cur), + u_stringify_int(IB(1), afl->stage_max), + ((double)afl->stage_cur) * 100 / afl->stage_max); + + } + + SAYF(bV bSTOP " number of pizzas : " cRST + "%-23s " bSTG bV bSTOP, + tmp); + + sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_with_cov), + ((double)afl->queued_with_cov) * 100 / afl->queued_items); + + SAYF(" new pizza type seen on Instagram : " cRST "%-20s" bSTG bV "\n", tmp); + + sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_crashes), + u_stringify_int(IB(1), afl->saved_crashes), + (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); + + if (afl->crash_mode) { + + SAYF(bV bSTOP " total pizzas : " cRST + "%-22s " bSTG bV bSTOP + " pizzas with pineapple : %s%-20s" bSTG bV "\n", + u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); + + } else { + + SAYF(bV bSTOP " total pizzas : " cRST + "%-22s " bSTG bV bSTOP + " total pizzas with pineapple : %s%-20s" bSTG bV "\n", + u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); + + } + + /* Show a warning about slow execution. */ + + if (afl->stats_avg_exec < 20) { + + sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec), + "zzzz..."); + + SAYF(bV bSTOP " pizza making speed : " cLRD + "%-22s ", + tmp); + + } else { + + sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec)); + SAYF(bV bSTOP " pizza making speed : " cRST + "%-22s ", + tmp); + + } + + sprintf(tmp, "%s (%s%s saved)", u_stringify_int(IB(0), afl->total_tmouts), + u_stringify_int(IB(1), afl->saved_tmouts), + (afl->saved_tmouts >= KEEP_UNIQUE_HANG) ? "+" : ""); + + SAYF(bSTG bV bSTOP " burned pizzas : " cRST "%-20s" bSTG bV + "\n", + tmp); + + /* Aaaalmost there... hold on! */ + + SAYF(bVR bH cCYA bSTOP " Promotional campaign on TikTok yields " bSTG bH30 bH2 + bH bH2 bX bH bSTOP cCYA + " Customer type " bSTG bH5 bH2 bH30 bH2 bH bVL "\n"); + + if (unlikely(afl->custom_only)) { + + strcpy(tmp, "oven off (custom-mutator-only mode)"); + + } else if (likely(afl->skip_deterministic)) { + + strcpy(tmp, "oven off (default, enable with -D)"); + + } else { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4])); + + } + + SAYF(bV bSTOP + " pizzas for celiac : " cRST "%-36s " bSTG bV bSTOP + " levels : " cRST "%-10s " bSTG bV + "\n", + tmp, u_stringify_int(IB(0), afl->max_depth)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32])); + + } + + SAYF(bV bSTOP + " pizzas for kids : " cRST "%-36s " bSTG bV bSTOP + " pizzas to make : " cRST "%-10s " bSTG bV + "\n", + tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32])); + + } + + SAYF(bV bSTOP + " pizza bianca : " cRST "%-36s " bSTG bV bSTOP + " nice table : " cRST "%-10s " bSTG bV + "\n", + tmp, u_stringify_int(IB(0), afl->pending_favored)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_INTEREST16]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_INTEREST16]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32])); + + } + + SAYF(bV bSTOP + " recurring customers : " cRST "%-36s " bSTG bV bSTOP + " new customers : " cRST "%-10s " bSTG bV + "\n", + tmp, u_stringify_int(IB(0), afl->queued_discovered)); + + if (unlikely(!afl->skip_deterministic)) { + + sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]), + u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]), + u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]), + u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]), + u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]), + u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]), + u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI])); + + } else if (unlikely(!afl->extras_cnt || afl->custom_only)) { + + strcpy(tmp, "n/a"); + + } else { + + strcpy(tmp, "18 year aniversary mode"); + + } + + SAYF(bV bSTOP + " dictionary : " cRST "%-36s " bSTG bV bSTOP + " patrons from old resturant : " cRST "%-10s " bSTG bV + "\n", + tmp, + afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) + : (u8 *)"n/a"); + + sprintf(tmp, "%s/%s, %s/%s", + u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]), + u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]), + u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]), + u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE])); + + SAYF(bV bSTOP " 18 year anniversary mode/cleaning : " cRST + "%-36s " bSTG bV bSTOP, + tmp); + + if (t_bytes) { + + sprintf(tmp, "%0.02f%%", stab_ratio); + + } else { + + strcpy(tmp, "n/a"); + + } + + SAYF(" oven flameout : %s%-10s " bSTG bV "\n", + (stab_ratio < 85 && afl->var_byte_count > 40) + ? cLRD + : ((afl->queued_variable && + (!afl->persistent_mode || afl->var_byte_count > 20)) + ? cMGN + : cRST), + tmp); + + if (unlikely(afl->afl_env.afl_python_module)) { + + sprintf(tmp, "%s/%s,", + u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]), + u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON])); + + } else { + + strcpy(tmp, "unused,"); + + } + + if (unlikely(afl->afl_env.afl_custom_mutator_library)) { + + strcat(tmp, " "); + strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR])); + strcat(tmp, "/"); + strcat(tmp, + u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); + strcat(tmp, ","); + + } else { + + strcat(tmp, " unused,"); + + } + + if (unlikely(afl->shm.cmplog_mode)) { + + strcat(tmp, " "); + strcat(tmp, u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION])); + strcat(tmp, "/"); + strcat(tmp, u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION])); + strcat(tmp, ", "); + strcat(tmp, u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS])); + strcat(tmp, "/"); + strcat(tmp, u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS])); + + } else { + + strcat(tmp, " unused, unused"); + + } + + SAYF(bV bSTOP " py/custom/rq : " cRST + "%-36s " bSTG bVR bH20 bH2 bH30 bH2 bH bH bRB "\n", + tmp); + + if (likely(afl->disable_trim)) { + + sprintf(tmp, "disabled, "); + + } else if (unlikely(!afl->bytes_trim_out)) { + + sprintf(tmp, "n/a, "); + + } else { + + sprintf(tmp, "%0.02f%%/%s, ", + ((double)(afl->bytes_trim_in - afl->bytes_trim_out)) * 100 / + afl->bytes_trim_in, + u_stringify_int(IB(0), afl->trim_execs)); + + } + + if (likely(afl->skip_deterministic)) { + + strcat(tmp, "disabled"); + + } else if (unlikely(!afl->blocks_eff_total)) { + + strcat(tmp, "n/a"); + + } else { + + u8 tmp2[128]; + + sprintf(tmp2, "%0.02f%%", + ((double)(afl->blocks_eff_total - afl->blocks_eff_select)) * 100 / + afl->blocks_eff_total); + + strcat(tmp, tmp2); + + } + + // if (afl->custom_mutators_count) { + + // + // sprintf(tmp, "%s/%s", + // u_stringify_int(IB(0), afl->stage_finds[STAGE_CUSTOM_MUTATOR]), + // u_stringify_int(IB(1), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); + // SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV RESET_G1, tmp); + // + //} else { + + SAYF(bV bSTOP " toilets clogged : " cRST + "%-36s " bSTG bV RESET_G1, + tmp); + + //} + + /* Provide some CPU utilization stats. */ + + if (afl->cpu_core_count) { + + char *spacing = SP10, snap[80] = " " cLGN "Pizzaioli's busyness " cRST " "; + + double cur_runnable = get_runnable_processes(); + u32 cur_utilization = cur_runnable * 100 / afl->cpu_core_count; + + u8 *cpu_color = cCYA; + + /* If we could still run one or more processes, use green. */ + + if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) { + + cpu_color = cLGN; + + } + + /* If we're clearly oversubscribed, use red. */ + + if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; } + + if (afl->fsrv.snapshot) { spacing = snap; } + +#ifdef HAVE_AFFINITY + + if (afl->cpu_aff >= 0) { + + SAYF("%s" cGRA "[cpu%03u:%s%3u%%" cGRA "]\r" cRST, spacing, + MIN(afl->cpu_aff, 999), cpu_color, MIN(cur_utilization, (u32)999)); + + } else { + + SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color, + MIN(cur_utilization, (u32)999)); + + } + +#else + + SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color, + MIN(cur_utilization, (u32)999)); + +#endif /* ^HAVE_AFFINITY */ + + } else { + + SAYF("\r"); + + } + + /* Last line */ + SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bH20 bH2 bH bRB bSTOP cRST RESET_G1); + +#undef IB + + /* Hallelujah! */ + + fflush(0); + +} + +/* Display quick statistics at the end of processing the input directory, + plus a bunch of warnings. Some calibration stuff also ended up here, + along with several hardcoded constants. Maybe clean up eventually. */ + +void show_init_stats(afl_state_t *afl) { + + struct queue_entry *q; + u32 min_bits = 0, max_bits = 0, max_len = 0, count = 0, i; + u64 min_us = 0, max_us = 0; + u64 avg_us = 0; + + u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX]; +#define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)]) + + if (afl->total_cal_cycles) { + + avg_us = afl->total_cal_us / afl->total_cal_cycles; + + } + + for (i = 0; i < afl->queued_items; i++) { + + q = afl->queue_buf[i]; + if (unlikely(q->disabled)) { continue; } + + if (!min_us || q->exec_us < min_us) { min_us = q->exec_us; } + if (q->exec_us > max_us) { max_us = q->exec_us; } + + if (!min_bits || q->bitmap_size < min_bits) { min_bits = q->bitmap_size; } + if (q->bitmap_size > max_bits) { max_bits = q->bitmap_size; } + + if (q->len > max_len) { max_len = q->len; } + + ++count; + + } + + // SAYF("\n"); + + if (avg_us > ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->unicorn_mode) + ? 50000 + : 10000)) { + + WARNF(cLRD + "The target binary is pretty slow! See " + "%s/fuzzing_in_depth.md#i-improve-the-speed", + doc_path); + + } + + /* Let's keep things moving with slow binaries. */ + + if (unlikely(afl->fixed_seed)) { + + afl->havoc_div = 1; + + } else if (avg_us > 50000) { + + afl->havoc_div = 10; /* 0-19 execs/sec */ + + } else if (avg_us > 20000) { + + afl->havoc_div = 5; /* 20-49 execs/sec */ + + } else if (avg_us > 10000) { + + afl->havoc_div = 2; /* 50-100 execs/sec */ + + } + + if (!afl->resuming_fuzz) { + + if (max_len > 50 * 1024) { + + WARNF(cLRD + "Some test cases are huge (%s) - see " + "%s/fuzzing_in_depth.md#i-improve-the-speed", + stringify_mem_size(IB(0), max_len), doc_path); + + } else if (max_len > 10 * 1024) { + + WARNF( + "Some test cases are big (%s) - see " + "%s/fuzzing_in_depth.md#i-improve-the-speed", + stringify_mem_size(IB(0), max_len), doc_path); + + } + + if (afl->useless_at_start && !afl->in_bitmap) { + + WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); + + } + + if (afl->queued_items > 100) { + + WARNF(cLRD + "You probably have far too many input files! Consider trimming " + "down."); + + } else if (afl->queued_items > 20) { + + WARNF("You have lots of input files; try starting small."); + + } + + } + + OKF("Here are some useful stats:\n\n" + + cGRA " Test case count : " cRST + "%u favored, %u variable, %u ignored, %u total\n" cGRA + " Bitmap range : " cRST + "%u to %u bits (average: %0.02f bits)\n" cGRA + " Exec timing : " cRST "%s to %s us (average: %s us)\n", + afl->queued_favored, afl->queued_variable, afl->queued_items - count, + afl->queued_items, min_bits, max_bits, + ((double)afl->total_bitmap_size) / + (afl->total_bitmap_entries ? afl->total_bitmap_entries : 1), + stringify_int(IB(0), min_us), stringify_int(IB(1), max_us), + stringify_int(IB(2), avg_us)); + + if (afl->timeout_given == 3) { + + ACTF("Applying timeout settings from resumed session (%u ms).", + afl->fsrv.exec_tmout); + + } else if (afl->timeout_given != 1) { + + /* Figure out the appropriate timeout. The basic idea is: 5x average or + 1x max, rounded up to EXEC_TM_ROUND ms and capped at 1 second. + + If the program is slow, the multiplier is lowered to 2x or 3x, because + random scheduler jitter is less likely to have any impact, and because + our patience is wearing thin =) */ + + if (unlikely(afl->fixed_seed)) { + + afl->fsrv.exec_tmout = avg_us * 5 / 1000; + + } else if (avg_us > 50000) { + + afl->fsrv.exec_tmout = avg_us * 2 / 1000; + + } else if (avg_us > 10000) { + + afl->fsrv.exec_tmout = avg_us * 3 / 1000; + + } else { + + afl->fsrv.exec_tmout = avg_us * 5 / 1000; + + } + + afl->fsrv.exec_tmout = MAX(afl->fsrv.exec_tmout, max_us / 1000); + afl->fsrv.exec_tmout = + (afl->fsrv.exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; + + if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) { + + afl->fsrv.exec_tmout = EXEC_TIMEOUT; + + } + + ACTF("No -t option specified, so I'll use an exec timeout of %u ms.", + afl->fsrv.exec_tmout); + + afl->timeout_given = 1; + + } else { + + ACTF("-t option specified. We'll use an exec timeout of %u ms.", + afl->fsrv.exec_tmout); + + } + + /* In non-instrumented mode, re-running every timing out test case with a + generous time + limit is very expensive, so let's select a more conservative default. */ + + if (afl->non_instrumented_mode && !(afl->afl_env.afl_hang_tmout)) { + + afl->hang_tmout = MIN((u32)EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100); + + } + + OKF("All set and ready to roll!"); +#undef IB + +} + +inline void update_calibration_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->calibration_time_us += cur - *time; + *time = cur; + +} + +inline void update_trim_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->trim_time_us += cur - *time; + *time = cur; + +} + +inline void update_sync_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->sync_time_us += cur - *time; + *time = cur; + +} + +inline void update_cmplog_time(afl_state_t *afl, u64 *time) { + + u64 cur = get_cur_time_us(); + afl->cmplog_time_us += cur - *time; + *time = cur; + +} +