Page 27 - 《软件学报》2025年第7期
P. 27
2948 软件学报 2025 年第 36 卷第 7 期
近年来, 模糊测试领域取得了重要的技术进展 [1−10] . 通过自动为待测软件生成大量测试用例, 模糊测试工具为
大量软件发现了成千上万的关键性缺陷. 这些自动暴露的缺陷能够得到开发者的及时修复, 从而显著提高基础软
件生态的质量和可靠性. 模糊测试技术现已被包括微软 [11,12] 和谷歌 [13−15] 在内的重要软件公司用于日夜不间断的安
全测试和软件质量保障.
以代码覆盖率为导向的灰盒模糊测试技术是目前为止最成功的模糊测试技术之一 [1] , 其引起了学术界的广泛
关注并在工业界广泛应用 [16−19] . AFL++ [20] 作为最先进的灰盒模糊测试工具代表, 已在 Web 浏览器 (例如 Firefox、
Internet Explorer)、网络工具 (例如 tcpdump、Wireshark)、图像处理器 (例如 ImageMagick、libtiff)、系统库 (如
OpenSSH、PCRE)、数据库 [21] 等软件系统中发现了大量漏洞. 如图 1 所示, 覆盖率导向的模糊测试技术以遗传算
法为基础, 通过从种子池中抽取种子输入并生成变异后代的方式, 实现提升代码覆盖率的优化目标. 类似于生物种
群的优胜劣汰, 新生成的优秀变异体测试输入 (探索到被测软件新分支) 会被保存在种子池中, 进入下一轮迭代
搜索.
种子池 选取 是
P′ int f(int a) 运行被测 是否覆盖 更新种子池
P {return aint*a;} 软件 新代码
int foo(int a) 否 丢弃
{return a*a;} 变异 字符级别的变异
易引入编译错误
图 1 传统灰盒模糊测试工具的工作流程
然而灰盒模糊测试却难以有效应用于编译器测试, 特别是对于静态类型语言的编译器 [1,22] , 如 C/C++编译器.
如图 1 所示, 灰盒模糊测试中广泛采用了字符串级别 [1,20] 的变异操作符生成变异后代. 然而, 这些操作符无法理解
输入程序的语义结构, 在随机位置变异极易破坏程序的合法性, 致使产生的绝大部分后代变异体均无法通过编译
器前端检查 (语法检查、类型检查和语义检查等), 无法有效探索中间代码生成、中间代码优化、二进制代码生成
等编译器中/后端功能模块的功能和行为, 覆盖率信息亦无法在此情形下提供搜索导向.
目前虽有一些工作致力于为灰盒模糊测试引入对结构化输入的感知能力, 如 Gramatron [23] 、Superion . 但到
[1]
目前为止, 这些工作也仅支持语法级别的输入结构感知能力, 其测试能力主要在 XML 解析器等仅关注输入语法
合法性的被测软件. 这些技术无法应对编译器等复杂软件系统对输入语义级别的合法性约束 (如程序的类型正确
性、作用域正确性等), 易生成无法通过编译器前端检查的测试输入. 因此, 我们需要开发一种新的模糊测试方法,
能够理解并正确处理输入的语义结构, 以满足更复杂软件系统 (如编译器) 的测试需求. 这种方法不仅应提高模糊
测试的有效性, 还应尽可能确保测试过程中对输入的语义正确性保持不变, 从而提升发现深层次、语义相关错误
的能力.
本文尝试为灰盒模糊测试引入感知语义的能力, 即利用语义分析结果进行有导向的输入变异, 以弥补现有灰
盒模糊测试在编译器测试领域的不足. 本文针对传统变异操作符不建模测试输入语义的局限, 将它们替换为基于
语法树节点和语义分析结果进行变异的操作符, 从而实现在变换程序时大幅保持程序的语义合法性以及编译器深
层次代码的高效探索. 尽管已有工作专门实现了基于语义信息的变异操作工具 [22] , 但为实际工业级灰盒模糊测试
实现引入此类变异操作符, 依旧面临以下挑战.
挑战 1: 现有利用语义信息进行程序变异的工具在可用性和可靠性方面仍有不足, 难以应用到灰盒模糊测试.
在可用性方面, 现有最先进的语义级别程序变异工具 GrayC [22] , 其支持的语义操作符数量和种类都相当有限, 在实
际应用中超过 80% 的程序无法被其成功变异, 使图 1 中的模糊测试主循环长期处于缺少新变异输入的低效空转
状态. 在可靠性方面, GrayC 对丰富语法特性和边界情况的处理不足, 在实践中很容易触发工具自身崩溃, 与工业
级模糊测试工具实现不匹配.
为应对这一挑战, 本文在可用性和可靠性两个方面均进行了改进. 在可用性方面, 我们调研了 GrayC 无法变
异的程序类型, 并设计新的变异操作符以扩大覆盖范围. 在可靠性方面, 我们通过大量人工测试和修复, 将变异操

