“18670363079” 2 months ago
commit 0319921f2d

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "windows-gcc-x86",
"includePath": [
"${workspaceFolder}/**"
],
"compilerPath": "C:/Program Files/MinGW/bin/gcc.exe",
"cStandard": "${default}",
"cppStandard": "${default}",
"intelliSenseMode": "windows-gcc-x86",
"compilerArgs": [
""
]
}
],
"version": 4
}

File diff suppressed because it is too large Load Diff

@ -14,6 +14,8 @@
limitations under the License. limitations under the License.
*/ */
// 这部分是版权声明和许可证信息说明这个文件是在Apache License 2.0下发布的。
/* /*
american fuzzy lop - wrapper for GCC and clang american fuzzy lop - wrapper for GCC and clang
---------------------------------------------- ----------------------------------------------
@ -38,7 +40,7 @@
specify its location via AFL_CC or AFL_CXX. specify its location via AFL_CC or AFL_CXX.
*/ */
// 这部分是注释,提供了关于这个程序的概述和使用说明。
#define AFL_MAIN #define AFL_MAIN
#include "config.h" #include "config.h"
@ -51,6 +53,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
// 这些是包含的头文件其中一些是AFL自己的头文件其他的是C标准库的头文件
static u8* as_path; /* Path to the AFL 'as' wrapper */ static u8* as_path; /* Path to the AFL 'as' wrapper */
static u8** cc_params; /* Parameters passed to the real CC */ static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */ static u32 cc_par_cnt = 1; /* Param count, including argv0 */
@ -58,11 +62,14 @@ static u8 be_quiet, /* Quiet mode */
clang_mode; /* Invoked as afl-clang*? */ clang_mode; /* Invoked as afl-clang*? */
// 这些是全局变量声明。`as_path`存储AFL汇编器的路径`cc_params`存储传递给实际编译器的参数,`cc_par_cnt`是参数计数器,`be_quiet`用于控制
// 是否静默模式,`clang_mode`指示是否以`afl-clang`或`afl-clang++`模式调用。
/* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived /* Try to find our "fake" GNU assembler in AFL_PATH or at the location derived
from argv[0]. If that fails, abort. */ from argv[0]. If that fails, abort. */
static void find_as(u8* argv0) { static void find_as(u8* argv0) {
// 这个函数尝试在AFL_PATH环境变量指定的路径或从argv[0]派生的路径中找到AFL的“假”GNU汇编器。如果找不到程序将终止。
u8 *afl_path = getenv("AFL_PATH"); u8 *afl_path = getenv("AFL_PATH");
u8 *slash, *tmp; u8 *slash, *tmp;
@ -116,31 +123,32 @@ static void find_as(u8* argv0) {
/* Copy argv to cc_params, making the necessary edits. */ /* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char** argv) { static void edit_params(u32 argc, char** argv) {
//定义了一个函数edit_params它接受两个参数argc是参数的数量argv是参数的数组。
u8 fortify_set = 0, asan_set = 0; u8 fortify_set = 0, asan_set = 0;//声明两个变量fortify_set和asan_set用于跟踪是否已经设置了FORTIFY_SOURCE和address sanitizerASan标志
u8 *name; u8 *name;//用于存储程序的名称
#if defined(__FreeBSD__) && defined(__x86_64__) #if defined(__FreeBSD__) && defined(__x86_64__)
u8 m32_set = 0; u8 m32_set = 0;
#endif #endif
cc_params = ck_alloc((argc + 128) * sizeof(u8*)); cc_params = ck_alloc((argc + 128) * sizeof(u8*));//分配内存以存储修改后的参数列表大小为argc + 128个u8*类型的指针。
name = strrchr(argv[0], '/'); name = strrchr(argv[0], '/');//找到argv[0](程序的路径)中最后一个'/'字符,这通常用于获取程序的名称。
if (!name) name = argv[0]; else name++; if (!name) name = argv[0]; else name++;//如果name为NULL即argv[0]中没有'/'则name指向argv[0]的开始。否则name向前移动一个字符跳过'/'。
if (!strncmp(name, "afl-clang", 9)) { if (!strncmp(name, "afl-clang", 9)) {
clang_mode = 1; clang_mode = 1;//检查程序名称是否以"afl-clang"开头如果是设置clang_mode标志为1
setenv(CLANG_ENV_VAR, "1", 1); setenv(CLANG_ENV_VAR, "1", 1);//设置环境变量CLANG_ENV_VAR为"1"这可能用于通知其他部分的AFL工具链正在使用Clang。
if (!strcmp(name, "afl-clang++")) { if (!strcmp(name, "afl-clang++")) {
u8* alt_cxx = getenv("AFL_CXX"); u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++"; cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";//如果AFL_CXX设置将其值作为第一个参数否则使用"clang++"。
} else { } else {
u8* alt_cc = getenv("AFL_CC"); u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";//否则尝试获取环境变量AFL_CC的值。
} }
} else { } else {
@ -152,13 +160,13 @@ static void edit_params(u32 argc, char** argv) {
binaries. Meh. */ binaries. Meh. */
#ifdef __APPLE__ #ifdef __APPLE__
//在Apple系统上根据程序名称设置不同的编译器。如果AFL_CXX、AFL_GCJ或AFL_CC环境变量设置使用它们的值否则使用默认的编译器名称
if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX"); if (!strcmp(name, "afl-g++")) cc_params[0] = getenv("AFL_CXX");
else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ"); else if (!strcmp(name, "afl-gcj")) cc_params[0] = getenv("AFL_GCJ");
else cc_params[0] = getenv("AFL_CC"); else cc_params[0] = getenv("AFL_CC");
if (!cc_params[0]) { if (!cc_params[0]) {
//输出错误信息指出在MacOS X上需要设置AFL_CC或AFL_CXX环境变量。
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST
"On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n" "On Apple systems, 'gcc' is usually just a wrapper for clang. Please use the\n"
" 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n" " 'afl-clang' utility instead of 'afl-gcc'. If you really have GCC installed,\n"
@ -169,7 +177,7 @@ static void edit_params(u32 argc, char** argv) {
} }
#else #else
//对于非Apple系统根据程序名称设置不同的编译器。如果相应的环境变量设置使用它们的值否则使用默认的编译器名称。
if (!strcmp(name, "afl-g++")) { if (!strcmp(name, "afl-g++")) {
u8* alt_cxx = getenv("AFL_CXX"); u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++"; cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++";
@ -188,27 +196,27 @@ static void edit_params(u32 argc, char** argv) {
while (--argc) { while (--argc) {
u8* cur = *(++argv); u8* cur = *(++argv);
if (!strncmp(cur, "-B", 2)) { if (!strncmp(cur, "-B", 2)) {//如果当前参数以"-B"开头,输出警告信息,并跳过后续参数(如果当前参数后面紧跟着的是编译器的路径)。
if (!be_quiet) WARNF("-B is already set, overriding"); if (!be_quiet) WARNF("-B is already set, overriding");//如果程序不在静默模式,输出警告信息。
if (!cur[2] && argc > 1) { argc--; argv++; } if (!cur[2] && argc > 1) { argc--; argv++; }//如果-B后面紧跟着的是编译器的路径跳过这个路径。
continue; continue;
} }
if (!strcmp(cur, "-integrated-as")) continue; if (!strcmp(cur, "-integrated-as")) continue;//如果参数是"-integrated-as",跳过它。
if (!strcmp(cur, "-pipe")) continue; if (!strcmp(cur, "-pipe")) continue;//如果参数是"-pipe",跳过它。
#if defined(__FreeBSD__) && defined(__x86_64__) #if defined(__FreeBSD__) && defined(__x86_64__)
if (!strcmp(cur, "-m32")) m32_set = 1; if (!strcmp(cur, "-m32")) m32_set = 1;
#endif #endif
if (!strcmp(cur, "-fsanitize=address") || if (!strcmp(cur, "-fsanitize=address") ||
!strcmp(cur, "-fsanitize=memory")) asan_set = 1; !strcmp(cur, "-fsanitize=memory")) asan_set = 1;//如果参数是"-fsanitize=address"或"-fsanitize=memory"设置asan_set标志。
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;//如果参数包含"FORTIFY_SOURCE"设置fortify_set标志。
cc_params[cc_par_cnt++] = cur; cc_params[cc_par_cnt++] = cur;
@ -216,9 +224,11 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-B"; cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = as_path; cc_params[cc_par_cnt++] = as_path;
//向参数列表中添加"-B"和AFL汇编器的路径。
if (clang_mode) if (clang_mode)
cc_params[cc_par_cnt++] = "-no-integrated-as"; cc_params[cc_par_cnt++] = "-no-integrated-as";//如果clang_mode标志设置向参数列表中添加`"-no-integrated-as"
if (getenv("AFL_HARDEN")) { if (getenv("AFL_HARDEN")) {
@ -229,38 +239,38 @@ static void edit_params(u32 argc, char** argv) {
} }
if (asan_set) { if (asan_set) {//检查是否设置了asan_set标志。
/* Pass this on to afl-as to adjust map density. */ /* Pass this on to afl-as to adjust map density. */
setenv("AFL_USE_ASAN", "1", 1); setenv("AFL_USE_ASAN", "1", 1);//如果设置设置环境变量AFL_USE_ASAN为"1"
} else if (getenv("AFL_USE_ASAN")) { } else if (getenv("AFL_USE_ASAN")) {//如果asan_set标志未设置但设置了环境变量AFL_USE_ASAN。
if (getenv("AFL_USE_MSAN")) if (getenv("AFL_USE_MSAN"))
FATAL("ASAN and MSAN are mutually exclusive"); FATAL("ASAN and MSAN are mutually exclusive");//如果同时设置了AFL_USE_MSAN输出错误信息并终止程序。
if (getenv("AFL_HARDEN")) if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive"); FATAL("ASAN and AFL_HARDEN are mutually exclusive");//如果同时设置了AFL_HARDEN输出错误信息并终止程序。
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=address"; cc_params[cc_par_cnt++] = "-fsanitize=address";//向参数列表中添加"-U_FORTIFY_SOURCE"和"-fsanitize=address"。
} else if (getenv("AFL_USE_MSAN")) { } else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN")) if (getenv("AFL_USE_ASAN"))
FATAL("ASAN and MSAN are mutually exclusive"); FATAL("ASAN and MSAN are mutually exclusive");//如果同时设置了AFL_USE_ASAN输出错误信息并终止程序。
if (getenv("AFL_HARDEN")) if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive"); FATAL("MSAN and AFL_HARDEN are mutually exclusive");//如果同时设置了AFL_HARDEN输出错误信息并终止程序。
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=memory"; cc_params[cc_par_cnt++] = "-fsanitize=memory";//向参数列表中添加"-U_FORTIFY_SOURCE"和"-fsanitize=memory"。
} }
if (!getenv("AFL_DONT_OPTIMIZE")) { if (!getenv("AFL_DONT_OPTIMIZE")) {//检查是否设置了环境变量AFL_DONT_OPTIMIZE。
#if defined(__FreeBSD__) && defined(__x86_64__) #if defined(__FreeBSD__) && defined(__x86_64__)
@ -269,22 +279,23 @@ static void edit_params(u32 argc, char** argv) {
that bug. */ that bug. */
if (!clang_mode || !m32_set) if (!clang_mode || !m32_set)
cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-g";//如果不是Clang模式或没有设置m32_set标志向参数列表中添加"-g"。
#else #else
cc_params[cc_par_cnt++] = "-g"; cc_params[cc_par_cnt++] = "-g";
#endif #endif//结束#if defined(__FreeBSD__) && defined(__x86_64__)条件编译块。
cc_params[cc_par_cnt++] = "-O3"; cc_params[cc_par_cnt++] = "-O3";
cc_params[cc_par_cnt++] = "-funroll-loops"; cc_params[cc_par_cnt++] = "-funroll-loops";//向参数列表中添加"-O3"和"-funroll-loops",这些是优化选项。
/* Two indicators that you're building for fuzzing; one of them is /* Two indicators that you're building for fuzzing; one of them is
AFL-specific, the other is shared with libfuzzer. */ AFL-specific, the other is shared with libfuzzer. */
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1"; cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1"; cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
//向参数列表中添加两个宏定义,这些宏定义指示编译器代码将用于模糊测试。
} }
@ -297,7 +308,7 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp"; cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr"; cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr"; cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
//如果设置,向参数列表中添加一系列"-fno-builtin-*"选项,这些选项禁用编译器的内置函数。
} }
cc_params[cc_par_cnt] = NULL; cc_params[cc_par_cnt] = NULL;
@ -306,7 +317,7 @@ static void edit_params(u32 argc, char** argv) {
/* Main entry point */ /* Main entry point */
//最后是函数结束语,结束函数定义。
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (isatty(2) && !getenv("AFL_QUIET")) { if (isatty(2) && !getenv("AFL_QUIET")) {

@ -54,31 +54,31 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/resource.h> #include <sys/resource.h>
static s32 child_pid; /* PID of the tested program */ static s32 child_pid; /* 被测试程序的进程 PID */
static u8* trace_bits; /* SHM with instrumentation bitmap */ static u8* trace_bits; /* 用于存储插桩信息的共享内存 */
static u8 *out_file, /* Trace output file */ static u8 *out_file, /* 输出文件路径 */
*doc_path, /* Path to docs */ *doc_path, /* 文档目录路径 */
*target_path, /* Path to target binary */ *target_path, /* 被测目标程序的路径 */
*at_file; /* Substitution string for @@ */ *at_file; /* `@@` 的替换字符串,用于输入文件 */
static u32 exec_tmout; /* Exec timeout (ms) */ static u32 exec_tmout; /* 测试程序的执行超时时间 (毫秒) */
static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ static u64 mem_limit = MEM_LIMIT; /* 测试程序的内存限制 (MB) */
static s32 shm_id; /* ID of the SHM region */ static s32 shm_id; /* 共享内存 (SHM) 的标识符 */
static u8 quiet_mode, /* Hide non-essential messages? */ static u8 quiet_mode, /* 是否隐藏非必要的信息 */
edges_only, /* Ignore hit counts? */ edges_only, /* 是否只关心边覆盖率 */
cmin_mode, /* Generate output in afl-cmin mode? */ cmin_mode, /* 是否以 `afl-cmin` 模式生成输出 */
binary_mode, /* Write output as a binary map */ binary_mode, /* 是否以二进制方式输出插桩信息 */
keep_cores; /* Allow coredumps? */ keep_cores; /* A是否允许生成 core dump 文件 */
static volatile u8 static volatile u8
stop_soon, /* Ctrl-C pressed? */ stop_soon, /* 是否按下了 Ctrl-C (中止标志) */
child_timed_out, /* Child timed out? */ child_timed_out, /* 子进程是否超时 */
child_crashed; /* Child crashed? */ child_crashed; /* 子进程是否崩溃 */
/* Classify tuple counts. Instead of mapping to individual bits, as in /* Classify tuple counts. Instead of mapping to individual bits, as in
afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */
@ -95,7 +95,7 @@ static const u8 count_class_human[256] = {
[32 ... 127] = 7, [32 ... 127] = 7,
[128 ... 255] = 8 [128 ... 255] = 8
}; }; // 映射插桩命中计数到 1-8 的更具可读性的区间。0 代表未命中1-3 被保留为原值;其余区间依次分段映射,便于统计分析。
static const u8 count_class_binary[256] = { static const u8 count_class_binary[256] = {
@ -109,23 +109,24 @@ static const u8 count_class_binary[256] = {
[32 ... 127] = 64, [32 ... 127] = 64,
[128 ... 255] = 128 [128 ... 255] = 128
}; }; // 将插桩计数按指数方式映射到二进制值,便于程序进一步处理。
static void classify_counts(u8* mem, const u8* map) { static void classify_counts(u8* mem, const u8* map) {//对插桩命中计数 (mem) 进行分类处理,基于全局变量 edges_only 的值选择分类模式。
//u8* mem插桩数据的内存指针。const u8* map分类映射表
u32 i = MAP_SIZE; u32 i = MAP_SIZE;
if (edges_only) { if (edges_only) {
while (i--) { while (i--) {
if (*mem) *mem = 1; if (*mem) *mem = 1;// 只关心边的覆盖情况,命中计数直接归一
mem++; mem++;
} }
} else { } else {
while (i--) { while (i--) {
*mem = map[*mem]; *mem = map[*mem];// 使用提供的映射表对命中计数进行分类
mem++; mem++;
} }
@ -134,95 +135,105 @@ static void classify_counts(u8* mem, const u8* map) {
} }
/* Get rid of shared memory (atexit handler). */ /* 删除共享内存 (atexit 处理程序). */
static void remove_shm(void) { static void remove_shm(void) {//释放分配的共享内存。
shmctl(shm_id, IPC_RMID, NULL); shmctl(shm_id, IPC_RMID, NULL); //使用 shmctl 函数删除共享内存区域
//IPC_RMID 标志用于标记共享内存为 "移除",在无其他进程访问后会自动释放。
//通过 atexit 注册,在程序退出时自动调用,确保清理资源。
} }
/* Configure shared memory. */ /* 配置共享内存 */
static void setup_shm(void) { static void setup_shm(void) {// 创建共享内存,分配给 trace_bits 用于记录插桩数据。通过 atexit 注册清理函数,确保资源的释放。
u8* shm_str; u8* shm_str;
/* 创建一个私有的共享内存区域,大小为 MAP_SIZE */
shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
if (shm_id < 0) PFATAL("shmget() failed"); if (shm_id < 0) PFATAL("shmget() failed");/* 创建失败时输出错误并退出 */
atexit(remove_shm); atexit(remove_shm);/* 注册 atexit 处理程序以在程序退出时删除共享内存 */
/* 将共享内存 ID 转换为字符串并设置环境变量 */
shm_str = alloc_printf("%d", shm_id); shm_str = alloc_printf("%d", shm_id);
setenv(SHM_ENV_VAR, shm_str, 1); setenv(SHM_ENV_VAR, shm_str, 1);
ck_free(shm_str); ck_free(shm_str);/* 释放临时字符串内存 */
/* 将共享内存附加到当前进程的地址空间 */
trace_bits = shmat(shm_id, NULL, 0); trace_bits = shmat(shm_id, NULL, 0);
if (trace_bits == (void *)-1) PFATAL("shmat() failed"); if (trace_bits == (void *)-1) PFATAL("shmat() failed"); /* 附加失败时退出 */
} }
/* Write results. */ <<<<<<< HEAD
/* 写入测试结果 */
=======
/* 配置共享内存。 */
>>>>>>> 31b9bf56f4cc249d8b6bb414203bff28d8cf724a
static u32 write_results(void) { static u32 write_results(void) { //将插桩结果输出到文件,支持二进制和文本模式。
s32 fd; s32 fd; /* 文件描述符 */
u32 i, ret = 0; u32 i, ret = 0; /* 计数器和返回值 */
u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), /* 仅输出崩溃路径? */
caa = !!getenv("AFL_CMIN_ALLOW_ANY"); caa = !!getenv("AFL_CMIN_ALLOW_ANY"); /* 是否允许所有路径? */
if (!strncmp(out_file, "/dev/", 5)) { /* 根据输出文件路径的类型处理 */
if (!strncmp(out_file, "/dev/", 5)) { /* 如果是设备文件路径 */
fd = open(out_file, O_WRONLY, 0600); fd = open(out_file, O_WRONLY, 0600);
if (fd < 0) PFATAL("Unable to open '%s'", out_file); if (fd < 0) PFATAL("Unable to open '%s'", out_file);
} else if (!strcmp(out_file, "-")) { } else if (!strcmp(out_file, "-")) { /* 如果是标准输出 */
fd = dup(1); fd = dup(1); /* 复制标准输出描述符 */
if (fd < 0) PFATAL("Unable to open stdout"); if (fd < 0) PFATAL("Unable to open stdout");
} else { } else { /* 普通文件路径 */
unlink(out_file); /* Ignore errors */ unlink(out_file); /* 删除已有的同名文件 (忽略错误) */
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", out_file); if (fd < 0) PFATAL("Unable to create '%s'", out_file);
} }
/* 如果以二进制模式输出结果 */
if (binary_mode) { if (binary_mode) {
for (i = 0; i < MAP_SIZE; i++) for (i = 0; i < MAP_SIZE; i++)
if (trace_bits[i]) ret++; if (trace_bits[i]) ret++;/* 统计非零插桩计数 */
ck_write(fd, trace_bits, MAP_SIZE, out_file); ck_write(fd, trace_bits, MAP_SIZE, out_file);/* 将插桩数据写入文件 */
close(fd); close(fd);
} else { } else { /* 文本模式输出 */
FILE* f = fdopen(fd, "w"); FILE* f = fdopen(fd, "w");
if (!f) PFATAL("fdopen() failed"); if (!f) PFATAL("fdopen() failed");
/* 遍历插桩数据,按文本格式输出 */
for (i = 0; i < MAP_SIZE; i++) { for (i = 0; i < MAP_SIZE; i++) {
if (!trace_bits[i]) continue; if (!trace_bits[i]) continue;/* 跳过空条目 */
ret++; ret++;
if (cmin_mode) { if (cmin_mode) {/* afl-cmin 模式 */
if (child_timed_out) break; if (child_timed_out) break; /* 如果子进程超时,停止输出 */
if (!caa && child_crashed != cco) break; if (!caa && child_crashed != cco) break;/* 根据环境变量条件过滤 */
fprintf(f, "%u%u\n", trace_bits[i], i); fprintf(f, "%u%u\n", trace_bits[i], i);
} else fprintf(f, "%06u:%u\n", i, trace_bits[i]); } else fprintf(f, "%06u:%u\n", i, trace_bits[i]);/* 标准格式 */
} }
@ -235,42 +246,54 @@ static u32 write_results(void) {
} }
/* Handle timeout signal. */ <<<<<<< HEAD
/* 处理超时信号 */
=======
/* 处理超时信号。 */
>>>>>>> 31b9bf56f4cc249d8b6bb414203bff28d8cf724a
static void handle_timeout(int sig) { static void handle_timeout(int sig) {
child_timed_out = 1; child_timed_out = 1; /* 设置子进程超时标志 */
if (child_pid > 0) kill(child_pid, SIGKILL); if (child_pid > 0) kill(child_pid, SIGKILL); /* 强制杀死子进程 */
} }
/* Execute target application. */ <<<<<<< HEAD
/* 执行目标程序 */
=======
/* 执行目标应用程序。 */
/* 运行目标程序并等待其结束。 */
/* 处理超时和信号。 */
>>>>>>> 31b9bf56f4cc249d8b6bb414203bff28d8cf724a
static void run_target(char** argv) { static void run_target(char** argv) {
static struct itimerval it; static struct itimerval it;/* 定时器结构 */
int status = 0; int status = 0;
if (!quiet_mode) if (!quiet_mode)
SAYF("-- Program output begins --\n" cRST); SAYF("-- Program output begins --\n" cRST);/* 输出调试信息 */
MEM_BARRIER(); MEM_BARRIER(); /* 防止编译器重排内存操作 */
child_pid = fork(); child_pid = fork();/* 创建子进程 */
if (child_pid < 0) PFATAL("fork() failed"); if (child_pid < 0) PFATAL("fork() failed");/* 如果 fork 失败,退出程序 */
if (!child_pid) { if (!child_pid) { /* 子进程逻辑 */
struct rlimit r; struct rlimit r;
if (quiet_mode) { if (quiet_mode) { /* 如果静默模式开启,将子进程输出重定向到 `/dev/null` */
s32 fd = open("/dev/null", O_RDWR); s32 fd = open("/dev/null", O_RDWR);
if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) { if (fd < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) {
*(u32*)trace_bits = EXEC_FAIL_SIG; *(u32*)trace_bits = EXEC_FAIL_SIG; /* 设置错误标志 */
PFATAL("Descriptor initialization failed"); PFATAL("Descriptor initialization failed");
} }
@ -278,35 +301,35 @@ static void run_target(char** argv) {
} }
if (mem_limit) { if (mem_limit) {/* 设置子进程内存限制 */
r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20; r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
#ifdef RLIMIT_AS #ifdef RLIMIT_AS
setrlimit(RLIMIT_AS, &r); /* Ignore errors */ setrlimit(RLIMIT_AS, &r); /* 设置内存限制 (按地址空间限制),忽略错误 */
#else #else
setrlimit(RLIMIT_DATA, &r); /* Ignore errors */ setrlimit(RLIMIT_DATA, &r); /* 设置内存限制 (按数据段大小限制),忽略错误 */
#endif /* ^RLIMIT_AS */ #endif /* ^RLIMIT_AS */
} }
// 根据平台使用适当的资源限制类型 (RLIMIT_AS 或 RLIMIT_DATA) 限制子进程的内存使用。
if (!keep_cores) r.rlim_max = r.rlim_cur = 0; /* 禁止 core dump */
// 控制是否允许子进程生成 core dump 文件。
else r.rlim_max = r.rlim_cur = RLIM_INFINITY; /* 允许无限 core dump */
if (!keep_cores) r.rlim_max = r.rlim_cur = 0; setrlimit(RLIMIT_CORE, &r); /* 设置 core dump 限制,忽略错误 */
else r.rlim_max = r.rlim_cur = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); // 强制目标程序加载动态库时立即绑定符号,避免延迟加载可能引发的问题。
setsid(); setsid(); /* 创建一个新会话,隔离子进程 */
execv(target_path, argv); execv(target_path, argv);/* 替换当前进程镜像为目标程序 */
*(u32*)trace_bits = EXEC_FAIL_SIG; *(u32*)trace_bits = EXEC_FAIL_SIG; /* 如果 execv 返回,则标记执行失败 */
exit(0); exit(0);/* 终止子进程 */
} }
@ -320,9 +343,9 @@ static void run_target(char** argv) {
} }
setitimer(ITIMER_REAL, &it, NULL); setitimer(ITIMER_REAL, &it, NULL);/* 配置超时定时器 */
if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); /* 等待子进程结束 */
child_pid = 0; child_pid = 0;
it.it_value.tv_sec = 0; it.it_value.tv_sec = 0;
@ -338,7 +361,7 @@ static void run_target(char** argv) {
classify_counts(trace_bits, binary_mode ? classify_counts(trace_bits, binary_mode ?
count_class_binary : count_class_human); count_class_binary : count_class_human);
/* 将 trace_bits 中的插桩命中数据分类为二进制或人类可读格式 */
if (!quiet_mode) if (!quiet_mode)
SAYF(cRST "-- Program output ends --\n"); SAYF(cRST "-- Program output ends --\n");
@ -362,11 +385,11 @@ static void run_target(char** argv) {
/* Handle Ctrl-C and the like. */ /* Handle Ctrl-C and the like. */
static void handle_stop_sig(int sig) { static void handle_stop_sig(int sig) {//捕获停止信号 (SIGHUP, SIGINT, SIGTERM) 并设置全局停止标志。终止子进程以确保程序退出。
stop_soon = 1; stop_soon = 1;/* 设置标志,通知主程序停止 */
if (child_pid > 0) kill(child_pid, SIGKILL); if (child_pid > 0) kill(child_pid, SIGKILL);/* 强制杀死子进程 */
} }
@ -374,7 +397,7 @@ static void handle_stop_sig(int sig) {
/* Do basic preparations - persistent fds, filenames, etc. */ /* Do basic preparations - persistent fds, filenames, etc. */
static void set_up_environment(void) { static void set_up_environment(void) {
// 设置环境变量,配置 AddressSanitizer (ASAN) 和 MemorySanitizer (MSAN) 行为:禁用内存泄漏检测 (detect_leaks=0)。禁用符号化输出 (symbolize=0)。配置错误退出行为 (abort_on_error=1)。
setenv("ASAN_OPTIONS", "abort_on_error=1:" setenv("ASAN_OPTIONS", "abort_on_error=1:"
"detect_leaks=0:" "detect_leaks=0:"
"symbolize=0:" "symbolize=0:"
@ -385,7 +408,7 @@ static void set_up_environment(void) {
"abort_on_error=1:" "abort_on_error=1:"
"allocator_may_return_null=1:" "allocator_may_return_null=1:"
"msan_track_origins=0", 0); "msan_track_origins=0", 0);
// 如果存在 AFL_PRELOAD 环境变量,将其设置为动态库预加载路径。
if (getenv("AFL_PRELOAD")) { if (getenv("AFL_PRELOAD")) {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@ -407,32 +430,34 @@ static void setup_signal_handlers(void) {
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
/* Various ways of saying "stop". */ /* Various ways of saying "stop". */
// 为停止信号 (SIGHUP, SIGINT, SIGTERM) 注册处理函数 handle_stop_sig。
sa.sa_handler = handle_stop_sig; sa.sa_handler = handle_stop_sig; /* 设置停止信号的处理函数 */
sigaction(SIGHUP, &sa, NULL); sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL); sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL); sigaction(SIGTERM, &sa, NULL);
/* Exec timeout notifications. */ /* Exec timeout notifications. */
sa.sa_handler = handle_timeout; sa.sa_handler = handle_timeout;/* 设置超时信号的处理函数 */
sigaction(SIGALRM, &sa, NULL); sigaction(SIGALRM, &sa, NULL);
} }
/* Detect @@ in args. */ /* 检测@@在参数中。 */
/* 检测并替换@@参数。 */
/* 用于处理传递给目标程序的文件路径参数。 */
static void detect_file_args(char** argv) { static void detect_file_args(char** argv) {
// 获取当前工作目录,用于构造绝对路径。
u32 i = 0; u32 i = 0;
u8* cwd = getcwd(NULL, 0); u8* cwd = getcwd(NULL, 0);/* 获取当前工作目录 */
if (!cwd) PFATAL("getcwd() failed"); if (!cwd) PFATAL("getcwd() failed");
while (argv[i]) { while (argv[i]) {
u8* aa_loc = strstr(argv[i], "@@"); u8* aa_loc = strstr(argv[i], "@@");/* 查找命令行参数中的 @@ */
if (aa_loc) { if (aa_loc) {
@ -442,13 +467,13 @@ static void detect_file_args(char** argv) {
/* Be sure that we're always using fully-qualified paths. */ /* Be sure that we're always using fully-qualified paths. */
if (at_file[0] == '/') aa_subst = at_file; if (at_file[0] == '/') aa_subst = at_file;/* 如果是绝对路径,直接使用 */
else aa_subst = alloc_printf("%s/%s", cwd, at_file); else aa_subst = alloc_printf("%s/%s", cwd, at_file);/* 构造绝对路径 */
/* Construct a replacement argv value. */ /* Construct a replacement argv value. */
*aa_loc = 0; *aa_loc = 0;
n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2); n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2);/* 替换 @@ */
argv[i] = n_arg; argv[i] = n_arg;
*aa_loc = '@'; *aa_loc = '@';
@ -465,20 +490,25 @@ static void detect_file_args(char** argv) {
} }
<<<<<<< HEAD
/* Show banner. */ /* Show banner. */
// 打印工具的名称和版本信息。
=======
>>>>>>> 31b9bf56f4cc249d8b6bb414203bff28d8cf724a
static void show_banner(void) { static void show_banner(void) {
SAYF(cCYA "afl-showmap " cBRI VERSION cRST " by <lcamtuf@google.com>\n"); SAYF(cCYA "afl-showmap " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
} }
/* Display usage hints. */ /* 显示使用提示。 */
static void usage(u8* argv0) { static void usage(u8* argv0) {
show_banner(); show_banner();
// 显示工具的用法说明,包括参数和选项说明。
SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n" SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
"Required parameters:\n\n" "Required parameters:\n\n"
@ -492,7 +522,7 @@ static void usage(u8* argv0) {
" -Q - use binary-only instrumentation (QEMU mode)\n\n" " -Q - use binary-only instrumentation (QEMU mode)\n\n"
"Other settings:\n\n" "Other settings:\n\n"
// 描述可用的执行控制选项,包括超时时间和内存限制。
" -q - sink program's output and don't show messages\n" " -q - sink program's output and don't show messages\n"
" -e - show edge coverage only, ignore hit counts\n" " -e - show edge coverage only, ignore hit counts\n"
" -c - allow core dumps\n" " -c - allow core dumps\n"
@ -508,17 +538,23 @@ static void usage(u8* argv0) {
} }
<<<<<<< HEAD
/* Find binary. */ /* Find binary. */
// 找到目标程序的可执行文件路径 (target_path)。
=======
/* 查找二进制文件。 */
/* 查找并验证二进制文件。 */
/* 如果二进制文件不存在或不可执行,则打印错误信息并退出。 */
>>>>>>> 31b9bf56f4cc249d8b6bb414203bff28d8cf724a
static void find_binary(u8* fname) { static void find_binary(u8* fname) {
// fname目标程序的文件名。如果 fname 包含斜杠(表明是路径)或没有设置 PATH 环境变量,则直接检查 fname 是否是一个可执行文件。否则,遍历 PATH 环境变量中定义的路径,尝试找到 fname。
u8* env_path = 0; u8* env_path = 0;
struct stat st; struct stat st;
if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
// 如果 fname 是路径(包含斜杠),直接检查其合法性。
target_path = ck_strdup(fname); target_path = ck_strdup(fname);
// 如果 PATH 环境变量未设置,同样直接检查 fname。
if (stat(target_path, &st) || !S_ISREG(st.st_mode) || if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
!(st.st_mode & 0111) || st.st_size < 4) !(st.st_mode & 0111) || st.st_size < 4)
FATAL("Program '%s' not found or not executable", fname); FATAL("Program '%s' not found or not executable", fname);
@ -538,14 +574,14 @@ static void find_binary(u8* fname) {
} else cur_elem = ck_strdup(env_path); } else cur_elem = ck_strdup(env_path);
env_path = delim; env_path = delim;
// 按冒号分隔符解析 PATH 环境变量,依次检查每个路径是否包含目标文件。
if (cur_elem[0]) if (cur_elem[0])
target_path = alloc_printf("%s/%s", cur_elem, fname); target_path = alloc_printf("%s/%s", cur_elem, fname);
else else
target_path = ck_strdup(fname); target_path = ck_strdup(fname);
ck_free(cur_elem); ck_free(cur_elem);
// 将文件名与路径组合成完整路径。检查文件是否存在、是否是普通文件、是否可执行且文件大小合理。如果找到符合条件的文件路径,则退出循环。
if (!stat(target_path, &st) && S_ISREG(st.st_mode) && if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
(st.st_mode & 0111) && st.st_size >= 4) break; (st.st_mode & 0111) && st.st_size >= 4) break;
@ -553,7 +589,7 @@ static void find_binary(u8* fname) {
target_path = 0; target_path = 0;
} }
// 如果遍历完所有路径后仍未找到目标文件,则程序退出。
if (!target_path) FATAL("Program '%s' not found or not executable", fname); if (!target_path) FATAL("Program '%s' not found or not executable", fname);
} }
@ -561,24 +597,33 @@ static void find_binary(u8* fname) {
} }
<<<<<<< HEAD
/* Fix up argv for QEMU. */ /* Fix up argv for QEMU. */
// 为在 QEMU 模式下执行目标程序,调整参数列表 argv。
=======
/*修正argv以用于QEMU*/
/* 为QEMU模式修正参数*/
/* 返回新的参数数组*/
>>>>>>> 31b9bf56f4cc249d8b6bb414203bff28d8cf724a
static char** get_qemu_argv(u8* own_loc, char** argv, int argc) { static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
// own_loc当前程序的路径用于寻找 afl-qemu-trace。argv原始参数列表。argc参数个数。
char** new_argv = ck_alloc(sizeof(char*) * (argc + 4)); char** new_argv = ck_alloc(sizeof(char*) * (argc + 4));
u8 *tmp, *cp, *rsl, *own_copy; u8 *tmp, *cp, *rsl, *own_copy;
/* Workaround for a QEMU stability glitch. */ /* 设置 QEMU 的环境变量 QEMU_LOG禁用链式日志。 */
setenv("QEMU_LOG", "nochain", 1); setenv("QEMU_LOG", "nochain", 1);
memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc); memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc);
// 为新参数列表分配空间。
// 将原始参数 argv 复制到新参数列表的合适位置。
// 添加必要的 QEMU 参数 -- 和 target_path。
new_argv[2] = target_path; new_argv[2] = target_path;
new_argv[1] = "--"; new_argv[1] = "--";
/* Now we need to actually find qemu for argv[0]. */ /* Now we need to actually find qemu for argv[0]. */
// 检查 AFL_PATH 环境变量是否指向 afl-qemu-trace并验证其是否可执行。
tmp = getenv("AFL_PATH"); tmp = getenv("AFL_PATH");
if (tmp) { if (tmp) {
@ -592,7 +637,7 @@ static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
return new_argv; return new_argv;
} }
// 使用当前程序的路径 own_loc 尝试找到 afl-qemu-trace。
own_copy = ck_strdup(own_loc); own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/'); rsl = strrchr(own_copy, '/');
@ -611,40 +656,48 @@ static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
} }
} else ck_free(own_copy); } else ck_free(own_copy);
// 检查预定义路径 BIN_PATH 下是否存在 afl-qemu-trace。
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace"; target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace";
return new_argv; return new_argv;
} }
// 如果未找到 afl-qemu-trace程序退出并报错。
FATAL("Unable to find 'afl-qemu-trace'."); FATAL("Unable to find 'afl-qemu-trace'.");
} }
/* Main entry point */ /* Main entry point */
/*解析命令行参数并执行目标程序 */
/*根据参数执行不同的操作 */
int main(int argc, char** argv) { int main(int argc, char** argv) {
//opt用于存储当前解析的命令行选项。
//mem_limit_given标志是否设置了内存限制选项。
//timeout_given标志是否设置了超时选项。
//qemu_mode标志是否启用了 QEMU 模式。
//tcnt存储记录的插桩数据元组计数。
//use_argv用于执行目标程序的参数列表。
s32 opt; s32 opt;
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0; u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0;
u32 tcnt; u32 tcnt;
char** use_argv; char** use_argv;
// 检查 DOC_PATH 是否存在,如果不存在则回退到默认路径 "docs"。
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
// 使用 getopt 解析命令行选项,支持的选项包括:
while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQbcV")) > 0) while ((opt = getopt(argc,argv,"+o:m:t:A:eqZQbcV")) > 0)
switch (opt) { switch (opt) {
// -o指定输出文件。
case 'o': case 'o':
if (out_file) FATAL("Multiple -o options not supported"); if (out_file) FATAL("Multiple -o options not supported");
out_file = optarg; out_file = optarg;
break; break;
// -m设置内存限制。
case 'm': { case 'm': {
u8 suffix = 'M'; u8 suffix = 'M';
@ -681,7 +734,7 @@ int main(int argc, char** argv) {
} }
break; break;
// -t设置超时时间。
case 't': case 't':
if (timeout_given) FATAL("Multiple -t options not supported"); if (timeout_given) FATAL("Multiple -t options not supported");
@ -696,19 +749,19 @@ int main(int argc, char** argv) {
} }
break; break;
// -e只关注边覆盖率。
case 'e': case 'e':
if (edges_only) FATAL("Multiple -e options not supported"); if (edges_only) FATAL("Multiple -e options not supported");
edges_only = 1; edges_only = 1;
break; break;
// -q静默模式不显示多余信息。
case 'q': case 'q':
if (quiet_mode) FATAL("Multiple -q options not supported"); if (quiet_mode) FATAL("Multiple -q options not supported");
quiet_mode = 1; quiet_mode = 1;
break; break;
// -Z启用 afl-cmin 模式,内部使用,设置 cmin_mode 和 quiet_mode。
case 'Z': case 'Z':
/* This is an undocumented option to write data in the syntax expected /* This is an undocumented option to write data in the syntax expected
@ -717,13 +770,13 @@ int main(int argc, char** argv) {
cmin_mode = 1; cmin_mode = 1;
quiet_mode = 1; quiet_mode = 1;
break; break;
// -A设置 @@ 替换文件路径。
case 'A': case 'A':
/* Another afl-cmin specific feature. */ /* Another afl-cmin specific feature. */
at_file = optarg; at_file = optarg;
break; break;
// -Q启用 QEMU 模式,如果未指定内存限制,使用默认值 MEM_LIMIT_QEMU。
case 'Q': case 'Q':
if (qemu_mode) FATAL("Multiple -Q options not supported"); if (qemu_mode) FATAL("Multiple -Q options not supported");
@ -731,7 +784,7 @@ int main(int argc, char** argv) {
qemu_mode = 1; qemu_mode = 1;
break; break;
// -b启用二进制输出模式设置全局变量 binary_mode = 1。
case 'b': case 'b':
/* Secret undocumented mode. Writes output in raw binary format /* Secret undocumented mode. Writes output in raw binary format
@ -739,13 +792,13 @@ int main(int argc, char** argv) {
binary_mode = 1; binary_mode = 1;
break; break;
// -c允许生成核心转储文件设置全局变量 keep_cores = 1。
case 'c': case 'c':
if (keep_cores) FATAL("Multiple -c options not supported"); if (keep_cores) FATAL("Multiple -c options not supported");
keep_cores = 1; keep_cores = 1;
break; break;
// -V显示版本号并退出程序。
case 'V': case 'V':
show_banner(); show_banner();
@ -757,39 +810,40 @@ int main(int argc, char** argv) {
} }
if (optind == argc || !out_file) usage(argv[0]); if (optind == argc || !out_file) usage(argv[0]); //如果未指定目标程序路径或输出文件,则显示用法说明并退出。
setup_shm(); setup_shm();// 调用 setup_shm 函数,配置用于插桩数据存储的共享内存。
setup_signal_handlers(); setup_signal_handlers();// 注册信号处理函数处理程序停止SIGINT、SIGTERM或超时SIGALRM等事件。
set_up_environment(); set_up_environment();// 配置环境变量,例如 ASAN_OPTIONS 和 MSAN_OPTIONS。
find_binary(argv[optind]); find_binary(argv[optind]);//使用 find_binary 函数查找目标程序的可执行文件路径,并存储到全局变量 target_path。
if (!quiet_mode) {
if (!quiet_mode) {// 如果未启用静默模式,显示工具信息和目标程序路径。
show_banner(); show_banner();
ACTF("Executing '%s'...\n", target_path); ACTF("Executing '%s'...\n", target_path);
} }
detect_file_args(argv + optind); detect_file_args(argv + optind); //检测命令行参数中的 @@ 并将其替换为指定的文件路径。
if (qemu_mode) if (qemu_mode) //如果启用了 QEMU 模式,调用 get_qemu_argv 函数为 QEMU 准备参数列表。
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind); use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
else else // 否则直接使用原始参数。
use_argv = argv + optind; use_argv = argv + optind;
run_target(use_argv); run_target(use_argv);
tcnt = write_results(); tcnt = write_results(); // 调用 write_results 函数,将插桩数据写入指定的输出文件。
if (!quiet_mode) { if (!quiet_mode) {
if (!tcnt) FATAL("No instrumentation detected" cRST); if (!tcnt) FATAL("No instrumentation detected" cRST); //如果没有捕获插桩数据,显示错误并退出。
OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file); OKF("Captured %u tuples in '%s'." cRST, tcnt, out_file); // 否则显示捕获的元组数量和输出文件路径。
} }
exit(child_crashed * 2 + child_timed_out); exit(child_crashed * 2 + child_timed_out);
// 根据子进程状态退出.如果子进程崩溃:返回 2。如果子进程超时返回 1。正常退出返回 0。
} }

@ -36,8 +36,7 @@
#include "types.h" #include "types.h"
#include "debug.h" #include "debug.h"
/* User-facing macro to sprintf() to a dynamically allocated buffer. */ /* 提供给用户使用的宏用于将sprintf()的输出到一个动态分配的缓冲区。 */
#define alloc_printf(_str...) ({ \ #define alloc_printf(_str...) ({ \
u8* _tmp; \ u8* _tmp; \
s32 _len = snprintf(NULL, 0, _str); \ s32 _len = snprintf(NULL, 0, _str); \
@ -47,29 +46,24 @@
_tmp; \ _tmp; \
}) })
/* Macro to enforce allocation limits as a last-resort defense against /* 宏,用于强制执行分配限制,作为防止整数溢出的最后一道防线。 */
integer overflows. */
#define ALLOC_CHECK_SIZE(_s) do { \ #define ALLOC_CHECK_SIZE(_s) do { \
if ((_s) > MAX_ALLOC) \ if ((_s) > MAX_ALLOC) \
ABORT("Bad alloc request: %u bytes", (_s)); \ ABORT("Bad alloc request: %u bytes", (_s)); \
} while (0) } while (0)
/* Macro to check malloc() failures and the like. */ /* 宏用于检查malloc()失败等情况。 */
#define ALLOC_CHECK_RESULT(_r, _s) do { \ #define ALLOC_CHECK_RESULT(_r, _s) do { \
if (!(_r)) \ if (!(_r)) \
ABORT("Out of memory: can't allocate %u bytes", (_s)); \ ABORT("Out of memory: can't allocate %u bytes", (_s)); \
} while (0) } while (0)
/* Magic tokens used to mark used / freed chunks. */ /* 用于标记已使用/已释放块的魔术标记。 */
#define ALLOC_MAGIC_C1 0xFF00FF00 /* 已使用头部(双字) */
#define ALLOC_MAGIC_C1 0xFF00FF00 /* Used head (dword) */ #define ALLOC_MAGIC_F 0xFE00FE00 /* 已释放头部(双字) */
#define ALLOC_MAGIC_F 0xFE00FE00 /* Freed head (dword) */ #define ALLOC_MAGIC_C2 0xF0 /* 已使用尾部(字节) */
#define ALLOC_MAGIC_C2 0xF0 /* Used tail (byte) */
/* Positions of guard tokens in relation to the user-visible pointer. */
/* 与用户可见指针相关的保护标记的位置。 */
#define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2]) #define ALLOC_C1(_ptr) (((u32*)(_ptr))[-2])
#define ALLOC_S(_ptr) (((u32*)(_ptr))[-1]) #define ALLOC_S(_ptr) (((u32*)(_ptr))[-1])
#define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)]) #define ALLOC_C2(_ptr) (((u8*)(_ptr))[ALLOC_S(_ptr)])
@ -77,15 +71,13 @@
#define ALLOC_OFF_HEAD 8 #define ALLOC_OFF_HEAD 8
#define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1) #define ALLOC_OFF_TOTAL (ALLOC_OFF_HEAD + 1)
/* Allocator increments for ck_realloc_block(). */ /* ck_realloc_block()的分配器增量。 */
#define ALLOC_BLK_INC 256 #define ALLOC_BLK_INC 256
/* Sanity-checking macros for pointers. */ /* 用于指针的合理性检查宏。 */
#define CHECK_PTR(_p) do { \ #define CHECK_PTR(_p) do { \
if (_p) { \ if (_p) { \
if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) {\ if (ALLOC_C1(_p) ^ ALLOC_MAGIC_C1) { \
if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \ if (ALLOC_C1(_p) == ALLOC_MAGIC_F) \
ABORT("Use after free."); \ ABORT("Use after free."); \
else ABORT("Corrupted head alloc canary."); \ else ABORT("Corrupted head alloc canary."); \
@ -101,246 +93,206 @@
_tmp; \ _tmp; \
}) })
/* 分配一个缓冲区明确不将其清零。对于零大小的请求返回NULL。 */
/* Allocate a buffer, explicitly not zeroing it. Returns NULL for zero-sized
requests. */
static inline void* DFL_ck_alloc_nozero(u32 size) { static inline void* DFL_ck_alloc_nozero(u32 size) {
void* ret; void* ret;
if (!size) return NULL; if (!size) return NULL;
ALLOC_CHECK_SIZE(size); ALLOC_CHECK_SIZE(size);
ret = malloc(size + ALLOC_OFF_TOTAL); ret = malloc(size + ALLOC_OFF_TOTAL);
ALLOC_CHECK_RESULT(ret, size); ALLOC_CHECK_RESULT(ret, size);
ret += ALLOC_OFF_HEAD; ret += ALLOC_OFF_HEAD;
ALLOC_C1(ret) = ALLOC_MAGIC_C1; ALLOC_C1(ret) = ALLOC_MAGIC_C1;
ALLOC_S(ret) = size; ALLOC_S(ret) = size;
ALLOC_C2(ret) = ALLOC_MAGIC_C2; ALLOC_C2(ret) = ALLOC_MAGIC_C2;
return ret; return ret;
} }
/* 分配一个缓冲区,返回清零后的内存。 */
/* Allocate a buffer, returning zeroed memory. */
static inline void* DFL_ck_alloc(u32 size) { static inline void* DFL_ck_alloc(u32 size) {
void* mem; void* mem;
if (!size) return NULL; if (!size) return NULL;
mem = DFL_ck_alloc_nozero(size); mem = DFL_ck_alloc_nozero(size);
return memset(mem, 0, size); return memset(mem, 0, size);
} }
/* Free memory, checking for double free and corrupted heap. When DEBUG_BUILD /* 释放内存检查是否重复释放和堆损坏。当DEBUG_BUILD被设置时
is set, the old memory will be also clobbered with 0xFF. */ 0xFF */
static inline void DFL_ck_free(void* mem) { static inline void DFL_ck_free(void* mem) {
if (!mem) return; /* 如果指针为空,不执行任何操作 */
if (!mem) return; CHECK_PTR(mem); /* 检查是否重复释放和堆损坏 */
CHECK_PTR(mem);
#ifdef DEBUG_BUILD
/* Catch pointer issues sooner. */
memset(mem, 0xFF, ALLOC_S(mem));
#ifdef DEBUG_BUILD /* 如果是调试构建用0xFF覆盖内存 */
/* 尽早捕捉指针问题。 */
memset(mem, 0xFF, ALLOC_S(mem)); /* 用0xFF覆盖内存 */
#endif /* DEBUG_BUILD */ #endif /* DEBUG_BUILD */
ALLOC_C1(mem) = ALLOC_MAGIC_F; ALLOC_C1(mem) = ALLOC_MAGIC_F; /* 标记内存为已释放 */
free(mem - ALLOC_OFF_HEAD);
free(mem - ALLOC_OFF_HEAD); /* 释放内存,调整头偏移 */
} }
/* 重新分配缓冲区,检查问题并清零任何新添加的尾部。
/* Re-allocate a buffer, checking for issues and zeroing any newly-added tail. DEBUG_BUILD0xFF */
With DEBUG_BUILD, the buffer is always reallocated to a new addresses and the
old memory is clobbered with 0xFF. */
static inline void* DFL_ck_realloc(void* orig, u32 size) { static inline void* DFL_ck_realloc(void* orig, u32 size) {
void* ret;
u32 old_size = 0;
void* ret; if (!size) {
u32 old_size = 0; DFL_ck_free(orig); /* 如果新大小为0释放原始内存 */
return NULL;
if (!size) { }
DFL_ck_free(orig);
return NULL;
}
if (orig) {
CHECK_PTR(orig); if (orig) {
CHECK_PTR(orig); /* 检查是否重复释放和堆损坏 */
#ifndef DEBUG_BUILD #ifndef DEBUG_BUILD /* 在非调试构建中,可以重用内存 */
ALLOC_C1(orig) = ALLOC_MAGIC_F; ALLOC_C1(orig) = ALLOC_MAGIC_F; /* 标记内存为已释放 */
#endif /* !DEBUG_BUILD */ #endif /* !DEBUG_BUILD */
old_size = ALLOC_S(orig); old_size = ALLOC_S(orig); /* 获取原始大小 */
orig -= ALLOC_OFF_HEAD; orig -= ALLOC_OFF_HEAD; /* 调整指针以适应头部偏移 */
ALLOC_CHECK_SIZE(old_size);
}
ALLOC_CHECK_SIZE(size);
#ifndef DEBUG_BUILD
ret = realloc(orig, size + ALLOC_OFF_TOTAL);
ALLOC_CHECK_RESULT(ret, size);
#else
/* Catch pointer issues sooner: force relocation and make sure that the
original buffer is wiped. */
ret = malloc(size + ALLOC_OFF_TOTAL);
ALLOC_CHECK_RESULT(ret, size);
if (orig) { ALLOC_CHECK_SIZE(old_size); /* 检查原始大小是否有效 */
}
memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size));
memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size);
ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; ALLOC_CHECK_SIZE(size); /* 检查新大小是否有效 */
free(orig); #ifndef DEBUG_BUILD /* 在非调试构建中,尝试原地调整内存大小 */
ret = realloc(orig, size + ALLOC_OFF_TOTAL); /* 重新分配内存 */
ALLOC_CHECK_RESULT(ret, size); /* 检查重新分配是否成功 */
#else /* 在调试构建中,总是分配新内存并清除旧内存 */
/* 尽早捕捉指针问题:强制重新定位,并确保旧缓冲区被清除。 */
} ret = malloc(size + ALLOC_OFF_TOTAL); /* 分配新内存 */
ALLOC_CHECK_RESULT(ret, size); /* 检查分配是否成功 */
if (orig) {
memcpy(ret + ALLOC_OFF_HEAD, orig + ALLOC_OFF_HEAD, MIN(size, old_size)); /* 将数据复制到新内存 */
memset(orig + ALLOC_OFF_HEAD, 0xFF, old_size); /* 用0xFF覆盖旧内存 */
ALLOC_C1(orig + ALLOC_OFF_HEAD) = ALLOC_MAGIC_F; /* 标记旧内存为已释放 */
free(orig); /* 释放旧内存 */
}
#endif /* ^!DEBUG_BUILD */ #endif /* ^!DEBUG_BUILD */
ret += ALLOC_OFF_HEAD; ret += ALLOC_OFF_HEAD; /* 调整指针以适应头部偏移 */
ALLOC_C1(ret) = ALLOC_MAGIC_C1; ALLOC_C1(ret) = ALLOC_MAGIC_C1; /* 标记内存为已使用 */
ALLOC_S(ret) = size; ALLOC_S(ret) = size; /* 存储内存块的大小 */
ALLOC_C2(ret) = ALLOC_MAGIC_C2; ALLOC_C2(ret) = ALLOC_MAGIC_C2; /* 标记内存块的结尾 */
if (size > old_size) if (size > old_size) /* 如果新大小更大,清零新的尾部 */
memset(ret + old_size, 0, size - old_size); memset(ret + old_size, 0, size - old_size);
return ret;
return ret; /* 返回(可能新的)内存块 */
} }
/* Re-allocate a buffer with ALLOC_BLK_INC increments (used to speed up /* 以ALLOC_BLK_INC的增量重新分配缓冲区用于加速重复的小realloc操作而不需要复杂化用户代码。 */
repeated small reallocs without complicating the user code). */
static inline void* DFL_ck_realloc_block(void* orig, u32 size) { static inline void* DFL_ck_realloc_block(void* orig, u32 size) {
#ifndef DEBUG_BUILD #ifndef DEBUG_BUILD
if (orig) { if (orig) {
CHECK_PTR(orig); CHECK_PTR(orig); /* 检查原始指针是否有效 */
if (ALLOC_S(orig) >= size) return orig; if (ALLOC_S(orig) >= size) return orig; /* 如果当前大小已满足需求则不进行realloc */
size += ALLOC_BLK_INC; size += ALLOC_BLK_INC; /* 增加ALLOC_BLK_INC以减少频繁的小realloc操作 */
} }
#endif /* !DEBUG_BUILD */ #endif /* !DEBUG_BUILD */
return DFL_ck_realloc(orig, size); return DFL_ck_realloc(orig, size); /* 调用DFL_ck_realloc进行实际的realloc操作 */
} }
/* 创建一个包含字符串副本的缓冲区。对于NULL输入返回NULL。 */
/* Create a buffer with a copy of a string. Returns NULL for NULL inputs. */
static inline u8* DFL_ck_strdup(u8* str) { static inline u8* DFL_ck_strdup(u8* str) {
void* ret; void* ret;
u32 size; u32 size;
if (!str) return NULL; if (!str) return NULL; /* 如果输入字符串为空则返回NULL */
size = strlen((char*)str) + 1; size = strlen((char*)str) + 1; /* 计算字符串长度加1为'\0'留空间) */
ALLOC_CHECK_SIZE(size); ALLOC_CHECK_SIZE(size); /* 检查分配大小是否超出限制 */
ret = malloc(size + ALLOC_OFF_TOTAL); ret = malloc(size + ALLOC_OFF_TOTAL); /* 分配内存 */
ALLOC_CHECK_RESULT(ret, size); ALLOC_CHECK_RESULT(ret, size); /* 检查内存分配是否成功 */
ret += ALLOC_OFF_HEAD; ret += ALLOC_OFF_HEAD; /* 调整指针以适应头部偏移 */
ALLOC_C1(ret) = ALLOC_MAGIC_C1; ALLOC_C1(ret) = ALLOC_MAGIC_C1; /* 设置头部魔术标记 */
ALLOC_S(ret) = size; ALLOC_S(ret) = size; /* 存储分配的大小 */
ALLOC_C2(ret) = ALLOC_MAGIC_C2; ALLOC_C2(ret) = ALLOC_MAGIC_C2; /* 设置尾部魔术标记 */
return memcpy(ret, str, size); return memcpy(ret, str, size); /* 复制字符串并返回新指针 */
} }
/* 创建一个包含内存块副本的缓冲区。对于零大小或NULL输入返回NULL。 */
/* Create a buffer with a copy of a memory block. Returns NULL for zero-sized
or NULL inputs. */
static inline void* DFL_ck_memdup(void* mem, u32 size) { static inline void* DFL_ck_memdup(void* mem, u32 size) {
void* ret; void* ret;
if (!mem || !size) return NULL;
ALLOC_CHECK_SIZE(size); if (!mem || !size) return NULL; /* 如果内存块为空或大小为零则返回NULL */
ret = malloc(size + ALLOC_OFF_TOTAL);
ALLOC_CHECK_RESULT(ret, size);
ret += ALLOC_OFF_HEAD;
ALLOC_C1(ret) = ALLOC_MAGIC_C1; ALLOC_CHECK_SIZE(size); /* 检查分配大小是否超出限制 */
ALLOC_S(ret) = size; ret = malloc(size + ALLOC_OFF_TOTAL); /* 分配内存 */
ALLOC_C2(ret) = ALLOC_MAGIC_C2; ALLOC_CHECK_RESULT(ret, size); /* 检查内存分配是否成功 */
return memcpy(ret, mem, size); ret += ALLOC_OFF_HEAD; /* 调整指针以适应头部偏移 */
} ALLOC_C1(ret) = ALLOC_MAGIC_C1; /* 设置头部魔术标记 */
ALLOC_S(ret) = size; /* 存储分配的大小 */
ALLOC_C2(ret) = ALLOC_MAGIC_C2; /* 设置尾部魔术标记 */
return memcpy(ret, mem, size); /* 复制内存块并返回新指针 */
/* Create a buffer with a block of text, appending a NUL terminator at the end. }
Returns NULL for zero-sized or NULL inputs. */
/* 创建一个包含文本块的缓冲区并在末尾追加NUL终止符。对于零大小或NULL输入返回NULL。 */
static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) { static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) {
u8* ret; u8* ret;
if (!mem || !size) return NULL; if (!mem || !size) return NULL; /* 如果内存块为空或大小为零则返回NULL */
ALLOC_CHECK_SIZE(size); ALLOC_CHECK_SIZE(size); /* 检查分配大小是否超出限制 */
ret = malloc(size + ALLOC_OFF_TOTAL + 1); ret = malloc(size + ALLOC_OFF_TOTAL + 1); /* 分配内存,额外+1用于NUL终止符 */
ALLOC_CHECK_RESULT(ret, size); ALLOC_CHECK_RESULT(ret, size); /* 检查内存分配是否成功 */
ret += ALLOC_OFF_HEAD;
ALLOC_C1(ret) = ALLOC_MAGIC_C1; ret += ALLOC_OFF_HEAD; /* 调整指针以适应头部偏移 */
ALLOC_S(ret) = size;
ALLOC_C2(ret) = ALLOC_MAGIC_C2;
memcpy(ret, mem, size); ALLOC_C1(ret) = ALLOC_MAGIC_C1; /* 设置头部魔术标记 */
ret[size] = 0; ALLOC_S(ret) = size; /* 存储分配的大小 */
ALLOC_C2(ret) = ALLOC_MAGIC_C2; /* 设置尾部魔术标记 */
return ret; memcpy(ret, mem, size); /* 复制内存块 */
ret[size] = 0; /* 设置NUL终止符 */
} return ret; /* 返回新指针 */
}
#ifndef DEBUG_BUILD #ifndef DEBUG_BUILD
/* In non-debug mode, we just do straightforward aliasing of the above functions /* 在非调试模式下我们直接将上述函数别名为用户可见的名称如ck_alloc()。 */
to user-visible names such as ck_alloc(). */
#define ck_alloc DFL_ck_alloc #define ck_alloc DFL_ck_alloc
#define ck_alloc_nozero DFL_ck_alloc_nozero #define ck_alloc_nozero DFL_ck_alloc_nozero
@ -355,223 +307,191 @@ static inline u8* DFL_ck_memdup_str(u8* mem, u32 size) {
#else #else
/* In debugging mode, we also track allocations to detect memory leaks, and the /* 在调试模式下,我们还跟踪内存分配以检测内存泄漏,这个过程会经历更多的间接层。 */
flow goes through one more layer of indirection. */
/* Alloc tracking data structures: */ /* 分配跟踪数据结构: */
#define ALLOC_BUCKETS 4096 #define ALLOC_BUCKETS 4096 /* 定义分配桶的数量 */
struct TRK_obj { struct TRK_obj {
void *ptr; void* ptr; /* 指向分配的内存块 */
char *file, *func; char* file, * func; /* 分配时的文件名和函数名 */
u32 line; u32 line; /* 分配时的代码行号 */
}; };
#ifdef AFL_MAIN #ifdef AFL_MAIN
struct TRK_obj* TRK[ALLOC_BUCKETS]; struct TRK_obj* TRK[ALLOC_BUCKETS]; /* 跟踪分配的内存对象数组 */
u32 TRK_cnt[ALLOC_BUCKETS]; u32 TRK_cnt[ALLOC_BUCKETS]; /* 每个桶中跟踪对象的数量 */
# define alloc_report() TRK_report() # define alloc_report() TRK_report() /* 定义alloc_report宏为TRK_report函数 */
#else #else
extern struct TRK_obj* TRK[ALLOC_BUCKETS]; extern struct TRK_obj* TRK[ALLOC_BUCKETS]; /* 外部声明跟踪分配的内存对象数组 */
extern u32 TRK_cnt[ALLOC_BUCKETS]; extern u32 TRK_cnt[ALLOC_BUCKETS]; /* 外部声明每个桶中跟踪对象的数量 */
# define alloc_report() # define alloc_report() /* 在非AFL_MAIN环境下alloc_report宏为空 */
#endif /* ^AFL_MAIN */ #endif /* ^AFL_MAIN */
/* Bucket-assigning function for a given pointer: */ /* 为给定指针分配桶的函数: */
#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS)
#define TRKH(_ptr) (((((u32)(_ptr)) >> 16) ^ ((u32)(_ptr))) % ALLOC_BUCKETS) /* 定义桶分配宏 */
/* Add a new entry to the list of allocated objects. */ /* 将新分配的内存对象添加到跟踪列表中。 */
static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func, static inline void TRK_alloc_buf(void* ptr, const char* file, const char* func,
u32 line) { u32 line) {
u32 i, bucket;
u32 i, bucket;
if (!ptr) return; if (!ptr) return; /* 如果指针为空,则返回 */
bucket = TRKH(ptr); bucket = TRKH(ptr); /* 获取桶编号 */
/* Find a free slot in the list of entries for that bucket. */ /* 在该桶的条目列表中找到一个空闲位置。 */
for (i = 0; i < TRK_cnt[bucket]; i++) for (i = 0; i < TRK_cnt[bucket]; i++)
if (!TRK[bucket][i].ptr) { /* 如果找到空闲位置 */
if (!TRK[bucket][i].ptr) { TRK[bucket][i].ptr = ptr;
TRK[bucket][i].file = (char*)file;
TRK[bucket][i].ptr = ptr; TRK[bucket][i].func = (char*)func;
TRK[bucket][i].file = (char*)file; TRK[bucket][i].line = line;
TRK[bucket][i].func = (char*)func; return;
TRK[bucket][i].line = line; }
return;
}
/* No space available - allocate more. */
TRK[bucket] = DFL_ck_realloc_block(TRK[bucket], /* 没有可用空间 - 分配更多空间。 */
(TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj));
TRK[bucket][i].ptr = ptr; TRK[bucket] = DFL_ck_realloc_block(TRK[bucket],
TRK[bucket][i].file = (char*)file; (TRK_cnt[bucket] + 1) * sizeof(struct TRK_obj)); /* 重新分配桶的大小 */
TRK[bucket][i].func = (char*)func;
TRK[bucket][i].line = line;
TRK_cnt[bucket]++; TRK[bucket][i].ptr = ptr;
TRK[bucket][i].file = (char*)file;
TRK[bucket][i].func = (char*)func;
TRK[bucket][i].line = line;
TRK_cnt[bucket]++; /* 更新桶中条目的数量 */
} }
/* 从分配的内存对象列表中移除条目。 */
/* Remove entry from the list of allocated objects. */
static inline void TRK_free_buf(void* ptr, const char* file, const char* func, static inline void TRK_free_buf(void* ptr, const char* file, const char* func,
u32 line) { u32 line) {
u32 i, bucket;
u32 i, bucket;
if (!ptr) return;
bucket = TRKH(ptr); if (!ptr) return; /* 如果指针为空,则返回 */
/* Find the element on the list... */ bucket = TRKH(ptr); /* 获取桶编号 */
for (i = 0; i < TRK_cnt[bucket]; i++) /* 在列表中找到该元素... */
if (TRK[bucket][i].ptr == ptr) { for (i = 0; i < TRK_cnt[bucket]; i++)
if (TRK[bucket][i].ptr == ptr) { /* 如果找到匹配的指针 */
TRK[bucket][i].ptr = 0; TRK[bucket][i].ptr = 0; /* 将指针设置为NULL */
return; return;
}
}
WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)",
func, file, line);
WARNF("ALLOC: Attempt to free non-allocated memory in %s (%s:%u)",
func, file, line); /* 警告:尝试释放未分配的内存 */
} }
/* 对所有未释放的对象进行最终报告。 */
/* Do a final report on all non-deallocated objects. */
static inline void TRK_report(void) { static inline void TRK_report(void) {
u32 i, bucket;
u32 i, bucket; fflush(0); /* 清空输出缓冲区 */
fflush(0);
for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++)
for (i = 0; i < TRK_cnt[bucket]; i++)
if (TRK[bucket][i].ptr)
WARNF("ALLOC: Memory never freed, created in %s (%s:%u)",
TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line);
for (bucket = 0; bucket < ALLOC_BUCKETS; bucket++)
for (i = 0; i < TRK_cnt[bucket]; i++)
if (TRK[bucket][i].ptr) /* 如果指针不为空 */
WARNF("ALLOC: Memory never freed, created in %s (%s:%u)",
TRK[bucket][i].func, TRK[bucket][i].file, TRK[bucket][i].line); /* 警告:内存从未释放 */
} }
/* 非调试函数的简单包装器: */
/* Simple wrappers for non-debugging functions: */
static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func, static inline void* TRK_ck_alloc(u32 size, const char* file, const char* func,
u32 line) { u32 line) {
void* ret = DFL_ck_alloc(size); /* 分配内存 */
void* ret = DFL_ck_alloc(size); TRK_alloc_buf(ret, file, func, line); /* 添加到跟踪列表 */
TRK_alloc_buf(ret, file, func, line); return ret;
return ret;
} }
static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file, static inline void* TRK_ck_realloc(void* orig, u32 size, const char* file,
const char* func, u32 line) { const char* func, u32 line) {
void* ret = DFL_ck_realloc(orig, size); /* 重新分配内存 */
void* ret = DFL_ck_realloc(orig, size); TRK_free_buf(orig, file, func, line); /* 从跟踪列表中移除 */
TRK_free_buf(orig, file, func, line); TRK_alloc_buf(ret, file, func, line); /* 添加到跟踪列表 */
TRK_alloc_buf(ret, file, func, line); return ret;
return ret;
} }
/* 重新分配内存块,同时更新跟踪信息。 */
static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file, static inline void* TRK_ck_realloc_block(void* orig, u32 size, const char* file,
const char* func, u32 line) { const char* func, u32 line) {
void* ret = DFL_ck_realloc_block(orig, size); /* 调用DFL_ck_realloc_block重新分配内存 */
void* ret = DFL_ck_realloc_block(orig, size); TRK_free_buf(orig, file, func, line); /* 从跟踪列表中移除原始内存块 */
TRK_free_buf(orig, file, func, line); TRK_alloc_buf(ret, file, func, line); /* 将新内存块添加到跟踪列表 */
TRK_alloc_buf(ret, file, func, line); return ret; /* 返回新内存块 */
return ret;
} }
/* 复制字符串并分配内存,同时更新跟踪信息。 */
static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func, static inline void* TRK_ck_strdup(u8* str, const char* file, const char* func,
u32 line) { u32 line) {
void* ret = DFL_ck_strdup(str); /* 调用DFL_ck_strdup复制字符串 */
void* ret = DFL_ck_strdup(str); TRK_alloc_buf(ret, file, func, line); /* 将新内存块添加到跟踪列表 */
TRK_alloc_buf(ret, file, func, line); return ret; /* 返回新内存块 */
return ret;
} }
/* 复制内存块并分配内存,同时更新跟踪信息。 */
static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file, static inline void* TRK_ck_memdup(void* mem, u32 size, const char* file,
const char* func, u32 line) { const char* func, u32 line) {
void* ret = DFL_ck_memdup(mem, size); /* 调用DFL_ck_memdup复制内存块 */
void* ret = DFL_ck_memdup(mem, size); TRK_alloc_buf(ret, file, func, line); /* 将新内存块添加到跟踪列表 */
TRK_alloc_buf(ret, file, func, line); return ret; /* 返回新内存块 */
return ret;
} }
/* 复制内存块并添加字符串终止符,同时更新跟踪信息。 */
static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file, static inline void* TRK_ck_memdup_str(void* mem, u32 size, const char* file,
const char* func, u32 line) { const char* func, u32 line) {
void* ret = DFL_ck_memdup_str(mem, size); /* 调用DFL_ck_memdup_str复制内存块并添加终止符 */
void* ret = DFL_ck_memdup_str(mem, size); TRK_alloc_buf(ret, file, func, line); /* 将新内存块添加到跟踪列表 */
TRK_alloc_buf(ret, file, func, line); return ret; /* 返回新内存块 */
return ret;
} }
/* 释放内存并更新跟踪信息。 */
static inline void TRK_ck_free(void* ptr, const char* file, static inline void TRK_ck_free(void* ptr, const char* file,
const char* func, u32 line) { const char* func, u32 line) {
TRK_free_buf(ptr, file, func, line); /* 从跟踪列表中移除内存块 */
TRK_free_buf(ptr, file, func, line); DFL_ck_free(ptr); /* 释放内存块 */
DFL_ck_free(ptr);
} }
/* Aliasing user-facing names to tracking functions: */ /* 将用户可见的名称别名为跟踪函数: */
#define ck_alloc(_p1) \ #define ck_alloc(_p1) \
TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_alloc宏为TRK_ck_alloc */
#define ck_alloc_nozero(_p1) \ #define ck_alloc_nozero(_p1) \
TRK_ck_alloc(_p1, __FILE__, __FUNCTION__, __LINE__) TRK_ck_alloc_nozero(_p1, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_alloc_nozero宏为TRK_ck_alloc_nozero */
#define ck_realloc(_p1, _p2) \ #define ck_realloc(_p1, _p2) \
TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) TRK_ck_realloc(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_realloc宏为TRK_ck_realloc */
#define ck_realloc_block(_p1, _p2) \ #define ck_realloc_block(_p1, _p2) \
TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) TRK_ck_realloc_block(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_realloc_block宏为TRK_ck_realloc_block */
#define ck_strdup(_p1) \ #define ck_strdup(_p1) \
TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) TRK_ck_strdup(_p1, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_strdup宏为TRK_ck_strdup */
#define ck_memdup(_p1, _p2) \ #define ck_memdup(_p1, _p2) \
TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) TRK_ck_memdup(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_memdup宏为TRK_ck_memdup */
#define ck_memdup_str(_p1, _p2) \ #define ck_memdup_str(_p1, _p2) \
TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) TRK_ck_memdup_str(_p1, _p2, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_memdup_str宏为TRK_ck_memdup_str */
#define ck_free(_p1) \ #define ck_free(_p1) \
TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) TRK_ck_free(_p1, __FILE__, __FUNCTION__, __LINE__) /* 定义ck_free宏为TRK_ck_free */
#endif /* ^!DEBUG_BUILD */ #endif /* ^!DEBUG_BUILD */
#endif /* ! _HAVE_ALLOC_INL_H */ #endif /* ! _HAVE_ALLOC_INL_H */

