Compare commits

...

5 Commits

@ -34,6 +34,7 @@
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
@ -1551,141 +1552,115 @@ static int compare_extras_use_d(const void* p1, const void* p2) {
/* Read extras from a file, sort by size. */ /* Read extras from a file, sort by size. */
static void load_extras_file(u8* fname, u32* min_len, u32* max_len, // 定义一个函数,用于加载额外的数据文件
u32 dict_level) { static void load_extras_file(u8* fname, u32* min_len, u32* max_len, u32 dict_level) {
FILE* f; // 文件指针
FILE* f; u8 buf[MAX_LINE]; // 用于存储每行数据的缓冲区
u8 buf[MAX_LINE]; u8 *lptr; // 指向当前行数据的指针
u8 *lptr; u32 cur_line = 0; // 当前行号
u32 cur_line = 0;
// 尝试打开文件,如果失败则打印错误信息并退出
f = fopen(fname, "r"); f = fopen(fname, "r");
if (!f) PFATAL("Unable to open '%s'", fname); if (!f) PFATAL("Unable to open '%s'", fname);
// 逐行读取文件内容
while ((lptr = fgets(buf, MAX_LINE, f))) { while ((lptr = fgets(buf, MAX_LINE, f))) {
u8 *rptr, *wptr; // 指向行数据的指针
u32 klen = 0; // 关键词长度
u8 *rptr, *wptr; cur_line++; // 行号增加
u32 klen = 0;
cur_line++;
/* Trim on left and right. */
// 去除行首的空白字符
while (isspace(*lptr)) lptr++; while (isspace(*lptr)) lptr++;
// 去除行尾的空白字符,并找到行尾的结束符
rptr = lptr + strlen(lptr) - 1; rptr = lptr + strlen(lptr) - 1;
while (rptr >= lptr && isspace(*rptr)) rptr--; while (rptr >= lptr && isspace(*rptr)) rptr--;
rptr++; rptr++;
*rptr = 0; *rptr = 0;
/* Skip empty lines and comments. */ // 跳过空行和注释行
if (!*lptr || *lptr == '#') continue; if (!*lptr || *lptr == '#') continue;
/* All other lines must end with '"', which we can consume. */ // 检查行尾是否有双引号,如果没有则报错
rptr--; rptr--;
if (rptr < lptr || *rptr != '"') if (rptr < lptr || *rptr != '"')
FATAL("Malformed name=\"value\" pair in line %u.", cur_line); FATAL("Malformed name=\"value\" pair in line %u.", cur_line);
*rptr = 0; *rptr = 0; // 去除行尾的双引号
/* Skip alphanumerics and dashes (label). */
// 跳过字母数字和下划线(标签)
while (isalnum(*lptr) || *lptr == '_') lptr++; while (isalnum(*lptr) || *lptr == '_') lptr++;
/* If @number follows, parse that. */ // 如果标签后跟有@数字,则解析该数字
if (*lptr == '@') { if (*lptr == '@') {
lptr++; lptr++;
if (atoi(lptr) > dict_level) continue; if (atoi(lptr) > dict_level) continue; // 如果数字大于字典级别,则跳过
while (isdigit(*lptr)) lptr++; while (isdigit(*lptr)) lptr++; // 跳过数字
} }
/* Skip whitespace and = signs. */ // 跳过空白字符和等号
while (isspace(*lptr) || *lptr == '=') lptr++; while (isspace(*lptr) || *lptr == '=') lptr++;
/* Consume opening '"'. */ // 检查等号后是否有双引号,如果没有则报错
if (*lptr != '"') if (*lptr != '"')
FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line);
lptr++; lptr++; // 跳过双引号
if (!*lptr) FATAL("Empty keyword in line %u.", cur_line);
/* Okay, let's allocate memory and copy data between "...", handling if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); // 检查关键词是否为空
\xNN escaping, \\, and \". */
extras = ck_realloc_block(extras, (extras_cnt + 1) *
sizeof(struct extra_data));
// 分配内存并复制数据,处理转义字符
extras = ck_realloc_block(extras, (extras_cnt + 1) * sizeof(struct extra_data));
wptr = extras[extras_cnt].data = ck_alloc(rptr - lptr); wptr = extras[extras_cnt].data = ck_alloc(rptr - lptr);
// 复制数据,处理转义字符
while (*lptr) { while (*lptr) {
char* hexdigits = "0123456789abcdef"; char* hexdigits = "0123456789abcdef";
switch (*lptr) { switch (*lptr) {
case 1 ... 31: // 非打印字符
case 1 ... 31: case 128 ... 255: // 非ASCII字符
case 128 ... 255:
FATAL("Non-printable characters in line %u.", cur_line); FATAL("Non-printable characters in line %u.", cur_line);
break;
case '\\': case '\\': // 处理转义字符
lptr++; lptr++;
if (*lptr == '\\' || *lptr == '"') { if (*lptr == '\\' || *lptr == '"') {
*(wptr++) = *(lptr++); *(wptr++) = *(lptr++); // 直接复制转义字符
klen++; klen++;
break; break;
} }
if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2]))
FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line);
// 处理\xNN形式的转义字符
*(wptr++) = *(wptr++) = ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) |
((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) |
(strchr(hexdigits, tolower(lptr[2])) - hexdigits); (strchr(hexdigits, tolower(lptr[2])) - hexdigits);
lptr += 3; lptr += 3;
klen++; klen++;
break; break;
default: default: // 复制普通字符
*(wptr++) = *(lptr++); *(wptr++) = *(lptr++);
klen++; klen++;
} }
} }
extras[extras_cnt].len = klen; extras[extras_cnt].len = klen; // 设置关键词长度
if (extras[extras_cnt].len > MAX_DICT_FILE) if (extras[extras_cnt].len > MAX_DICT_FILE)
FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line, FATAL("Keyword too big in line %u (%s, limit is %s)", cur_line,
DMS(klen), DMS(MAX_DICT_FILE)); DMS(klen), DMS(MAX_DICT_FILE)); // 检查关键词长度是否超过限制
if (*min_len > klen) *min_len = klen; if (*min_len > klen) *min_len = klen; // 更新最小长度
if (*max_len < klen) *max_len = klen; if (*max_len < klen) *max_len = klen; // 更新最大长度
extras_cnt++;
extras_cnt++; // 增加额外数据计数
} }
fclose(f); fclose(f); // 关闭文件
} }
/* Read extras from the extras directory and sort them by size. */ /* Read extras from the extras directory and sort them by size. */
static void load_extras(u8* dir) { static void load_extras(u8* dir) {
@ -2571,32 +2546,56 @@ static void show_stats(void);
to warn about flaky or otherwise problematic test cases early on; and when to warn about flaky or otherwise problematic test cases early on; and when
new paths are discovered to detect variable behavior and so on. */ new paths are discovered to detect variable behavior and so on. */
//start_us, stop_us; //start_us, stop_us;
<<<<<<< HEAD
=======
//保存了一些旧的状态值,以便在函数执行完毕后恢复。 //保存了一些旧的状态值,以便在函数执行完毕后恢复。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
//保存了一些旧的状态值,以便在函数执行完毕后恢复。
// 定义一个用于校准测试用例的函数
static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem, static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,
u32 handicap, u8 from_queue) { u32 handicap, u8 from_queue) {
// 定义一个静态数组用于存储第一次执行时的trace bits
static u8 first_trace[MAP_SIZE]; static u8 first_trace[MAP_SIZE];
// 定义一些局部变量
u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0, u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0,
first_run = (q->exec_cksum == 0); first_run = (q->exec_cksum == 0);
// 定义变量用于计时
u64 start_us, stop_us; u64 start_us, stop_us;
// 保存旧的阶段状态
s32 old_sc = stage_cur, old_sm = stage_max; s32 old_sc = stage_cur, old_sm = stage_max;
u32 use_tmout = exec_tmout; u32 use_tmout = exec_tmout;
u8* old_sn = stage_name; u8* old_sn = stage_name;
<<<<<<< HEAD
/* 如果是在恢复会话或校准已经添加的测试用例时,会放宽超时限制。
*/
=======
/* Be a bit more generous about timeouts when resuming sessions, or when /* Be a bit more generous about timeouts when resuming sessions, or when
trying to calibrate already-added finds. This helps avoid trouble due trying to calibrate already-added finds. This helps avoid trouble due
to intermittent latency. */ to intermittent latency. */
//如果是在恢复会话或校准已经添加的测试用例时,会放宽超时限制。 //如果是在恢复会话或校准已经添加的测试用例时,会放宽超时限制。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
if (!from_queue || resuming_fuzz) if (!from_queue || resuming_fuzz)
use_tmout = MAX(exec_tmout + CAL_TMOUT_ADD, use_tmout = MAX(exec_tmout + CAL_TMOUT_ADD,
exec_tmout * CAL_TMOUT_PERC / 100); exec_tmout * CAL_TMOUT_PERC / 100);
// 增加校准失败计数
q->cal_failed++; q->cal_failed++;
<<<<<<< HEAD
// 设置当前阶段为“calibration”并根据是否快速校准设置阶段最大值
stage_name = "calibration";
stage_max = fast_cal ? 3 : CAL_CYCLES;
/* 确保在执行任何操作之前fork服务器已经启动并且不将其启动时间计入二进制校准。 */
// 如果没有运行在“dumb”模式并且没有使用fork服务器那么初始化fork服务器
=======
//设置当前阶段为“calibration”并根据是否快速校准设置阶段最大值。 //设置当前阶段为“calibration”并根据是否快速校准设置阶段最大值。
stage_name = "calibration"; stage_name = "calibration";
stage_max = fast_cal ? 3 : CAL_CYCLES; stage_max = fast_cal ? 3 : CAL_CYCLES;
@ -2604,24 +2603,44 @@ static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,
/* Make sure the forkserver is up before we do anything, and let's not /* Make sure the forkserver is up before we do anything, and let's not
count its spin-up time toward binary calibration. */ count its spin-up time toward binary calibration. */
//如果没有运行在“dumb”模式并且没有使用fork服务器那么初始化fork服务器。 //如果没有运行在“dumb”模式并且没有使用fork服务器那么初始化fork服务器。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
if (dumb_mode != 1 && !no_forkserver && !forksrv_pid) if (dumb_mode != 1 && !no_forkserver && !forksrv_pid)
init_forkserver(argv); init_forkserver(argv);
// 如果队列条目已经有执行校验和那么将第一次执行的trace bits复制到first_trace
if (q->exec_cksum) { if (q->exec_cksum) {
<<<<<<< HEAD
=======
//如果队列条目已经有执行校验和那么将第一次执行的trace bits复制到first_trace。 //如果队列条目已经有执行校验和那么将第一次执行的trace bits复制到first_trace。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
memcpy(first_trace, trace_bits, MAP_SIZE); memcpy(first_trace, trace_bits, MAP_SIZE);
hnb = has_new_bits(virgin_bits); hnb = has_new_bits(virgin_bits);
if (hnb > new_bits) new_bits = hnb; if (hnb > new_bits) new_bits = hnb;
} }
<<<<<<< HEAD
// 计时开始
start_us = get_cur_time_us();
=======
start_us = get_cur_time_us();//计时 start_us = get_cur_time_us();//计时
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
// 校准循环
for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { for (stage_cur = 0; stage_cur < stage_max; stage_cur++) {
u32 cksum; u32 cksum;
// 如果不是第一次运行并且到了更新频率,显示统计信息
if (!first_run && !(stage_cur % stats_update_freq)) show_stats(); if (!first_run && !(stage_cur % stats_update_freq)) show_stats();
<<<<<<< HEAD
// 将测试用例数据写入文件
write_to_testcase(use_mem, q->len);
// 运行目标程序并获取执行结果
fault = run_target(argv, use_tmout);
/* 如果用户按下Ctrl+Cstop_soon会被设置我们希望快速退出。 */
if (stop_soon || fault != crash_mode) goto abort_calibration;
=======
//如果不是第一次运行并且到了更新频率,显示统计信息。 //如果不是第一次运行并且到了更新频率,显示统计信息。
write_to_testcase(use_mem, q->len);//将测试用例数据写入文件。 write_to_testcase(use_mem, q->len);//将测试用例数据写入文件。
@ -2631,13 +2650,28 @@ static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,
we want to bail out quickly. */ we want to bail out quickly. */
if (stop_soon || fault != crash_mode) goto abort_calibration;//如果用户请求停止或者执行结果不是崩溃模式,则跳到校准中止。 if (stop_soon || fault != crash_mode) goto abort_calibration;//如果用户请求停止或者执行结果不是崩溃模式,则跳到校准中止。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
// 如果不是“dumb”模式并且是第一次校准并且没有新的代码覆盖则设置错误为FAULT_NOINST
if (!dumb_mode && !stage_cur && !count_bytes(trace_bits)) { if (!dumb_mode && !stage_cur && !count_bytes(trace_bits)) {
//如果不是“dumb”模式并且是第一次校准并且没有新的代码覆盖则设置错误为FAULT_NOINST并跳到校准中止。 //如果不是“dumb”模式并且是第一次校准并且没有新的代码覆盖则设置错误为FAULT_NOINST并跳到校准中止。
fault = FAULT_NOINST; fault = FAULT_NOINST;
goto abort_calibration; goto abort_calibration;
} }
<<<<<<< HEAD
// 计算当前trace bits的哈希值并与队列条目的执行校验和比较
cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);
if (q->exec_cksum != cksum) {
// 如果有新的bits被设置则更新new_bits
hnb = has_new_bits(virgin_bits);
if (hnb > new_bits) new_bits = hnb;
// 如果队列条目之前有执行校验和,则检查变量字节
if (q->exec_cksum) {
u32 i;
// 对于每个不同的字节,将其标记为变量字节,并增加校准周期
=======
cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);//计算当前trace bits的哈希值并与队列条目的执行校验和比较。 cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);//计算当前trace bits的哈希值并与队列条目的执行校验和比较。
if (q->exec_cksum != cksum) { if (q->exec_cksum != cksum) {
@ -2649,82 +2683,107 @@ static u8 calibrate_case(char** argv, struct queue_entry* q, u8* use_mem,
u32 i; u32 i;
//对于每个不同的字节,将其标记为变量字节,并增加校准周期。 //对于每个不同的字节,将其标记为变量字节,并增加校准周期。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
for (i = 0; i < MAP_SIZE; i++) { for (i = 0; i < MAP_SIZE; i++) {
if (!var_bytes[i] && first_trace[i] != trace_bits[i]) { if (!var_bytes[i] && first_trace[i] != trace_bits[i]) {
var_bytes[i] = 1; var_bytes[i] = 1;
stage_max = CAL_CYCLES_LONG; stage_max = CAL_CYCLES_LONG;
} }
} }
var_detected = 1; var_detected = 1;
<<<<<<< HEAD
=======
//如果队列条目之前没有执行校验和则更新其执行校验和并复制当前trace bits。 //如果队列条目之前没有执行校验和则更新其执行校验和并复制当前trace bits。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
} else { } else {
// 如果队列条目之前没有执行校验和则更新其执行校验和并复制当前trace bits
q->exec_cksum = cksum; q->exec_cksum = cksum;
memcpy(first_trace, trace_bits, MAP_SIZE); memcpy(first_trace, trace_bits, MAP_SIZE);
} }
} }
} }
// 计时结束
stop_us = get_cur_time_us(); stop_us = get_cur_time_us();
<<<<<<< HEAD
// 更新总校准时间和周期
total_cal_us += stop_us - start_us;
total_cal_cycles += stage_max;
/* 收集一些关于这个测试用例性能的统计数据。
calculate_score()fuzzing */
// 更新队列条目的执行时间、位图大小和校准失败计数
=======
total_cal_us += stop_us - start_us;//更新总校准时间和周期。 total_cal_us += stop_us - start_us;//更新总校准时间和周期。
total_cal_cycles += stage_max; total_cal_cycles += stage_max;
/* OK, let's collect some stats about the performance of this test case. /* OK, let's collect some stats about the performance of this test case.
This is used for fuzzing air time calculations in calculate_score(). */ This is used for fuzzing air time calculations in calculate_score(). */
//更新队列条目的执行时间、位图大小和校准失败计数。 //更新队列条目的执行时间、位图大小和校准失败计数。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
q->exec_us = (stop_us - start_us) / stage_max; q->exec_us = (stop_us - start_us) / stage_max;
q->bitmap_size = count_bytes(trace_bits); q->bitmap_size = count_bytes(trace_bits);
q->handicap = handicap; q->handicap = handicap;
q->cal_failed = 0; q->cal_failed = 0;
<<<<<<< HEAD
// 更新总位图大小和条目数
total_bitmap_size += q->bitmap_size;
=======
total_bitmap_size += q->bitmap_size;//更新总位图大小和条目数 total_bitmap_size += q->bitmap_size;//更新总位图大小和条目数
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
total_bitmap_entries++; total_bitmap_entries++;
// 更新位图得分
update_bitmap_score(q); update_bitmap_score(q);
/* If this case didn't result in new output from the instrumentation, tell /* 如果这个案例没有产生新的来自仪器的输出,告诉父进程。
parent. This is a non-critical problem, but something to warn the user */
about. */
if (!dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS; if (!dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS;
abort_calibration: abort_calibration:
<<<<<<< HEAD
// 如果有新的bits被设置并且队列条目之前没有新覆盖则更新队列条目的新覆盖标志
=======
//如果有新的bits被设置并且队列条目之前没有新覆盖则更新队列条目的新覆盖标志。 //如果有新的bits被设置并且队列条目之前没有新覆盖则更新队列条目的新覆盖标志。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
if (new_bits == 2 && !q->has_new_cov) { if (new_bits == 2 && !q->has_new_cov) {
q->has_new_cov = 1; q->has_new_cov = 1;
queued_with_cov++; queued_with_cov++;
} }
/* Mark variable paths. */ /* 标记可变路径。 */
if (var_detected) { if (var_detected) {
<<<<<<< HEAD
// 如果检测到变量行为,则标记队列条目
=======
//如果检测到变量行为,则标记队列条目。 //如果检测到变量行为,则标记队列条目。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
var_byte_count = count_bytes(var_bytes); var_byte_count = count_bytes(var_bytes);
if (!q->var_behavior) { if (!q->var_behavior) {
mark_as_variable(q); mark_as_variable(q);
queued_variable++; queued_variable++;
} }
} }
<<<<<<< HEAD
// 恢复旧的状态值
=======
//恢复旧的状态值。 //恢复旧的状态值。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
stage_name = old_sn; stage_name = old_sn;
stage_cur = old_sc; stage_cur = old_sc;
stage_max = old_sm; stage_max = old_sm;
<<<<<<< HEAD
// 如果校准中止,则跳到函数末尾
if (!first_run) show_stats();
=======
if (!first_run) show_stats();//如果校准中止,则跳到函数末尾。 if (!first_run) show_stats();//如果校准中止,则跳到函数末尾。
>>>>>>> 78837268ef8db0dafd64b331e2b9f6380dbb1090
// 返回错误代码
return fault; return fault;
} }

Loading…
Cancel
Save