首页> 中国专利> 一种用于软件测试的交叉式动态法和装置

一种用于软件测试的交叉式动态法和装置

摘要

本发明公开了一种用于软件测试的交叉式动态法和装置,其中,用于软件测试的交叉动态法,包括如下步骤:①通过动态随机测试法对被测程序执行随机检测,检测程序漏洞,如果检测到程序异常则记录异常信息退出测试,否则在本次执行完后,计算代码覆盖率,检查代码覆盖率是否达到饱和,如果饱和则调用符号切换函数,切换到动态符号执行,将该父进程挂起,否则继续进行下次测试,直到检测到代码覆盖率饱和;②通过动态符号执行法搜索新的未被覆盖代码块,如果有新的代码块被检测到则将状态还原到步骤①的随机执行状态,如果所有的基本块都已被覆盖,则退出测试。本发明能全面检测较大应用程序,达到较高的代码覆盖率,缓解动态符号执行路径爆炸的问题。

著录项

  • 公开/公告号CN102508780A

    专利类型发明专利

  • 公开/公告日2012-06-20

    原文格式PDF

  • 申请/专利权人 电子科技大学;

    申请/专利号CN201110371268.2

  • 申请日2011-11-21

  • 分类号G06F11/36(20060101);

  • 代理机构成都华典专利事务所(普通合伙);

  • 代理人杨保刚;徐丰

  • 地址 611731 四川省成都市高新区(西区)西源大道2006号

  • 入库时间 2023-12-18 05:34:25

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2014-08-20

    授权

    授权

  • 2013-09-11

    专利申请权的转移 IPC(主分类):G06F11/36 变更前: 变更后: 登记生效日:20130822 申请日:20111121

    专利申请权、专利权的转移

  • 2013-09-11

    著录事项变更 IPC(主分类):G06F11/36 变更前: 变更后: 申请日:20111121

    著录事项变更

  • 2012-07-18

    实质审查的生效 IPC(主分类):G06F11/36 申请日:20111121

    实质审查的生效

  • 2012-06-20

    公开

    公开

说明书

技术领域

本发明涉及软件的测试方法,尤其涉及软件的动态测试法。

背景技术

软件测试主要用于软件正确性分析和软件漏洞检测,可分为静态测试方式和动态测试方式。静态测试指不运行被测程序,通过人工或借助专业软件来对程序的静态特性进行分析,通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性。动态测试指实际运行被测程序,提供相应的测试数据,通过检查软件的动态行为或判断运行结果的正确性来检测软件。动态测试方法避免了静态测试方法人工开销大、效率低、误报率高等缺陷,成为了当前主流的软件测试方式,动态测试常用的技术包括动态随机测试和动态符号执行。

动态随机测试方法能随机产生大量的数据作为程序的输入,动态运行程序,从而检测程序漏洞。因其直接运行被测程序,不需了解内部结构细节,也不需要额外的开销,具有良好的扩展性,容易实现,所以被广泛采用。然而,当输入值是特定的字符或数字时,随机测试要随机产生该特定值的概率非常小(示例1详细说明)。另一方面,对于较大应用程序,随机测试虽能迅速深入被测程序内部,但测试具有随机性,只能覆盖局部程序行为,从而不能保证测试的全面性、精确性。如图1所示是针对随机测试特点的模拟图,带箭头的折线表示随机测试的路径,黑色方块表示代码块,折线与方块相交,表示该代码块被执行到。由图1可看出,该方法测试能够深入测试,但也具有随机性、单一性,不能全面覆盖周围的代码块。由于以上不可避免的原因,限制了随机测试的扩展,使其在通常情况下仅被作为其它测试技术的辅助方法使用。

动态符号测试技术通过多次执行被测程序,并且自动产生使被测程序每次执行不同路径的输入值,企图测试到新的代码块。通过全路径的搜索从而达到对整个程序路径状态空间的覆盖,全面检测被测程序。有以下几个执行步骤:

1)将输入数据映射为特定的符号,实际执行程序,同时跟踪输入符号的执行流程,用符号在路径上的操作更新符号,并搜集符号在分支语句上的条件表达式。通过示例1(符号路径约束条件表达式示例)简单说明该过程:

1. int test(intx){

2.x=x-1;

3.if(x>0){

4.…

5. }else{…}

6.}