@ -1,82 +1,88 @@
// 如果是Android平台且尚未定义_ANDROID_ASHMEM_H则定义它
#ifdef __ANDROID__ #ifdef __ANDROID__
#ifndef _ANDROID_ASHMEM_H #ifndef _ANDROID_ASHMEM_H
#define _ANDROID_ASHMEM_H #define _ANDROID_ASHMEM_H
// 包含所需的头文件
#include <fcntl.h> #include <fcntl.h>
#include <linux/ashmem.h> #include <linux/ashmem.h> // 包含ashmem相关的ioctl操作
#include <linux/shm.h> #include <linux/shm.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h> // 包含内存映射函数
// 如果Android API级别大于或等于26Android 8.0则使用Bionic的shm*函数
#if __ANDROID_API__ >= 26 #if __ANDROID_API__ >= 26
#define shmat bionic_shmat #define shmat bionic_shmat
#define shmctl bionic_shmctl #define shmctl bionic_shmctl
#define shmdt bionic_shmdt #define shmdt bionic_shmdt
#define shmget bionic_shmget #define shmget bionic_shmget
#endif #endif
#include <sys/shm.h> #include <sys/shm.h> // 包含标准的共享内存函数
#undef shmat #undef shmat
#undef shmctl #undef shmctl
#undef shmdt #undef shmdt
#undef shmget #undef shmget // 取消对Bionic函数的重定义
#include <stdio.h> #include <stdio.h>
// 定义ashmem设备的路径
#define ASHMEM_DEVICE "/dev/ashmem" #define ASHMEM_DEVICE "/dev/ashmem"
static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { // 定义shmctl函数的封装用于删除共享内存
int ret = 0; static inline int shmctl(int __shmid, int __cmd, struct shmid_ds* __buf) {
if (__cmd == IPC_RMID) { int ret = 0;
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); if (__cmd == IPC_RMID) {
struct ashmem_pin pin = {0, length}; int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); struct ashmem_pin pin = { 0, length };
close(__shmid); ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
} close(__shmid);
}
return ret; return ret;
} }
// 定义shmget函数的封装用于创建共享内存
static inline int shmget(key_t __key, size_t __size, int __shmflg) { static inline int shmget(key_t __key, size_t __size, int __shmflg) {
(void) __shmflg; (void)__shmflg;
int fd, ret; int fd, ret;
char ourkey[11]; char ourkey[11];
fd = open(ASHMEM_DEVICE, O_RDWR); fd = open(ASHMEM_DEVICE, O_RDWR);
if (fd < 0) if (fd < 0)
return fd; return fd;
sprintf(ourkey, "%d", __key); sprintf(ourkey, "%d", __key);
ret = ioctl(fd, ASHMEM_SET_NAME, ourkey); ret = ioctl(fd, ASHMEM_SET_NAME, ourkey);
if (ret < 0) if (ret < 0)
goto error; goto error;
ret = ioctl(fd, ASHMEM_SET_SIZE, __size); ret = ioctl(fd, ASHMEM_SET_SIZE, __size);
if (ret < 0) if (ret < 0)
goto error; goto error;
return fd; return fd;
error: error:
close(fd); close(fd);
return ret; return ret;
} }
static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) { // 定义shmat函数的封装用于将共享内存附加到进程地址空间
(void) __shmflg; static inline void* shmat(int __shmid, const void* __shmaddr, int __shmflg) {
int size; (void)__shmflg;
void *ptr; int size;
void* ptr;
size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
if (size < 0) { if (size < 0) {
return NULL; return NULL;
} }
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0); ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0);
if (ptr == MAP_FAILED) { if (ptr == MAP_FAILED) {
return NULL; return NULL;
} }
return ptr; return ptr;
} }
#endif /* !_ANDROID_ASHMEM_H */ #endif /* !_ANDROID_ASHMEM_H */
#endif /* !__ANDROID__ */ #endif /* !__ANDROID__ */

