ECFuzz:面向大规模系统配置项设置的高效模糊测试

· 2025-07-11 10:26 · 0 阅读

原创 FuzzWiki 2025-07-11 10:26 四川


基本信息

原文名称:ECFuzz: Effective Configuration Fuzzing for Large-Scale Systems

原文作者:Junqiang Li,Senyi Li,Keyao Li,Falin Luo,Hongfang Yu,Shanshan Li,Xiang Li 

原文链接:https://doi.org/10.1145/3597503.3623315

发表期刊:2024 IEEE/ACM 46th International Conference on Software Engineering (ICSE)

开源代码:https://github.com/ecfuzz/ECFuzz

 

一、引言

配置在模糊测试中是另一个程序输入,它像输入数据一样直接控制程序行为。大规模系统因其海量配置参数导致配置空间庞大,且大多数配置参数具有灵活的约束,因此,在探索配置输入空间时,会导致配置参数间的组合爆炸问题。现有的测试方法在处理复杂配置时存在显著局限性。首先,多数方法独立生成单个配置参数,忽视参数间依赖关系,导致无效测试和代码覆盖率低。其次,直接依赖耗时系统测试验证配置,未利用单元测试预筛选,浪费资源。

针对上述问题,作者提出ECFuzz,一种基于多维度配置生成与单元测试导向验证的模糊测试框架。其核心贡献在于:

(1)多维度配置生成策略:通过分析配置参数间的控制、数值、默认值及行为依赖关系,设计差异化变异规则,动态调整参数组合规模,有效覆盖深层交互场景;

(2)单元测试驱动的验证机制:利用配置参数与单元测试的映射关系,优先执行轻量级单元测试筛选潜在错误配置,显著降低高开销系统测试的无效执行。

实验表明,ECFuzz在HCommon、HDFS等5个主流大规模系统中注入1000个测试用例时,意外故障发现数量较ConfTest等工具提升1.87-2.63倍,平均测试用例质量达92.5‰,并成功检测出14个未知配置错误(5个已确认)。

二、研究动机

为了提高配置测试的有效性,关键是选择一小部分有代表性的配置参数作为测试用例。要实现这一目标需要考虑两个因素:

1)配置参数生成:生成高质量的配置参数作为测试用例,避免在PUT启动阶段被提前过滤掉,在程序运行阶段探索更多的代码。

2)配置参数验证:有效的测试用例验证方法可以快速验证生成的测试用例是否有助于发现错误,并避免在不太可能产生错误的测试用例上浪费大量时间在系统测试期间。

然而,现有的配置测试技术没有充分考虑大规模系统的复杂性,导致测试有效性低。有以下两个挑战:

挑战:

(1) 如何有效生成配置参数。现有的工作一些使用基于字典或基于语法的模糊技术来生成满足语法有效性的配置参数;另一些使用基于约束的模糊技术来生成违反配置约束的配置参数。多数方法每次仅针对单一参数生成测试用例,忽略参数间存在依赖关系,生成大量无效配置。

(2)如何有效验证生成的配置参数。现有的配置测试技术往往直接将生成的配置参数注入到PUT中进行系统测试,然后监控PUT的状态,验证配置参数是否会触发bug。在小规模程序中,由于系统测试的执行速度快,该方法的时间开销是可以接受的。然而,在大型系统中,执行系统测试的时间成本非常高。一旦生成了不太可能产生错误的配置参数,通常需要花费大量时间对其进行系统测试,资源浪费严重。

针对上述的问题,作者设计了ECFuzz:

(1)多维配置生成策略。为了有效地生成大规模系统中的配置参数,提出一种多维配置生成策略。ECFuzz通过分析配置参数间的依赖关系,设计智能变异策略;动态选择多参数组合进行协同变异,并根据测试反馈智能调整参数规模,突破传统单参数变异的局限性。

(2)单元测试导向的配置验证策略。ECFuzz利用大规模系统完备的单元测试特性,构建配置参数与单元测试的映射关系,通过轻量级单元测试实现高效配置筛选。

三、概述

图 1  ECFuzz的完整流程图

ECFuzz的完整架构如图1所示,主要包括两个关键部分:

