|
|
|
@ -6090,476 +6090,376 @@ skip_user_extras:
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_EXTRAS_AO] += stage_max;
|
|
|
|
|
stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; // 更新STAGE_EXTRAS_AO阶段的发现计数
|
|
|
|
|
stage_cycles[STAGE_EXTRAS_AO] += stage_max; // 更新STAGE_EXTRAS_AO阶段的循环计数
|
|
|
|
|
|
|
|
|
|
skip_extras:
|
|
|
|
|
skip_extras: // 跳过额外的处理步骤
|
|
|
|
|
|
|
|
|
|
/* If we made this to here without jumping to havoc_stage or abandon_entry,
|
|
|
|
|
we're properly done with deterministic steps and can mark it as such
|
|
|
|
|
in the .state/ directory. */
|
|
|
|
|
in the .state/ directory. */ // 如果程序执行到这里而没有跳转到havoc_stage或abandon_entry,说明我们已经完成了确定性步骤,可以在.state/目录中标记为已完成
|
|
|
|
|
|
|
|
|
|
if (!queue_cur->passed_det) mark_as_det_done(queue_cur);
|
|
|
|
|
if (!queue_cur->passed_det) mark_as_det_done(queue_cur); // 如果当前队列项尚未标记为完成确定性步骤,则标记为完成
|
|
|
|
|
|
|
|
|
|
/****************
|
|
|
|
|
* RANDOM HAVOC *
|
|
|
|
|
****************/
|
|
|
|
|
****************/ // 随机破坏阶段
|
|
|
|
|
|
|
|
|
|
havoc_stage:
|
|
|
|
|
havoc_stage: // 随机破坏阶段的标签
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = -1;
|
|
|
|
|
stage_cur_byte = -1; // 初始化当前字节位置为-1
|
|
|
|
|
|
|
|
|
|
/* The havoc stage mutation code is also invoked when splicing files; if the
|
|
|
|
|
splice_cycle variable is set, generate different descriptions and such. */
|
|
|
|
|
splice_cycle variable is set, generate different descriptions and such. */ // 当拼接文件时也会调用随机破坏阶段的变异代码;如果splice_cycle变量被设置,生成不同的描述等
|
|
|
|
|
|
|
|
|
|
if (!splice_cycle) {
|
|
|
|
|
if (!splice_cycle) { // 如果没有进行文件拼接
|
|
|
|
|
|
|
|
|
|
stage_name = "havoc";
|
|
|
|
|
stage_short = "havoc";
|
|
|
|
|
stage_name = "havoc"; // 设置阶段名称为"havoc"
|
|
|
|
|
stage_short = "havoc"; // 设置阶段简称为"havoc"
|
|
|
|
|
stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
|
|
|
|
|
perf_score / havoc_div / 100;
|
|
|
|
|
perf_score / havoc_div / 100; // 根据是否进行确定性测试和性能评分计算最大阶段循环次数
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
static u8 tmp[32];
|
|
|
|
|
} else { // 如果进行文件拼接
|
|
|
|
|
|
|
|
|
|
perf_score = orig_perf;
|
|
|
|
|
static u8 tmp[32]; // 定义一个静态的32字节缓冲区
|
|
|
|
|
|
|
|
|
|
sprintf(tmp, "splice %u", splice_cycle);
|
|
|
|
|
stage_name = tmp;
|
|
|
|
|
stage_short = "splice";
|
|
|
|
|
stage_max = SPLICE_HAVOC * perf_score / havoc_div / 100;
|
|
|
|
|
perf_score = orig_perf; // 恢复原始性能评分
|
|
|
|
|
|
|
|
|
|
sprintf(tmp, "splice %u", splice_cycle); // 格式化拼接周期的描述
|
|
|
|
|
stage_name = tmp; // 设置阶段名称为拼接周期的描述
|
|
|
|
|
stage_short = "splice"; // 设置阶段简称为"splice"
|
|
|
|
|
stage_max = SPLICE_HAVOC * perf_score / havoc_div / 100; // 根据拼接周期的性能评分计算最大阶段循环次数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stage_max < HAVOC_MIN) stage_max = HAVOC_MIN;
|
|
|
|
|
if (stage_max < HAVOC_MIN) stage_max = HAVOC_MIN; // 如果最大阶段循环次数小于HAVOC_MIN,则将其设置为HAVOC_MIN
|
|
|
|
|
|
|
|
|
|
temp_len = len;
|
|
|
|
|
temp_len = len; // 将临时长度设置为输入缓冲区的长度
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
orig_hit_cnt = queued_paths + unique_crashes; // 记录当前已排队的路径和唯一崩溃的总数
|
|
|
|
|
|
|
|
|
|
havoc_queued = queued_paths;
|
|
|
|
|
havoc_queued = queued_paths; // 记录当前已排队的路径数
|
|
|
|
|
|
|
|
|
|
/* We essentially just do several thousand runs (depending on perf_score)
|
|
|
|
|
where we take the input file and make random stacked tweaks. */
|
|
|
|
|
where we take the input file and make random stacked tweaks. */ // 我们基本上会进行数千次运行(取决于性能评分),对输入文件进行随机的堆叠调整
|
|
|
|
|
|
|
|
|
|
for (stage_cur = 0; stage_cur < stage_max; stage_cur++) {
|
|
|
|
|
for (stage_cur = 0; stage_cur < stage_max; stage_cur++) { // 遍历最大阶段循环次数
|
|
|
|
|
|
|
|
|
|
u32 use_stacking = 1 << (1 + UR(HAVOC_STACK_POW2));
|
|
|
|
|
u32 use_stacking = 1 << (1 + UR(HAVOC_STACK_POW2)); // 随机生成一个堆叠次数,用于决定每次循环中进行多少次变异
|
|
|
|
|
|
|
|
|
|
stage_cur_val = use_stacking;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < use_stacking; i++) {
|
|
|
|
|
stage_cur_val = use_stacking; // 记录当前堆叠次数
|
|
|
|
|
|
|
|
|
|
switch (UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))) {
|
|
|
|
|
for (i = 0; i < use_stacking; i++) { // 遍历堆叠次数
|
|
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
|
switch (UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))) { // 随机选择一个变异操作
|
|
|
|
|
|
|
|
|
|
/* Flip a single bit somewhere. Spooky! */
|
|
|
|
|
case 0: // 操作0:翻转一个随机位
|
|
|
|
|
|
|
|
|
|
FLIP_BIT(out_buf, UR(temp_len << 3));
|
|
|
|
|
/* Flip a single bit somewhere. Spooky! */ // 翻转某个随机位
|
|
|
|
|
FLIP_BIT(out_buf, UR(temp_len << 3)); // 在输出缓冲区中随机翻转一个位
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
|
|
/* Set byte to interesting value. */
|
|
|
|
|
case 1: // 操作1:将随机字节设置为一个有趣的值
|
|
|
|
|
|
|
|
|
|
out_buf[UR(temp_len)] = interesting_8[UR(sizeof(interesting_8))];
|
|
|
|
|
/* Set byte to interesting value. */ // 将随机字节设置为一个有趣的值
|
|
|
|
|
out_buf[UR(temp_len)] = interesting_8[UR(sizeof(interesting_8))]; // 从interesting_8数组中随机选择一个值并设置到随机位置
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
|
|
/* Set word to interesting value, randomly choosing endian. */
|
|
|
|
|
case 2: // 操作2:将随机字设置为一个有趣的值,随机选择字节序
|
|
|
|
|
|
|
|
|
|
if (temp_len < 2) break;
|
|
|
|
|
|
|
|
|
|
if (UR(2)) {
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + UR(temp_len - 1)) =
|
|
|
|
|
interesting_16[UR(sizeof(interesting_16) >> 1)];
|
|
|
|
|
/* Set word to interesting value, randomly choosing endian. */ // 将随机字设置为一个有趣的值,随机选择字节序
|
|
|
|
|
if (temp_len < 2) break; // 如果缓冲区长度小于2,跳过
|
|
|
|
|
|
|
|
|
|
if (UR(2)) { // 随机选择字节序
|
|
|
|
|
*(u16*)(out_buf + UR(temp_len - 1)) = interesting_16[UR(sizeof(interesting_16) >> 1)]; // 使用小端序设置值
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + UR(temp_len - 1)) = SWAP16(
|
|
|
|
|
interesting_16[UR(sizeof(interesting_16) >> 1)]);
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + UR(temp_len - 1)) = SWAP16(interesting_16[UR(sizeof(interesting_16) >> 1)]); // 使用大端序设置值
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
|
|
/* Set dword to interesting value, randomly choosing endian. */
|
|
|
|
|
case 3: // 操作3:将随机双字设置为一个有趣的值,随机选择字节序
|
|
|
|
|
|
|
|
|
|
if (temp_len < 4) break;
|
|
|
|
|
|
|
|
|
|
if (UR(2)) {
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + UR(temp_len - 3)) =
|
|
|
|
|
interesting_32[UR(sizeof(interesting_32) >> 2)];
|
|
|
|
|
/* Set dword to interesting value, randomly choosing endian. */ // 将随机双字设置为一个有趣的值,随机选择字节序
|
|
|
|
|
if (temp_len < 4) break; // 如果缓冲区长度小于4,跳过
|
|
|
|
|
|
|
|
|
|
if (UR(2)) { // 随机选择字节序
|
|
|
|
|
*(u32*)(out_buf + UR(temp_len - 3)) = interesting_32[UR(sizeof(interesting_32) >> 2)]; // 使用小端序设置值
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + UR(temp_len - 3)) = SWAP32(
|
|
|
|
|
interesting_32[UR(sizeof(interesting_32) >> 2)]);
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + UR(temp_len - 3)) = SWAP32(interesting_32[UR(sizeof(interesting_32) >> 2)]); // 使用大端序设置值
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
|
|
|
|
/* Randomly subtract from byte. */
|
|
|
|
|
case 4: // 操作4:随机减少一个字节的值
|
|
|
|
|
|
|
|
|
|
out_buf[UR(temp_len)] -= 1 + UR(ARITH_MAX);
|
|
|
|
|
/* Randomly subtract from byte. */ // 随机减少一个字节的值
|
|
|
|
|
out_buf[UR(temp_len)] -= 1 + UR(ARITH_MAX); // 随机减少一个字节的值
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
|
|
|
|
/* Randomly add to byte. */
|
|
|
|
|
case 5: // 操作5:随机增加一个字节的值
|
|
|
|
|
|
|
|
|
|
out_buf[UR(temp_len)] += 1 + UR(ARITH_MAX);
|
|
|
|
|
/* Randomly add to byte. */ // 随机增加一个字节的值
|
|
|
|
|
out_buf[UR(temp_len)] += 1 + UR(ARITH_MAX); // 随机增加一个字节的值
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
|
case 6: // 操作6:随机减少一个字的值,随机选择字节序
|
|
|
|
|
|
|
|
|
|
/* Randomly subtract from word, random endian. */
|
|
|
|
|
|
|
|
|
|
if (temp_len < 2) break;
|
|
|
|
|
|
|
|
|
|
if (UR(2)) {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 1);
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + pos) -= 1 + UR(ARITH_MAX);
|
|
|
|
|
/* Randomly subtract from word, random endian. */ // 随机减少一个字的值,随机选择字节序
|
|
|
|
|
if (temp_len < 2) break; // 如果缓冲区长度小于2,跳过
|
|
|
|
|
|
|
|
|
|
if (UR(2)) { // 随机选择字节序
|
|
|
|
|
u32 pos = UR(temp_len - 1); // 随机选择位置
|
|
|
|
|
*(u16*)(out_buf + pos) -= 1 + UR(ARITH_MAX); // 减少字的值
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 1);
|
|
|
|
|
u16 num = 1 + UR(ARITH_MAX);
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + pos) =
|
|
|
|
|
SWAP16(SWAP16(*(u16*)(out_buf + pos)) - num);
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 1); // 随机选择位置
|
|
|
|
|
u16 num = 1 + UR(ARITH_MAX); // 随机生成减少的值
|
|
|
|
|
*(u16*)(out_buf + pos) = SWAP16(SWAP16(*(u16*)(out_buf + pos)) - num); // 使用大端序减少字的值
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
|
|
|
|
/* Randomly add to word, random endian. */
|
|
|
|
|
|
|
|
|
|
if (temp_len < 2) break;
|
|
|
|
|
case 7: // 操作7:随机增加一个字的值,随机选择字节序
|
|
|
|
|
|
|
|
|
|
if (UR(2)) {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 1);
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + pos) += 1 + UR(ARITH_MAX);
|
|
|
|
|
/* Randomly add to word, random endian. */ // 随机增加一个字的值,随机选择字节序
|
|
|
|
|
if (temp_len < 2) break; // 如果缓冲区长度小于2,跳过
|
|
|
|
|
|
|
|
|
|
if (UR(2)) { // 随机选择字节序
|
|
|
|
|
u32 pos = UR(temp_len - 1); // 随机选择位置
|
|
|
|
|
*(u16*)(out_buf + pos) += 1 + UR(ARITH_MAX); // 增加字的值
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 1);
|
|
|
|
|
u16 num = 1 + UR(ARITH_MAX);
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + pos) =
|
|
|
|
|
SWAP16(SWAP16(*(u16*)(out_buf + pos)) + num);
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 1); // 随机选择位置
|
|
|
|
|
u16 num = 1 + UR(ARITH_MAX); // 随机生成增加的值
|
|
|
|
|
*(u16*)(out_buf + pos) = SWAP16(SWAP16(*(u16*)(out_buf + pos)) + num); // 使用大端序增加字的值
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
|
|
|
|
/* Randomly subtract from dword, random endian. */
|
|
|
|
|
|
|
|
|
|
if (temp_len < 4) break;
|
|
|
|
|
|
|
|
|
|
if (UR(2)) {
|
|
|
|
|
case 8: // 操作8:随机减少一个双字的值,随机选择字节序
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 3);
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + pos) -= 1 + UR(ARITH_MAX);
|
|
|
|
|
/* Randomly subtract from dword, random endian. */ // 随机减少一个双字的值,随机选择字节序
|
|
|
|
|
if (temp_len < 4) break; // 如果缓冲区长度小于4,跳过
|
|
|
|
|
|
|
|
|
|
if (UR(2)) { // 随机选择字节序
|
|
|
|
|
u32 pos = UR(temp_len - 3); // 随机选择位置
|
|
|
|
|
*(u32*)(out_buf + pos) -= 1 + UR(ARITH_MAX); // 减少双字的值
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 3);
|
|
|
|
|
u32 num = 1 + UR(ARITH_MAX);
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + pos) =
|
|
|
|
|
SWAP32(SWAP32(*(u32*)(out_buf + pos)) - num);
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 3); // 随机选择位置
|
|
|
|
|
u32 num = 1 + UR(ARITH_MAX); // 随机生成减少的值
|
|
|
|
|
*(u32*)(out_buf + pos) = SWAP32(SWAP32(*(u32*)(out_buf + pos)) - num); // 使用大端序减少双字的值
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 9:
|
|
|
|
|
|
|
|
|
|
/* Randomly add to dword, random endian. */
|
|
|
|
|
case 9: // 操作9:随机增加一个双字的值,随机选择字节序
|
|
|
|
|
|
|
|
|
|
if (temp_len < 4) break;
|
|
|
|
|
|
|
|
|
|
if (UR(2)) {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 3);
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + pos) += 1 + UR(ARITH_MAX);
|
|
|
|
|
/* Randomly add to dword, random endian. */ // 随机增加一个双字的值,随机选择字节序
|
|
|
|
|
if (temp_len < 4) break; // 如果缓冲区长度小于4,跳过
|
|
|
|
|
|
|
|
|
|
if (UR(2)) { // 随机选择字节序
|
|
|
|
|
u32 pos = UR(temp_len - 3); // 随机选择位置
|
|
|
|
|
*(u32*)(out_buf + pos) += 1 + UR(ARITH_MAX); // 增加双字的值
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 3);
|
|
|
|
|
u32 num = 1 + UR(ARITH_MAX);
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + pos) =
|
|
|
|
|
SWAP32(SWAP32(*(u32*)(out_buf + pos)) + num);
|
|
|
|
|
|
|
|
|
|
u32 pos = UR(temp_len - 3); // 随机选择位置
|
|
|
|
|
u32 num = 1 + UR(ARITH_MAX); // 随机生成增加的值
|
|
|
|
|
*(u32*)(out_buf + pos) = SWAP32(SWAP32(*(u32*)(out_buf + pos)) + num); // 使用大端序增加双字的值
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
|
case 10: // 操作10:随机异或一个字节的值
|
|
|
|
|
|
|
|
|
|
/* Just set a random byte to a random value. Because,
|
|
|
|
|
why not. We use XOR with 1-255 to eliminate the
|
|
|
|
|
possibility of a no-op. */
|
|
|
|
|
|
|
|
|
|
out_buf[UR(temp_len)] ^= 1 + UR(255);
|
|
|
|
|
possibility of a no-op. */ // 随机异或一个字节的值,避免无操作
|
|
|
|
|
out_buf[UR(temp_len)] ^= 1 + UR(255); // 随机异或一个字节的值
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 11 ... 12: {
|
|
|
|
|
case 11 ... 12: { // 操作11-12:删除随机长度的字节
|
|
|
|
|
|
|
|
|
|
/* Delete bytes. We're making this a bit more likely
|
|
|
|
|
than insertion (the next option) in hopes of keeping
|
|
|
|
|
files reasonably small. */
|
|
|
|
|
|
|
|
|
|
u32 del_from, del_len;
|
|
|
|
|
|
|
|
|
|
if (temp_len < 2) break;
|
|
|
|
|
|
|
|
|
|
/* Don't delete too much. */
|
|
|
|
|
|
|
|
|
|
del_len = choose_block_len(temp_len - 1);
|
|
|
|
|
|
|
|
|
|
del_from = UR(temp_len - del_len + 1);
|
|
|
|
|
files reasonably small. */ // 删除字节,比插入操作更频繁,以保持文件大小合理
|
|
|
|
|
u32 del_from, del_len; // 定义删除的起始位置和长度
|
|
|
|
|
|
|
|
|
|
memmove(out_buf + del_from, out_buf + del_from + del_len,
|
|
|
|
|
temp_len - del_from - del_len);
|
|
|
|
|
if (temp_len < 2) break; // 如果缓冲区长度小于2,跳过
|
|
|
|
|
|
|
|
|
|
temp_len -= del_len;
|
|
|
|
|
/* Don't delete too much. */ // 不要删除太多
|
|
|
|
|
del_len = choose_block_len(temp_len - 1); // 随机选择删除的长度
|
|
|
|
|
del_from = UR(temp_len - del_len + 1); // 随机选择删除的起始位置
|
|
|
|
|
|
|
|
|
|
memmove(out_buf + del_from, out_buf + del_from + del_len, temp_len - del_from - del_len); // 移动缓冲区内容以删除字节
|
|
|
|
|
temp_len -= del_len; // 更新缓冲区长度
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 13:
|
|
|
|
|
|
|
|
|
|
if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
|
|
|
|
|
|
|
|
|
|
/* Clone bytes (75%) or insert a block of constant bytes (25%). */
|
|
|
|
|
|
|
|
|
|
u8 actually_clone = UR(4);
|
|
|
|
|
u32 clone_from, clone_to, clone_len;
|
|
|
|
|
u8* new_buf;
|
|
|
|
|
|
|
|
|
|
if (actually_clone) {
|
|
|
|
|
|
|
|
|
|
clone_len = choose_block_len(temp_len);
|
|
|
|
|
clone_from = UR(temp_len - clone_len + 1);
|
|
|
|
|
case 13: // 操作13:克隆或插入随机长度的字节
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
if (temp_len + HAVOC_BLK_XL < MAX_FILE) { // 如果缓冲区长度加上最大块长度小于最大文件大小
|
|
|
|
|
|
|
|
|
|
clone_len = choose_block_len(HAVOC_BLK_XL);
|
|
|
|
|
clone_from = 0;
|
|
|
|
|
/* Clone bytes (75%) or insert a block of constant bytes (25%). */ // 克隆字节(75%)或插入一个常量字节块(25%)
|
|
|
|
|
u8 actually_clone = UR(4); // 随机决定是否克隆
|
|
|
|
|
u32 clone_from, clone_to, clone_len; // 定义克隆的起始位置、目标位置和长度
|
|
|
|
|
u8* new_buf; // 定义新的缓冲区
|
|
|
|
|
|
|
|
|
|
if (actually_clone) { // 如果选择克隆
|
|
|
|
|
clone_len = choose_block_len(temp_len); // 随机选择克隆的长度
|
|
|
|
|
clone_from = UR(temp_len - clone_len + 1); // 随机选择克隆的起始位置
|
|
|
|
|
} else { // 如果选择插入常量字节块
|
|
|
|
|
clone_len = choose_block_len(HAVOC_BLK_XL); // 随机选择插入的长度
|
|
|
|
|
clone_from = 0; // 起始位置为0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clone_to = UR(temp_len);
|
|
|
|
|
clone_to = UR(temp_len); // 随机选择目标位置
|
|
|
|
|
|
|
|
|
|
new_buf = ck_alloc_nozero(temp_len + clone_len);
|
|
|
|
|
|
|
|
|
|
/* Head */
|
|
|
|
|
new_buf = ck_alloc_nozero(temp_len + clone_len); // 分配新的缓冲区
|
|
|
|
|
|
|
|
|
|
/* Head */ // 复制头部
|
|
|
|
|
memcpy(new_buf, out_buf, clone_to);
|
|
|
|
|
|
|
|
|
|
/* Inserted part */
|
|
|
|
|
|
|
|
|
|
/* Inserted part */ // 插入部分
|
|
|
|
|
if (actually_clone)
|
|
|
|
|
memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
|
|
|
|
|
memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); // 克隆字节
|
|
|
|
|
else
|
|
|
|
|
memset(new_buf + clone_to,
|
|
|
|
|
UR(2) ? UR(256) : out_buf[UR(temp_len)], clone_len);
|
|
|
|
|
|
|
|
|
|
/* Tail */
|
|
|
|
|
memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
|
|
|
|
|
temp_len - clone_to);
|
|
|
|
|
memset(new_buf + clone_to, UR(2) ? UR(256) : out_buf[UR(temp_len)], clone_len); // 插入常量字节块
|
|
|
|
|
|
|
|
|
|
ck_free(out_buf);
|
|
|
|
|
out_buf = new_buf;
|
|
|
|
|
temp_len += clone_len;
|
|
|
|
|
/* Tail */ // 复制尾部
|
|
|
|
|
memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to);
|
|
|
|
|
|
|
|
|
|
ck_free(out_buf); // 释放旧的缓冲区
|
|
|
|
|
out_buf = new_buf; // 更新缓冲区指针
|
|
|
|
|
temp_len += clone_len; // 更新缓冲区长度
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 14: {
|
|
|
|
|
case 14: { // 操作14:覆盖随机长度的字节
|
|
|
|
|
|
|
|
|
|
/* Overwrite bytes with a randomly selected chunk (75%) or fixed
|
|
|
|
|
bytes (25%). */
|
|
|
|
|
|
|
|
|
|
u32 copy_from, copy_to, copy_len;
|
|
|
|
|
|
|
|
|
|
if (temp_len < 2) break;
|
|
|
|
|
bytes (25%). */ // 用随机选择的块(75%)或固定字节(25%)覆盖字节
|
|
|
|
|
u32 copy_from, copy_to, copy_len; // 定义覆盖的起始位置、目标位置和长度
|
|
|
|
|
|
|
|
|
|
copy_len = choose_block_len(temp_len - 1);
|
|
|
|
|
if (temp_len < 2) break; // 如果缓冲区长度小于2,跳过
|
|
|
|
|
|
|
|
|
|
copy_from = UR(temp_len - copy_len + 1);
|
|
|
|
|
copy_to = UR(temp_len - copy_len + 1);
|
|
|
|
|
|
|
|
|
|
if (UR(4)) {
|
|
|
|
|
copy_len = choose_block_len(temp_len - 1); // 随机选择覆盖的长度
|
|
|
|
|
copy_from = UR(temp_len - copy_len + 1); // 随机选择覆盖的起始位置
|
|
|
|
|
copy_to = UR(temp_len - copy_len + 1); // 随机选择目标位置
|
|
|
|
|
|
|
|
|
|
if (UR(4)) { // 75%的概率使用随机选择的块覆盖
|
|
|
|
|
if (copy_from != copy_to)
|
|
|
|
|
memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
|
|
|
|
|
|
|
|
|
|
} else memset(out_buf + copy_to,
|
|
|
|
|
UR(2) ? UR(256) : out_buf[UR(temp_len)], copy_len);
|
|
|
|
|
|
|
|
|
|
memmove(out_buf + copy_to, out_buf + copy_from, copy_len); // 移动缓冲区内容以覆盖字节
|
|
|
|
|
} else { // 25%的概率使用固定字节覆盖
|
|
|
|
|
memset(out_buf + copy_to, UR(2) ? UR(256) : out_buf[UR(temp_len)], copy_len); // 使用固定字节覆盖
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Values 15 and 16 can be selected only if there are any extras
|
|
|
|
|
present in the dictionaries. */
|
|
|
|
|
|
|
|
|
|
case 15: {
|
|
|
|
|
present in the dictionaries. */ // 只有在字典中存在额外数据时,才能选择操作15和16
|
|
|
|
|
|
|
|
|
|
/* Overwrite bytes with an extra. */
|
|
|
|
|
case 15: { // 操作15:用额外数据覆盖字节
|
|
|
|
|
|
|
|
|
|
if (!extras_cnt || (a_extras_cnt && UR(2))) {
|
|
|
|
|
/* Overwrite bytes with an extra. */ // 用额外数据覆盖字节
|
|
|
|
|
if (!extras_cnt || (a_extras_cnt && UR(2))) { // 如果没有用户指定的额外数据,或者有自动检测的额外数据且随机选择
|
|
|
|
|
|
|
|
|
|
/* No user-specified extras or odds in our favor. Let's use an
|
|
|
|
|
auto-detected one. */
|
|
|
|
|
auto-detected one. */ // 使用自动检测的额外数据
|
|
|
|
|
u32 use_extra = UR(a_extras_cnt); // 随机选择一个自动检测的额外数据
|
|
|
|
|
u32 extra_len = a_extras[use_extra].len; // 获取额外数据的长度
|
|
|
|
|
u32 insert_at; // 定义插入位置
|
|
|
|
|
|
|
|
|
|
u32 use_extra = UR(a_extras_cnt);
|
|
|
|
|
u32 extra_len = a_extras[use_extra].len;
|
|
|
|
|
u32 insert_at;
|
|
|
|
|
if (extra_len > temp_len) break; // 如果额外数据长度大于缓冲区长度,跳过
|
|
|
|
|
|
|
|
|
|
if (extra_len > temp_len) break;
|
|
|
|
|
insert_at = UR(temp_len - extra_len + 1); // 随机选择插入位置
|
|
|
|
|
memcpy(out_buf + insert_at, a_extras[use_extra].data, extra_len); // 用额外数据覆盖字节
|
|
|
|
|
} else { // 如果有用户指定的额外数据且随机选择
|
|
|
|
|
|
|
|
|
|
insert_at = UR(temp_len - extra_len + 1);
|
|
|
|
|
memcpy(out_buf + insert_at, a_extras[use_extra].data, extra_len);
|
|
|
|
|
/* No auto extras or odds in our favor. Use the dictionary. */ // 使用用户指定的额外数据
|
|
|
|
|
u32 use_extra = UR(extras_cnt); // 随机选择一个用户指定的额外数据
|
|
|
|
|
u32 extra_len = extras[use_extra].len; // 获取额外数据的长度
|
|
|
|
|
u32 insert_at; // 定义插入位置
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* No auto extras or odds in our favor. Use the dictionary. */
|
|
|
|
|
|
|
|
|
|
u32 use_extra = UR(extras_cnt);
|
|
|
|
|
u32 extra_len = extras[use_extra].len;
|
|
|
|
|
u32 insert_at;
|
|
|
|
|
|
|
|
|
|
if (extra_len > temp_len) break;
|
|
|
|
|
|
|
|
|
|
insert_at = UR(temp_len - extra_len + 1);
|
|
|
|
|
memcpy(out_buf + insert_at, extras[use_extra].data, extra_len);
|
|
|
|
|
if (extra_len > temp_len) break; // 如果额外数据长度大于缓冲区长度,跳过
|
|
|
|
|
|
|
|
|
|
insert_at = UR(temp_len - extra_len + 1); // 随机选择插入位置
|
|
|
|
|
memcpy(out_buf + insert_at, extras[use_extra].data, extra_len); // 用额外数据覆盖字节
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 16: {
|
|
|
|
|
case 16: { // 操作16:插入额外数据
|
|
|
|
|
|
|
|
|
|
u32 use_extra, extra_len, insert_at = UR(temp_len + 1);
|
|
|
|
|
u8* new_buf;
|
|
|
|
|
u32 use_extra, extra_len, insert_at = UR(temp_len + 1); // 定义额外数据、长度和插入位置
|
|
|
|
|
u8* new_buf; // 定义新的缓冲区
|
|
|
|
|
|
|
|
|
|
/* Insert an extra. Do the same dice-rolling stuff as for the
|
|
|
|
|
previous case. */
|
|
|
|
|
|
|
|
|
|
if (!extras_cnt || (a_extras_cnt && UR(2))) {
|
|
|
|
|
previous case. */ // 插入额外数据,与操作15类似
|
|
|
|
|
if (!extras_cnt || (a_extras_cnt && UR(2))) { // 如果没有用户指定的额外数据,或者有自动检测的额外数据且随机选择
|
|
|
|
|
|
|
|
|
|
use_extra = UR(a_extras_cnt);
|
|
|
|
|
extra_len = a_extras[use_extra].len;
|
|
|
|
|
use_extra = UR(a_extras_cnt); // 随机选择一个自动检测的额外数据
|
|
|
|
|
extra_len = a_extras[use_extra].len; // 获取额外数据的长度
|
|
|
|
|
|
|
|
|
|
if (temp_len + extra_len >= MAX_FILE) break;
|
|
|
|
|
if (temp_len + extra_len >= MAX_FILE) break; // 如果插入后缓冲区长度超过最大文件大小,跳过
|
|
|
|
|
|
|
|
|
|
new_buf = ck_alloc_nozero(temp_len + extra_len);
|
|
|
|
|
new_buf = ck_alloc_nozero(temp_len + extra_len); // 分配新的缓冲区
|
|
|
|
|
|
|
|
|
|
/* Head */
|
|
|
|
|
/* Head */ // 复制头部
|
|
|
|
|
memcpy(new_buf, out_buf, insert_at);
|
|
|
|
|
|
|
|
|
|
/* Inserted part */
|
|
|
|
|
memcpy(new_buf + insert_at, a_extras[use_extra].data, extra_len);
|
|
|
|
|
/* Inserted part */ // 插入部分
|
|
|
|
|
memcpy(new_buf + insert_at, a_extras[use_extra].data, extra_len); // 插入自动检测的额外数据
|
|
|
|
|
} else { // 如果有用户指定的额外数据且随机选择
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
use_extra = UR(extras_cnt); // 随机选择一个用户指定的额外数据
|
|
|
|
|
extra_len = extras[use_extra].len; // 获取额外数据的长度
|
|
|
|
|
|
|
|
|
|
use_extra = UR(extras_cnt);
|
|
|
|
|
extra_len = extras[use_extra].len;
|
|
|
|
|
if (temp_len + extra_len >= MAX_FILE) break; // 如果插入后缓冲区长度超过最大文件大小,跳过
|
|
|
|
|
|
|
|
|
|
if (temp_len + extra_len >= MAX_FILE) break;
|
|
|
|
|
new_buf = ck_alloc_nozero(temp_len + extra_len); // 分配新的缓冲区
|
|
|
|
|
|
|
|
|
|
new_buf = ck_alloc_nozero(temp_len + extra_len);
|
|
|
|
|
|
|
|
|
|
/* Head */
|
|
|
|
|
/* Head */ // 复制头部
|
|
|
|
|
memcpy(new_buf, out_buf, insert_at);
|
|
|
|
|
|
|
|
|
|
/* Inserted part */
|
|
|
|
|
memcpy(new_buf + insert_at, extras[use_extra].data, extra_len);
|
|
|
|
|
|
|
|
|
|
/* Inserted part */ // 插入部分
|
|
|
|
|
memcpy(new_buf + insert_at, extras[use_extra].data, extra_len); // 插入用户指定的额外数据
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tail */
|
|
|
|
|
memcpy(new_buf + insert_at + extra_len, out_buf + insert_at,
|
|
|
|
|
temp_len - insert_at);
|
|
|
|
|
|
|
|
|
|
ck_free(out_buf);
|
|
|
|
|
out_buf = new_buf;
|
|
|
|
|
temp_len += extra_len;
|
|
|
|
|
/* Tail */ // 复制尾部
|
|
|
|
|
memcpy(new_buf + insert_at + extra_len, out_buf + insert_at, temp_len - insert_at);
|
|
|
|
|
|
|
|
|
|
ck_free(out_buf); // 释放旧的缓冲区
|
|
|
|
|
out_buf = new_buf; // 更新缓冲区指针
|
|
|
|
|
temp_len += extra_len; // 更新缓冲区长度
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, temp_len))
|
|
|
|
|
goto abandon_entry;
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, temp_len)) // 调用通用模糊测试函数处理当前缓冲区
|
|
|
|
|
goto abandon_entry; // 如果返回非零值,跳转到abandon_entry
|
|
|
|
|
|
|
|
|
|
/* out_buf might have been mangled a bit, so let's restore it to its
|
|
|
|
|
original size and shape. */
|
|
|
|
|
|
|
|
|
|
if (temp_len < len) out_buf = ck_realloc(out_buf, len);
|
|
|
|
|
temp_len = len;
|
|
|
|
|
memcpy(out_buf, in_buf, len);
|
|
|
|
|
original size and shape. */ // out_buf可能已被修改,因此将其恢复到原始大小和形状
|
|
|
|
|
if (temp_len < len) out_buf = ck_realloc(out_buf, len); // 如果缓冲区长度小于原始长度,重新分配内存
|
|
|
|
|
temp_len = len; // 恢复缓冲区长度
|
|
|
|
|
memcpy(out_buf, in_buf, len); // 将输入缓冲区内容复制回输出缓冲区
|
|
|
|
|
|
|
|
|
|
/* If we're finding new stuff, let's run for a bit longer, limits
|
|
|
|
|
permitting. */
|
|
|
|
|
|
|
|
|
|
if (queued_paths != havoc_queued) {
|
|
|
|
|
|
|
|
|
|
if (perf_score <= HAVOC_MAX_MULT * 100) {
|
|
|
|
|
stage_max *= 2;
|
|
|
|
|
perf_score *= 2;
|
|
|
|
|
permitting. */ // 如果发现了新的路径,允许在限制范围内运行更长时间
|
|
|
|
|
if (queued_paths != havoc_queued) { // 如果已排队的路径数发生变化
|
|
|
|
|
if (perf_score <= HAVOC_MAX_MULT * 100) { // 如果性能评分小于等于HAVOC_MAX_MULT * 100
|
|
|
|
|
stage_max *= 2; // 将最大阶段循环次数翻倍
|
|
|
|
|
perf_score *= 2; // 将性能评分翻倍
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
havoc_queued = queued_paths;
|
|
|
|
|
|
|
|
|
|
havoc_queued = queued_paths; // 更新已排队的路径数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes; // 计算新的命中计数
|
|
|
|
|
|
|
|
|
|
if (!splice_cycle) {
|
|
|
|
|
stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_HAVOC] += stage_max;
|
|
|
|
|
} else {
|
|
|
|
|
stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_SPLICE] += stage_max;
|
|
|
|
|
if (!splice_cycle) { // 如果没有进行文件拼接
|
|
|
|
|
stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt; // 更新HAVOC阶段的发现计数
|
|
|
|
|
stage_cycles[STAGE_HAVOC] += stage_max; // 更新HAVOC阶段的循环计数
|
|
|
|
|
} else { // 如果进行了文件拼接
|
|
|
|
|
stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt; // 更新SPLICE阶段的发现计数
|
|
|
|
|
stage_cycles[STAGE_SPLICE] += stage_max; // 更新SPLICE阶段的循环计数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef IGNORE_FINDS
|
|
|
|
|
#ifndef IGNORE_FINDS // 如果没有定义IGNORE_FINDS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/************
|
|
|
|
|
* SPLICING *
|
|
|
|
|