diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index e6a2b74..04327d7 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -8082,101 +8082,138 @@ int main(int argc, char** argv) { bind_to_free_cpu(); #endif /* HAVE_AFFINITY */ +/* 检查崩溃处理机制 */ check_crash_handling(); +/* 检查CPU调节器设置 */ check_cpu_governor(); +/* 设置后处理操作 */ setup_post(); +/* 设置共享内存 */ setup_shm(); +/* 初始化计数类16 */ init_count_class16(); +/* 设置目录和文件描述符 */ setup_dirs_fds(); +/* 读取测试用例 */ read_testcases(); +/* 加载自动化设置 */ load_auto(); +/* 处理输入的转换 */ pivot_inputs(); + // 此代码段为 afl-fuzz.c 文件中的初始化和参数处理部分 + // 主要功能是配置执行环境并检查传入的文件参数 + // 包括加载额外目录、查找超时、检测文件参数、设置输出文件、检查二进制文件及获取当前时间 + + if (extras_dir) load_extras(extras_dir); + + if (!timeout_given) find_timeout(); + + detect_file_args(argv + optind + 1); + + if (!out_file) setup_stdio_file(); + + check_binary(argv[optind]); + + start_time = get_cur_time(); + + if (qemu_mode) + use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); + else + use_argv = argv + optind; - if (extras_dir) load_extras(extras_dir); - - if (!timeout_given) find_timeout(); - - detect_file_args(argv + optind + 1); - - if (!out_file) setup_stdio_file(); - - check_binary(argv[optind]); - - start_time = get_cur_time(); - - if (qemu_mode) - use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); - else - use_argv = argv + optind; - - perform_dry_run(use_argv); - - cull_queue(); - - show_init_stats(); - - seek_to = find_start_position(); - - write_stats_file(0, 0, 0); - save_auto(); - - if (stop_soon) goto stop_fuzzing; - - /* Woop woop woop */ - - if (!not_on_tty) { - sleep(4); - start_time += 4000; + /* + * 此函数实现了模糊测试的初始步骤,包括执行干运行、清理队列、 + * 显示初始化统计信息、寻找起始位置并写入统计文件。 + */ + perform_dry_run(use_argv); + + cull_queue(); + + show_init_stats(); + + seek_to = find_start_position(); + + write_stats_file(0, 0, 0); + save_auto(); + + /* + * 如果状态指示测试需要停止,则跳转到停止模糊测试的标签。 + */ if (stop_soon) goto stop_fuzzing; - } + + /* Woop woop woop */ + + /* + * 如果不是在终端上运行,则暂停4秒,增加开始时间。 + */ + if (!not_on_tty) { + sleep(4); + start_time += 4000; + /* + * 再次检查是否需要停止模糊测试。 + */ + if (stop_soon) goto stop_fuzzing; + } + // 该段代码实现了一个持续循环,处理模糊测试队列中的条目。 while (1) { - - u8 skipped_fuzz; - - cull_queue(); - - if (!queue_cur) { - - queue_cycle++; - current_entry = 0; - cur_skipped_paths = 0; - queue_cur = queue; - - while (seek_to) { - current_entry++; - seek_to--; - queue_cur = queue_cur->next; - } - - show_stats(); - - if (not_on_tty) { - ACTF("Entering queue cycle %llu.", queue_cycle); - fflush(stdout); - } + + u8 skipped_fuzz; + + // 清理当前模糊测试队列 + cull_queue(); + + if (!queue_cur) { + + // 如果当前队列为空,增加队列周期计数 + queue_cycle++; + current_entry = 0; + cur_skipped_paths = 0; + queue_cur = queue; + + // 根据指定的跳过路径数量,定位到队列中的特定条目 + while (seek_to) { + current_entry++; + seek_to--; + queue_cur = queue_cur->next; + } + + // 显示当前状态统计 + show_stats(); + + if (not_on_tty) { + // 在非终端模式下,输出当前队列周期信息 + ACTF("Entering queue cycle %llu.", queue_cycle); + fflush(stdout); + } /* If we had a full queue cycle with no new finds, try recombination strategies next. */ + // 检查当前队列路径是否与前一个队列路径相同 if (queued_paths == prev_queued) { + // 根据是否使用拼接,决定增加无发现循环次数或启用拼接 if (use_splicing) cycles_wo_finds++; else use_splicing = 1; } else cycles_wo_finds = 0; + // 更新前一个队列路径值 prev_queued = queued_paths; + // 检查同步ID,队列循环和环境变量以同步模糊测试器 if (sync_id && queue_cycle == 1 && getenv("AFL_IMPORT_FIRST")) sync_fuzzers(use_argv); } + // 执行模糊测试 skipped_fuzz = fuzz_one(use_argv); + // 如果没有停止标志且没有跳过模糊测试,根据同步间隔决定是否同步 if (!stop_soon && sync_id && !skipped_fuzz) { if (!(sync_interval_cnt++ % SYNC_INTERVAL)) @@ -8184,38 +8221,47 @@ int main(int argc, char** argv) { } + // 如果没有停止标志且 exit_1 为真,则设置停止标志 if (!stop_soon && exit_1) stop_soon = 2; + // 如果设置了停止标志,则跳出循环 if (stop_soon) break; - queue_cur = queue_cur->next; - current_entry++; + // 更新当前队列指针和当前条目计数 + queue_cur = queue_cur->next; + current_entry++; } - if (queue_cur) show_stats(); - - /* If we stopped programmatically, we kill the forkserver and the current runner. - If we stopped manually, this is done by the signal handler. */ - if (stop_soon == 2) { - if (child_pid > 0) kill(child_pid, SIGKILL); - if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); - } - /* Now that we've killed the forkserver, we wait for it to be able to get rusage stats. */ - if (waitpid(forksrv_pid, NULL, 0) <= 0) { - WARNF("error waitpid\n"); - } - - write_bitmap(); - write_stats_file(0, 0, 0); - save_auto(); + /* + * 该段代码用于处理程序终止的情况,包括被程序控制的终止和手动终止。 + * 在终止时会杀死子进程和forkserver,并等待forkserver获取资源使用统计信息。 + * 此外,还会写入位图和统计文件以保存当前状态。 + */ + if (queue_cur) show_stats(); + + /* If we stopped programmatically, we kill the forkserver and the current runner. + If we stopped manually, this is done by the signal handler. */ + if (stop_soon == 2) { + if (child_pid > 0) kill(child_pid, SIGKILL); + if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); + } + /* Now that we've killed the forkserver, we wait for it to be able to get rusage stats. */ + if (waitpid(forksrv_pid, NULL, 0) <= 0) { + WARNF("error waitpid\n"); + } + + write_bitmap(); + write_stats_file(0, 0, 0); + save_auto(); +/* 停止模糊测试的函数 */ stop_fuzzing: SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, stop_soon == 2 ? "programmatically" : "by user"); - /* Running for more than 30 minutes but still doing first cycle? */ + /* 运行超过30分钟但仍在进行第一次周期? */ if (queue_cycle == 1 && get_cur_time() - start_time > 30 * 60 * 1000) {