diff --git a/src/AFLplusplus-stable/src/afl-fuzz.c b/src/AFLplusplus-stable/src/afl-fuzz.c index 7a94003..3c57cde 100644 --- a/src/AFLplusplus-stable/src/afl-fuzz.c +++ b/src/AFLplusplus-stable/src/afl-fuzz.c @@ -23,6 +23,9 @@ how they affect the execution path. */ +//慕容承霖提交 +//引入了 AFL++ 的核心头文件、CMPLog 相关头文件、通用函数头文件等。 +//根据编译选项,可能还会包含其他系统头文件,如内存映射、文件操作等。 #include "afl-fuzz.h" #include "cmplog.h" @@ -82,7 +85,9 @@ \ \ } while (0) - +//定义了与 zlib 相关的宏,用于处理压缩文件的读写操作。 +//对于苹果系统,引入了特定的头文件以支持线程优先级设置。 +//如果启用了性能分析,则声明了一个外部变量 time_spent_working 用于记录工作时间 #include #define ZLIBOPEN gzopen #define ZLIBREAD ck_gzread @@ -106,13 +111,14 @@ #ifdef PROFILING extern u64 time_spent_working; #endif - -static void at_exit() { - +//程序退出时的清理函数 +static void at_exit() {//at_exit 函数在 AFL++ 程序退出时被调用,用于清理资源和终止子进程 +//首先尝试获取环境变量 __AFL_TARGET_PID2 和 __AFL_TARGET_PID1,这些变量存储了目标进程的 PID s32 i, pid1 = 0, pid2 = 0, pgrp = -1; char *list[4] = {SHM_ENV_VAR, SHM_FUZZ_ENV_VAR, CMPLOG_SHM_ENV_VAR, NULL}; char *ptr; - +//如果找到有效的 PID,则获取其进程组 ID 并向进程组发送 SIGTERM 信号以终止整个进程组, +//然后单独向目标进程发送 SIGTERM 信号。 ptr = getenv("__AFL_TARGET_PID2"); if (ptr && *ptr && (pid2 = atoi(ptr)) > 0) { @@ -130,10 +136,11 @@ static void at_exit() { kill(pid1, SIGTERM); } - +//尝试获取环境变量 CPU_AFFINITY_ENV_VAR,如果存在且非空,则删除该文件以解除 CPU 亲和性设置 ptr = getenv(CPU_AFFINITY_ENV_VAR); if (ptr && *ptr) unlink(ptr); - +//遍历 list 数组,获取每个环境变量的值,如果存在且非空, +//则根据编译选项使用不同的共享内存删除函数(shm_unlink 或 shmctl)来删除共享内存 i = 0; while (list[i] != NULL) { @@ -173,13 +180,14 @@ static void at_exit() { pgrp = getpgid(pid1); if (pgrp > 0) { killpg(pgrp, kill_signal); } kill(pid2, kill_signal); - +//最后,获取环境变量 AFL_KILL_SIGNAL 的值作为要发送的信号类型(默认为 SIGKILL), +//然后再次检查 PID1 和 PID2,获取其进程组 ID 并向进程组发送相应的信号,单独向目标进程发送信号以确保其被终止 } } /* Display usage hints. */ - +//主要为显示说明 static void usage(u8 *argv0, int more_help) { SAYF( @@ -190,7 +198,8 @@ static void usage(u8 *argv0, int more_help) { "also see \n" " AFL_AUTORESUME)\n" " -o dir - output directory for fuzzer findings\n\n" - + //-i dir:指定输入目录,该目录包含用于模糊测试的测试用例。如果输入为 -,则表示恢复之前的模糊测试会话。 + //-o dir:指定输出目录,用于存储模糊测试过程中发现的结果。 "Execution control settings:\n" " -P strategy - set fix mutation strategy: explore (focus on new " "coverage),\n" @@ -211,6 +220,11 @@ static void usage(u8 *argv0, int more_help) { "maximum.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" +//-P strategy:设置固定的变异策略。可以选择 explore(专注于发现新覆盖率)或 exploit(专注于触发崩溃)。还可以设置在没有发现新结果时自动切换到 exploit 模式的时间(以秒为单位),并在发现新覆盖率时切换回 explore 模式。 +//-p schedule:设置功率调度策略,用于计算种子的性能得分。可选的策略包括 explore(默认)、fast、exploit、seek、rare、mmopt、coe、lin 和 quad。具体的策略选择和效果可以参考 AFL++ 的文档。 +//-f file:指定被模糊测试程序读取的文件位置,默认为标准输入或 @@。 +//-t msec:设置每次运行的超时时间(自动缩放,默认为指定的毫秒数)。可以在超时值后加上 +,表示自动计算超时时间,指定的值为最大值。 +//-m megs:设置子进程的内存限制(以兆字节为单位,默认为 0,表示不限制) #if defined(__linux__) && defined(__aarch64__) " -A - use binary-only instrumentation (ARM CoreSight mode)\n" #endif @@ -223,6 +237,12 @@ static void usage(u8 *argv0, int more_help) { #if defined(__linux__) " -X - use VM fuzzing (NYX mode - standalone mode)\n" " -Y - use VM fuzzing (NYX mode - multiple instances mode)\n" +//-A:在 ARM 架构的 Linux 系统上,使用二进制插桩(ARM CoreSight 模式)。 +//-O:使用 FRIDA 模式进行二进制插桩。 +//-Q:在 Linux 系统上,使用 QEMU 模式进行二进制插桩。 +//-U:在 Linux 系统上,使用基于 Unicorn 的插桩(Unicorn 模式)。 +//-W:在 Linux 系统上,使用基于 QEMU 和 Wine 的插桩(Wine 模式)。 +//-X 和 -Y:在 Linux 系统上,使用 VM 模糊测试(NYX 模式),分别支持独立模式和多实例模式。 #endif "\n" @@ -296,10 +316,11 @@ static void usage(u8 *argv0, int more_help) { #if defined USE_COLOR && !defined ALWAYS_COLORED #define DYN_COLOR \ "AFL_NO_COLOR or AFL_NO_COLOUR: switch colored console output off\n" + //定义了 USE_COLOR 但未定义 ALWAYS_COLORED,则定义 DYN_COLOR 宏,用于提示用户如何关闭控制台的颜色输出 #else #define DYN_COLOR #endif - +//如果定义了 AFL_PERSISTENT_RECORD,则定义 PERSISTENT_MSG 宏,用于提示用户 AFL_PERSISTENT_RECORD 环境变量的作用 #ifdef AFL_PERSISTENT_RECORD #define PERSISTENT_MSG \ "AFL_PERSISTENT_RECORD: record the last X inputs to every crash in " \ @@ -308,7 +329,7 @@ static void usage(u8 *argv0, int more_help) { #define PERSISTENT_MSG #endif - SAYF( + SAYF(//用于输出详细的帮助信息,包括 AFL++ 使用的各种环境变量及其作用。 "Environment variables used:\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n" "ASAN_OPTIONS: custom settings for ASAN\n" @@ -411,7 +432,59 @@ static void usage(u8 *argv0, int more_help) { " seconds (default: 60, minimum: 1)\n" "\n" ); - + /* + LD_BIND_LAZY:指示 AFL++ 不要为目标程序设置 LD_BIND_NOW 环境变量。 +ASAN_OPTIONS 和 MSAN_OPTIONS:用于自定义 ASAN 和 MSAN 的设置,必须包含特定的选项以确保 AFL++ 正常工作。 +AFL_AUTORESUME:如果输出目录已存在,则自动恢复模糊测试。 +AFL_BENCH_JUST_ONE 和 AFL_BENCH_UNTIL_CRASH:用于性能测试,分别表示只运行目标程序一次和在找到第一个崩溃输入后退出。 +AFL_CMPLOG_ONLY_NEW:在初始测试用例上不运行 CMPLog,适用于恢复模糊测试。 +AFL_CRASH_EXITCODE:指定 AFL++ 应解释为崩溃的子进程退出代码。 +AFL_CUSTOM_MUTATOR_LIBRARY 和 AFL_CUSTOM_MUTATOR_ONLY:用于自定义变异器库和仅使用自定义变异器。 +AFL_CYCLE_SCHEDULES:在完成一个周期后切换到不同的功率调度策略。 +AFL_DEBUG 和 AFL_DEBUG_CHILD:用于调试输出和不抑制目标程序的 stdout/stderr。 +AFL_DISABLE_REDUNDANT 和 AFL_DISABLE_TRIM:禁用冗余队列项和测试用例的修剪。 +AFL_DUMB_FORKSRV:使用没有目标反馈的 fork 服务器。 +AFL_EXIT_WHEN_DONE 和 AFL_EXIT_ON_TIME:在所有输入运行完毕且没有新发现时退出,或在指定时间内没有发现新覆盖率时退出。 +AFL_EXIT_ON_SEED_ISSUES:在种子问题时退出。 +AFL_EXPAND_HAVOC_NOW:立即启用扩展的 Havoc 模式。 +AFL_FAST_CAL:限制校准阶段为三个周期以加速。 +AFL_FORCE_UI:强制显示状态屏幕(适用于虚拟控制台)。 +AFL_FORKSRV_INIT_TMOUT:在启动时等待 fork 服务器的时间(以毫秒为单位)。 +AFL_HANG_TMOUT:覆盖超时值(以毫秒为单位)。 +AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES:不警告关于核心转储处理器的问题。 +AFL_IGNORE_PROBLEMS 和 AFL_IGNORE_PROBLEMS_COVERAGE:不因检测到不正确的设置而终止模糊测试,以及忽略相关库的覆盖率。 +AFL_IGNORE_SEED_PROBLEMS 和 AFL_IGNORE_TIMEOUTS:在种子中跳过崩溃和超时,而不是退出。 +AFL_IGNORE_UNKNOWN_ENVS:不警告未知的环境变量。 +AFL_IMPORT_FIRST:首先同步并导入来自其他模糊测试实例的测试用例。 +AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX:设置 AFL++ 产生的模糊长度的最小值和最大值。 +AFL_PIZZA_MODE:控制 AFL++ 是否在 4 月 1 日启用“披萨模式”。 +AFL_KILL_SIGNAL 和 AFL_FORK_SERVER_KILL_SIGNAL:指定在超时等情况下发送给子进程和 fork 服务器的信号 ID。 +AFL_MAP_SIZE:目标程序的共享内存大小,必须大于或等于目标程序编译时的大小。 +AFL_MAX_DET_EXTRAS:如果字典列表中的条目多于该值,则随机选择而不是使用所有条目。 +AFL_NO_AFFINITY 和 AFL_TRY_AFFINITY:不检查未使用的 CPU 核心用于模糊测试,或尝试绑定到未使用的 CPU 核心但不失败。 +AFL_NO_ARITH 和 AFL_NO_AUTODICT:在确定性阶段跳过算术变异和不加载目标程序中编译的自动字典。 +AFL_NO_CPU_RED 和 AFL_NO_FORKSRV:避免显示非常高的 CPU 使用率的红色和通过 execve 运行目标程序而不是使用 fork 服务器。 +AFL_NO_SNAPSHOT 和 AFL_NO_STARTUP_CALIBRATION:不使用快照功能和不进行初始种子校准。 +AFL_NO_WARN_INSTABILITY 和 AFL_NO_UI:不在启动校准期间警告稳定性问题和关闭状态屏幕。 +AFL_NYX_AUX_SIZE:Nyx 辅助缓冲区的大小,必须是 4096 的倍数。 +AFL_NYX_DISABLE_SNAPSHOT_MODE 和 AFL_NYX_LOG:禁用快照模式和将 NYX hprintf 消息输出到另一个文件。 +AFL_NYX_REUSE_SNAPSHOT:重用现有的 Nyx 根快照。 +AFL_PATH:AFL 支持二进制文件的路径。 +AFL_PYTHON_MODULE:使用指定的 Python 模块变异和修剪输入。 +AFL_QUIET:抑制 fork 服务器状态消息。 +AFL_POST_PROCESS_KEEP_ORIGINAL:保存后处理前的文件到队列中,但执行后处理后的文件。 +AFL_PRELOAD:目标程序的 LD_PRELOAD/DYLD_INSERT_LIBRARIES 设置。 +AFL_TARGET_ENV:传递额外的环境变量给目标程序。 +AFL_SHUFFLE_QUEUE:在启动时随机重新排序输入队列。 +AFL_SKIP_BIN_CHECK 和 AFL_SKIP_CPUFREQ:跳过 AFL 兼容性检查和不警告 CPU 时钟变化。 +AFL_STATSD 和相关变量:启用 StatsD 指标收集及其配置。 +AFL_NO_FASTRESUME 和 AFL_NO_SYNC:不读写快速恢复文件和禁用所有同步。 +AFL_SYNC_TIME 和 AFL_FINAL_SYNC:模糊测试实例之间的同步时间和退出时的最终同步。 +AFL_NO_CRASH_README:不在崩溃目录中创建 README 文件。 +AFL_TESTCACHE_SIZE 和 AFL_TMPDIR:测试用例缓存大小和输入文件生成目录。 +AFL_EARLY_FORKSERVER 和 AFL_PERSISTENT:在 AFL-clang-fast/AFL-clang-lto/AFL-gcc-fast 目标中强制早期 fork 服务器和持久模式。 +AFL_DEFER_FORKSRV:强制延迟 fork 服务器(__AFL_INIT 在共享库中)。 +AFL_FUZZER_STATS_UPDATE_INTERVAL:更新 fuzzer_stats 文件的间隔(以秒为单位)。*/ } else { SAYF( @@ -423,50 +496,56 @@ static void usage(u8 *argv0, int more_help) { #ifdef USE_PYTHON SAYF("Compiled with %s module support, see docs/custom_mutators.md\n", (char *)PYTHON_VERSION); +/* +如果定义了 USE_PYTHON,则输出 AFL++ 是使用 Python 模块支持编译的,并提示用户查看相关文档以了解如何使用自定义变异器。 +否则,输出 AFL++ 是没有 Python 模块支持编译的*/ #else SAYF("Compiled without Python module support.\n"); #endif - +/*如果定义了 AFL_PERSISTENT_RECORD,则输出 AFL++ 是使用持久记录支持编译的。 +否则,输出 AFL++ 是没有持久记录支持编译的。*/ #ifdef AFL_PERSISTENT_RECORD SAYF("Compiled with AFL_PERSISTENT_RECORD support.\n"); + #else SAYF("Compiled without AFL_PERSISTENT_RECORD support.\n"); #endif - + /*如果定义了 USEMMAP,则输出 AFL++ 是使用 shm_open 支持编译的。 +否则,输出 AFL++ 是使用 shmat 支持编译的。*/ #ifdef USEMMAP SAYF("Compiled with shm_open support.\n"); #else SAYF("Compiled with shmat support.\n"); #endif - +/*如果定义了 ASAN_BUILD,则输出 AFL++ 是使用 ASAN 构建编译的。*/ #ifdef ASAN_BUILD SAYF("Compiled with ASAN_BUILD.\n"); #endif - +/*如果定义了 NO_SPLICING,则输出 AFL++ 是使用禁止拼接选项编译的*/ #ifdef NO_SPLICING SAYF("Compiled with NO_SPLICING.\n"); #endif - +/*如果定义了 FANCY_BOXES_NO_UTF,则输出 AFL++ 是没有 UTF-8 支持编译的,这会影响状态屏幕中的线条渲染。*/ #ifdef FANCY_BOXES_NO_UTF SAYF("Compiled without UTF-8 support for line rendering in status screen.\n"); #endif - +/*如果定义了 PROFILING,则输出 AFL++ 是使用性能分析编译的。*/ #ifdef PROFILING SAYF("Compiled with PROFILING.\n"); #endif - +/*如果定义了 INTROSPECTION,则输出 AFL++ 是使用自省编译的。*/ #ifdef INTROSPECTION SAYF("Compiled with INTROSPECTION.\n"); #endif - +/*如果定义了 _DEBUG,则输出 AFL++ 是使用调试模式编译的*/ #ifdef _DEBUG SAYF("Compiled with _DEBUG.\n"); #endif - +/*如果定义了 _AFL_DOCUMENT_MUTATIONS,则输出 AFL++ 是使用记录变异编译的。*/ #ifdef _AFL_DOCUMENT_MUTATIONS SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n"); #endif - +/*如果定义了 _AFL_SPECIAL_PERFORMANCE,则输出 AFL++ 是使用特定系统的特殊性能选项编译的,并提醒用户这可能不适用于其他平台。*/ #ifdef _AFL_SPECIAL_PERFORMANCE SAYF( "Compiled with special performance options for this specific system, it " @@ -477,7 +556,9 @@ static void usage(u8 *argv0, int more_help) { exit(1); #undef PHYTON_SUPPORT - +/*额外帮助:输出提示信息,建议用户查阅 README.md 文件以获取更多帮助。 +退出程序:调用 exit(1) 退出程序,返回状态码 1 表示程序因错误或异常而退出。 +取消宏定义:使用 #undef PHYTON_SUPPORT 取消 PHYTON_SUPPORT 宏的定义,尽管这里可能是一个拼写错误,应该是 PYTHON_SUPPORT。*/ } #ifndef AFL_LIB @@ -544,9 +625,10 @@ static void fasan_check_afl_preload(char *afl_preload) { int main(int argc, char **argv_orig, char **envp) { - s32 opt, auto_sync = 0 /*, user_set_cache = 0*/; - u64 prev_queued = 0; - u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1, + s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;//用于存储 getopt 函数返回的选项字符 + u64 prev_queued = 0;//自动同步标志,初始值为 0。 + //用于记录上一次排队的项目数量。 + u32 sync_interval_cnt /*同步间隔计数器*/= 0, seek_to = 0, show_help = 0, default_output = 1, map_size = get_map_size(); u8 *extras_dir[4]; u8 mem_limit_given = 0, exit_1 = 0, debug = 0, @@ -557,9 +639,20 @@ int main(int argc, char **argv_orig, char **envp) { struct timeval tv; struct timezone tz; - +/*eek_to:用于指定从哪个位置开始处理队列。 +show_help:显示帮助信息的标志。 +default_output:默认输出标志,初始值为 1。 +map_size:共享内存映射的大小,通过 get_map_size 函数获取。 +extras_dir[4]:存储额外字典目录的数组。 +mem_limit_given:内存限制是否已指定的标志。 +exit_1:是否仅运行一次的标志。 +debug:调试模式标志。 +extras_dir_cnt:额外字典目录的数量。 +afl_preload 和 frida_afl_preload:用于存储 AFL 预加载库的路径。 +use_argv:用于存储处理后的命令行参数。 +struct timeval tv 和 struct timezone tz:用于获取当前时间*/ doc_path = access(DOC_PATH, F_OK) != 0 ? (u8 *)"docs" : (u8 *)DOC_PATH; - +//根据 DOC_PATH 环境变量或默认路径 "docs" 初始化文档路径 if (argc > 1 && strcmp(argv_orig[1], "--version") == 0) { printf("afl-fuzz" VERSION "\n"); @@ -573,7 +666,8 @@ int main(int argc, char **argv_orig, char **envp) { exit(0); } - +/*版本信息:如果命令行参数包含 --version,则输出 AFL++ 的版本信息并退出程序。 +帮助信息:如果命令行参数包含 --help,则调用 usage 函数显示帮助信息并退出程序。*/ #if defined USE_COLOR && defined ALWAYS_COLORED if (getenv("AFL_NO_COLOR") || getenv("AFL_NO_COLOUR")) { @@ -582,11 +676,11 @@ int main(int argc, char **argv_orig, char **envp) { "compile time)"); } - +/*颜色输出:如果定义了 USE_COLOR 和 ALWAYS_COLORED,并且环境变量 AFL_NO_COLOR 或 AFL_NO_COLOUR 被设置,则输出警告信息,提示用户颜色设置在编译时已配置。*/ #endif char **argv = argv_cpy_dup(argc, argv_orig); - +//argv_cpy_dup:复制命令行参数数组,以便在后续处理中使用 afl_state_t *afl = calloc(1, sizeof(afl_state_t)); if (!afl) { FATAL("Could not create afl state"); } @@ -599,15 +693,22 @@ int main(int argc, char **argv_orig, char **envp) { read_afl_environment(afl, envp); if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; } exit_1 = !!afl->afl_env.afl_bench_just_one; - +//SAYF:输出 AFL++ 的版本信息和基于的原始 AFL 作者信息。 SAYF(cCYA "afl-fuzz" VERSION cRST " based on afl by Michal Zalewski and a large online community\n"); - +//gettimeofday:获取当前时间。 +//rand_set_seed:根据当前时间设置随机种子,用于后续的随机数生成 gettimeofday(&tv, &tz); rand_set_seed(afl, tv.tv_sec ^ tv.tv_usec ^ getpid()); - +//afl->shmem_testcase_mode:设置为 1,表示始终尝试使用共享内存进行模糊测试。 afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing - +/*分配内存:为 afl_state_t 结构体分配内存,用于存储 AFL++ 的状态信息。 +调试模式:检查环境变量 AFL_DEBUG,如果设置,则启用调试模式。 +初始化状态:调用 afl_state_init 函数初始化 AFL 状态,设置共享内存映射大小。 +文件服务器初始化:调用 afl_fsrv_init 函数初始化文件服务器状态。 +读取环境变量:调用 read_afl_environment 函数读取 AFL++ 相关的环境变量设置。 +内存映射大小:如果环境变量中指定了共享内存映射大小,则更新文件服务器状态中的映射大小。 +仅运行一次:检查是否仅运行一次的标志*/ // still available: HjJkKqruvwz while ((opt = getopt(argc, argv, "+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:" @@ -694,12 +795,25 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("Bad syntax used for -b"); } +/*getopt 循环:使用 getopt 函数解析命令行选项。 +-a 选项:设置输入模式,可以是 "text"、"binary" 或 "default"。 +-P 选项:设置固定的变异策略,可以是 "explore"、"exploit" 或指定一个秒数,表示在没有发现新结果时自动切换到 "exploit" 模式的时间。 +-g 选项:设置生成的模糊输入的最小长度。 +-G 选项:设置生成的模糊输入的最大长度。 +-Z 选项:启用旧的种子选择方式。 +-I 选项:设置信息执行命令。 +-b 选项:绑定 AFL++ 进程到指定的 CPU 核心*/ break; } case 'c': { +/*-c 选项 +功能:用于启用或禁用 CMPLog 模式。 +逻辑: +如果选项参数为 "-",则表示禁用 CMPLog 模式。如果之前已经启用,则输出提示信息并禁用 CMPLog 模式,同时将 cmplog_binary 设置为 NULL。 +如果选项参数不为 "-",则启用 CMPLog 模式,并将 cmplog_binary 设置为选项参数指定的路径。*/ if (strcmp(optarg, "-") == 0) { @@ -723,7 +837,11 @@ int main(int argc, char **argv_orig, char **envp) { } case 's': { - +/*-s 选项 +功能:用于设置固定的随机种子。 +逻辑: +如果选项参数为 NULL,则输出错误信息并终止程序。 +否则,使用选项参数指定的种子值初始化随机数生成器,并设置 fixed_seed 标志为 1,表示使用固定的随机种子。*/ if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); } rand_set_seed(afl, strtoul(optarg, 0L, 10)); afl->fixed_seed = 1; @@ -732,7 +850,12 @@ int main(int argc, char **argv_orig, char **envp) { } case 'p': /* Power schedule */ - +/*-p 选项 +功能:用于设置功率调度策略,决定如何计算种子的性能得分。 +逻辑: +根据选项参数的值,将 afl->schedule 设置为相应的功率调度策略枚举值。支持的策略包括 FAST、COE、EXPLOIT、LIN、QUAD、MMOPT、RARE、EXPLORE 和 SEEK。 +如果选项参数不匹配任何已知策略,则输出错误信息并终止程序。 +*/ if (!stricmp(optarg, "fast")) { afl->schedule = FAST; @@ -784,7 +907,11 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'e': - +/*-e 选项 +功能:用于设置目标程序输入文件的扩展名。 +逻辑: +如果 afl->file_extension 已经被设置,则输出错误信息并终止程序,表示不支持多个 -e 选项。 +否则,将 afl->file_extension 设置为选项参数指定的扩展名。*/ if (afl->file_extension) { FATAL("Multiple -e options not supported"); } afl->file_extension = optarg; @@ -792,7 +919,13 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'i': /* input dir */ - +/*-i 选项 +功能:用于指定输入目录,该目录包含用于模糊测试的测试用例。 +逻辑: +如果 afl->in_dir 已经被设置,则输出错误信息并终止程序,表示不支持多个 -i 选项。 +如果选项参数为 NULL,则输出错误信息并终止程序,表示无效的 -i 选项。 +否则,将 afl->in_dir 设置为选项参数指定的输入目录路径。 +如果输入目录为 "-",则设置 afl->in_place_resume 标志为 1,表示恢复之前的模糊测试会话。*/ if (afl->in_dir) { FATAL("Multiple -i options not supported"); } if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); } afl->in_dir = optarg; @@ -802,13 +935,28 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'o': /* output dir */ - +/*-o 选项 +功能:用于指定输出目录,用于存储模糊测试过程中发现的结果。 +逻辑: +如果 afl->out_dir 已经被设置,则输出错误信息并终止程序,表示不支持多个 -o 选项。 +否则,将 afl->out_dir 设置为选项参数指定的输出目录路径。*/ if (afl->out_dir) { FATAL("Multiple -o options not supported"); } afl->out_dir = optarg; break; case 'M': { /* main sync ID */ - +/*-M 选项 +功能:用于设置主同步 ID,用于分布式模糊测试中的主节点。 +逻辑: +检查是否处于非插桩模式或 ARM CoreSight 模式,如果是,则输出错误信息并终止程序,因为这些模式不支持 -M 选项。 +检查是否已经设置了同步 ID,如果是,则输出错误信息并终止程序,表示不支持多个 -S 或 -M 选项。 +检查选项参数是否以 - 开头,如果是,则输出错误信息并终止程序,因为 - 通常用于选项。 +将同步 ID 设置为选项参数指定的值。 +设置 old_seed_selection 标志为 1,表示使用旧的队列遍历种子选择方式。 +设置 disable_trim 标志为 1,表示禁用修剪功能。 +如果同步 ID 中包含 :,则解析主节点 ID 和主节点最大值,并进行有效性检查。如果解析失败或值无效,则输出错误信息并终止程序。 +设置 is_main_node 标志为 1,表示当前节点是主节点。 +*/ u8 *c; if (afl->non_instrumented_mode) { @@ -862,7 +1010,14 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'S': /* secondary sync id */ - +/*-S 选项 +功能:用于设置次级同步 ID,用于分布式模糊测试中的次级节点。 +逻辑: +检查是否处于非插桩模式或 ARM CoreSight 模式,如果是,则输出错误信息并终止程序,因为这些模式不支持 -S 选项。 +检查是否已经设置了同步 ID,如果是,则输出错误信息并终止程序,表示不支持多个 -S 或 -M 选项。 +检查选项参数是否以 - 开头,如果是,则输出错误信息并终止程序,因为 - 通常用于选项。 +将同步 ID 设置为选项参数指定的值。 +设置 is_secondary_node 标志为 1,表示当前节点是次级节点*/ if (afl->non_instrumented_mode) { FATAL("-S is not supported in non-instrumented mode"); @@ -892,7 +1047,13 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'F': /* foreign sync dir */ - +/*-F 选项 +功能:用于指定外部同步目录,用于分布式模糊测试中与其他模糊测试实例同步。 +逻辑: +检查是否提供了选项参数,如果没有,则输出错误信息并终止程序。 +检查是否是主节点,如果不是,则输出错误信息并终止程序,因为 -F 选项只能在主节点中指定。 +检查是否已经达到外部同步目录的最大数量限制,如果是,则输出错误信息并终止程序。 +将外部同步目录添加到 foreign_syncs 数组中,并去除路径末尾的斜杠。*/ if (!optarg) { FATAL("Missing path for -F"); } if (!afl->is_main_node) { @@ -924,7 +1085,13 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'f': /* target file */ - +/*-f 选项 +功能:用于指定目标程序读取的文件路径。 +逻辑: +检查是否已经设置了输出文件,如果是,则输出错误信息并终止程序,表示不支持多个 -f 选项。 +将输出文件路径设置为选项参数指定的值。 +设置 use_stdin 标志为 0,表示不使用标准输入。 +设置 default_output 标志为 0,表示不使用默认输出。*/ if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); } afl->fsrv.out_file = ck_strdup(optarg); @@ -933,7 +1100,11 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'x': /* dictionary */ - +/*-x 选项 +功能:用于指定字典文件路径,用于辅助模糊测试。 +逻辑: +检查是否已经设置了超过四个字典文件,如果是,则输出错误信息并终止程序,表示不支持超过四个 -x 选项。 +将字典文件路径添加到 extras_dir 数组中,并增加 extras_dir_cnt 计数。*/ if (extras_dir_cnt >= 4) { FATAL("More than four -x options are not supported"); @@ -944,7 +1115,13 @@ int main(int argc, char **argv_orig, char **envp) { break; case 't': { /* timeout */ - +/*-t 选项 +功能:用于设置每次运行的超时时间。 +逻辑: +检查是否已经设置了超时时间,如果是,则输出错误信息并终止程序,表示不支持多个 -t 选项。 +解析选项参数,提取超时时间值和可能的后缀(如 +)。 +如果超时时间值小于 5 毫秒,则输出错误信息并终止程序,表示超时时间过低。 +根据后缀设置 timeout_given 标志,+ 表示自动计算超时时间。*/ u8 suffix = 0; if (afl->timeout_given) { FATAL("Multiple -t options not supported"); } @@ -974,7 +1151,14 @@ int main(int argc, char **argv_orig, char **envp) { } case 'm': { /* mem limit */ - +/*-m 选项 +功能:用于设置子进程的内存限制。 +逻辑: +检查是否已经设置了内存限制,如果是,则输出警告信息,表示将覆盖之前的 -m 选项。 +解析选项参数,提取内存限制值和可能的单位后缀(如 T、G、k、M)。 +根据单位后缀将内存限制值转换为相应的字节数。 +如果内存限制值小于 5 字节,则输出错误信息并终止程序,表示内存限制过低。 +在 32 位系统上,如果内存限制值大于 2000 MB,则输出错误信息并终止程序,表示内存限制超出范围。*/ u8 suffix = 'M'; if (mem_limit_given) { @@ -1040,19 +1224,30 @@ int main(int argc, char **argv_orig, char **envp) { case 'd': case 'D': /* old deterministic */ - +/*-d 和 -D 选项 +功能:这两个选项已被弃用,用于旧的确定性模糊测试。 +逻辑: +输出警告信息,提示用户新的增强确定性模糊测试已默认激活,如果需要禁用,请使用 -z 选项。*/ WARNF( "Parameters -d and -D are deprecated, a new enhanced deterministic " "fuzzing is active by default, to disable it use -z"); break; case 'z': /* no deterministic */ - +/*-z 选项 +功能:用于禁用确定性模糊测试。 +逻辑: +设置 skip_deterministic 标志为 1,表示跳过确定性模糊测试阶段。*/ afl->skip_deterministic = 1; break; case 'B': /* load bitmap */ - +/*-B 选项 +功能:用于加载位图,这是一个未公开的选项。 +逻辑: +如果已经设置了 in_bitmap,则输出错误信息并终止程序,表示不支持多个 -B 选项。 +将 in_bitmap 设置为选项参数指定的位图文件路径。 +说明:该选项用于在正常的模糊测试过程中发现有趣的测试用例时,加载之前运行产生的位图,*/ /* This is a secret undocumented option! It is useful if you find an interesting test case during a normal fuzzing process, and want to mutate it without rediscovering any of the test cases already @@ -1070,13 +1265,22 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'C': /* crash mode */ - +/*-C 选项 +功能:用于设置崩溃模式。 +逻辑: +如果已经设置了 crash_mode,则输出错误信息并终止程序,表示不支持多个 -C 选项。 +将 crash_mode 设置为 FSRV_RUN_CRASH,表示启用崩溃模式。*/ if (afl->crash_mode) { FATAL("Multiple -C options not supported"); } afl->crash_mode = FSRV_RUN_CRASH; break; case 'n': /* dumb mode */ - +/*-n 选项 +功能:用于设置非插桩模式。 +逻辑: +检查是否是主节点或次级节点,如果是,则输出错误信息并终止程序,因为非插桩模式不支持与 -M 或 -S 一起使用。 +检查是否已经设置了 non_instrumented_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -n 选项。 +根据环境变量 AFL_DUMB_FORKSRV 的设置,将 non_instrumented_mode 设置为 1 或 2,表示启用非插桩模式。*/ if (afl->is_main_node || afl->is_secondary_node) { FATAL("Non instrumented mode is not supported with -M / -S"); @@ -1102,14 +1306,26 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'T': /* banner */ - +/*-T 选项 +功能:用于设置横幅。 +逻辑: +如果已经设置了 use_banner,则输出错误信息并终止程序,表示不支持多个 -T 选项。 +将 use_banner 设置为选项参数指定的横幅文本。*/ if (afl->use_banner) { FATAL("Multiple -T options not supported"); } afl->use_banner = optarg; break; #ifdef __linux__ case 'X': /* NYX mode */ - +/*-X 和 -Y 选项(仅限 Linux) +功能:用于设置 Nyx 模式。 +逻辑: +-X 选项:设置 Nyx 独立模式。 +检查是否已经设置了 nyx_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -X 选项。 +设置 nyx_parent、nyx_standalone 和 nyx_mode 标志,表示启用 Nyx 独立模式。 +-Y 选项:设置 Nyx 分布式模式。 +检查是否已经设置了 nyx_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -Y 选项。 +设置 nyx_mode 标志,表示启用 Nyx 分布式模式*/ if (afl->fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); } afl->fsrv.nyx_parent = true; @@ -1132,7 +1348,12 @@ int main(int argc, char **argv_orig, char **envp) { break; #endif case 'A': /* CoreSight mode */ - +/*-A 选项(仅限 ARM64 和 Linux) +功能:用于设置 ARM CoreSight 模式。 +逻辑: +检查是否是主节点或次级节点,如果是,则输出错误信息并终止程序,因为 ARM CoreSight 模式不支持与 -M 或 -S 一起使用。 +检查是否已经设置了 cs_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -A 选项。 +设置 cs_mode 标志,表示启用 ARM CoreSight 模式。*/ #if !defined(__aarch64__) || !defined(__linux__) FATAL("-A option is not supported on this platform"); #endif @@ -1150,7 +1371,12 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'O': /* FRIDA mode */ - +/*-O 选项 +功能:用于设置 FRIDA 模式。 +逻辑: +检查是否已经设置了 frida_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -O 选项。 +设置 frida_mode 标志,表示启用 FRIDA 模式。 +检查环境变量 AFL_USE_FASAN,如果设置,则设置 frida_asan 标志为 1,表示使用 FRIDA 地址制裁模式。*/ if (afl->fsrv.frida_mode) { FATAL("Multiple -O options not supported"); @@ -1163,7 +1389,12 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'Q': /* QEMU mode */ - +/*-Q 选项 +功能:用于启用 QEMU 模式。 +逻辑: +检查是否已经设置了 qemu_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -Q 选项。 +设置 qemu_mode 标志为 1,表示启用 QEMU 模式。 +如果没有指定内存限制,则将 mem_limit 设置为 MEM_LIMIT_QEMU,即 QEMU 模式的默认内存限制。*/ if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); } afl->fsrv.qemu_mode = 1; @@ -1173,14 +1404,24 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'N': /* Unicorn mode */ - +/*-N 选项 +功能:用于设置不删除模糊测试输入文件的标志。 +逻辑: +检查是否已经设置了 no_unlink,如果是,则输出错误信息并终止程序,表示不支持多个 -N 选项。 +设置 no_unlink 标志为 true,表示在模糊测试过程中不删除输入文件。*/ if (afl->no_unlink) { FATAL("Multiple -N options not supported"); } afl->fsrv.no_unlink = (afl->no_unlink = true); break; case 'U': /* Unicorn mode */ - +/*-U 选项 +功能:用于启用 Unicorn 模式。 +逻辑: +检查是否已经设置了 unicorn_mode,如果是,则输出错误信息并终止程序,表示不支持多个 -U 选项。 +设置 unicorn_mode 标志为 1,表示启用 Unicorn 模式。 +如果没有指定内存限制,则将 mem_limit 设置为 MEM_LIMIT_UNICORN,即 Unicorn 模式的默认内存限制。 +*/ if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); } afl->unicorn_mode = 1; @@ -1189,7 +1430,13 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'W': /* Wine+QEMU mode */ - +/*-W 选项 +功能:用于启用 Wine+QEMU 模式。 +逻辑: +检查是否已经设置了 use_wine,如果是,则输出错误信息并终止程序,表示不支持多个 -W 选项。 +设置 qemu_mode 标志为 1,表示启用 QEMU 模式。 +设置 use_wine 标志为 1,表示启用 Wine 模式。 +如果没有指定内存限制,则将 mem_limit 设置为 0,即不限制内存。*/ if (afl->use_wine) { FATAL("Multiple -W options not supported"); } afl->fsrv.qemu_mode = 1; afl->use_wine = 1; @@ -1199,7 +1446,12 @@ int main(int argc, char **argv_orig, char **envp) { break; case 'V': { - +/*-V 选项 +功能:用于设置 AFL++ 运行的最大时间。 +逻辑: +设置 most_time_key 标志为 1,表示启用了运行时间限制。 +解析选项参数,提取最大运行时间值。 +如果解析失败或参数格式不正确,则输出错误信息并终止程序。*/ afl->most_time_key = 1; if (!optarg || sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') { @@ -1211,7 +1463,12 @@ int main(int argc, char **argv_orig, char **envp) { } break; case 'E': { - +/*-E 选项 +功能:用于设置 AFL++ 运行的最大执行次数。 +逻辑: +设置 most_execs_key 标志为 1,表示启用了执行次数限制。 +解析选项参数,提取最大执行次数值。 +如果解析失败或参数格式不正确,则输出错误信息并终止程序。*/ afl->most_execs_key = 1; if (!optarg || sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') { @@ -1223,7 +1480,20 @@ int main(int argc, char **argv_orig, char **envp) { } break; case 'l': { - +/*-l 选项 +功能:用于配置 CMPLog 的行为。 +逻辑: +检查是否提供了选项参数,如果没有,则输出错误信息并终止程序。 +遍历选项参数中的每个字符,根据字符设置相应的 CMPLog 配置: +'0'、'1':设置 CMPLog 级别为 1。 +'2':设置 CMPLog 级别为 2。 +'3':设置 CMPLog 级别为 3,并禁用修剪功能。 +'a'、'A':启用算术求解。 +'s'、'S':启用缩放求解。 +'t'、'T':启用变换求解。 +'x'、'X':启用极端变换求解。 +'r'、'R':启用随机颜色化。 +如果 CMPLog 级别达到最大值 CMPLOG_LVL_MAX,则将 cmplog_max_filesize 设置为 MAX_FILE,即最大文件大小限制。*/ if (!optarg) { FATAL("missing parameter for 'l'"); } char *c = optarg; while (*c) { @@ -1286,7 +1556,23 @@ int main(int argc, char **argv_orig, char **envp) { } break; case 'L': { /* MOpt mode */ - +/*-L 选项 +功能:用于设置 MOpt 模式的时间限制,以分钟为单位。 +逻辑: +检查是否已经设置了 limit_time_sig,如果是,则输出错误信息并终止程序,表示不支持多个 -L 选项。 +设置 havoc_max_mult 为 HAVOC_MAX_MULT_MOPT,这是 MOpt 模式下的 Havoc 变异次数乘数。 +解析选项参数,提取时间限制值。 +如果解析失败,则输出错误信息并终止程序。 +如果时间限制值为 -1,则将 limit_time_sig 设置为 -1,表示立即进入 MOpt 模式,并将 limit_time_puppet 设置为 0。 +如果时间限制值小于 0 但不等于 -1,则输出错误信息并终止程序,因为时间限制值必须在 0 到 2000000 之间或为 -1。 +否则,将 limit_time_sig 设置为 1,表示时间限制有效。 +设置 old_seed_selection 为 1,表示使用旧的种子选择方式。 +将时间限制值转换为毫秒(乘以 60 * 1000),并检查是否发生溢出。 +初始化 MOpt 模式相关的变量,包括 swarm_now、key_puppet、g_now、w_now 等。 +遍历每个“swarm”(群体),初始化相关的变量,如 swarm_fitness、stage_finds_puppet、probability_now、x_now、v_now、L_best、G_best、eff_best 等。 +计算每个操作符的概率和速度。 +确保概率值在合理范围内。 +输出警告信息,提示用户 MOpt 模式不再被维护,且不如正常的 Havoc 模式有效。*/ if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); } afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT; @@ -1435,35 +1721,55 @@ int main(int argc, char **argv_orig, char **envp) { case 'h': show_help++; break; // not needed - +/*-h 选项 +功能:用于显示帮助信息。 +逻辑: +增加 show_help 计数器的值。 +break 语句实际上在这里是多余的,因为 switch 语句的每个 case 都是独立的。 +*/ case 'R': - +/*-R 选项 +功能:用于处理 Radamsa 相关的选项。 +逻辑: +输出错误信息并终止程序,提示用户 Radamsa 现在是一个自定义变异器,应该使用自定义变异器的方式(custom_mutators/radamsa/)来使用。*/ FATAL( "Radamsa is now a custom mutator, please use that " "(custom_mutators/radamsa/)."); break; - +/*默认情况 +功能:处理未匹配的选项。 +逻辑: +如果 show_help 未被设置,则将其设置为 1,表示需要显示帮助信息。*/ default: if (!show_help) { show_help = 1; } } } - +/*同步 ID 检查 +功能:检查同步 ID 是否为保留名称。 +逻辑: +如果 sync_id 被设置为 "addseeds",则输出错误信息并终止程序,因为 "addseeds" 是一个保留名称,不能用作同步 ID*/ if (afl->sync_id && strcmp(afl->sync_id, "addseeds") == 0) { FATAL("-M/-S name 'addseeds' is a reserved name, choose something else"); } - +/*主节点和功率调度检查 +功能:检查主节点的功率调度设置。 +逻辑: +如果当前是主节点(is_main_node 为 1),并且功率调度不是 FAST 或 EXPLORE,则输出错误信息并终止程序,因为 -M 选项仅与 FAST 和 EXPLORE 功率调度兼容*/ if (afl->is_main_node == 1 && afl->schedule != FAST && afl->schedule != EXPLORE) { FATAL("-M is compatible only with fast and explore -p power schedules"); } - +/*参数检查和帮助信息显示 +功能:检查命令行参数的完整性,并在需要时显示帮助信息。 +逻辑: +如果 optind 等于 argc(表示没有剩余的命令行参数)、输入目录未设置、输出目录未设置或 show_help 被设置,则调用 usage 函数显示帮助信息并退出程序。*/ if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) { usage(argv[0], show_help); @@ -1473,7 +1779,14 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->afl_env.afl_persistent_record)) { #ifdef AFL_PERSISTENT_RECORD - +/*持久记录配置检查 +功能:检查 AFL_PERSISTENT_RECORD 环境变量的设置。 +逻辑: +如果 afl_env.afl_persistent_record 被设置: +如果 AFL++ 是使用 AFL_PERSISTENT_RECORD 编译的: +将 fsrv.persistent_record 设置为环境变量的值。 +如果设置的值小于 2,则输出错误信息并终止程序,因为 AFL_PERSISTENT_RECORD 的值必须至少为 2,推荐值为 100 或 1000。 +如果 AFL++ 未使用 AFL_PERSISTENT_RECORD 编译,则输出错误信息并终止程序,提示 AFL++ 未启用 AFL_PERSISTENT_RECORD 支持。*/ afl->fsrv.persistent_record = atoi(afl->afl_env.afl_persistent_record); if (afl->fsrv.persistent_record < 2) { @@ -1495,13 +1808,19 @@ int main(int argc, char **argv_orig, char **envp) { } if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260; - +/*内存限制调整 +逻辑: +如果设置了内存限制并且启用了 CMPLog 模式,则将内存限制增加 260 字节。这可能是为了确保 CMPLog 模式有足够的内存来存储额外的信息。*/ OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea " "Fioraldi and Heiko \"hexcoder\" Eißfeldt"); OKF("AFL++ is open source, get it at " "https://github.com/AFLplusplus/AFLplusplus"); OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md"); - +/*版本信息显示 +逻辑: +输出 AFL++ 的维护者信息,包括 Marc "van Hauser" Heuse、Dominik Maier、Andrea Fioraldi 和 Heiko "hexcoder" Eißfeldt。 +提示 AFL++ 是开源软件,并提供 GitHub 仓库链接。 +提醒用户 AFL++ 从版本 3 开始改变了默认设置和行为,建议查看 README.md 文件了解详细信息。*/ #ifdef __linux__ if (afl->fsrv.nyx_mode) { @@ -1510,18 +1829,24 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz"); } - +/*Nyx 模式信息显示(仅限 Linux) +逻辑: +如果启用了 Nyx 模式,输出 Nyx 模式的信息,包括开发者和维护者 Sergej Schumilo,以及 Nyx 的 GitHub 仓库链接。*/ #endif // silently disable deterministic mutation if custom mutators are used if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) { - +/*确定性变异禁用 +逻辑: +如果启用了自定义变异器且未禁用确定性变异,则自动禁用确定性变异。这是因为自定义变异器可能已经包含了确定性变异的功能。*/ afl->skip_deterministic = 1; } if (afl->fixed_seed) { - +/*固定种子信息显示 +逻辑: +如果设置了固定种子,则输出正在使用的固定种子值。*/ OKF("Running with fixed seed: %u", (u32)afl->init_seed); } @@ -1535,7 +1860,9 @@ int main(int argc, char **argv_orig, char **envp) { } #endif - +/*信号配置 +逻辑: +调用 configure_afl_kill_signals 函数配置 AFL++ 的信号处理,设置子进程和 fork 服务器的终止信号。如果启用了 QEMU、Unicorn、fauxsrv 或 Nyx 模式,则使用 SIGKILL 信号,否则使用 SIGTERM 信号。*/ configure_afl_kill_signals( &afl->fsrv, afl->afl_env.afl_child_kill_signal, afl->afl_env.afl_fsrv_kill_signal, @@ -1546,12 +1873,21 @@ int main(int argc, char **argv_orig, char **envp) { ) ? SIGKILL : SIGTERM); - +/*信号处理设置 +逻辑: +调用 setup_signal_handlers 函数设置 AFL++ 的信号处理程序,以便在接收到特定信号时执行相应的操作。*/ setup_signal_handlers(); check_asan_opts(afl); - +/*ASAN 构建内存限制禁用(仅限 ASAN 构建) +逻辑: +如果 AFL++ 是使用 ASAN 构建的,并且设置了内存限制,则输出警告信息并禁用内存限制。这是因为 ASAN 可能需要更多的内存来检测内存问题。*/ afl->power_name = power_names[afl->schedule]; - +/*ASAN 选项检查 +逻辑: +调用 check_asan_opts 函数检查 ASAN 相关的选项设置,确保 AFL++ 能够与 ASAN 正常配合使用。*/ +/*功率调度名称设置 +逻辑: +根据当前的功率调度策略,从 power_names 数组中获取对应的名称,并将其存储在 afl->power_name 中。*/ if (!afl->non_instrumented_mode && !afl->sync_id) { auto_sync = 1; @@ -1560,7 +1896,13 @@ int main(int argc, char **argv_orig, char **envp) { OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id); } - +/*Nyx 模式同步配置(仅限 Linux) +逻辑: +如果启用了 Nyx 模式: +如果是 Nyx 独立模式且同步 ID 不是 "default",则输出错误信息并终止程序,因为独立模式不支持分布式模糊测试。 +如果是 Nyx 分布式模式: +如果是主节点且同步 ID 不是 "0",则输出错误信息并终止程序,因为主节点的 ID 必须是 "0"。 +如果是次级节点,则解析同步 ID 并进行有效性检查。如果 ID 不是有效的数字或小于 1,则输出错误信息并终止程序。*/ #ifdef __linux__ if (afl->fsrv.nyx_mode) {