@ -27,8 +27,7 @@
#include "types.h" #include "types.h"
/* Version string: */ /* Version string: */
#define VERSION "2.57b" // 定义版本号字符串
#define VERSION "2.57b"
/****************************************************** /******************************************************
* * * *
@ -36,228 +35,196 @@
* * * *
******************************************************/ ******************************************************/
/* Comment out to disable terminal colors (note that this makes afl-analyze /* Comment out to disable terminal colors (note that this makes afl-analyze
a lot less nice): */ a lot less nice): */
#define USE_COLOR // 启用终端颜色
#define USE_COLOR
/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ /* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */
#define FANCY_BOXES // 启用ANSI框绘制
#define FANCY_BOXES
/* Default timeout for fuzzed code (milliseconds). This is the upper bound, /* Default timeout for fuzzed code (milliseconds). This is the upper bound,
also used for detecting hangs; the actual value is auto-scaled: */ also used for detecting hangs; the actual value is auto-scaled: */
#define EXEC_TIMEOUT 1000 // 默认超时时间(毫秒)
#define EXEC_TIMEOUT 1000 /* Timeout rounding factor when auto-scaling (milliseconds): */
#define EXEC_TM_ROUND 20 // 自动缩放时的超时舍入因子(毫秒)
/* Timeout rounding factor when auto-scaling (milliseconds): */
#define EXEC_TM_ROUND 20
/* 64bit arch MACRO */ /* 64bit arch MACRO */
#if (defined (__x86_64__) || defined (__arm64__) || defined (__aarch64__)) #if (defined (__x86_64__) || defined (__arm64__) || defined (__aarch64__))
#define WORD_SIZE_64 1 #define WORD_SIZE_64 1 // 定义64位架构宏
#endif #endif
/* Default memory limit for child process (MB): */ /* Default memory limit for child process (MB): */
#ifndef WORD_SIZE_64 #ifndef WORD_SIZE_64
# define MEM_LIMIT 25 # define MEM_LIMIT 25 // 非64位架构的默认内存限制MB
#else #else
# define MEM_LIMIT 50 # define MEM_LIMIT 50 // 64位架构的默认内存限制MB
#endif /* ^!WORD_SIZE_64 */ #endif /* ^!WORD_SIZE_64 */
/* Default memory limit when running in QEMU mode (MB): */ /* Default memory limit when running in QEMU mode (MB): */
#define MEM_LIMIT_QEMU 200 // QEMU模式下的默认内存限制MB
#define MEM_LIMIT_QEMU 200
/* Number of calibration cycles per every new test case (and for test /* Number of calibration cycles per every new test case (and for test
cases that show variable behavior): */ cases that show variable behavior): */
#define CAL_CYCLES 8 // 每个新测试用例的校准周期数
#define CAL_CYCLES_LONG 40 // 长校准周期数
#define CAL_CYCLES 8 /* Number of subsequent timeouts before abandoning an input file: */
#define CAL_CYCLES_LONG 40 #define TMOUT_LIMIT 250 // 超时次数限制
/* Number of subsequent timeouts before abandoning an input file: */
#define TMOUT_LIMIT 250
/* Maximum number of unique hangs or crashes to record: */ /* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500 // 最大记录的唯一挂起数
#define KEEP_UNIQUE_HANG 500 #define KEEP_UNIQUE_CRASH 5000 // 最大记录的唯一崩溃数
#define KEEP_UNIQUE_CRASH 5000
/* Baseline number of random tweaks during a single 'havoc' stage: */ /* Baseline number of random tweaks during a single 'havoc' stage: */
#define HAVOC_CYCLES 256 // 'havoc'阶段的随机调整基数
#define HAVOC_CYCLES 256 #define HAVOC_CYCLES_INIT 1024 // 'havoc'阶段的初始随机调整数
#define HAVOC_CYCLES_INIT 1024
/* Maximum multiplier for the above (should be a power of two, beware /* Maximum multiplier for the above (should be a power of two, beware
of 32-bit int overflows): */ of 32-bit int overflows): */
#define HAVOC_MAX_MULT 16 // 'havoc'阶段的最大乘数
#define HAVOC_MAX_MULT 16 /* Absolute minimum number of havoc cycles (after all adjustments): */
#define HAVOC_MIN 16 // 'havoc'阶段的绝对最小周期数
/* Absolute minimum number of havoc cycles (after all adjustments): */
#define HAVOC_MIN 16
/* Maximum stacking for havoc-stage tweaks. The actual value is calculated /* Maximum stacking for havoc-stage tweaks. The actual value is calculated
like this: like this:
n = random between 1 and HAVOC_STACK_POW2 n = random between 1 and HAVOC_STACK_POW2
stacking = 2^n stacking = 2^n
In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or In other words, the default (n = 7) produces 2, 4, 8, 16, 32, 64, or
128 stacked tweaks: */ 128 stacked tweaks: */
#define HAVOC_STACK_POW2 7 // 'havoc'阶段的最大堆叠指数
#define HAVOC_STACK_POW2 7 /* Caps on block sizes for cloning and deletion operations. Each of these
ranges has a 33% probability of getting picked, except for the first
/* Caps on block sizes for cloning and deletion operations. Each of these two cycles where smaller blocks are favored: */
ranges has a 33% probability of getting picked, except for the first #define HAVOC_BLK_SMALL 32 // 小块大小限制
two cycles where smaller blocks are favored: */ #define HAVOC_BLK_MEDIUM 128 // 中块大小限制
#define HAVOC_BLK_LARGE 1500 // 大块大小限制
#define HAVOC_BLK_SMALL 32
#define HAVOC_BLK_MEDIUM 128
#define HAVOC_BLK_LARGE 1500
/* Extra-large blocks, selected very rarely (<5% of the time): */ /* Extra-large blocks, selected very rarely (<5% of the time): */
#define HAVOC_BLK_XL 32768 // 特大块大小限制
#define HAVOC_BLK_XL 32768
/* Probabilities of skipping non-favored entries in the queue, expressed as /* Probabilities of skipping non-favored entries in the queue, expressed as
percentages: */ percentages: */
#define SKIP_TO_NEW_PROB 99 // 跳过非优先队列项的概率(有新的待处理优先项)
#define SKIP_NFAV_OLD_PROB 95 // 跳过非优先队列项的概率(没有新的优先项,当前项已测试)
#define SKIP_NFAV_NEW_PROB 75 // 跳过非优先队列项的概率(没有新的优先项,当前项未测试)
#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ /* Splicing cycle count: */
#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ #define SPLICE_CYCLES 15 // 拼接周期数
#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */
/* Splicing cycle count: */
#define SPLICE_CYCLES 15
/* Nominal per-splice havoc cycle length: */ /* Nominal per-splice havoc cycle length: */
#define SPLICE_HAVOC 32 // 每次拼接的'havoc'周期长度
#define SPLICE_HAVOC 32
/* Maximum offset for integer addition / subtraction stages: */ /* Maximum offset for integer addition / subtraction stages: */
#define ARITH_MAX 35 // 整数加减阶段的最大偏移量
#define ARITH_MAX 35
/* Limits for the test case trimmer. The absolute minimum chunk size; and /* Limits for the test case trimmer. The absolute minimum chunk size; and
the starting and ending divisors for chopping up the input file: */ the starting and ending divisors for chopping up the input file: */
#define TRIM_MIN_BYTES 4 // 测试用例修剪器的最小块大小
#define TRIM_START_STEPS 16 // 测试用例修剪器的起始除数
#define TRIM_END_STEPS 1024 // 测试用例修剪器的结束除数
#define TRIM_MIN_BYTES 4 /* Maximum size of input file, in bytes (keep under 100MB): */
#define TRIM_START_STEPS 16 #define MAX_FILE (1 * 1024 * 1024) // 输入文件的最大大小(字节)
#define TRIM_END_STEPS 1024
/* Maximum size of input file, in bytes (keep under 100MB): */
#define MAX_FILE (1 * 1024 * 1024)
/* The same, for the test case minimizer: */ /* The same, for the test case minimizer: */
#define TMIN_MAX_FILE (10 * 1024 * 1024) // 测试用例最小化器的最大文件大小
#define TMIN_MAX_FILE (10 * 1024 * 1024)
/* Block normalization steps for afl-tmin: */ /* Block normalization steps for afl-tmin: */
#define TMIN_SET_MIN_SIZE 4 // afl-tmin的块归一化最小大小
#define TMIN_SET_MIN_SIZE 4 #define TMIN_SET_STEPS 128 // afl-tmin的块归一化步数
#define TMIN_SET_STEPS 128
/* Maximum dictionary token size (-x), in bytes: */ /* Maximum dictionary token size (-x), in bytes: */
#define MAX_DICT_FILE 128 // 最大字典令牌大小(字节)
#define MAX_DICT_FILE 128
/* Length limits for auto-detected dictionary tokens: */ /* Length limits for auto-detected dictionary tokens: */
#define MIN_AUTO_EXTRA 3 // 自动检测的字典令牌的最小长度
#define MIN_AUTO_EXTRA 3 #define MAX_AUTO_EXTRA 32 // 自动检测的字典令牌的最大长度
#define MAX_AUTO_EXTRA 32
/* Maximum number of user-specified dictionary tokens to use in deterministic /* Maximum number of user-specified dictionary tokens to use in deterministic
steps; past this point, the "extras/user" step will be still carried out, steps; past this point, the "extras/user" step will be still carried out,
but with proportionally lower odds: */ but with proportionally lower odds: */
#define MAX_DET_EXTRAS 200 // 最大用户指定字典令牌数
#define MAX_DET_EXTRAS 200 /* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing
(first value), and to keep in memory as candidates. The latter should be much
/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing higher than the former. */
(first value), and to keep in memory as candidates. The latter should be much #define USE_AUTO_EXTRAS 50 // 实际用于模糊测试的自动提取字典令牌数
higher than the former. */ #define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) // 内存中候选的自动提取字典令牌数
#define USE_AUTO_EXTRAS 50
#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10)
/* Scaling factor for the effector map used to skip some of the more
expensive deterministic steps. The actual divisor is set to
2^EFF_MAP_SCALE2 bytes: */
#define EFF_MAP_SCALE2 3 /* Scaling factor for the effector map used to skip some of the more
expensive deterministic steps. The actual divisor is set to
2^EFF_MAP_SCALE2 bytes: */
#define EFF_MAP_SCALE2 3 // 效应器映射的缩放因子
/* Minimum input file length at which the effector logic kicks in: */ /* Minimum input file length at which the effector logic kicks in: */
#define EFF_MIN_LEN 128 // 效应器逻辑触发的最小输入文件长度
#define EFF_MIN_LEN 128
/* Maximum effector density past which everything is just fuzzed /* Maximum effector density past which everything is just fuzzed
unconditionally (%): */ unconditionally (%): */
#define EFF_MAX_PERC 90 // 最大效应器密度(%
#define EFF_MAX_PERC 90 /* UI refresh frequency (Hz): */
#define UI_TARGET_HZ 5 // UI刷新频率Hz
/* UI refresh frequency (Hz): */
#define UI_TARGET_HZ 5
/* Fuzzer stats file and plot update intervals (sec): */ /* Fuzzer stats file and plot update intervals (sec): */
#define STATS_UPDATE_SEC 60 // 模糊统计文件更新间隔(秒)
#define STATS_UPDATE_SEC 60 #define PLOT_UPDATE_SEC 5 // 模糊统计图表更新间隔(秒)
#define PLOT_UPDATE_SEC 5
/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ /* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */
#define AVG_SMOOTHING 16 // CPU负载和执行速度统计的平滑除数
#define AVG_SMOOTHING 16
/* Sync interval (every n havoc cycles): */ /* Sync interval (every n havoc cycles): */
#define SYNC_INTERVAL 5 // 同步间隔每n个havoc周期
#define SYNC_INTERVAL 5
/* Output directory reuse grace period (minutes): */ /* Output directory reuse grace period (minutes): */
#define OUTPUT_GRACE 25 // 输出目录重用宽限期(分钟)
#define OUTPUT_GRACE 25
/* Uncomment to use simple file names (id_NNNNNN): */ /* Uncomment to use simple file names (id_NNNNNN): */
// #define SIMPLE_FILES // 取消注释以使用简单文件名
// #define SIMPLE_FILES
/* List of interesting values to use in fuzzing. */ /* List of interesting values to use in fuzzing. */
// 定义一系列有趣的值,用于模糊测试
/* 定义一组有趣的8位值用于模糊测试包括边界值和常见缓冲区大小 */
#define INTERESTING_8 \ #define INTERESTING_8 \
-128, /* Overflow signed 8-bit when decremented */ \ -128, /* 减1时溢出的有符号8位值 */ \
-1, /* */ \ -1, /* 通用的有趣值 */ \
0, /* */ \ 0, /* 零值,常用于测试 */ \
1, /* */ \ 1, /* 通用的有趣值 */ \
16, /* One-off with common buffer size */ \ 16, /* 常用缓冲区大小的偏移量 */ \
32, /* One-off with common buffer size */ \ 32, /* 常用缓冲区大小的偏移量 */ \
64, /* One-off with common buffer size */ \ 64, /* 常用缓冲区大小的偏移量 */ \
100, /* One-off with common buffer size */ \ 100, /* 常用缓冲区大小的偏移量 */ \
127 /* Overflow signed 8-bit when incremented */ 127 /* 加1时溢出的有符号8位值 */
/* 定义一组有趣的16位值用于模糊测试包括边界值和常见缓冲区大小 */
#define INTERESTING_16 \ #define INTERESTING_16 \
-32768, /* Overflow signed 16-bit when decremented */ \ -32768, /* 减1时溢出的有符号16位值 */ \
-129, /* Overflow signed 8-bit */ \ -129, /* 溢出的有符号8位值 */ \
128, /* Overflow signed 8-bit */ \ 128, /* 溢出的有符号8位值 */ \
255, /* Overflow unsig 8-bit when incremented */ \ 255, /* 增1时溢出的无符号8位值 */ \
256, /* Overflow unsig 8-bit */ \ 256, /* 溢出的无符号8位值 */ \
512, /* One-off with common buffer size */ \ 512, /* 常用缓冲区大小的偏移量 */ \
1000, /* One-off with common buffer size */ \ 1000, /* 常用缓冲区大小的偏移量 */ \
1024, /* One-off with common buffer size */ \ 1024, /* 常用缓冲区大小的偏移量 */ \
4096, /* One-off with common buffer size */ \ 4096, /* 常用缓冲区大小的偏移量 */ \
32767 /* Overflow signed 16-bit when incremented */ 32767 /* 加1时溢出的有符号16位值 */
/* 定义一组有趣的32位值用于模糊测试包括边界值和大数值 */
#define INTERESTING_32 \ #define INTERESTING_32 \
-2147483648LL, /* Overflow signed 32-bit when decremented */ \ -2147483648LL, /* 减1时溢出的有符号32位值 */ \
-100663046, /* Large negative number (endian-agnostic) */ \ -100663046, /* 大的负数(与字节序无关) */ \
-32769, /* Overflow signed 16-bit */ \ -32769, /* 溢出的有符号16位值 */ \
32768, /* Overflow signed 16-bit */ \ 32768, /* 溢出的有符号16位值 */ \
65535, /* Overflow unsig 16-bit when incremented */ \ 65535, /* 增1时溢出的无符号16位值 */ \
65536, /* Overflow unsig 16 bit */ \ 65536, /* 溢出的无符号16位值 */ \
100663045, /* Large positive number (endian-agnostic) */ \ 100663045, /* 大的正数(与字节序无关) */ \
2147483647 /* Overflow signed 32-bit when incremented */ 2147483647 /* 加1时溢出的有符号32位值 */
/*********************************************************** /***********************************************************
* * * *
@ -265,98 +232,66 @@
* * * *
***********************************************************/ ***********************************************************/
/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ /* 定义 libc 伪随机数生成器重新播种的调用计数间隔 */
#define RESEED_RNG 10000 #define RESEED_RNG 10000
/* Maximum line length passed from GCC to 'as' and used for parsing /* 定义从 GCC 传递给 'as' 的最大行长度,并用于解析配置文件 */
configuration files: */
#define MAX_LINE 8192 #define MAX_LINE 8192
/* Environment variable used to pass SHM ID to the called program. */ /* 定义用于传递共享内存ID给被调用程序的环境变量 */
#define SHM_ENV_VAR "__AFL_SHM_ID" #define SHM_ENV_VAR "__AFL_SHM_ID"
/* Other less interesting, internal-only variables. */ /* 定义其他不太有趣,仅内部使用的变量 */
#define CLANG_ENV_VAR "__AFL_CLANG_MODE" #define CLANG_ENV_VAR "__AFL_CLANG_MODE"
#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" #define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK"
#define PERSIST_ENV_VAR "__AFL_PERSISTENT" #define PERSIST_ENV_VAR "__AFL_PERSISTENT"
#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" #define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV"
/* In-code signatures for deferred and persistent mode. */ /* 定义代码中用于延迟和持久模式的签名 */
#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" #define PERSIST_SIG "##SIG_AFL_PERSISTENT##"
#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" #define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##"
/* Distinctive bitmap signature used to indicate failed execution: */ /* 定义用于表示执行失败的独特位图签名 */
#define EXEC_FAIL_SIG 0xfee1dead #define EXEC_FAIL_SIG 0xfee1dead
/* Distinctive exit code used to indicate MSAN trip condition: */ /* 定义用于表示MSAN内存sanitizer触发条件的独特退出代码 */
#define MSAN_ERROR 86 #define MSAN_ERROR 86
/* Designated file descriptors for forkserver commands (the application will /* 定义用于fork服务器命令的指定文件描述符 */
use FORKSRV_FD and FORKSRV_FD + 1): */
#define FORKSRV_FD 198 #define FORKSRV_FD 198
/* Fork server init timeout multiplier: we'll wait the user-selected /* 定义fork服务器初始化超时乘数 */
timeout plus this much for the fork server to spin up. */
#define FORK_WAIT_MULT 10 #define FORK_WAIT_MULT 10
/* Calibration timeout adjustments, to be a bit more generous when resuming /* 定义校准超时调整,恢复模糊测试会话或校准已添加的内部发现时更加宽松 */
fuzzing sessions or trying to calibrate already-added internal finds.
The first value is a percentage, the other is in milliseconds: */
#define CAL_TMOUT_PERC 125 #define CAL_TMOUT_PERC 125
#define CAL_TMOUT_ADD 50 #define CAL_TMOUT_ADD 50
/* Number of chances to calibrate a case before giving up: */ /* 定义校准一个案例前放弃的机会数 */
#define CAL_CHANCES 3 #define CAL_CHANCES 3
/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than /* 定义跟踪二进制文件的映射大小 */
2; you probably want to keep it under 18 or so for performance reasons
(adjusting AFL_INST_RATIO when compiling is probably a better way to solve
problems with complex programs). You need to recompile the target binary
after changing this - otherwise, SEGVs may ensue. */
#define MAP_SIZE_POW2 16 #define MAP_SIZE_POW2 16
#define MAP_SIZE (1 << MAP_SIZE_POW2) #define MAP_SIZE (1 << MAP_SIZE_POW2)
/* Maximum allocator request size (keep well under INT_MAX): */ /* 定义最大分配请求大小 */
#define MAX_ALLOC 0x40000000 #define MAX_ALLOC 0x40000000
/* A made-up hashing seed: */ /* 定义一个虚构的哈希种子 */
#define HASH_CONST 0xa5b35705 #define HASH_CONST 0xa5b35705
/* Constants for afl-gotcpu to control busy loop timing: */ /* 定义 afl-gotcpu 控制忙循环计时的常量 */
#define CTEST_TARGET_MS 5000 #define CTEST_TARGET_MS 5000
#define CTEST_CORE_TRG_MS 1000 #define CTEST_CORE_TRG_MS 1000
#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) #define CTEST_BUSY_CYCLES (10 * 1000 * 1000)
/* Uncomment this to use inferior block-coverage-based instrumentation. Note /* 如果需要使用基于块覆盖的仪器,取消注释此宏 */
that you need to recompile the target binary for this to have any effect: */
// #define COVERAGE_ONLY // #define COVERAGE_ONLY
/* Uncomment this to ignore hit counts and output just one bit per tuple. /* 如果需要忽略命中计数并且每个元组只输出一个位,取消注释此宏 */
As with the previous setting, you will need to recompile the target
binary: */
// #define SKIP_COUNTS // #define SKIP_COUNTS
/* Uncomment this to use instrumentation data to record newly discovered paths, /* 如果需要使用仪器数据记录新发现的路径,但不使用它们作为模糊测试的种子,取消注释此宏 */
but do not use them as seeds for fuzzing. This is useful for conveniently
measuring coverage that could be attained by a "dumb" fuzzing algorithm: */
// #define IGNORE_FINDS // #define IGNORE_FINDS
#endif /* ! _HAVE_CONFIG_H */ #endif /* ! _HAVE_CONFIG_H */