在实际执行过程中,调用test函数时会为x变量提供确定的输入值,但是在符号执行时不用考虑这些确定输入值,而是将x变量映射为符号,如“input0”;执行到第2句时更新x变量对应的符号,形成表达式“input0 -1”;到第三句的if条件语句,根据“x>0”是否成立建立条件表达式,如果成立,则建立符号条件表达式为“input0 -1>0”,且本次执行路径为1-2-3-4-6。反之,沿第5行的else语句执行,条件表达式为“input0 -1≤0”,执行路径为1-2-3-5-6。整体路径上的条件表达式的连接与组成该路径的路径约束条件。如该示例路径1-2-3-4-6对应的路径约束条件为 (input0 -1>0) ∧ξ1,ξ1为第4行内省略的约束条件。

2)对某条路径约束条件取反,通过后继步骤的操作,预使下次执行沿不同的路径,覆盖到新的代码块。

所谓取反就是将条件关系取反,如将“/=”取反得到“=”,将“>”取反为“<=”。对示例1,假设if条件成立,则本次执行路径为1-2-3-4-6,那么第5行的代码块没有被覆盖到(执行到)。如果将第3行将对应的约束条件条件取反为“input0 -1≤0”,就可使下次沿else分支执行,从而覆盖到新的代码块执行。

通过对分支语句的条件表达式取反,使每次执行不同的分支路径,企图通过该方式覆盖到新的代码块,是动态符号执行最本质的特征。

3)对取反的路径约束条件用SMT求解器求解。如果有解,则产生一组实际值,该实际值作为新的输入驱动下一次的符号执行沿该预定的路径执行。这里说明一下,一条有解的路径约束条件必定对应一条路径,两者是一一对应的关系。

4)如此,直到被测程序的所有路径被测试完成。整个测试状态空间是一颗路径二叉树。

如图2所示是针对动态符号执行特点的模拟图。图中黑色方块代表代码块,同心圆代表动态符号执行的测试范围,因为动态符号执行每次都能覆盖邻近的代码块的特征,使其能够全面的覆盖被测程序,因此用同心圆表示执行路线。

符号执行虽比随机执行有多余的开销,但是符号执行保证测试的精确性、全面性,能达到更高的代码覆盖率,使其成为比随机测试更有前景的软件测试技术。但是,动态符号执行有一个不能避免的缺陷,随着被测程序的增大或者循环次数的增加,整条路径的约束条件长度也线性的增加,每增加一条路径约束条件,路径二叉树的高度加1,需要测试的路径增加一倍。如此,随着路径长度的线性增长,需测路径按2的幂级数增加,引起路径爆炸,在有限的时间资源条件下,不可能测试完成,并且路径长度的增加也需要花费更多的求解器求解时间。

受应用程序增大、对本地库函数调用、循环次数不确定性等几个因素影响,引起的路径爆炸问题,使动态符号执行不能实际应用于主流大型软件的测试,如Firefox,OpenOffice,MYSQL等。

发明内容

针对上述现有技术,本发明要解决的技术问题是提供一种结合随机测试和动态符号执行的用于软件测试的交叉式动态法和装置,其能全面检测较大应用程序,且能缓解动态符号执行面临的路径爆炸问题。

为了解决上述技术问题,本发明采用如下技术方案:一种用于软件测试的交叉动态法,包括如下步骤:

(1)通过动态随机测试法对被测程序执行随机检测,检测程序漏洞,如果检测到程序异常则记录异常信息退出测试,否则在本次执行完后,计算代码覆盖率,检查代码覆盖率是否达到饱和,如果饱和则调用符号切换函数,切换到动态符号执行,将该父进程挂起,否则继续进行下次测试,直到检测到代码覆盖率饱和;

(2)通过动态符号执行法搜索新的未被覆盖代码块,如果有新的代码块被检测到则将状态还原到步骤(1)的随机执行状态,如果所有的基本块都已被覆盖,则退出测试。

进一步地,所述代码覆盖率的计算方法为:在测试之前使用一个IDA Pro的插件,用于搜集静态可执行程序的所有基本块,通过动态获取的基本块与静态基本块的比值得出当前的代码覆盖率。

进一步地,所述动态符号执行法包括如下步骤:

①利用随机测试法中的测试用例实际执行被测程序同时动态符号执行,搜集路径约束条件;

②使用Generational算法对每条约束条件都取反,生成该路径邻近的所有路径对应的路径约束条件;

③用求解器对生成的每个路径约束条件分别求解,生成测试用例集合;

