Merge pull request '添加了afl-gcc.c 7000行到8000行注释' (#2) from dev-suhongye into main

pull/5/head
pjzuvftbk 9 months ago
commit 295a40ad4b

@ -7775,6 +7775,7 @@ static void save_cmdline(u32 argc, char** argv) {
/* Main entry point */
// 主函数,程序的入口点
int main(int argc, char** argv) {
s32 opt;
@ -7788,94 +7789,114 @@ int main(int argc, char** argv) {
struct timeval tv;
struct timezone tz;
SAYF(cCYA "afl-fuzz " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
gettimeofday(&tv, &tz);
srandom(tv.tv_sec ^ tv.tv_usec ^ getpid());
// argv 处理
while ((opt = getopt(argc, argv, "+i:o:f:m:b:t:T:dnCB:S:M:x:QV")) > 0)
switch (opt) {
case 'i': /* input dir */
// 初始 corpus 目录
if (in_dir) FATAL("Multiple -i options not supported");
in_dir = optarg;
// 若使用 "-i -",则表示 in-place resume
if (!strcmp(in_dir, "-")) in_place_resume = 1;
break;
case 'o': /* output dir */
if (out_dir) FATAL("Multiple -o options not supported");
out_dir = optarg;
break;
case 'M': { /* master sync ID */
u8* c;
if (sync_id) FATAL("Multiple -S or -M options not supported");
sync_id = ck_strdup(optarg);
if ((c = strchr(sync_id, ':'))) {
*c = 0;
if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 ||
!master_id || !master_max || master_id > master_max ||
master_max > 1000000) FATAL("Bogus master ID passed to -M");
SAYF(cCYA "afl-fuzz " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
}
/***************************************************************
* /:
* : ID
***************************************************************/
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
gettimeofday(&tv, &tz);
srandom(tv.tv_sec ^ tv.tv_usec ^ getpid());
// argv 处理
while ((opt = getopt(argc, argv, "+i:o:f:m:b:t:T:dnCB:S:M:x:QV")) > 0)
switch (opt) {
case 'i': /* input dir */
// 初始 corpus 目录
if (in_dir) FATAL("Multiple -i options not supported");
in_dir = optarg;
// 若使用 "-i -",则表示 in-place resume
if (!strcmp(in_dir, "-")) in_place_resume = 1;
break;
/* 处理输出目录的命令行选项 */
case 'o': /* output dir */
if (out_dir) FATAL("Multiple -o options not supported");
out_dir = optarg;
break;
case 'M': { /* master sync ID */
// 处理选项 'M',用于设定主同步 ID
u8* c;
if (sync_id) FATAL("Multiple -S or -M options not supported");
sync_id = ck_strdup(optarg);
if ((c = strchr(sync_id, ':'))) {
// 解析同步ID中的主ID和最大ID
*c = 0;
if (sscanf(c + 1, "%u/%u", &master_id, &master_max) != 2 ||
!master_id || !master_max || master_id > master_max ||
master_max > 1000000) FATAL("Bogus master ID passed to -M");
}
force_deterministic = 1;
// 强制使用确定性执行
}
force_deterministic = 1;
}
break;
case 'S':
if (sync_id) FATAL("Multiple -S or -M options not supported");
sync_id = ck_strdup(optarg);
break;
case 'f': /* target file */
if (out_file) FATAL("Multiple -f options not supported");
out_file = optarg;
break;
case 'x': /* dictionary */
if (extras_dir) FATAL("Multiple -x options not supported");
extras_dir = optarg;
break;
case 't': { /* timeout */
u8 suffix = 0;
if (timeout_given) FATAL("Multiple -t options not supported");
if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 ||
optarg[0] == '-') FATAL("Bad syntax used for -t");
if (exec_tmout < 5) FATAL("Dangerously low value of -t");
if (suffix == '+') timeout_given = 2; else timeout_given = 1;
break;
}
// 处理-S选项的代码逻辑
/************************************************************************************
* ID *
* FATAL *
************************************************************************************/
case 'S':
if (sync_id) FATAL("Multiple -S or -M options not supported");
sync_id = ck_strdup(optarg);
break;
case 'f': /* target file */
if (out_file) FATAL("Multiple -f options not supported");
out_file = optarg;
break;
case 'x': /* dictionary */
if (extras_dir) FATAL("Multiple -x options not supported");
extras_dir = optarg;
break;
/**************************************
*
* -t
**************************************/
case 't': { /* timeout */
u8 suffix = 0;
if (timeout_given) FATAL("Multiple -t options not supported");
if (sscanf(optarg, "%u%c", &exec_tmout, &suffix) < 1 ||
optarg[0] == '-') FATAL("Bad syntax used for -t");
if (exec_tmout < 5) FATAL("Dangerously low value of -t");
if (suffix == '+') timeout_given = 2; else timeout_given = 1;
break;
}
case 'm': { /* mem limit */
// 处理内存限制选项的相关逻辑
u8 suffix = 'M';
@ -7883,15 +7904,16 @@ int main(int argc, char** argv) {
mem_limit_given = 1;
if (!strcmp(optarg, "none")) {
// 如果选项参数为"none"则将内存限制设置为0
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;
@ -7903,8 +7925,10 @@ int main(int argc, char** argv) {
}
// 检查内存限制值是否低于安全阈值
if (mem_limit < 5) FATAL("Dangerously low value of -m");
// 在32位系统上检查内存限制的范围
if (sizeof(rlim_t) == 4 && mem_limit > 2000)
FATAL("Value of -m out of range on 32-bit systems");
@ -7913,10 +7937,11 @@ int main(int argc, char** argv) {
break;
case 'b': { /* bind CPU core */
// 处理 CPU 绑定选项,确保只能使用一次
if (cpu_to_bind_given) FATAL("Multiple -b options not supported");
cpu_to_bind_given = 1;
// 解析用户输入的 CPU 核心编号,检查输入合法性
if (sscanf(optarg, "%u", &cpu_to_bind) < 1 ||
optarg[0] == '-') FATAL("Bad syntax used for -b");
@ -7924,6 +7949,7 @@ int main(int argc, char** argv) {
}
/* 处理命令行参数,选择跳过确定性测试的选项 */
case 'd': /* skip deterministic */
if (skip_deterministic) FATAL("Multiple -d options not supported");
@ -7932,24 +7958,19 @@ int main(int argc, char** argv) {
break;
case 'B': /* load 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
found during an earlier run.
To use this mode, you need to point -B to the fuzz_bitmap produced
by an earlier run for the exact same binary... and that's it.
I only used this once or twice to get variants of a particular
file, so I'm not making this an official setting. */
/*
使 -B fuzz_bitmap
使
*/
if (in_bitmap) FATAL("Multiple -B options not supported");
in_bitmap = optarg;
read_bitmap(in_bitmap);
break;
/* 处理命令行参数选项 'C',用于设置崩溃模式 */
case 'C': /* crash mode */
if (crash_mode) FATAL("Multiple -C options not supported");
@ -7957,27 +7978,34 @@ int main(int argc, char** argv) {
break;
case 'n': /* dumb mode */
// 处理-dumb模式的选项当程序收到'-n'时触发
if (dumb_mode) FATAL("Multiple -n options not supported");
if (getenv("AFL_DUMB_FORKSRV")) dumb_mode = 2; else dumb_mode = 1;
break;
/* 处理命令行选项 */
case 'T': /* banner */
/* 检查是否支持多个 -T 选项 */
if (use_banner) FATAL("Multiple -T options not supported");
use_banner = optarg;
break;
// 处理QEMU模式的代码段
// 如果启用QEMU模式检查是否已指定多个-Q选项
// 如果未指定内存限制则使用默认的QEMU内存限制
// 在处理完成后退出switch语句
case 'Q': /* QEMU mode */
if (qemu_mode) FATAL("Multiple -Q options not supported");
qemu_mode = 1;
if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
break;
case 'Q': /* QEMU mode */
if (qemu_mode) FATAL("Multiple -Q options not supported");
qemu_mode = 1;
if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
break;
/* 处理选项 'V' 的情况,显示版本号 */
case 'V': /* Show version number */
/* Version number has been printed already, just quit. */
@ -7989,44 +8017,57 @@ int main(int argc, char** argv) {
}
if (optind == argc || !in_dir || !out_dir) usage(argv[0]);
setup_signal_handlers();
check_asan_opts();
if (sync_id) fix_up_sync();
if (!strcmp(in_dir, out_dir))
FATAL("Input and output directories can't be the same");
if (dumb_mode) {
if (crash_mode) FATAL("-C and -n are mutually exclusive");
if (qemu_mode) FATAL("-Q and -n are mutually exclusive");
}
if (getenv("AFL_NO_FORKSRV")) no_forkserver = 1;
if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1;
if (getenv("AFL_NO_ARITH")) no_arith = 1;
if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1;
if (getenv("AFL_FAST_CAL")) fast_cal = 1;
if (getenv("AFL_HANG_TMOUT")) {
hang_tmout = atoi(getenv("AFL_HANG_TMOUT"));
if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT");
}
if (dumb_mode == 2 && no_forkserver)
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
// 检查命令行参数以及输入输出目录是否有效,若无效则显示使用方法
if (optind == argc || !in_dir || !out_dir) usage(argv[0]);
// 设置信号处理函数
setup_signal_handlers();
// 检查地址卫生选项
check_asan_opts();
// 处理同步ID和目录检查的逻辑
// 该段代码主要用于验证输入输出目录及模式的有效性
// 在不同的运行模式下进行相应的错误处理
if (sync_id) fix_up_sync();
if (!strcmp(in_dir, out_dir))
FATAL("Input and output directories can't be the same");
if (dumb_mode) {
if (crash_mode) FATAL("-C and -n are mutually exclusive");
if (qemu_mode) FATAL("-Q and -n are mutually exclusive");
}
if (getenv("AFL_PRELOAD")) {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
}
// 该代码段用于读取环境变量并根据其值设置相应的标志和超时值
// 主要功能是启动时配置这些参数以调整程序的行为
if (getenv("AFL_NO_FORKSRV")) no_forkserver = 1;
if (getenv("AFL_NO_CPU_RED")) no_cpu_meter_red = 1;
if (getenv("AFL_NO_ARITH")) no_arith = 1;
if (getenv("AFL_SHUFFLE_QUEUE")) shuffle_queue = 1;
if (getenv("AFL_FAST_CAL")) fast_cal = 1;
if (getenv("AFL_HANG_TMOUT")) {
hang_tmout = atoi(getenv("AFL_HANG_TMOUT"));
if (!hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT");
}
if (getenv("AFL_LD_PRELOAD"))
FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
// 此函数用于检查环境变量和启动模式的合法性
// 如果在不支持的模式下使用互斥选项,则会引发致命错误
// 处理环境变量以确保正确的库加载
if (dumb_mode == 2 && no_forkserver)
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
if (getenv("AFL_PRELOAD")) {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
}
if (getenv("AFL_LD_PRELOAD"))
FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
save_cmdline(argc, argv);
@ -8037,104 +8078,142 @@ int main(int argc, char** argv) {
get_core_count();
#ifdef HAVE_AFFINITY
// 将当前进程绑定到一个空闲的CPU上以优化性能
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))
@ -8142,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++;
}
if (queue_cur) show_stats();
// 更新当前队列指针和当前条目计数
queue_cur = queue_cur->next;
current_entry++;
/* 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();
/*
*
* forkserverforkserver使
*
*/
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) {

Loading…
Cancel
Save