@ -155,54 +155,50 @@
* Misc terminal codes * * Misc terminal codes *
***********************/ ***********************/
#define TERM_HOME "\x1b[H" // 定义一些额外的终端控制代码
#define TERM_CLEAR TERM_HOME "\x1b[2J" #define TERM_HOME "\x1b[H" // 移动光标到终端左上角
#define cEOL "\x1b[0K" #define TERM_CLEAR TERM_HOME "\x1b[2J" // 清除终端屏幕
#define CURSOR_HIDE "\x1b[?25l" #define cEOL "\x1b[0K" // 清除当前行从光标位置到行尾的内容
#define CURSOR_SHOW "\x1b[?25h" #define CURSOR_HIDE "\x1b[?25l" // 隐藏光标
#define CURSOR_SHOW "\x1b[?25h" // 显示光标
/************************ /************************
* Debug & error macros * * Debug & error macros *
************************/ ************************/
/* Just print stuff to the appropriate stream. */ // 定义一些宏用于调试和错误处理
// 如果配置中定义了MESSAGES_TO_STDOUT则使用printf否则使用fprintf(stderr, ...)
#ifdef MESSAGES_TO_STDOUT #ifdef MESSAGES_TO_STDOUT
# define SAYF(x...) printf(x) # define SAYF(x...) printf(x)
#else #else
# define SAYF(x...) fprintf(stderr, x) # define SAYF(x...) fprintf(stderr, x)
#endif /* ^MESSAGES_TO_STDOUT */ #endif /* ^MESSAGES_TO_STDOUT */
/* Show a prefixed warning. */ // 显示带前缀的警告信息
#define WARNF(x...) do { \ #define WARNF(x...) do { \
SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \ SAYF(cYEL "[!] " cBRI "WARNING: " cRST x); \
SAYF(cRST "\n"); \ SAYF(cRST "\n"); \
} while (0) } while (0)
/* Show a prefixed "doing something" message. */ // 显示带前缀的“正在执行”信息
#define ACTF(x...) do { \ #define ACTF(x...) do { \
SAYF(cLBL "[*] " cRST x); \ SAYF(cLBL "[*] " cRST x); \
SAYF(cRST "\n"); \ SAYF(cRST "\n"); \
} while (0) } while (0)
/* Show a prefixed "success" message. */ // 显示带前缀的成功信息
#define OKF(x...) do { \ #define OKF(x...) do { \
SAYF(cLGN "[+] " cRST x); \ SAYF(cLGN "[+] " cRST x); \
SAYF(cRST "\n"); \ SAYF(cRST "\n"); \
} while (0) } while (0)
/* Show a prefixed fatal error message (not used in afl). */ // 显示带前缀的严重错误信息不在afl中使用
#define BADF(x...) do { \ #define BADF(x...) do { \
SAYF(cLRD "\n[-] " cRST x); \ SAYF(cLRD "\n[-] " cRST x); \
SAYF(cRST "\n"); \ SAYF(cRST "\n"); \
} while (0) } while (0)
/* Die with a verbose non-OS fatal error message. */ // 以详细非操作系统致命错误消息退出程序
#define FATAL(x...) do { \ #define FATAL(x...) do { \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \
cBRI x); \ cBRI x); \
@ -211,8 +207,7 @@
exit(1); \ exit(1); \
} while (0) } while (0)
/* Die by calling abort() to provide a core dump. */ // 通过调用abort()退出程序以便提供core dump
#define ABORT(x...) do { \ #define ABORT(x...) do { \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] PROGRAM ABORT : " \
cBRI x); \ cBRI x); \
@ -221,8 +216,7 @@
abort(); \ abort(); \
} while (0) } while (0)
/* Die while also including the output of perror(). */ // 以包含perror()输出的方式退出程序
#define PFATAL(x...) do { \ #define PFATAL(x...) do { \
fflush(stdout); \ fflush(stdout); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \ SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD "\n[-] SYSTEM ERROR : " \
@ -233,16 +227,12 @@
exit(1); \ exit(1); \
} while (0) } while (0)
/* Die with FAULT() or PFAULT() depending on the value of res (used to // 根据res的值调用FAULT()或PFAULT()用于解释read()、write()等的不同失败模式
interpret different failure modes for read(), write(), etc). */
#define RPFATAL(res, x...) do { \ #define RPFATAL(res, x...) do { \
if (res < 0) PFATAL(x); else FATAL(x); \ if (res < 0) PFATAL(x); else FATAL(x); \
} while (0) } while (0)
/* Error-checking versions of read() and write() that call RPFATAL() as // 定义ck_write和ck_read宏用于检查write和read操作是否成功并在失败时调用RPFATAL
appropriate. */
#define ck_write(fd, buf, len, fn) do { \ #define ck_write(fd, buf, len, fn) do { \
u32 _len = (len); \ u32 _len = (len); \
s32 _res = write(fd, buf, _len); \ s32 _res = write(fd, buf, _len); \
@ -255,4 +245,4 @@
if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \
} while (0) } while (0)
#endif /* ! _HAVE_DEBUG_H */ #endif /* !_HAVE_DEBUG_H */

