Page 29 - 《软件学报》2025年第7期
P. 29

2950                                                       软件学报  2025  年第  36  卷第  7  期


                 合法性, 确保变异后的程序顺利通过编译器的前端检查; 其次, 它能诱导程序展现不同的优化模式, 从而触发编译
                 器的多样化优化行为. 相比之下, 字符串级别和语法级别的变异操作在实践中往往生成大量语义不合法的程序, 这
                 些程序通常在编译器运行初期就被前端检查拒绝, 难以深入探索编译器的行为.



                                              字符级别的变异                       降低数组维度





                                            语法可感知的变异


                         图 2 对   GCC  测试集中  pr21173  进行字符级别、语法可感知和语义可感知的变异效果对比

                 2   语义可感知灰盒模糊测试工具的设计实现与集成适配

                    图  3  展示了如何为灰盒模糊测试工具引入利用语义信息的能力. 相较于图                     1  的模糊测试流程, 我们将原本字
                 符串级别的变异模块替换为语义级别的变异模块. 为了实现这一替换, 我们需要设计实现一系列能够覆盖各种场
                 景的基于语义信息的变异操作符, 并且, 将这些变异操作符集成适配进图                      3  所示的变异模块.


                             种子池        选取
                                                                                  是
                                                                                      更新种子池
                                                P′ int f(int a)  运行被测    是否覆盖
                                                  {return a+a;}
                             P        基于语义                      软件        新代码
                          int foo(int a)                                                丢弃
                          {return a*a;}  信息的变                                     否
                                       异模块
                                             图 3 语义可感知的灰盒模糊工作流程

                    需要注意的是, 目前最先进的基于语义信息的程序变异工具                     GrayC  [22] 仅实现了  5  个语义级别的变异操作符,
                 其在实践中只有约       17%  的情况下可以变异出不一样的程序. 且           GrayC [22] 所实现的操作符实践中会有大量的崩溃,
                 在可用性和可靠性上均有明显的不足, 难以集成适配到灰盒模糊测试工具中. 因此, 我们选择自行设计实现变异操
                 作符.

                 2.1   设计实现与可用性增强
                    如图  4  所示, 我们会同时借助人工和        AI 来快速头脑风暴, 生成一个初始的变异操作符集合. 我们将变异操作
                 符视为一个三元组<名称, 功能描述, 代码实现>, 这里生成的初始变异操作符是指名称和功能描述部分. 随后, 对这
                 些操作符的功能描述进行人工分析处理. 一些语义重复的, 诸如“消除未使用变量”和“移除未使用变量”, 我们会进
                 行去重. 再之后, 我们会基于自身对编译器的专业知识, 筛选更利于探索编译器行为的操作符, 并进行人工实现. 这
                 一步结束后, 我们共计获得了         43  个变异操作符.

                                          AI
                                   设计变异
                                    操作符         测试程序集
                               去重、筛选、实现                                    设计实现新的    Human
                                                              不能被变异
                                   初始变异          测试运行                       变异操作符
                                  操作符集合
                                                              崩溃或变异         修复缺陷     Human
                                                              后程序非法

                                        图 4 基于语义信息的变异操作符的设计和实现流程
   24   25   26   27   28   29   30   31   32   33   34