choose_target_state
1:RANDOM_SELECTION
通过随机函数UR返回一个0-state_ids_count之间的数从而随机选取一个状态
2:ROUND_ROBIN
selected_state_index初始化为0,从此递增,至状态总数再回到0
3:FAVOR
- 如果state_cycles < 5,则先进行轮询
- 否则,result = update_scores_and_select_next_state(FAVOR)
update_scores_and_select_next_state
- 如果state_ids_count为0则直接返回0
- 为state_scores申请内存,每个state申请4字节
//state 结构
typedef struct {
u32 id; /* 状态id */
u8 is_covered; /* 状态是否被覆盖 */
u32 paths; /* 此状态经过的所有路径 */
u32 paths_discovered; /* 由此状态新发现的路径*/
u32 selected_times; /* 此状态被选择过的次数*/
u32 fuzzs; /* fuzz总次数 */
u32 score; /* 状态分数 */
u32 selected_seed_index; /* 最近选择过此状态的种子序号*/
void **seeds; /* 保存了所有能到达此状态的种子* */
u32 seeds_count; /* 能到达此状态的种子数量 */
} state_info_t;
- 函数通过kh_get函数查找哈希表khms_states中键为state_id的元素,并将对应的值赋值给state。
- 计算状态的分数,并将结果赋值给state->score。
- ceil:向上取整
state->score = ceil(1000 * pow(2, -log10(log10(state->fuzzs + 1) * state->selected_times + 1)) * pow(2, log(state->paths_discovered + 1)));
- 分数是累加的
- 在所有分数之和的范围内获取一个随机数
- index_search来获取最终的idx,这即找到第一个大于随机数的分数,将它的序号作为最后选出的idx
- 这么实现的道理是,保证了分数越高,被随机数命中的概率就越大,从而实现分数越高越容易选中,同时省去了排序操作效率更高,并且兼顾了随机性,还是比较巧妙的。
chose_seed
1:RANDOM_SELECTION
以种子数量为范围获取一个随机数然后赋给result
2:ROUND_ROBIN
从第一个种子开始,轮询到最后一个,周而复始。
3;FAVOR
- 如果种子数量小于10,则采用轮询模式
- 如果种子数量大于10,且循环次数不超过5,则按条件以一定概率选择种子
- 如果这个种子既不是初始种子,也不是在当前目标状态被选中时生成的种子,90%跳过
- 如果是待处理的受青睐路径,如果被fuzz过,或者没有偏爱,则99%跳过
- 如果不是待处理的受青睐路径,且种子不偏爱、序列路径大于10
- 循环超过一次,未被fuzz过,75%跳过
-其他, 95%跳过
- 循环超过一次,未被fuzz过,75%跳过