@ -31,81 +31,94 @@
Other code written and maintained by Michal Zalewski <lcamtuf@google.com> Other code written and maintained by Michal Zalewski <lcamtuf@google.com>
*/ */
// 检查_HAVE_HASH_H宏是否已定义如果没有则定义它以防止头文件被重复包含
#ifndef _HAVE_HASH_H #ifndef _HAVE_HASH_H
#define _HAVE_HASH_H #define _HAVE_HASH_H
// 包含types.h头文件可能包含一些基本类型的定义
#include "types.h" #include "types.h"
// 如果编译目标是x86_64架构则定义64位循环左移宏ROL64
#ifdef __x86_64__ #ifdef __x86_64__
#define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r)))) #define ROL64(_x, _r) ((((u64)(_x)) << (_r)) | (((u64)(_x)) >> (64 - (_r))))
// 定义一个内联函数hash32用于计算32位哈希值x86_64架构专用
static inline u32 hash32(const void* key, u32 len, u32 seed) { static inline u32 hash32(const void* key, u32 len, u32 seed) {
// 将key转换为u64指针
const u64* data = (u64*)key; const u64* data = (u64*)key;
u64 h1 = seed ^ len; // 初始化哈希值h1种子与长度异或
u64 h1 = seed ^ len;
len >>= 3;
// 将长度除以8因为u64是8字节
while (len--) { len >>= 3;
u64 k1 = *data++; // 循环处理每个u64数据块
while (len--) {
k1 *= 0x87c37b91114253d5ULL; // 读取下一个u64数据
k1 = ROL64(k1, 31); u64 k1 = *data++;
k1 *= 0x4cf5ad432745937fULL; // 应用MurmurHash算法的步骤
k1 *= 0x87c37b91114253d5ULL;
h1 ^= k1; k1 = ROL64(k1, 31);
h1 = ROL64(h1, 27); k1 *= 0x4cf5ad432745937fULL;
h1 = h1 * 5 + 0x52dce729;
// 将k1合并到h1
} h1 ^= k1;
h1 = ROL64(h1, 27);
h1 ^= h1 >> 33; h1 = h1 * 5 + 0x52dce729;
h1 *= 0xff51afd7ed558ccdULL; }
h1 ^= h1 >> 33;
h1 *= 0xc4ceb9fe1a85ec53ULL; // 最后的哈希值处理步骤
h1 ^= h1 >> 33; h1 ^= h1 >> 33;
h1 *= 0xff51afd7ed558ccdULL;
return h1; h1 ^= h1 >> 33;
h1 *= 0xc4ceb9fe1a85ec53ULL;
h1 ^= h1 >> 33;
// 返回最终的哈希值
return h1;
} }
// 如果编译目标不是x86_64架构则定义32位循环左移宏ROL32
#else #else
#define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r)))) #define ROL32(_x, _r) ((((u32)(_x)) << (_r)) | (((u32)(_x)) >> (32 - (_r))))
// 定义一个内联函数hash32用于计算32位哈希值非x86_64架构专用
static inline u32 hash32(const void* key, u32 len, u32 seed) { static inline u32 hash32(const void* key, u32 len, u32 seed) {
// 将key转换为u32指针
const u32* data = (u32*)key; const u32* data = (u32*)key;
u32 h1 = seed ^ len; // 初始化哈希值h1种子与长度异或
u32 h1 = seed ^ len;
len >>= 2;
// 将长度除以4因为u32是4字节
while (len--) { len >>= 2;
u32 k1 = *data++; // 循环处理每个u32数据块
while (len--) {
k1 *= 0xcc9e2d51; // 读取下一个u32数据
k1 = ROL32(k1, 15); u32 k1 = *data++;
k1 *= 0x1b873593; // 应用MurmurHash算法的步骤
k1 *= 0xcc9e2d51;
h1 ^= k1; k1 = ROL32(k1, 15);
h1 = ROL32(h1, 13); k1 *= 0x1b873593;
h1 = h1 * 5 + 0xe6546b64;
// 将k1合并到h1
} h1 ^= k1;
h1 = ROL32(h1, 13);
h1 ^= h1 >> 16; h1 = h1 * 5 + 0xe6546b64;
h1 *= 0x85ebca6b; }
h1 ^= h1 >> 13;
h1 *= 0xc2b2ae35; // 最后的哈希值处理步骤
h1 ^= h1 >> 16; h1 ^= h1 >> 16;
h1 *= 0x85ebca6b;
return h1; h1 ^= h1 >> 13;
h1 *= 0xc2b2ae35;
h1 ^= h1 >> 16;
// 返回最终的哈希值
return h1;
} }
#endif /* ^__x86_64__ */ #endif /* ^__x86_64__ */
// 结束宏定义_HAVE_HASH_H
#endif /* !_HAVE_HASH_H */ #endif /* !_HAVE_HASH_H */