④在测试用例集合中选择新代码块增量最大的测试用例作为该模块的返回值,如果本次符号执行没有新的代码块被检测到,那么从测试用例集合中随机选择一个测试用例作为①的输入驱动下一次的符号执行,直到有新的未被覆盖代码块被检测到。

一种用交叉动态法测试软件的装置,包括:

随机测试模块,用于实现随机检测功能,并计算代码覆盖率,检查代码覆盖率是否达到饱和;

动态符号执行模块,根据随机测试模块已测试的程序状态,利用动态符号执行,探索新的未被覆盖的代码块;

插桩模块,用于对被测程序插桩,搜集随机执行和动态符号执行覆盖到的代码块信息,同时在动态符号执行时搜集路径约束条件;

符号切换模块,用快照方式保存被测程序的当前状态,并创建子进程执行动态符号测试,父进程挂起等待子进程唤醒,子进程继承了父进程的当前所有状态,保证从当前状态继续执行;

随机还原模块,用动态符号执行产生的,能覆盖新代码块的测试用例更新父进程的输入,唤醒父进程,子进程退出,从当前状态继续执行随机测试;

状态检测模块,用于检测随机测试模块执行是否达到饱和,从而调用符号切换模块,准备切换到动态符号执行模块执行;同时检测动态符号执行是否检测到新的代码块,从而调用随机还原模块,准备还原到随机测试模块。

进一步地,所述插桩模块采用PIN工具。

与现有技术相比,本发明具有以下有益效果:

本方案提出的交叉式动态符号执行方案,是随机测试和动态符号执行两种技术的结合。开始执行随机测试,当覆盖率达到饱和时(代码覆盖率增量为零),通过符号切换模块保存当前的程序状态,切换到动态符号执行,利用动态符号执行检测新代码块,当有新代码块检测到时,通过随机还原模块又重新切换到随机测试。如此,利用随机测试和动态符号测试交叉执行,利用它们之间的互补关系弥补各自的缺陷,避免随机测试因需生成某一特定值而陷入,避免动态符号执行因循环而陷入。使该测试方案具有随机测试开销小、速度快的特点,又有动态符号执行全面性、精确性的特点。能达到比两者并行执行更高的代码覆盖率,并且能大幅度缓解路径爆炸,具有更好的测试性能。

附图说明

图1为动态随机测试模拟图;

图2为动态符号执行模拟图;

图3为交叉式动态符号执行模拟图;

图4为本发明实施例交叉式动态法执行装置图。

具体实施方式

下面将结合附图及具体实施方式对本发明作进一步的描述。

交叉式动态符号法执行的模拟图如图3所示,通过对三种技术的模拟图(图1,图2,图3)的比较也可以看出混合式符号执行的优势。图3代表的交叉式动态符号执行利用随机测试可以快速深入程序内部(折线所示),利用动态符号执行能够覆盖邻近的代码块(同心圆所示),与图1,图2相比,明显能覆盖更多的代码块(黑色方块所示)。

下面通过示例2(混合式动态符号测试算法)对以上三种技术作简单的说明及比较:

1.voidtestme() {

2. char* s, c;

3. int state = 0;

4. s = input();

5. while (1) {

6. c = input();

7. if (c == ’[’ && state == 0) state = 1;

8. if (c == ’(’ && state == 1) state = 2;

9. if (c == ’{’ && state == 2) state = 3;

10.if (c == ’˜’ && state == 3) state = 4;

11.if (c == ’a’ && state == 4) state = 5;

12.if (c == ’x’ && state == 5) state = 6;

13.if (c == ’}’ && state == 6) state = 7;

14.if (c == ’)’ && state == 7) state = 8;

15.if (c == ’]’ && state == 8) state = 9;

16.if (s[0] == ’r’ && s[1] == ’e’&& s[2] == ’s’ && s[3] == ’e’&&

17.s[4] == ’t’ && s[5] == 0&& state == 9) {

18.ERROR;

19.}}}

示例2中,循环每次接受两个输入s、c,s为字符串,c为字符。如果变量state达到9,并且字符串s为“reset”,则触发错误态ERROR,该示例的目的就是要检测出ERROR状态。

如果使用随机测试方式,经过可能几百或几千次循环(这样的开销对当前的计算机执行能力来说并不算大),很容易满足7~15行的if条件,使state的值达到9,但是使s的值为“reset”的概率为1/28*5>(5个字符,每个字符长度为8bit,s[5]为字符串结束符),如此,随机测试要击中ERROR的概率非常小,实际不可行。