(1)配置参数生成:ECFuzz将默认配置文件和依赖表作为初始输入,然后生成新的配置参数作为测试用例。配置参数生成包括种子生成和智能变异两部分,ECFuzz首先使用种子生成来选择在该模糊化活动中需要进行模糊化的配置参数作为种子,然后使用智能变异来变异这些配置参数以获得测试用例。

(2)配置参数验证:生成测试用例后,ECFuzz通过配置参数与单元测试的映射关系自动获取对应的单元测试,并实时监控它们的运行结果。一旦失败发生,ECFuzz终止单元测试并将单元测试的结果设置为失败。如果单元测试完成且未发生失败,则单元测试的结果设置为成功。

1.配置参数生成

(Generate configuration parameters)

(1)种子生成:在配置模糊中,种子是一组配置参数。它指示在模糊攻击中哪些配置参数值得花费精力进行变异,我们从默认配置文件中随机选择几个配置参数,然后根据依赖关系表查找相关配置参数,如算法1所示。

图 2 cDEP2分析的依赖关系表

依赖关系表:描述了cDEP2分析的依赖关系表中的依赖关系类型。这里以元组列表的形式描述依赖关系表本身。

Type:依赖类型(由工具cDEP2分析得出)。

ConfA和ConfB:存在依赖关系的两个配置参数。

随机选择:随机选择策略从默认配置文件中随机选择K个配置参数。

相关配置参数搜索:为了保证种子的质量,需要在选择配置参数后,根据种子的依赖关系,添加相应的依赖配置参数。ECFuzz遍历随机选择的配置参数数组。如果在依赖关系表中找到了相关的配置参数,并且这是它第一次出现在中,则配置参数将被添加到。最后,选择上述配置参数组来构造一个新的种子。

(2)智能变异。智能变异算法充分考虑了种子中配置参数对应的依赖关系和约束条件,具体算法如算法2所示。

在智能变异期间,ECFuzz首先初始化测试用例。然后,根据变异的数量开始智能突变。在每次变异开始之前,随机选择其中一个配置参数的索引作为变异对象。随后,ECFuzz确定配置参数是否具有相应的依赖关系。如果存在,则通过根据依赖关系的变异来获得newValue。否则,通过根据约束的变异来获得newValue。最后,newValue覆盖对应于测试用例的初始值。

根据依赖关系生成新的配置参数值:ECFuzz使用cDEP分析的依赖关系表(如图2所示)。cDEP支持控制依赖、值关系依赖、重写依赖、默认值依赖和行为依赖5种依赖。但覆盖依赖在表中只出现了3次,因此ECFuzz没有考虑覆盖依赖。根据不同依赖关系的特点,设计了相应的变异方法。

控制依赖:第二个参数仅在第一个参数为True时生效。

变异方法:在依赖关系表中,没有告诉我们哪一个是控制参数。因此,ECFuzz通过判断其类型是否为布尔类型来确定。如果配置参数都为非布尔类型则跳过这条依赖记录。如果是布尔类型且当前变异的配置参数是主控参数,ECFuzz会根据其约束条件进行变异;若是被控参数,ECFuzz会先将主控参数的值设置为True,然后根据其约束条件对被控参数进行变异。

值关系依赖:一个参数的值受到另一个参数的值约束。一般分为三种类型:数值约束,参数A的值必须大于参数B的值(A > B);逻辑约束,参数A为true时,参数B必须为特定取值范围;集合约束,参数A的值必须是参数B值的子集。

变异方法:根据约束条件同时改变两个变量的值。

默认值依赖:如果第一个参数的值不可用,则将第二个参数的值用作其默认值。

变异方法:根据其中一个配置参数的约束条件对其进行变异,然后将另一个配置参数设置为相同的值。

行为依赖:第一个参数与第二个参数一起作用于系统的某些行为。

变异方法:根据两个参数各自的约束条件对其进行变异。

对于智能变异,突变的数量显著影响其性能。N如果很小,则很难发现由多个配置参数引起的bug。在特殊情况下,如变异系数为1,智能变异算法退化为单变异算法。如果突变数很大,将大大增加突变的时间成本和难度。

解决方法:智能变异策略的动态切换。

单次变异优先(N=1),快速生成大量简单测试用例,覆盖常见错误。一段时间内未发现新的异常时,认为简单变异已无法触发深层错误。切换至堆叠变异(N=3~6),通过同时变异多个参数,生成更复杂的组合,暴露参数间交互引发的隐藏问题。

2.配置参数验证