@ -26,20 +26,28 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
// 定义程序的主函数接收命令行参数个数argc和参数值argv
int main(int argc, char** argv) { int main(int argc, char** argv) {
char buf[8]; // 定义一个字符数组buf大小为8用于存储从标准输入读取的数据
char buf[8];
if (read(0, buf, 8) < 1) {
printf("Hum?\n"); // 尝试从文件描述符0标准输入读取最多8个字节的数据到buf中
exit(1); if (read(0, buf, 8) < 1) {
} // 如果读取的字节数小于1即读取失败则打印消息并退出程序
printf("Hum?\n");
if (buf[0] == '0') exit(1);
printf("Looks like a zero to me!\n"); }
else
printf("A non-zero value? How quaint!\n"); // 检查buf的第一个字符是否为'0'
if (buf[0] == '0')
exit(0); // 如果是'0',则打印一条消息表示检测到零值
printf("Looks like a zero to me!\n");
else
// 如果不是'0',则打印一条消息表示检测到非零值
printf("A non-zero value? How quaint!\n");
// 正常退出程序
exit(0);
} }

@ -28,14 +28,20 @@
// TODO(metzman): Create a test/ directory to store this and other similar // TODO(metzman): Create a test/ directory to store this and other similar
// files. // files.
// 定义一个名为LLVMFuzzerTestOneInput的函数用于接收一个字节数组buf和其大小size
int LLVMFuzzerTestOneInput(uint8_t* buf, size_t size) { int LLVMFuzzerTestOneInput(uint8_t* buf, size_t size) {
if (size < 2) // 检查输入数据的大小是否小于2如果是则返回0表示测试不通过或无需进一步处理
if (size < 2)
return 0;
// 检查输入数据的第一个字节是否为'0'
if (buf[0] == '0')
// 如果是'0',则打印一条消息表示检测到零值
printf("Looks like a zero to me!\n");
else
// 如果不是'0',则打印一条消息表示检测到非零值
printf("A non-zero value? How quaint!\n");
// 函数返回0表示测试通过或没有发现异常
return 0; return 0;
if (buf[0] == '0')
printf("Looks like a zero to me!\n");
else
printf("A non-zero value? How quaint!\n");
return 0;
} }