如果使用动态符号执行方法,由于对路径约束条件取反,驱使每次执行不同的分支路径,所以能用很少的执行次数(1/26>以内)使s的值变成“reset”,驱第16-17行的if语句条件成立。但是,对于该示例的无限循环算法,每次循环产生16条约束条件,至少需要9次循环才能是state的值为9,一次执行的路径约束条件长度为16*9,需要测试的路径数量为216*9>,更不可能在有限的时间资源条件下触发ERROR。

而本方案实现的交叉式动态符号执行技术,结合以上两种方法的优势,对7~15行使用随机测试,快速使state值为9;对第16-17行使用动态符号执行产生字符串s=“reset”,利用随机测试技术和动态符号测试技术,使整个测试能在很小的时间开销内触发ERROR。

参见图4,一种用交叉动态法测试软件的装置,包括:

1. 随机测试模块

该模块的功能是通过产生随机值,实际执行被测程序,检测程序漏洞,不需要其他额外的操作。本方案利用现有的Fuzzing测试技术来实现该模块的功能。Fuzzing测试,即模糊测试,是一种基于缺陷注入的自动软件测试技术,它利用黑盒测试的思想,使用大量半有效的随机数据作为应用程序的输入,以程序是否出现异常为标志,来发现应用程序中可能存在的安全漏洞。特定类型的应用程序或者协议有不同的Fuzzing工具,如针对浏览器的mangleme、针对文件应用程序的FileFuzzing和SPIKE-file、针对ActiveX的COMRaider和AxMan、针对网络协议的SPIKE等。在本方案中根据被测软件类型来选择不同的工具。

该模块的具体执行流程如下:

1)分析被测程序类型,选择一款Fuzzing工具,转到2);

2)利用Fuzzing工具产生随机值,形成输入测试用例,转到3);

3)对被测程序插桩,将输入测试用例作为输入运行程序,监视程序的运行状态,并且保存该路径覆盖的代码块。如果检测到程序异常则转到6),否则转到4);

4)本次执行完后,计算代码覆盖率,检查代码覆盖率是否达到饱和。如果达到则转到5),否则转到2)继续进行下次测试;

5)调用符号切换函数,准备切换到符号执行,该进场将被挂起。

6)记录异常信息,包括异常的地址、触发异常的测试用例。转到7);

7)退出测试。

2. 动态符号执行模块

该模块的功能是利用动态符号执行来搜索新的未被覆盖代码块。该模块的输入是当前测试的程序状态,包括已测试路径、已覆盖基本块。为达到高效的新代码块查找功能,该模块没有利用现用的动态符号执行工具,而是自己实现的一套动态符号执行方案,具体执行流程如下:

1) 利用当前的测试用例实际执行被测程序同时符号执行,搜集路径约束条件。例如示例3是对示例2符号执行搜集到的路径约束条件的部分表内容。

(/= (CMP8 input6 91))

(/= (CMP8 input6 40))

(/= (CMP8 input6 123))

(/= (CMP8 input6 63))

(/= (CMP8 input6 97))

(/= (CMP8 input6 120))

(/= (CMP8 input6 125))

(/= (CMP8 input6 41))

(/= (CMP8 input6 93))

(/= (CMP8 (EXT0_7 (CAT8_24 input4 (CAT8_16 input3 (CAT8_8 input2 input1)))) 114))

示例 路径约束条件表达式

其中input6是字符c对应的符号,91,40等值是‘[’、‘(’等字符对应的ASCII码值。该格式是由PIN执行(插桩模块说明)的输出格式。将第一条转换成易理解的格式为“input6/= 91”。

2)使用Generational算法对每条约束条件都取反,生成该路径邻近的所有路径对应的路径约束条件。Generational算法是微软资深软件测试工程师Patrice Godfroid提出的一种动态符号测试算法。该算法将路径约束条件中的每一条路径都取反,从而生成一堆测试用例,从中选择能覆盖最多代码块的测试用例驱动下次符号执行。

3)用求解器对生成的每个路径约束条件分别求解,生成测试用例集合。这里说明一下,动态符号执行搜集到的路径约束条件都是SMT问题,而求解器就是用来求解这些问题是否可满足的,并给出一组可满足值。例如,表达式x-y>0,是可满足的,可给出满足该公式的一组值(2,1);x2+y2<0是不可满足的,不能给出一组(i0,i1)值,使该表达式成立。常见的SMT求解器有STP,CVC,OpenSMT,Yices,Z3等,在本模块中选择STP作为SMT的求解器。

