《KLEE:Unassisted and Automatic Generation of High-Coverage Tests for Complex Systems Programs 》

题目:KLEE:Unassisted and Automatic Generation of High-Coverage Tests for Complex Systems Programs
作者:Cristian Cadar, Daniel Dunbar, Dawson Engler
单位:Stanford University
问题:许多类型的错误在不执行一部分代码的情况下是很难发现的,依赖于随机或人工方法设计测试集难度大且效果不好。
方案:设计工具KLEE利用符号执行技术动态生成测试用例,可以达到高覆盖率而且可以采集代码执行过程中的状态信息用于分析,适用于多种复杂的对环境敏感的程序。
原理
1.路径约束条件(path condition):为每一条路径维护一个约束集。
当路径结束(exit调用)或KLEE检查出错误时,对当前路径约束条件集进行求解得到符合该条路径的输入数据,该输入用例在未经修改的测试程序上运行可以重走与KLEE走的相同的路径并触发bug。在KLEE外重跑测试可以降低误报率。
2.路径选择算法:
(1)随机路径选择:维护一个二进制树,为所有活跃的状态记录程序路径。从root遍历该树并在每个分支点随机地选择路径。
(2)覆盖率优化搜索:尽量选择能够覆盖新代码的状态。利用启发式方法计算每个状态的权重,然后根据权重随机选择一个状态。目前,这些启发式算法会考虑到达一个未被覆盖的指令的最短距离、状态的调用栈以及该状态近期是否覆盖了新代码。
3.状态(state):为了避免与UNIX进程相混淆,将KLEE的符号化过程用“状态”代表。如果检测到错误就产生一个测试用例去触发错误并该结束状态。
4.为每个符号化过程维护这些信息:register file,stack,heap,program counter,path condition
5.在赋值语句时比如%dst = add i32 %src0,%src1,就会创建表达式Add(%src0,%src1)并赋给%dst寄存器。
创建表达式的代码要查看是否所有给定的操作数都是具体的,如果是,就返回一个具体值的表达式。
6.查询优化:在到达STP前简化表达式并减少查询。简化表达式可以加快求解、减小内存开销并提高查询缓存的命中率。
查询优化的主要方法:1.表达式重写 2.约束集简化 3.隐含的值具体化 4.约束独立 5.反例缓存
7.(1)当一个约束集的子集无解时,该约束集也无解。
(2)当一个超集有解时,其原始约束集也有解。
(3)当一个约束子集有解时,它的原始集有可能有解。
8.当代码从环境读取数据时,想要返回所有可能的合法数据值,而不是单一的具体值。当代码向环境中写入时,这一改变要在之后的读取中反映出来。
实现
1.KLEE是在EXE系统上重新设计的,不需要对源码修改或者人工工作。利用常见的LLVM GNU C编译器将代码编译成字节码。在KLEE上运行字节码。
2.利用约束求解器STP求解路径约束条件。
3.为了提高效率,如果一个表达式的所有给定的操作数都是具体值,则直接按具体值处理返回一个常数表达式。
4.当遇到条件分支时,KLEE要查询约束求解器判断两个分支的可行性,如果两个都可以走,KLEE要把路径状态克隆一份,这样两台路径都保存着各自的路径状态。
5.每个危险操作的地方,检查当前路径约束条件允许的每个可能值是否会引起错误。
6.程序被LLVM编译为类似于精简指令集的形式,KLEE直接翻译这些指令并将其映射成约束条件。
7.大多数的表示被检测代码的内存使用用一个平字节数组(flat byte array)去表示。但STP约束求解器不能支持合成的约束的求解。
解决:像EXE中的方法一样,将每个内存目标映射到不同的STP数组。
8.当一个被间接引用的指针p可以指向N个目标,KLEE将当前状态克隆N次。
9.粗略地为40个系统调用定义了简单的模型。符号化的文件系统与实际的文件系统共存,所以应用程序既可以使用符号化的也可以使用具体的文件。
10.设计了系统调用失败的模式选项,模拟环境中失败的情况。例:使用write()函数时磁盘已满。
11.KLEE产生的测试用例集通过我们提供的replay driver重新在没有进行过修改的原始的二进制上运行。
评估
1.简化求解使运行时间减少了45%。利用独立性进行的简化使反例缓存的命中率大大提升。
2.覆盖率:使用行覆盖率作为KLEE产生测试集有效性的一个保守的度量。覆盖结果仅考虑工具中代码本身,不包括库文件代码。
3.定义大小度量ELOC(executable lines of code):计算全局优化后可执行行数的总数
4.产生测试集的能力:
(1)给定GNU COREUTILS全部89个实用程序,KLEE的测试集在每个工具中的覆盖率高达90.9%,总体覆盖率为84.5%。且以较少的测试用例产生高覆盖率。KLEE达到76.9%的分支覆盖率,而开发者本身的测试集只有56.5%的覆盖率。发现了COREUTILS中10个不同的bug。
(2)使用传统的方法,true分支和false分支都覆盖的话需要从程序开始到结尾跑两次,而KLEE中,分支之前的路径上的指令只需要跑一次即可。
(3)测试BUSYBOX的coreutils子目录下的75个实用程序,平均行覆盖率达90.5%以上,开发者的只有44.8%。
5.检查bug的能力:测试了BUSYBOX的全部279个工具和MINIX的84个工具,发现了BUSYBOX的21个bug,MINIX的21个bug。所有的bug都是内存错误。
8.检查工具等价的能力:给两个工具同样的符号化输入,断言它们返回相同的结果。但是这种等价仅局限于KLEE产生的路径的有限集。
贡献
1.传统的符号化执行系统不会运行环境进行任何交流,没办法应对需要利用环境或需要完整的工作模型的程序,而KLEE允许与外界环境交互且提供一个符号化的模拟交互的模型。
2.KLEE可以通过交叉检查对同一库函数的不同实现的方式判断正确性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值