@ -48,27 +48,32 @@ typedef uint32_t u32;
*/ */
// 条件编译指令用于定义64位无符号整数类型
#ifdef __x86_64__ #ifdef __x86_64__
typedef unsigned long long u64; typedef unsigned long long u64; // 在x86_64架构下使用unsigned long long作为u64
#else #else
typedef uint64_t u64; typedef uint64_t u64; // 否则使用标准库中的uint64_t作为u64
#endif /* ^__x86_64__ */ #endif /* ^__x86_64__ */
typedef int8_t s8; // 定义有符号整数类型
typedef int16_t s16; typedef int8_t s8; // 8位有符号整数
typedef int32_t s32; typedef int16_t s16; // 16位有符号整数
typedef int64_t s64; typedef int32_t s32; // 32位有符号整数
typedef int64_t s64; // 64位有符号整数
// 如果没有定义MIN则定义宏MIN和MAX
#ifndef MIN #ifndef MIN
# define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) # define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) // 取两个值中的最小值
# define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) # define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b)) // 取两个值中的最大值
#endif /* !MIN */ #endif /* !MIN */
// 宏定义SWAP16用于交换16位值的字节序
#define SWAP16(_x) ({ \ #define SWAP16(_x) ({ \
u16 _ret = (_x); \ u16 _ret = (_x); \
(u16)((_ret << 8) | (_ret >> 8)); \ (u16)((_ret << 8) | (_ret >> 8)); \
}) })
// 宏定义SWAP32用于交换32位值的字节序
#define SWAP32(_x) ({ \ #define SWAP32(_x) ({ \
u32 _ret = (_x); \ u32 _ret = (_x); \
(u32)((_ret << 24) | (_ret >> 24) | \ (u32)((_ret << 24) | (_ret >> 24) | \
@ -76,19 +81,23 @@ typedef int64_t s64;
((_ret >> 8) & 0x0000FF00)); \ ((_ret >> 8) & 0x0000FF00)); \
}) })
// 条件编译指令,用于定义随机数宏
#ifdef AFL_LLVM_PASS #ifdef AFL_LLVM_PASS
# define AFL_R(x) (random() % (x)) # define AFL_R(x) (random() % (x)) // 在AFL_LLVM_PASS模式下使用
#else #else
# define R(x) (random() % (x)) # define R(x) (random() % (x)) // 否则使用
#endif /* ^AFL_LLVM_PASS */ #endif /* ^AFL_LLVM_PASS */
// 宏定义STRINGIFY_INTERNAL和STRINGIFY用于将宏参数转换为字符串
#define STRINGIFY_INTERNAL(x) #x #define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x) #define STRINGIFY(x) STRINGIFY_INTERNAL(x)
// 内存屏障用于阻止编译器和CPU对指令重排
#define MEM_BARRIER() \ #define MEM_BARRIER() \
__asm__ volatile("" ::: "memory") __asm__ volatile("" ::: "memory")
#define likely(_x) __builtin_expect(!!(_x), 1) // 宏定义likely和unlikely用于优化分支预测
#define unlikely(_x) __builtin_expect(!!(_x), 0) #define likely(_x) __builtin_expect(!!(_x), 1) // 预期_x为真
#define unlikely(_x) __builtin_expect(!!(_x), 0) // 预期_x为假
#endif /* ! _HAVE_TYPES_H */ #endif /* ! _HAVE_TYPES_H */

Loading…
Cancel
Save