(Configuration Validation)

在配置验证中,ECFuzz为被测程序(PUT)构建运行环境,包括单元测试阶段和系统测试阶段,具体算法如算法3所示。

单元测试阶段:单元测试阶段通过搜索和执行与测试用例相关联的单元测试来快速测试测试用例的bug触发潜力。

单元测试阶段包括以下三个部分

单元测试搜索:ECFuzz根据ctest 的映射关系,从PUT提供的大量单元测试中,找出测试用例中只与配置参数相关的部分作为候选单元测试集。

单元测试缩减:当测试用例中包含大量配置参数时,单元测试搜索会生成规模庞大的候选测试集,其执行耗时很长。因此,ECFuzz使用采样和时间过滤算法来压缩候选单元测试集的大小。抽样算法是从候选单元测试集中按一定比例抽取一部分来替换原始集合。时间过滤算法检测每个单元测试的执行时间,并根据先验知识过滤掉耗时过长的单元测试。

单元测试执行:在得到候选单元测试的约简集后,ECFuzz构造出执行单元测试所需的运行环境。只有当测试用例通过所有单元测试时,单元测试阶段的结果才是成功的。ECFuzz不需要每次都运行所有的单元测试。一旦测试用例在单元测试中失败,则单元测试阶段被终止,并且单元测试结果被设置为失败。此外,不管单元测试是否通过,单元测试阶段的结果都返回到系统测试阶段,但是仅当单元测试失败时,才保存测试用例以供稍后分析。

系统测试阶段:运行单元测试后,ECFuzz进入系统测试阶段,进一步测试测试用例是否能在真实的系统环境中触发bug。

系统测试阶段包括以下三个部分

系统环境搭建:ECFuzz根据PUT的类型构造相应的系统编译环境、运行环境和测试输入。

配置文件替换:在开始系统测试之前,ECFuzz将测试用例中的配置参数信息转换为一个完整的符合大规模系统的输入要求配置文件。新配置文件用于替换默认配置文件,作为PUT的新输入。

系统测试执行与监控:ECFuzz创建进程来启动系统测试,并持续监视测试执行的状态。在系统测试阶段,ECFuzz会针对程序运行的三个关键环节进行异常监控:启动阶段、运行阶段以及关闭阶段。启动异常,程序前期不能完全启动;运行时异常,程序崩溃、挂起;关闭异常:程序无法正常关闭。如果系统在注入一些配置参数后出现启动异常,这是正常的反应,因为这意味着系统可以在配置上线生产之前立即检查这些配置参数。因此,将运行时异常和关闭异常视为意外故障。一旦测试用例触发了意外故障,我们就认为已经发现了潜在的错误,并将其记录下来以供后续的再现和分析。

、实验

RQ1:ECFuzz的多维配置生成策略与单次变异相比如何?

RQ2:ECFuzz的面向单元测试的配置验证策略在提高测试用例质量方面有多大的效果?

RQ3:与最先进的配置测试技术相比,ECFuzz的测试用例和异常类型的质量如何?

RQ4:与最先进的配置测试技术相比,ECFuzz在暴露未知错误方面的效率如何?

1.实验设置 

表 1 测试目标

环境:实验在KVM虚拟机上运行,配置为4核CPU、4GB内存,操作系统为Ubuntu 16.04 LTS。每个实验运行12小时,重复5次以确保结果统计意义。

测试目标:选取5个广泛使用的大型系统:HCommon、HDFS、HBase、ZooKeeper和Alluxio,覆盖分布式存储、数据库和协调服务等场景。

监控策略

内部监控:监视被测输入的PUT的内部状态。如果在PUT中发现异常(启动异常、运行时异常和关闭异常)则由内部监视器抛出异常。

外部监控:获取从内部监视器抛出的异常,并进行分析计算。此外,在系统测试期间,它会监视内存、CPU以及日志。如果异常是运行时异常或关闭异常,外部监视器将其视为意外故障。

