Page 32 - 《软件学报》2025年第7期
P. 32
欧先飞 等: 语义可感知的灰盒编译器模糊测试 2953
同步和互斥控制, 以避免竞态条件的发生. 此外, 还需要对负载均衡进行合理设计, 以确保各个服务器实例的工作
量基本均衡, 从而达到最优的整体性能.
算法 3. 客户端请求变异操作.
全局: 共享内存 M s , 请求信号量 S req , 回复信号量 S res ;
T tmout ;
超参: 最大等待时间
输入: 待变异的程序 p, 变异操作符 o;
′
输出: 变异后的程序 p .
1. function request_mutation( p,o) {
2. write_request( M s , p,o)
3. sem_signal( S req )
4. if ( ¬ timed_sem_wait( S res ,T tmout )) {
5. /* reset semaphores S req and S res */
6. /* restart mutation server */
7. return ⊥
8. }
9. M s )
p ← fetch_response(
′
10. return p ′
11. }
3 基于语义信息的操作符选择策略
灰盒模糊测试工具内部所实现的变异操作符选择策略往往是完全随机的. 由于其所支持的都是字符级别的变
异操作符, 如翻转位、交换字节, 这些变异操作符直接在最底层的字符流上进行操作, 因此无论如何被选择, 其总
能以接近 100% 的概率变异成功并生成新的与输入不一样的程序. 但是同样的策略在语义级别的变异操作符上却
会面临不小的困难.
挑战 1. 语义级别的变异操作符需要苛刻的前置语义条件. 灰盒模糊测试工具所实现的变异操作符直接在字
符级别进行, 其能对任意输入进行变异, 但语义级别的变异操作往往需要输入满足很强的限定条件之后才能应用
成功 (如“分支表达式反转”这样的语义级别的变异操作符需要输入中至少包含一个分支语句才能进行变异). 随机
给定一个程序, 往往只有很少一部分语义级别的变异操作符可以被应用. 这使得灰盒模糊测试工具惯用的随机尝
试策略对于语义级别的操作符效率非常低下, 随机选择往往会面临大量的失败变异.
挑战 2. 语义级别的变异操作符多次调用后容易生成重复的程序. 对于字符级别的变异操作符而言, 如交换字
节, 其在实践中几乎总能生成与变异前不一样的程序. 这里可以从概率层面做个简单的计算, 以交换字节为例, 想
2
1/size(p) size(p) 为输入程序的大小, 其通常不小于 100), 这样的概率已经非常之
(
要出现重复的程序, 其概率低至
低, 可以忽略不计. 而对于语义级别的变异操作符而言, 给定一个程序可选的变异点经常很少. 以移除语句为例, 其
可选的变异点与给定程序内所包含的语句数量一致, 如果选定的种子程序只有一条语句, 那么移除语句这一变异
操作符在变异一次之后即无法再贡献新的不一样的程序.
在这两个挑战下, 我们无法直接使用灰盒模糊测试工具既有的简单随机变异操作符选择策略. 因此, 我们开发
了一套动态权重选择算法, 这套算法会根据观测到的事件给程序 p 和变异操作符 o 动态调整选择权重. 在选择操
作符和种子程序的时候, 会根据权重去加权采样出一组<程序, 操作符>对进行变异. 由于我们的算法同时覆盖了操
作符选择和种子程序选择, 因此, 在实现中, 我们会同时将 AFL++的输入选择策略和操作符选择策略替换为我们
所实现的基于动态权重的选择策略. 同样的, 由于我们替换掉了 AFL++自身的选择策略, 这会引入新的挑战.

