|
|
|
@ -5542,390 +5542,414 @@ skip_bitflip:
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算新命中计数,是排队路径和唯一崩溃的总和
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
|
|
|
|
|
// 更新当前阶段的发现计数和周期
|
|
|
|
|
stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_ARITH8] += stage_max;
|
|
|
|
|
|
|
|
|
|
/* 16-bit arithmetics, both endians. */
|
|
|
|
|
/* 16位算术运算,支持两种字节序。 */
|
|
|
|
|
|
|
|
|
|
// 如果长度小于2,跳过算术操作
|
|
|
|
|
if (len < 2) goto skip_arith;
|
|
|
|
|
|
|
|
|
|
// 设置当前阶段的名称与短名称
|
|
|
|
|
stage_name = "arith 16/8";
|
|
|
|
|
stage_short = "arith16";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = 4 * (len - 1) * ARITH_MAX;
|
|
|
|
|
stage_cur = 0; // 当前计数器初始化为0
|
|
|
|
|
stage_max = 4 * (len - 1) * ARITH_MAX; // 最大操作数计算
|
|
|
|
|
|
|
|
|
|
// 保存原始的命中计数
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
|
|
|
|
|
// 遍历每个字节,进行算术操作
|
|
|
|
|
for (i = 0; i < len - 1; i++) {
|
|
|
|
|
|
|
|
|
|
// 读取当前字节和下一个字节作为16位数
|
|
|
|
|
u16 orig = *(u16*)(out_buf + i);
|
|
|
|
|
|
|
|
|
|
/* Let's consult the effector map... */
|
|
|
|
|
|
|
|
|
|
// 查看效应映射表
|
|
|
|
|
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
|
|
|
|
|
stage_max -= 4 * ARITH_MAX;
|
|
|
|
|
continue;
|
|
|
|
|
stage_max -= 4 * ARITH_MAX; // 减少最大值
|
|
|
|
|
continue; // 继续下一次循环
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当前操作的字节索引
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
|
|
|
|
|
// 尝试进行加法和减法操作
|
|
|
|
|
for (j = 1; j <= ARITH_MAX; j++) {
|
|
|
|
|
|
|
|
|
|
// 进行加法和异或操作
|
|
|
|
|
u16 r1 = orig ^ (orig + j),
|
|
|
|
|
r2 = orig ^ (orig - j),
|
|
|
|
|
r3 = orig ^ SWAP16(SWAP16(orig) + j),
|
|
|
|
|
r4 = orig ^ SWAP16(SWAP16(orig) - j);
|
|
|
|
|
|
|
|
|
|
/* Try little endian addition and subtraction first. Do it only
|
|
|
|
|
if the operation would affect more than one byte (hence the
|
|
|
|
|
& 0xff overflow checks) and if it couldn't be a product of
|
|
|
|
|
a bitflip. */
|
|
|
|
|
|
|
|
|
|
// 尝试小端加法
|
|
|
|
|
stage_val_type = STAGE_VAL_LE;
|
|
|
|
|
|
|
|
|
|
// 判断加法是否溢出,并且结果不应该是位翻转
|
|
|
|
|
if ((orig & 0xff) + j > 0xff && !could_be_bitflip(r1)) {
|
|
|
|
|
stage_cur_val = j; // 设置当前值为j
|
|
|
|
|
*(u16*)(out_buf + i) = orig + j; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
stage_cur_val = j;
|
|
|
|
|
*(u16*)(out_buf + i) = orig + j;
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
if ((orig & 0xff) < j && !could_be_bitflip(r2)) {
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
stage_cur_val = -j;
|
|
|
|
|
*(u16*)(out_buf + i) = orig - j;
|
|
|
|
|
// 尝试小端减法
|
|
|
|
|
if ((orig & 0xff) < j && !could_be_bitflip(r2)) {
|
|
|
|
|
stage_cur_val = -j; // 设置当前值为-j
|
|
|
|
|
*(u16*)(out_buf + i) = orig - j; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
|
|
|
|
|
/* Big endian comes next. Same deal. */
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 尝试大端加法
|
|
|
|
|
stage_val_type = STAGE_VAL_BE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 判断加法是否溢出,并且结果不应该是位翻转
|
|
|
|
|
if ((orig >> 8) + j > 0xff && !could_be_bitflip(r3)) {
|
|
|
|
|
stage_cur_val = j; // 设置当前值为j
|
|
|
|
|
*(u16*)(out_buf + i) = SWAP16(SWAP16(orig) + j); // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
stage_cur_val = j;
|
|
|
|
|
*(u16*)(out_buf + i) = SWAP16(SWAP16(orig) + j);
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 尝试大端减法
|
|
|
|
|
if ((orig >> 8) < j && !could_be_bitflip(r4)) {
|
|
|
|
|
stage_cur_val = -j; // 设置当前值为-j
|
|
|
|
|
*(u16*)(out_buf + i) = SWAP16(SWAP16(orig) - j); // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
stage_cur_val = -j;
|
|
|
|
|
*(u16*)(out_buf + i) = SWAP16(SWAP16(orig) - j);
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 恢复原值
|
|
|
|
|
*(u16*)(out_buf + i) = orig;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新命中计数
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
|
|
|
|
|
// 更新当前阶段的发现计数和周期
|
|
|
|
|
stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_ARITH16] += stage_max;
|
|
|
|
|
|
|
|
|
|
/* 32-bit arithmetics, both endians. */
|
|
|
|
|
/* 32位算术运算,支持两种字节序。 */
|
|
|
|
|
|
|
|
|
|
// 如果长度小于4,跳过算术操作
|
|
|
|
|
if (len < 4) goto skip_arith;
|
|
|
|
|
|
|
|
|
|
// 设置当前阶段的名称与短名称
|
|
|
|
|
stage_name = "arith 32/8";
|
|
|
|
|
stage_short = "arith32";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = 4 * (len - 3) * ARITH_MAX;
|
|
|
|
|
stage_cur = 0; // 当前计数器初始化为0
|
|
|
|
|
stage_max = 4 * (len - 3) * ARITH_MAX; // 最大操作数计算
|
|
|
|
|
|
|
|
|
|
// 保存原始的命中计数
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
|
|
|
|
|
// 遍历每个字节,进行算术操作
|
|
|
|
|
for (i = 0; i < len - 3; i++) {
|
|
|
|
|
|
|
|
|
|
// 读取当前字节和接下来三个字节作为32位数
|
|
|
|
|
u32 orig = *(u32*)(out_buf + i);
|
|
|
|
|
|
|
|
|
|
/* Let's consult the effector map... */
|
|
|
|
|
|
|
|
|
|
// 查看效应映射表
|
|
|
|
|
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
|
|
|
|
|
!eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
|
|
|
|
|
stage_max -= 4 * ARITH_MAX;
|
|
|
|
|
continue;
|
|
|
|
|
stage_max -= 4 * ARITH_MAX; // 减少最大值
|
|
|
|
|
continue; // 继续下一次循环
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当前操作的字节索引
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
|
|
|
|
|
// 尝试进行加法和减法操作
|
|
|
|
|
for (j = 1; j <= ARITH_MAX; j++) {
|
|
|
|
|
|
|
|
|
|
// 进行加法和异或操作
|
|
|
|
|
u32 r1 = orig ^ (orig + j),
|
|
|
|
|
r2 = orig ^ (orig - j),
|
|
|
|
|
r3 = orig ^ SWAP32(SWAP32(orig) + j),
|
|
|
|
|
r4 = orig ^ SWAP32(SWAP32(orig) - j);
|
|
|
|
|
|
|
|
|
|
/* Little endian first. Same deal as with 16-bit: we only want to
|
|
|
|
|
try if the operation would have effect on more than two bytes. */
|
|
|
|
|
|
|
|
|
|
// 尝试小端加法
|
|
|
|
|
stage_val_type = STAGE_VAL_LE;
|
|
|
|
|
|
|
|
|
|
// 判断加法是否溢出,并且结果不应该是位翻转
|
|
|
|
|
if ((orig & 0xffff) + j > 0xffff && !could_be_bitflip(r1)) {
|
|
|
|
|
|
|
|
|
|
stage_cur_val = j;
|
|
|
|
|
*(u32*)(out_buf + i) = orig + j;
|
|
|
|
|
stage_cur_val = j; // 设置当前值为j
|
|
|
|
|
*(u32*)(out_buf + i) = orig + j; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 尝试小端减法
|
|
|
|
|
if ((orig & 0xffff) < j && !could_be_bitflip(r2)) {
|
|
|
|
|
|
|
|
|
|
stage_cur_val = -j;
|
|
|
|
|
*(u32*)(out_buf + i) = orig - j;
|
|
|
|
|
stage_cur_val = -j; // 设置当前值为-j
|
|
|
|
|
*(u32*)(out_buf + i) = orig - j; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
|
|
|
|
|
/* Big endian next. */
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 尝试大端加法
|
|
|
|
|
stage_val_type = STAGE_VAL_BE;
|
|
|
|
|
|
|
|
|
|
// 判断加法是否溢出,并且结果不应该是位翻转
|
|
|
|
|
if ((SWAP32(orig) & 0xffff) + j > 0xffff && !could_be_bitflip(r3)) {
|
|
|
|
|
|
|
|
|
|
stage_cur_val = j;
|
|
|
|
|
*(u32*)(out_buf + i) = SWAP32(SWAP32(orig) + j);
|
|
|
|
|
stage_cur_val = j; // 设置当前值为j
|
|
|
|
|
*(u32*)(out_buf + i) = SWAP32(SWAP32(orig) + j); // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 尝试大端减法
|
|
|
|
|
if ((SWAP32(orig) & 0xffff) < j && !could_be_bitflip(r4)) {
|
|
|
|
|
|
|
|
|
|
stage_cur_val = -j;
|
|
|
|
|
*(u32*)(out_buf + i) = SWAP32(SWAP32(orig) - j);
|
|
|
|
|
stage_cur_val = -j; // 设置当前值为-j
|
|
|
|
|
*(u32*)(out_buf + i) = SWAP32(SWAP32(orig) - j); // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
// 执行模糊测试
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 成功计数
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 若不成功,则减少最大周期
|
|
|
|
|
|
|
|
|
|
// 恢复原值
|
|
|
|
|
*(u32*)(out_buf + i) = orig;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新命中计数
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
|
|
|
|
|
// 更新当前阶段的发现计数和周期
|
|
|
|
|
stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_ARITH32] += stage_max;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
skip_arith:
|
|
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
|
* INTERESTING VALUES *
|
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
|
|
stage_name = "interest 8/8";
|
|
|
|
|
stage_short = "int8";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = len * sizeof(interesting_8);
|
|
|
|
|
stage_name = "interest 8/8"; // 当前阶段名称:8位整数的有趣值
|
|
|
|
|
stage_short = "int8"; // 当前阶段缩写
|
|
|
|
|
stage_cur = 0; // 当前阶段计数器
|
|
|
|
|
stage_max = len * sizeof(interesting_8); // 当前阶段最大操作次数
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_LE;
|
|
|
|
|
stage_val_type = STAGE_VAL_LE; // 当前值类型:小端
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 记录原始命中计数
|
|
|
|
|
|
|
|
|
|
/* Setting 8-bit integers. */
|
|
|
|
|
/* 设置8位整数。 */
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
for (i = 0; i < len; i++) { // 遍历输入缓冲区的每个字节
|
|
|
|
|
|
|
|
|
|
u8 orig = out_buf[i];
|
|
|
|
|
u8 orig = out_buf[i]; // 保存原始字节值
|
|
|
|
|
|
|
|
|
|
/* Let's consult the effector map... */
|
|
|
|
|
/* 咨询效应地图... */
|
|
|
|
|
|
|
|
|
|
if (!eff_map[EFF_APOS(i)]) {
|
|
|
|
|
stage_max -= sizeof(interesting_8);
|
|
|
|
|
continue;
|
|
|
|
|
if (!eff_map[EFF_APOS(i)]) { // 如果当前字节位置没有效应
|
|
|
|
|
stage_max -= sizeof(interesting_8); // 减少最大操作次数
|
|
|
|
|
continue; // 跳过当前循环
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
stage_cur_byte = i; // 设置当前字节位置
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < sizeof(interesting_8); j++) {
|
|
|
|
|
for (j = 0; j < sizeof(interesting_8); j++) { // 遍历8位有趣值
|
|
|
|
|
|
|
|
|
|
/* Skip if the value could be a product of bitflips or arithmetics. */
|
|
|
|
|
/* 如果值可能是经过位翻转或算术操作的结果,则跳过。 */
|
|
|
|
|
|
|
|
|
|
if (could_be_bitflip(orig ^ (u8)interesting_8[j]) ||
|
|
|
|
|
could_be_arith(orig, (u8)interesting_8[j], 1)) {
|
|
|
|
|
stage_max--;
|
|
|
|
|
continue;
|
|
|
|
|
if (could_be_bitflip(orig ^ (u8)interesting_8[j]) || // 检查位翻转
|
|
|
|
|
could_be_arith(orig, (u8)interesting_8[j], 1)) { // 检查算术
|
|
|
|
|
stage_max--; // 减少最大操作次数
|
|
|
|
|
continue; // 跳过当前循环
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_cur_val = interesting_8[j];
|
|
|
|
|
out_buf[i] = interesting_8[j];
|
|
|
|
|
stage_cur_val = interesting_8[j]; // 设置当前值为有趣值
|
|
|
|
|
out_buf[i] = interesting_8[j]; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 进行模糊测试,若失败则放弃当前条目
|
|
|
|
|
|
|
|
|
|
out_buf[i] = orig;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
out_buf[i] = orig; // 恢复原始字节
|
|
|
|
|
stage_cur++; // 当前阶段计数器增加
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes; // 更新新的命中计数
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_INTEREST8] += stage_max;
|
|
|
|
|
stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt; // 记录阶段发现的次数
|
|
|
|
|
stage_cycles[STAGE_INTEREST8] += stage_max; // 更新阶段循环次数
|
|
|
|
|
|
|
|
|
|
/* Setting 16-bit integers, both endians. */
|
|
|
|
|
/* 设置16位整数,支持两种字节序。 */
|
|
|
|
|
|
|
|
|
|
if (no_arith || len < 2) goto skip_interest;
|
|
|
|
|
if (no_arith || len < 2) goto skip_interest; // 如果禁止算术或长度小于2,跳过
|
|
|
|
|
|
|
|
|
|
stage_name = "interest 16/8";
|
|
|
|
|
stage_short = "int16";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = 2 * (len - 1) * (sizeof(interesting_16) >> 1);
|
|
|
|
|
stage_name = "interest 16/8"; // 当前阶段名称:16位整数的有趣值
|
|
|
|
|
stage_short = "int16"; // 当前阶段缩写
|
|
|
|
|
stage_cur = 0; // 当前阶段计数器
|
|
|
|
|
stage_max = 2 * (len - 1) * (sizeof(interesting_16) >> 1); // 最大操作次数
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 记录原始命中计数
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len - 1; i++) {
|
|
|
|
|
for (i = 0; i < len - 1; i++) { // 遍历输入缓冲区的每两个字节
|
|
|
|
|
|
|
|
|
|
u16 orig = *(u16*)(out_buf + i);
|
|
|
|
|
u16 orig = *(u16*)(out_buf + i); // 保存原始16位值
|
|
|
|
|
|
|
|
|
|
/* Let's consult the effector map... */
|
|
|
|
|
/* 咨询效应地图... */
|
|
|
|
|
|
|
|
|
|
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) {
|
|
|
|
|
stage_max -= sizeof(interesting_16);
|
|
|
|
|
continue;
|
|
|
|
|
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)]) { // 如果两个字节位置没有效应
|
|
|
|
|
stage_max -= sizeof(interesting_16); // 减少最大操作次数
|
|
|
|
|
continue; // 跳过当前循环
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
stage_cur_byte = i; // 设置当前字节位置
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < sizeof(interesting_16) / 2; j++) {
|
|
|
|
|
for (j = 0; j < sizeof(interesting_16) / 2; j++) { // 遍历16位有趣值
|
|
|
|
|
|
|
|
|
|
stage_cur_val = interesting_16[j];
|
|
|
|
|
stage_cur_val = interesting_16[j]; // 设置当前值为有趣值
|
|
|
|
|
|
|
|
|
|
/* Skip if this could be a product of a bitflip, arithmetics,
|
|
|
|
|
or single-byte interesting value insertion. */
|
|
|
|
|
/* 如果这可能是位翻转、算术、或单字节有趣值插入的结果,则跳过。 */
|
|
|
|
|
|
|
|
|
|
if (!could_be_bitflip(orig ^ (u16)interesting_16[j]) &&
|
|
|
|
|
!could_be_arith(orig, (u16)interesting_16[j], 2) &&
|
|
|
|
|
!could_be_interest(orig, (u16)interesting_16[j], 2, 0)) {
|
|
|
|
|
if (!could_be_bitflip(orig ^ (u16)interesting_16[j]) && // 检查位翻转
|
|
|
|
|
!could_be_arith(orig, (u16)interesting_16[j], 2) && // 检查算术
|
|
|
|
|
!could_be_interest(orig, (u16)interesting_16[j], 2, 0)) { // 检查有趣值插入
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_LE;
|
|
|
|
|
stage_val_type = STAGE_VAL_LE; // 设置值类型为小端
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + i) = interesting_16[j];
|
|
|
|
|
*(u16*)(out_buf + i) = interesting_16[j]; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 进行模糊测试
|
|
|
|
|
stage_cur++; // 当前阶段计数器增加
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 否则减少最大操作次数
|
|
|
|
|
|
|
|
|
|
if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) &&
|
|
|
|
|
!could_be_bitflip(orig ^ SWAP16(interesting_16[j])) &&
|
|
|
|
|
!could_be_arith(orig, SWAP16(interesting_16[j]), 2) &&
|
|
|
|
|
!could_be_interest(orig, SWAP16(interesting_16[j]), 2, 1)) {
|
|
|
|
|
if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) && // 检查是否需要交换字节
|
|
|
|
|
!could_be_bitflip(orig ^ SWAP16(interesting_16[j])) && // 检查位翻转
|
|
|
|
|
!could_be_arith(orig, SWAP16(interesting_16[j]), 2) && // 检查算术
|
|
|
|
|
!could_be_interest(orig, SWAP16(interesting_16[j]), 2, 1)) { // 检查有趣值插入
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_BE;
|
|
|
|
|
stage_val_type = STAGE_VAL_BE; // 设置值类型为大端
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + i) = SWAP16(interesting_16[j]);
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
*(u16*)(out_buf + i) = SWAP16(interesting_16[j]); // 更新为交换字节的有趣值
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 进行模糊测试
|
|
|
|
|
stage_cur++; // 当前阶段计数器增加
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 否则减少最大操作次数
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*(u16*)(out_buf + i) = orig;
|
|
|
|
|
*(u16*)(out_buf + i) = orig; // 恢复原始16位值
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes; // 更新新的命中计数
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_INTEREST16] += stage_max;
|
|
|
|
|
stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; // 记录阶段发现的次数
|
|
|
|
|
stage_cycles[STAGE_INTEREST16] += stage_max; // 更新阶段循环次数
|
|
|
|
|
|
|
|
|
|
if (len < 4) goto skip_interest;
|
|
|
|
|
if (len < 4) goto skip_interest; // 如果长度小于4,跳过
|
|
|
|
|
|
|
|
|
|
/* Setting 32-bit integers, both endians. */
|
|
|
|
|
/* 设置32位整数,支持两种字节序。 */
|
|
|
|
|
|
|
|
|
|
stage_name = "interest 32/8";
|
|
|
|
|
stage_short = "int32";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = 2 * (len - 3) * (sizeof(interesting_32) >> 2);
|
|
|
|
|
stage_name = "interest 32/8"; // 当前阶段名称:32位整数的有趣值
|
|
|
|
|
stage_short = "int32"; // 当前阶段缩写
|
|
|
|
|
stage_cur = 0; // 当前阶段计数器
|
|
|
|
|
stage_max = 2 * (len - 3) * (sizeof(interesting_32) >> 2); // 最大操作次数
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 记录原始命中计数
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len - 3; i++) {
|
|
|
|
|
for (i = 0; i < len - 3; i++) { // 遍历输入缓冲区的每四个字节
|
|
|
|
|
|
|
|
|
|
u32 orig = *(u32*)(out_buf + i);
|
|
|
|
|
u32 orig = *(u32*)(out_buf + i); // 保存原始32位值
|
|
|
|
|
|
|
|
|
|
/* Let's consult the effector map... */
|
|
|
|
|
/* 咨询效应地图... */
|
|
|
|
|
|
|
|
|
|
if (!eff_map[EFF_APOS(i)] && !eff_map[EFF_APOS(i + 1)] &&
|
|
|
|
|
!eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) {
|
|
|
|
|
stage_max -= sizeof(interesting_32) >> 1;
|
|
|
|
|
continue;
|
|
|
|
|
!eff_map[EFF_APOS(i + 2)] && !eff_map[EFF_APOS(i + 3)]) { // 如果四个字节位置没有效应
|
|
|
|
|
stage_max -= sizeof(interesting_32) >> 1; // 减少最大操作次数
|
|
|
|
|
continue; // 跳过当前循环
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
stage_cur_byte = i; // 设置当前字节位置
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < sizeof(interesting_32) / 4; j++) {
|
|
|
|
|
for (j = 0; j < sizeof(interesting_32) / 4; j++) { // 遍历32位有趣值
|
|
|
|
|
|
|
|
|
|
stage_cur_val = interesting_32[j];
|
|
|
|
|
stage_cur_val = interesting_32[j]; // 设置当前值为有趣值
|
|
|
|
|
|
|
|
|
|
/* Skip if this could be a product of a bitflip, arithmetics,
|
|
|
|
|
or word interesting value insertion. */
|
|
|
|
|
/* 如果这可能是位翻转、算术、或字有趣值插入的结果,则跳过。 */
|
|
|
|
|
|
|
|
|
|
if (!could_be_bitflip(orig ^ (u32)interesting_32[j]) &&
|
|
|
|
|
!could_be_arith(orig, interesting_32[j], 4) &&
|
|
|
|
|
!could_be_interest(orig, interesting_32[j], 4, 0)) {
|
|
|
|
|
if (!could_be_bitflip(orig ^ (u32)interesting_32[j]) && // 检查位翻转
|
|
|
|
|
!could_be_arith(orig, interesting_32[j], 4) && // 检查算术
|
|
|
|
|
!could_be_interest(orig, interesting_32[j], 4, 0)) { // 检查有趣值插入
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_LE;
|
|
|
|
|
stage_val_type = STAGE_VAL_LE; // 设置值类型为小端
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + i) = interesting_32[j];
|
|
|
|
|
*(u32*)(out_buf + i) = interesting_32[j]; // 更新输出缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 进行模糊测试
|
|
|
|
|
stage_cur++; // 当前阶段计数器增加
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 否则减少最大操作次数
|
|
|
|
|
|
|
|
|
|
if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) &&
|
|
|
|
|
!could_be_bitflip(orig ^ SWAP32(interesting_32[j])) &&
|
|
|
|
|
!could_be_arith(orig, SWAP32(interesting_32[j]), 4) &&
|
|
|
|
|
!could_be_interest(orig, SWAP32(interesting_32[j]), 4, 1)) {
|
|
|
|
|
if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) && // 检查是否需要交换字节
|
|
|
|
|
!could_be_bitflip(orig ^ SWAP32(interesting_32[j])) && // 检查位翻转
|
|
|
|
|
!could_be_arith(orig, SWAP32(interesting_32[j]), 4) && // 检查算术
|
|
|
|
|
!could_be_interest(orig, SWAP32(interesting_32[j]), 4, 1)) { // 检查有趣值插入
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_BE;
|
|
|
|
|
stage_val_type = STAGE_VAL_BE; // 设置值类型为大端
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + i) = SWAP32(interesting_32[j]);
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
stage_cur++;
|
|
|
|
|
*(u32*)(out_buf + i) = SWAP32(interesting_32[j]); // 更新为交换字节的有趣值
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 进行模糊测试
|
|
|
|
|
stage_cur++; // 当前阶段计数器增加
|
|
|
|
|
|
|
|
|
|
} else stage_max--;
|
|
|
|
|
} else stage_max--; // 否则减少最大操作次数
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*(u32*)(out_buf + i) = orig;
|
|
|
|
|
*(u32*)(out_buf + i) = orig; // 恢复原始32位值
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes; // 更新新的命中计数
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_INTEREST32] += stage_max;
|
|
|
|
|
stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt; // 记录阶段发现的次数
|
|
|
|
|
stage_cycles[STAGE_INTEREST32] += stage_max; // 更新阶段循环次数
|
|
|
|
|
|
|
|
|
|
skip_interest:
|
|
|
|
|
|
|
|
|
@ -5933,161 +5957,210 @@ skip_interest:
|
|
|
|
|
* DICTIONARY STUFF *
|
|
|
|
|
********************/
|
|
|
|
|
|
|
|
|
|
if (!extras_cnt) goto skip_user_extras;
|
|
|
|
|
if (!extras_cnt) goto skip_user_extras; // 如果没有用户提供的额外数据,跳过用户额外数据的处理
|
|
|
|
|
|
|
|
|
|
/* Overwrite with user-supplied extras. */
|
|
|
|
|
|
|
|
|
|
stage_name = "user extras (over)";
|
|
|
|
|
stage_short = "ext_UO";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = extras_cnt * len;
|
|
|
|
|
stage_name = "user extras (over)"; // 设置当前阶段的名称
|
|
|
|
|
stage_short = "ext_UO"; // 设置当前阶段的简称
|
|
|
|
|
stage_cur = 0; // 初始化当前阶段的计数器
|
|
|
|
|
stage_max = extras_cnt * len; // 设置当前阶段的最大迭代次数
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_NONE;
|
|
|
|
|
stage_val_type = STAGE_VAL_NONE; // 设置当前阶段的值类型为无
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 保存当前的命中计数
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
for (i = 0; i < len; i++) { // 遍历输入缓冲区的每个字节
|
|
|
|
|
|
|
|
|
|
u32 last_len = 0;
|
|
|
|
|
u32 last_len = 0; // 记录上一次写入的额外数据长度
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
stage_cur_byte = i; // 设置当前处理的字节位置
|
|
|
|
|
|
|
|
|
|
/* Extras are sorted by size, from smallest to largest. This means
|
|
|
|
|
that we don't have to worry about restoring the buffer in
|
|
|
|
|
between writes at a particular offset determined by the outer
|
|
|
|
|
loop. */
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < extras_cnt; j++) {
|
|
|
|
|
for (j = 0; j < extras_cnt; j++) { // 遍历所有用户提供的额外数据
|
|
|
|
|
|
|
|
|
|
/* Skip extras probabilistically if extras_cnt > MAX_DET_EXTRAS. Also
|
|
|
|
|
skip them if there's no room to insert the payload, if the token
|
|
|
|
|
is redundant, or if its entire span has no bytes set in the effector
|
|
|
|
|
map. */
|
|
|
|
|
|
|
|
|
|
if ((extras_cnt > MAX_DET_EXTRAS && UR(extras_cnt) >= MAX_DET_EXTRAS) ||
|
|
|
|
|
extras[j].len > len - i ||
|
|
|
|
|
!memcmp(extras[j].data, out_buf + i, extras[j].len) ||
|
|
|
|
|
!memchr(eff_map + EFF_APOS(i), 1, EFF_SPAN_ALEN(i, extras[j].len))) {
|
|
|
|
|
if ((extras_cnt > MAX_DET_EXTRAS && UR(extras_cnt) >= MAX_DET_EXTRAS) || // 如果额外数据过多,随机跳过
|
|
|
|
|
extras[j].len > len - i || // 如果额外数据长度超出剩余缓冲区长度,跳过
|
|
|
|
|
!memcmp(extras[j].data, out_buf + i, extras[j].len) || // 如果额外数据与当前缓冲区内容相同,跳过
|
|
|
|
|
!memchr(eff_map + EFF_APOS(i), 1, EFF_SPAN_ALEN(i, extras[j].len))) { // 如果额外数据所在的区域没有有效字节,跳过
|
|
|
|
|
|
|
|
|
|
stage_max--;
|
|
|
|
|
continue;
|
|
|
|
|
stage_max--; // 减少最大迭代次数
|
|
|
|
|
continue; // 跳过当前额外数据
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_len = extras[j].len;
|
|
|
|
|
memcpy(out_buf + i, extras[j].data, last_len);
|
|
|
|
|
last_len = extras[j].len; // 记录当前额外数据的长度
|
|
|
|
|
memcpy(out_buf + i, extras[j].data, last_len); // 将额外数据复制到输出缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 执行模糊测试,如果失败则跳转到abandon_entry
|
|
|
|
|
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 增加当前阶段的计数器
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore all the clobbered memory. */
|
|
|
|
|
memcpy(out_buf + i, in_buf + i, last_len);
|
|
|
|
|
memcpy(out_buf + i, in_buf + i, last_len); // 恢复被覆盖的内存
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes; // 更新命中计数
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_EXTRAS_UO] += stage_max;
|
|
|
|
|
stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt; // 更新当前阶段的发现计数
|
|
|
|
|
stage_cycles[STAGE_EXTRAS_UO] += stage_max; // 更新当前阶段的循环计数
|
|
|
|
|
|
|
|
|
|
/* Insertion of user-supplied extras. */
|
|
|
|
|
|
|
|
|
|
stage_name = "user extras (insert)";
|
|
|
|
|
stage_short = "ext_UI";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = extras_cnt * (len + 1);
|
|
|
|
|
stage_name = "user extras (insert)"; // 设置当前阶段的名称
|
|
|
|
|
stage_short = "ext_UI"; // 设置当前阶段的简称
|
|
|
|
|
stage_cur = 0; // 初始化当前阶段的计数器
|
|
|
|
|
stage_max = extras_cnt * (len + 1); // 设置当前阶段的最大迭代次数
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 保存当前的命中计数
|
|
|
|
|
|
|
|
|
|
ex_tmp = ck_alloc(len + MAX_DICT_FILE);
|
|
|
|
|
ex_tmp = ck_alloc(len + MAX_DICT_FILE); // 分配临时缓冲区
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= len; i++) {
|
|
|
|
|
for (i = 0; i <= len; i++) { // 遍历输入缓冲区的每个字节
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
stage_cur_byte = i; // 设置当前处理的字节位置
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < extras_cnt; j++) {
|
|
|
|
|
for (j = 0; j < extras_cnt; j++) { // 遍历所有用户提供的额外数据
|
|
|
|
|
|
|
|
|
|
if (len + extras[j].len > MAX_FILE) {
|
|
|
|
|
if (len + extras[j].len > MAX_FILE) { // 如果插入额外数据后超出最大文件大小,跳过
|
|
|
|
|
stage_max--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Insert token */
|
|
|
|
|
memcpy(ex_tmp + i, extras[j].data, extras[j].len);
|
|
|
|
|
memcpy(ex_tmp + i, extras[j].data, extras[j].len); // 将额外数据插入到临时缓冲区
|
|
|
|
|
|
|
|
|
|
/* Copy tail */
|
|
|
|
|
memcpy(ex_tmp + i + extras[j].len, out_buf + i, len - i);
|
|
|
|
|
memcpy(ex_tmp + i + extras[j].len, out_buf + i, len - i); // 复制剩余的数据到临时缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, ex_tmp, len + extras[j].len)) {
|
|
|
|
|
if (common_fuzz_stuff(argv, ex_tmp, len + extras[j].len)) { // 执行模糊测试,如果失败则跳转到abandon_entry
|
|
|
|
|
ck_free(ex_tmp);
|
|
|
|
|
goto abandon_entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 增加当前阶段的计数器
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy head */
|
|
|
|
|
ex_tmp[i] = out_buf[i];
|
|
|
|
|
ex_tmp[i] = out_buf[i]; // 复制当前字节到临时缓冲区
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ck_free(ex_tmp);
|
|
|
|
|
ck_free(ex_tmp); // 释放临时缓冲区
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes; // 更新命中计数
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
|
|
|
|
|
stage_cycles[STAGE_EXTRAS_UI] += stage_max;
|
|
|
|
|
stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt; // 更新当前阶段的发现计数
|
|
|
|
|
stage_cycles[STAGE_EXTRAS_UI] += stage_max; // 更新当前阶段的循环计数
|
|
|
|
|
|
|
|
|
|
skip_user_extras:
|
|
|
|
|
|
|
|
|
|
if (!a_extras_cnt) goto skip_extras;
|
|
|
|
|
if (!a_extras_cnt) goto skip_extras; // 如果没有自动生成的额外数据,跳过自动额外数据的处理
|
|
|
|
|
|
|
|
|
|
stage_name = "auto extras (over)";
|
|
|
|
|
stage_short = "ext_AO";
|
|
|
|
|
stage_cur = 0;
|
|
|
|
|
stage_max = MIN(a_extras_cnt, USE_AUTO_EXTRAS) * len;
|
|
|
|
|
stage_name = "auto extras (over)"; // 设置当前阶段的名称
|
|
|
|
|
stage_short = "ext_AO"; // 设置当前阶段的简称
|
|
|
|
|
stage_cur = 0; // 初始化当前阶段的计数器
|
|
|
|
|
stage_max = MIN(a_extras_cnt, USE_AUTO_EXTRAS) * len; // 设置当前阶段的最大迭代次数
|
|
|
|
|
|
|
|
|
|
stage_val_type = STAGE_VAL_NONE;
|
|
|
|
|
stage_val_type = STAGE_VAL_NONE; // 设置当前阶段的值类型为无
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt;
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 保存当前的命中计数
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
for (i = 0; i < len; i++) { // 遍历输入缓冲区的每个字节
|
|
|
|
|
|
|
|
|
|
u32 last_len = 0;
|
|
|
|
|
u32 last_len = 0; // 记录上一次写入的额外数据长度
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i;
|
|
|
|
|
stage_cur_byte = i; // 设置当前处理的字节位置
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < MIN(a_extras_cnt, USE_AUTO_EXTRAS); j++) {
|
|
|
|
|
for (j = 0; j < MIN(a_extras_cnt, USE_AUTO_EXTRAS); j++) { // 遍历所有自动生成的额外数据
|
|
|
|
|
|
|
|
|
|
/* See the comment in the earlier code; extras are sorted by size. */
|
|
|
|
|
|
|
|
|
|
if (a_extras[j].len > len - i ||
|
|
|
|
|
!memcmp(a_extras[j].data, out_buf + i, a_extras[j].len) ||
|
|
|
|
|
!memchr(eff_map + EFF_APOS(i), 1, EFF_SPAN_ALEN(i, a_extras[j].len))) {
|
|
|
|
|
if (a_extras[j].len > len - i || // 如果额外数据长度超出剩余缓冲区长度,跳过
|
|
|
|
|
!memcmp(a_extras[j].data, out_buf + i, a_extras[j].len) || // 如果额外数据与当前缓冲区内容相同,跳过
|
|
|
|
|
!memchr(eff_map + EFF_APOS(i), 1, EFF_SPAN_ALEN(i, a_extras[j].len))) { // 如果额外数据所在的区域没有有效字节,跳过
|
|
|
|
|
|
|
|
|
|
stage_max--;
|
|
|
|
|
continue;
|
|
|
|
|
stage_max--; // 减少最大迭代次数
|
|
|
|
|
continue; // 跳过当前额外数据
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
last_len = a_extras[j].len;
|
|
|
|
|
memcpy(out_buf + i, a_extras[j].data, last_len);
|
|
|
|
|
last_len = a_extras[j].len; // 记录当前额外数据的长度
|
|
|
|
|
memcpy(out_buf + i, a_extras[j].data, last_len); // 将额外数据复制到输出缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry;
|
|
|
|
|
if (common_fuzz_stuff(argv, out_buf, len)) goto abandon_entry; // 执行模糊测试,如果失败则跳转到abandon_entry
|
|
|
|
|
|
|
|
|
|
stage_cur++;
|
|
|
|
|
stage_cur++; // 增加当前阶段的计数器
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore all the clobbered memory. */
|
|
|
|
|
memcpy(out_buf + i, in_buf + i, last_len);
|
|
|
|
|
memcpy(out_buf + i, in_buf + i, last_len); // 恢复被覆盖的内存
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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; // 更新当前阶段的循环计数
|
|
|
|
|
|
|
|
|
|
/* Insertion of auto-generated extras. */
|
|
|
|
|
|
|
|
|
|
stage_name = "auto extras (insert)"; // 设置当前阶段的名称
|
|
|
|
|
stage_short = "ext_AI"; // 设置当前阶段的简称
|
|
|
|
|
stage_cur = 0; // 初始化当前阶段的计数器
|
|
|
|
|
stage_max = MIN(a_extras_cnt, USE_AUTO_EXTRAS) * (len + 1); // 设置当前阶段的最大迭代次数
|
|
|
|
|
|
|
|
|
|
orig_hit_cnt = new_hit_cnt; // 保存当前的命中计数
|
|
|
|
|
|
|
|
|
|
ex_tmp = ck_alloc(len + MAX_DICT_FILE); // 分配临时缓冲区
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= len; i++) { // 遍历输入缓冲区的每个字节
|
|
|
|
|
|
|
|
|
|
stage_cur_byte = i; // 设置当前处理的字节位置
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < MIN(a_extras_cnt, USE_AUTO_EXTRAS); j++) { // 遍历所有自动生成的额外数据
|
|
|
|
|
|
|
|
|
|
if (len + a_extras[j].len > MAX_FILE) { // 如果插入额外数据后超出最大文件大小,跳过
|
|
|
|
|
stage_max--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Insert token */
|
|
|
|
|
memcpy(ex_tmp + i, a_extras[j].data, a_extras[j].len); // 将额外数据插入到临时缓冲区
|
|
|
|
|
|
|
|
|
|
/* Copy tail */
|
|
|
|
|
memcpy(ex_tmp + i + a_extras[j].len, out_buf + i, len - i); // 复制剩余的数据到临时缓冲区
|
|
|
|
|
|
|
|
|
|
if (common_fuzz_stuff(argv, ex_tmp, len + a_extras[j].len)) { // 执行模糊测试,如果失败则跳转到abandon_entry
|
|
|
|
|
ck_free(ex_tmp);
|
|
|
|
|
goto abandon_entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_cur++; // 增加当前阶段的计数器
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy head */
|
|
|
|
|
ex_tmp[i] = out_buf[i]; // 复制当前字节到临时缓冲区
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ck_free(ex_tmp); // 释放临时缓冲区
|
|
|
|
|
|
|
|
|
|
new_hit_cnt = queued_paths + unique_crashes;
|
|
|
|
|
|
|
|
|
|
stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt; // 更新STAGE_EXTRAS_AO阶段的发现计数
|
|
|
|
|