2.多维配置生成策略评估(RQ1

表 2 不同配置测试工具的测试用例质量

表 3 多维配置生成策略评估的异常类型

单变异是指在每个模糊活动期间仅从候选配置参数中选择单个配置参数而不考虑依赖性。我们将这种单突变策略称为ECFuzz-S。表2和表3分别显示了不同策略的测试用例质量和异常类型的结果。

ECFuzzz测试用例的质量比ECFuzz-S有了显著的提高。ECFuzz-S和ECFuzz的测试用例总质量分别为20.6‰和92.5‰。这意味着,当相同的1000个测试用例被注入到系统中时,ECFuzz会多发现71.9个意外失败。对于异常类型,ECFuzz可以找到ECFuzz-S在所有五个程序中都找不到的多个唯一异常。总体而言,ECFuzz比ECFuzz-S多发现了9种异常类型,增加了128.6%。

ECFuzz之所以能取得上述好的结果,有两个原因:1)ECFuzz充分考虑了大规模系统中的配置依赖关系,并为每种依赖关系设计了相应的变异策略,提高了发现意外故障的能力; 2)ECFuzz在每次模糊化活动中从候选配置参数中选择多个配置参数,并根据测试结果进行智能调整,因此ECFuzz可以在同一次模糊化过程中探索更多的程序代码。

3.单元测试导向的的配置验证策略评估(RQ2)

表 4 不同配置测试工具的测试用例质量

为了有效地验证生成的配置参数,ECFuzz设计了一个面向单元测试的配置验证策略。为了证明其有效性,我们将其与直接注入系统测试而不使用单元测试的策略进行了比较。我们将此策略称为ECFuzz-W。表4显示了不同策略的测试用例的质量结果。

我们发现ECFuzz-W和ECFuzz的测试用例的总质量分别为38.4‰和92.5‰。这意味着,当相同的1000个测试用例被注入到系统中时,ECFuzz会多发现54.1个意外失败。ECFuzz-W直接将生成的测试用例注入到PUT中执行系统测试,生成更多的测试用例。然而,大多数测试用例都被PUT的配置解析代码过滤,导致启动异常。与ECFuzz-W相比,ECFuzz使用单元测试导向的配置验证策略,在执行系统测试之前提前过滤掉不太可能产生错误的测试用例,减少了昂贵的系统测试开销。因此,ECFuzz可以显著提高测试用例的质量。

4.与其他工具的对比(RQ3)

为了展示ECFuzz的有效性,我们将其与三种最先进的配置测试工具进行了比较,ConfTest,ConfErr和ConfDiagDetector。表5显示了不同工具的测试用例质量,图2显示了异常类型的结果。

表 5 不同配置测试工具的测试用例质量

图 3 异常类型图

ECFuzz的测试用例质量与其他最先进的工具相比取得了显著的进步。其中,ConfTest、ConfErr、ConfDiagDetector和ECFuzz的测试用例总质量分别为26.5‰、25.5‰、32.2‰和92.5‰。这意味着当同样的1000个测试用例被注入到系统中时,ECFuzz会发现60.3- 67个更多的意外失败。对于异常类型,我们发现ECFuzz在大多数程序中优于其他最先进的工具。ECFuzz分别在HDFS、Zookeeper和Alluxio程序上发现了1、1和2种异常类型。对于HCommon和HBase程序,ECFuzz至少保持了与其他最先进工具相同的有效性。总体而言,ECFuzz在测试用例质量和异常类型方面都取得了较好的效果,证明了ECFuzz中多维配置生成策略和面向单元测试的配置验证策略的有效性。

5.未知Bug发现能力(RQ4)

表 6 未知错误发现情况

ECFuzz作为一个有效的大规模系统的配置模糊,并发现了许多以前未知的配置引起的错误会。与其他最先进的工具相比,ECFuzz发现了最多的未知错误。具体来说,ECFuzz已经检测到14个以前未知的配置引起的错误,其中5个已经得到确认。

五、总结

本文提出了一种针对大规模系统的高效配置模糊测试工具ECFuzz,通过多维度配置生成策略单元测试导向的验证策略,显著提升了测试效率。实验表明,ECFuzz在Hadoop、HBase等系统中意外失败率较现有工具提升1.87-2.63倍,发现14个未知配置错误(5个已确认),有效解决了传统方法因忽略参数依赖和系统测试耗时导致的效率低下问题,为大规模系统配置测试提供了创新性解决方案。

—END—


WhiteFox:由大型语言模型驱动的白盒编译器模糊测试

BAZZAFL:通过面向漏洞的种子分组将模糊测试活动导向漏洞

通过命令行反馈利用大语言模型提高编译器选项黑盒模糊测试

阅读原文

跳转微信打开