4)在测试用例集合中选择新代码块增量最大的测试用例作为该模块的返回值。如果本次符号执行没有新的代码块被检测到,那么从测试用例集合中随机选择一个测试用例作为1)的输入驱动下一次的符号执行,直到有新的代码块被检测到。

3. 插桩模块

该模块的功能是对运行时的被测程序进行动态二进制插桩,记录已被测试到的代码块,并在符号执行时搜集路径约束条件。对动态程序插桩是动态符号执行的一项基本且不可或缺的措施。现有的二进制插桩工具有ATOM、Dynins、Valgrind、PIN、Nirvana、HDTrans等,在本方案中采用PIN作为插桩工具。PIN是一款开源的动态插桩工具,支持IA-32,Intel(R)64,IA-64指令结构,可用于Windows OS和Linux系列操作系统平台上,PIN可以将任意代码植入处于运行态程序的任意位置,跟踪指令流程,并记录寄存器、内存的数据信息。另外,本方案在测试之前还使用了一个IDA Pro的插件,用来搜集静态可执行程序的所有基本块。通过动态获取的基本块与静态基本块的比值可以得出当前的代码覆盖率。

在动态符号执行时,通过对被测程序插桩,可以监测符号的流动路径、操作运算,从而收集路径约束条件。

4. 状态检测模块

本模块有两个功能,一是检测随机执行是否达到饱和,即代码覆盖率不再增加,从而调用符号切换模块,准备切换到动态符号执行模块执行。该部分功能的实现是在每次随机测试后都检测当前的代码覆盖率增量。若在一定界限内(本示例设置为50)该增量为0,说明当前随机测试因特定值的选取而陷入,使代码覆盖率达到饱和,需要使用动态符号执行来破解该陷入,探索新的代码块。

另一功能是检测动态符号执行是否检测到新的代码块,从而调用随机还原模块,准备还原到随机测试模块。如果动态符号执行检测到新的代码块,则代码覆盖率必定有所增加,根据该增量标志,使动态符号执行退出,切换到随机测试模块继续运行。

该模块的输入是一个布尔值的转换标识符translate,当该值为false时切换到符号执行模块,值为true时切换到随机测试模块。

5. 符号切换模块

该模块的功能是从随机测试切换到符号执行。使用如虚拟机的快照方式保存当前的测试状态(如已执行的路径、已覆盖代码块等),并创建动态符号执行子进程,且将当前父进程挂起。子进程继承父进程的所有资源,所以在动态符号执行时不会重复执行已被测试的路径。

6. 随机还原模块

该模块的功能是从动态符号执行模块还原到随机测试模块。该模块是在动态符号执行检测到新的代码块后,退出动态符号执行子进程,且将随机测试父进程唤醒。并用动态符号子进程产生的新的测试用例更新原来的测试用例,使随机测试模块跳出原来的陷入状态,从不同的代码块继续执行。

下面简单的给出了本发明的实现步骤:

1)对被测程序执行随机检测,并计算代码覆盖率。如果代码覆盖率的增量为0),即代码覆盖率达到饱和,则转到2),否则继续1)的随机检测。

2)保存当前的检测状态(已检测的路径、已覆盖的代码块等),创建动态符号执行子进程。

3)动态符号执行被测程序,探索新的代码块,如果有新的代码块被检测到,则转到4),如果所有的基本块都已被覆盖,则转到5)退出测试,否则继续3)的符号执行。

4)状态还原到随机执行状态,并将当前的测试用例更替父进程的测试用例,唤醒父进程,退出当前子进程,转到1)。

5)结束。

其中各个模块之间的衔接并没有明显的分割,如随机还原模块完成后是回到了随机模块的第3)步,利用新的测试用例继续执行,状态检测模块是在随机测试模块和动态符号执行模块的内部展现其功能的。

本发明结合随机测试的快速性、低开销以及符号执行的全面性、探索新代码块的特性,避免了随机测试因需取特定值时面临的小概率性、不确定性以及动态符号执行因程序较大或循环引起的路径爆炸问题,从而能够更全面、更快速的测试软件,并且与完全的动态符号执行相比大大降低了软件测试的开销。能够全面检测较大应用程序,能够缓解动态符号执行面临的路径爆炸问题。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号