应用跨函数分析的软件测试方法

文档序号:6618868阅读:235来源:国知局
专利名称:应用跨函数分析的软件测试方法
技术领域
本发明涉及软件自动化测试技术,尤其涉及一种应用跨函数分析的软件测试方法。
背景技术
软件测试是软件开发过程的重要组成部分,是用来确认一个程序的品质或性能是 否符合开发之前所提出的一些要求。软件测试通常可分为动态测试和静态测试两类。动态 测试是指通过运行被测程序,检查运行结果与预期结果的差异,并分析运行效率和健壮性 等性能,因此,动态测试的方法一般由三部分组成,即构造测试实例、执行程序和分析程序 的输出结果。静态测试是指不运行被测程序本身,只通过搜集、查找程序的信息、分析或检 查源程序的语法、结构、过程和接口等特征来检查源程序的正确性。静态测试方法通过程序 静态特性的分析,可以找到缺陷和可疑之处,如不匹配的参数、不适当的循环嵌套和分支 嵌套、不允许的递归、未使用过的变量、空指针的引用和可疑的计算等,并且其测试结果还 可用于进一步的查找错误,并为测试用例的选取提供指导,因此其优点是能够在程序运行 之前就可以对程序故障进行全面检测,故在较重要的软件工程中得到广泛应用。在实际的软件静态测试中,由于源程序中存在函数间的嵌套调用关系,一个函数 的执行可能会对其调用者或其他函数产生影响,如函数中对全局变量或类成员变量的更 改、对指针型参数或引用型参数的更改以及函数的返回值等情况;另外,在测试函数被调用 时,函数的参数及外部变量在特定的条件下会有一些取值,由于缺少对参数变量及外部变 量的有效性判断,可能导致函数内部的变量使用错误;再者,程序内部的异常处理逻辑也会 改变函数的出口,从而影响被测程序内部的控制逻辑。以上所述内容涉及到函数的内部控制流信息,以及由此影响的函数间数据流信 息,因此,会给软件静态分析和测试工作带来巨大困难,导致检测结果中含有大量的误报信 息和漏报信息,从而降低了软件测试的意义。

发明内容
有鉴于此,本发明的主要目的在于提供一种应用跨函数分析的软件测试方法,以 降低软件静态测试过程中函数调用对区间计算精度的影响,提高函数间分析的准确度、降 低测试结果的误报率和漏报率。为达到上述目的,本发明的技术方案是这样实现的—种应用跨函数分析的软件测试方法,该方法包括A、分析项目源程序中所有函数间的调用关系,建立函数调用关系图;B、在所述函数调用关系图中确定当前节点,判断当前节点是否为最后一个节点, 若所述当前节点为最后一个节点,则执行步骤G ;否则,执行步骤C ;C、利用所述当前节点中的相关变量,生成约束信息,然后执行步骤D ;D、读取所述函数调用关系图中所在节点对应的控制流图中的下一个节点作为当
5前节点,若所述当前节点为最后一个节点,则执行步骤F ;否则,执行步骤E ;E、应用已获得的函数后置信息,并根据当前节点所对应的语句类型对所述节点的 各变量进行区间运算,得到变量的新的区间取值,然后返回执行步骤D ;F、结束对当前控制流图的遍历,为调用关系图中当前节点生成函数后置信息和函 数特征信息,然后返回执行步骤B ;G、按照拓扑顺序取所述函数调用关系图中的下一个节点作为当前节点,若所述当 前节点为最后一个节点,则执行步骤I ;否则,执行步骤H;H、为所述函数调用关系图中当前节点生成函数前置信息,然后返回执行步骤G ;I、结束对当前函数调用关系图的遍历,输出程序中所有函数的摘要信息。其中,步骤A所述建立函数调用关系图的过程如下Al、编译项目源程序中的所有文件,若编译失败,则返回错误信息;若编译成功,则 执行步骤A2 ;A2、根据编译后的类class文件,提取所有类型信息,所属类型信息包括程序中所 有定义的类名称、类中所有成员变量及其类型、类中所有成员方法及其返回类型,然后执行 步骤A3 ;A3、再顺序分析程序中的所有函数或成员方法,若在其语法树中遇到其它函数或 成员方法的使用,则在函数调用图中添加相应的内容。步骤B所述确定函数调用关系图中的当前节点,具体为按照拓扑逆序选取所述函数调用关系图中的下一个节点作为当前节点。步骤C所述利用当前节点中的相关变量生成约束信息的过程具体为Cl、提取当前节点中所有引用的全局指针变量及参数指针变量,分别对这些变量 作如下判断若存在一条从函数入口到引用指针变量内容的路径,且在引用内容前未判断 指针是否为空,则将该变量及路径信息加入到当前节点的空指针引用约束信息中,然后执 行步骤C2 ;C2、当判断完所有的指针变量后,则提取当前节点中所有引用的全局指针变量及 参数指针变量,并分别对这些变量作如下判断若存在一条从函数入口到释放指针内容的 路径,且在释放内容前未判断指针是否变更,则将该变量及路径信息加入到当前节点的内 存泄露约束信息中;然后执行步骤C3 ;C3、提取当前节点中所有数组类型参数变量,分别对这些变量作如下判断若存在 一条从函数入口到数组下标引用的路径,则将引用下标的最大、最小值加入到当前节点的 数组越界约束信息中;执行步骤C4 ;C4、提取当前节点中所有全局变量及参数变量,分别对这些变量作如下判断若存 在一条从函数入口到引用变量内容的路径,且在引用内容前未对其赋值,则将该变量及路 径信息加入到当前节点的未初始化约束信息中;然后执行步骤C5 ;C5、提取当前节点中所有引用的全局变量及参数变量,分别对这些变量作如下判 断若存在一条从函数入口到对该变量作算术运算的路径,且在使用其内容前未判断其有 效性,则将该变量及路径信息加入到当前节点的非法计算约束信息中;其中,所述有效性判 断包括分母不能为零、平方根不能为负。所述步骤E进一步包括对所有节点的各变量进行区间运算前,需根据进入当前节点前的输入状态,计算经过当前节点的所有可能的输出状态,其过程如下E1、若当前节点为控制流图的入口节点,则该节点输入状态为空,输出状态为当前 节点的新增状态,则执行步骤D ;否则执行步骤E2 ;E2、若当前节点为控制流图的非分支节点或汇合节点,则该节点输入状态为其所 有前驱节点的输出状态相并,其输出状态为当前节点的输入状态减去其删减状态并上新增 状态,然后执行步骤D ;否则执行步骤E3 ;E3、若当前节点为控制流图的分支节点,则该节点输入状态为其前驱接点的输出 状态,输出状态为当前节点的输入状态与所有条件相交后的并集,然后执行步骤D ;否则, 执行步骤E4 ;E4、如果当前节点的前驱为控制流图的分支节点,则该节点输入状态为其前驱节 点的输出状态与该分支条件的交集,输出状态为当前节点的输入状态减去其删减状态并上 新增状态,然后执行步骤D ;否则执行步骤E5 ;E5、如果当前节点为控制流图的汇合节点,则该节点输入状态为其所有前驱节点 的输出状态的并集,输出状态等于其输入状态。步骤F所述后置信息的生成过程为F1、将当前节点可能的返回值及其相应条件加入到后置信息中,然后执行步骤 F2 ;F2、将当前节点的指针型参数和引用型参数的可能区间及其相应条件加入到后置 信息中,然后再执行步骤F3;F3、将当前节点所有调用的函数的后置信息中未被修改的部分加入到当前节点的
后置信息中。步骤F进一步包括,利用所述生成的后置信息生成所述函数特征信息,其生成过 程为F4、分析所述调用关系图的当前节点是否为分配资源、释放资源或可抛出异常的 类型;若在调用关系图中的当前节点中存在一条路径,返回由库函数或者具有分配资源特 征的函数分配的资源,或者将库函数或具有分配资源特征的函数分配的资源赋值给全局变 量,则当前节点的特征为分配资源,然后执行步骤F6 ;否则,执行步骤F5 ;F5、若在调用关系图中的当前节点的所有路径中,都存在由库函数或者具有释放 资源特征的函数来释放参数资源,或者由库函数或者具有释放资源特征的函数来释放全 局资源,则当前节点的特征为释放资源,其中,当前节点的抛出异常包括显式及隐式抛出异

巾ο步骤H所述前置信息的生成过程为HI、将当前节点中所有与被调函数的参数变量相关的变量区间及其相应条件加入 到被调函数的前置信息中,然后执行步骤H2 ;H2、将当前节点的前置信息中没有被修改的部分加入到被调函数的前置信息中。本发明所提供的应用跨函数分析的软件测试方法,具有以下优点本发明提出的跨函数分析的软件测试方法,在现有的静态测试中的区间计算和函 数间分析技术的基础上,扩展函数摘要信息在基于缺陷模式的软件测试中的具体内容,完 善了函数内的区间迭代技术,将函数副作用及其分支条件计算到迭代公式中,从而在缺陷
7判定过程中充分利用所述函数摘要信息,大幅提高了函数间分析的准确度即提高测试结果 的准确性、降低了测试结果中的误报率和漏报率。


图1为本发明实施例应用跨函数分析的方法进行软件测试的流程示意图;图2为本发明实施例中表1所示源程序的函数调用关系图;图3为本发明实施例中表1所示源程序的函数f的控制流图;图4为本发明实施例中表1所示源程序的函数f2的控制流图。
具体实施例方式下面结合附图及本发明的实施例对本发明的方法作进一步详细的说明。软件在实际运行过程中,某一变量或表达式的取值是存放在计算机的内存中的, 且其取值是唯一确定的。然而在静态测试中,由于程序未被执行,变量及表达式的确定取值 情况必须通过对程序内部逻辑的分析才能近似得到。本发明提出的跨函数分析的方法在现有的静态测试中的区间计算和函数间分析 技术的基础上,扩展函数摘要信息在基于缺陷模式的软件测试中的具体内容;完善函数内 区间迭代技术,将函数副作用及分支条件计算到迭代公式中,从而在缺陷判定过程中使用 函数摘要信息,起到提高函数间分析的准确度即提高测试结果的准确性、降低测试结果的 误报率和漏报率的作用。为了将本发明提出的函数摘要信息应用在软件测试中,本发明首先定义出函数摘 要信息中前置信息、后置信息、约束信息和特征信息的内容,然后给出每种类型信息的计算 方法。下面分别对上述各种类型信息的定义、生成及使用规则举例说明为了便于后文的说明,下面首先给出函数调用图、控制流图和函数摘要信息等结 构的基本定义。一、函数调用图(FCG)是一个五元组(NODE,EDGE, RELATION, TOP, BOTTOM),其中 NODE表示一个节点集合,每个节点代表一个函数;EDGE表示一个边集合,每条边代表两个 函数间的调用关系;RELA TION表示一个关系集合,表示所有节点所代表的函数之间的关 系,RELATION = {ANCESTORS, PARENTS, CHILDRENS, DESCENDENTS} ;TOP 和 BOTTOM 分别代表 一个节点集合,包含程序P中没有直接调用者的函数和没有调用其它函数的函数。二、控制流图(CFG)是一个五元组(NODE,EDGE, RELATION, begin, end),其中 NODE 表示一个节点集合;EDGE表示一个边集合;RELATION表示所有节点所代表的语句块之间的 关系,RELATION = {PRED, NEXT} ;begin 表示 CFG (F)的入口,end 表示 CFG (F)的出口。三、函数摘要信息(FSI)是一个四元组(P0ST_INF0,PRE_INF0,C0NS_INF0, CHAR_ INFO),其中P0ST_INF0表示函数F执行后对上下文的影响,PRE_INF0表示函数F执行前受 上下文的影响,C0NS_INF0表示函数执行前对环境的约束,CHAR_INF0是函数F的特征信息, 用于在静态分析的过程中辅助缺陷状态的判断。下面分别说明函数摘要信息中的相关内容。函数约束信息是指函数对其调用者的 约束,由相关变量的取值区间和达到该取值区间的条件构成。在静态分析的过程中,当处理到调用函数F的语句时,需要参考FSI (F). C0NS_INF0判断是否发生故障。对应不同类型的 缺陷,函数摘要信息中的约束信息内容也有所不同,下面分别说明。1、空指针引用(NPD)约束信息在函数F中存在一个外部指针p,如果没有判断是否为空就引用它的内容,则会发 生空指针引用的异常。指针P的约束值以及达到其内容引用语句的条件,构成函数F中指 针P的空指针引用约束信息,记做C0NS_NPD (F,ρ) = {VAL (ρ) = N0T_NULL,COND (ρ)},其中 COND(p) = {[C1,VAL (C1) ],[c2,VAL(c2) ],...,[cn,VAL(cn)]}为到达引用指针 ρ 处的条件, 由一些相外部量的取值区间构成。函数F中所有具有这种特性指针的约束信息,构成函数F的空指针引用约束信息, 记做C0NS_NPD (F),且有
C0NS NPD(F)=I I{CONS _ NPD(F, v) | PO!NTER{v) λ
—v,lref{Kpara(f)NULL _ NOTSURE{v)}
O
其中POINTER(v)表示变量V为指针类型,NULL_N0TSURE(v)表示无法确定指针变量ν是否为空。2、未初始化变量(UV)约束信息在函数F中使用一个外部变量V,如果在使用该变量前没有初始化,则会导致程序 内部处理错误。变量ν的约束值以及达到其内容使用语句的条件,可以构成函数F中变量 ν 的未初始化约束信息,记做 C0NS_UV(F,ν) = {VAL (ν) = INIT,COND (ν)}。函数F中所有具有这种特性的变量的约束信息,构成函数F的未初始化约束信息, 记做C0NS_UV(F),且有
其中REF(v)表示变量ν的内容被使用,DEF_N0TSURE(v)表示无法确定在使用变量ν前是 否对其内容定义。3、误用指针(WUP)约束信息在函数F中存在一个外部指针ρ,如果没有经过有效性判断就引用它的内容,则会 发生无法预知的错误。指针P的约束值以及达到其内容引用语句的条件,可以构成函数F 中指针P的错误使用指针约束信息,记做C0NS_WUP(F,p) = {VAL (ρ) = VALID, COND (ρ)}函数F中所有具有这种特性的指针的约束信息,构成函数F的错误使用指针约束 信息,记做C0NS_WUP (F),且有
其中VALID_NOTSURE(p)表示无法确定指针变量ρ是否有效。4、非法计算(IA)约束信息在函数F中存在一些可能违背操作数ν约束的运算操作,如除法分母为零、平方根 操作数为负数等,如果在运算前没有判断这些非法取值,则会发生非法计算异常。相关变量 ν的约束值以及达到其非法计算位置的条件,可以构成函数F中变量ν的非法计算约束 信息,记做 C0NS_IA(F,ν) = {VAL (ν) = LEGAL, COND (ν)}函数F中所有具有这种特性的变量的约束信息,构成函数F的非法计算约束信息,记做C0NS_IA(F),且有
其中ARITHMETIC (V)表示变量ν参与算术运算,ILLEGAL_NOTSURE (ν)表示无法确定变量ν 在算术运算中的合法性。5、数组越界(OOB)约束信息在函数F的形参中使用一个数组a,如果对其使用的下标超过了定义时的范围, 则会导致程序内部处理错误。数组a的约束取值范围以及达到其内容使用语句的条件,构 成函数F中变量a的数组越界故束信息,记做C0NS_00B(F,a) = {VAL(a) = [LOW,UP], COND (a) },其中LOW和UP分别表示函数内部使用数组a下标的最小值和最大值。函数F中所有具有这种特性的数组的约束信息,构成函数F的数组越界约束信息, 记做C0NS_00B (F),且有
其中ARRAY (a)表示a为数组,B0UND_N0TSURE (a)表示无法确定数组a的有效边界。通过前面的描述,函数摘要信息中的约束信息可表示为FSI (F). C0NS_INF0 = C0NS_NPD(F) U C0NS_UV(F) U C0NS_WUP(F) U C0NS_IA(F) U。 C0NS_00B(F)在常见的缺陷检测算法中,对大多数缺陷模式需要获取控制流信息,如空指针引 用故障、资源泄露故障、内存不当使用故障和变量未初始化故障等。在考虑函数副作用影响 的同时,应用函数内控制流区间迭代技术,既可以计算出进入和退出节点N时的所有可能 状态,又可以通过矛盾状态排除不可达路径。如果函数F的控制流图CFG(F)的一个节点N中声明了若干局部变量V = Iv1, v2, ... , vn},则这些变量V及其初始取值区间VAL(V)构成节点N的进入作用域变量集合, 记做 IS(N) = {[vi; VAL (V1) ],[v2,VAL (v2) ],···,[vn, VAL (vn) ]} (Vi e N)。如果函数F的控制流图CFG(F)中的一个节点N退出了若干局部变量V = Iv1, v2,...,vj的作用域,则这些变量V构成节点N的退出作用域变量集合,记做OS (N) = Iv1, v2, ... , vn} (Vi e N) ο如果函数F的控制流图CFG(F)中的一个节点N引用了若干外部变量V = Iv1, v2,...,vn},则这些变量V及其取值区间VAL(V)构成节点N的本地引用集合,记做LREF (N) ={[vi; VAL (V1) ], [v2, VAL (v2) ],···,[vn, VAL (vn) ]} (Vi G N)。如果函数F的控制流图CFG(F)中的一个节点N调用了若干函数,则这些函数的全 局使用集合构成节点ν的全局引用集合,记做⑶"(m^y^^^f)
.ο如果函数F的控制流图CFG(F)中的一个节点N修改了若干变量V = {Vl,v2,..., VnI的值,则这些变量V及其修改后的取值区间VAL(V)构成节点N的本地更改集合,记做 LMOD (N) = {[vi; VAL (V1) ],[v2, VAL (V2) ],···,[vn, VAL (vn) ]} (Vi e N)如果函数F的控制流图CFG(F)中的一个节点N调用了若干函数,则这些函数的全
局更改集合构成节点ν的全局更改集合,记做gm^w)=J^gmod(P)如果函数F的控制流图CFG(F)中的一个节点N的后继节点数量大于1,即
10SUM (NEXT (N)) > 1,则该节点为若干条件分支的分流节点,记做DIFF (N)。如果CFG(F)中的 一个节点N的前驱节点数量大于1,即SUM(PRED(N)) > 1,则该节点为若干条件分支的合流 节点,记做CONF(N)。如果N' e NEXT (N),则满足从节点N到N'的变量及其取值区间构成条件满足集 合,记做 C0N(N,N' ) = ([V1JAL(V1)], [v2,VAL(v2)],...,[vn,VAL (vn)]} (Vi e N)。如果函数F的控制流图CFG(F)中的一个节点N新产生或改变了相关变量的取值 区间,则这些变量V及其取值区间VAL(V)构成节点N的更新变量区间集合,记做GEN(N)= (IS(N) U LREF(N) U GREF(N) U LMOD(N) U GMOD(N)}。如果函数F的控制流图CFG(F)中的一个节点N注销或改变了相关变量的取 值区间,则这些变量V构成节点N的消除变量区间集合,记做KILL(N) = IOS(N) U VAR (LMOD(N)) U VAR(GM0D(N))}。在CFG(F)中的某个节点N执行前,相关变量V= Iv1, V2, ... , vj及其取值区间 VAL(V)构成通过节点N前的所有可能状态集合,记做IN(N),且有 在CFG(F)中的某个节点N执行后,相关变量V= Iv1, V2, ... , vj及其取值区间 VAL(V)构成通过节点N后的所有可能状态集合,记做OUT(N),且有 根据上式,函数F中所有节点的IN和OUT可以按照CFG(F)的拓扑有序的顺序迭 代获得。函数后置信息用来确定函数的副作用,即函数执行后对上下文的影响,包括函数 及其内部嵌套调用的函数对全局变量和类成员变量的更改、指针及引用型参数的变更对其 调用者的影响、以及函数的返回值对其调用者的影响。如果函数F中使用了若干外部变量V = Iv1, v2,...,vj,则这些变量V及其取值区 间 VAL (V)构成函数 F 的本地引用集合,记做 LREF (F) = {[Vl,VAL (V1) ],[v2,VAL (V2)],..., [vn,VAL(Vn) ]}。如果函数F中使用了若干外部变量V = Iv1, v2,...,vn},并且其中包括程序P中 所有直接或间接调用F的函数F' =ANCESTORS(F)中使用的外部变量,则这些变量ν及其 取值区间VAL (V)构成函数F的全局引用集合,记做GREF (F),且有
根据上式可得,程序P中所有函数的GREF可以按照FCG (P)的拓扑有序的顺序迭 代获得。
如果函数F中使用了若干外部变量V= {Vl,v2, ...,vn},并且其中包括程序 P中所有被函数F直接或间接调用的函数F' = DESCENDENTS(F)中使用的外部变量, 则这些变量V及其取值区间VAL(V)构成函数F的全局使用集合,记做GUSE(F),且有
'LREF(F),Fe BOTTOM ( FCG (P))
GUSE(F)='
LREF(F)<j[UGUSE(F')], F i BOTTOM (FCG {P))
F'eCHILDRENS(F)根据上式可得,程序P中所有函数的GUSE可以按照FCG (P)的拓扑逆序的顺序迭 代获得。如果函数F更改了若干外部变量V = {Vl,v2,. . .,vn},则这些变量V及其取值区 间 VAL (V)构成函数 F 的本地更改集合,记做 LMOD (F) = {[v” VAL (Vl) ],[v2,VAL (v2) ], , [vn,VAL(vn)]}。如果函数F中的形参列表中出现指针变量或者引用变量,这些变量及其取值区间
构成函数 F 的可更改参数集合,记做 PARA (F) = {[Vl,VAL(Vl)],[v2, VAL(v2)], ... , [vn,
VAL(vn)]}。而函数F中所有被调函数的PARA(F’),构成函数F的参数更改集合,记做
PASS(F) H 有U 腿(F)。 ,-tLflF^HLDRENS(F)如果函数F更改了若干外部变量v,其中包括F直接或间接调 用的函数F ‘ = DESCENDENTS(F)中更改的外部变量,则这些变量v及 其取值区间VAL(v)构成函数F的全局更改集合,记做GMOD(F),且有
'lMOD(F)^jPASS(F)^RET(F),FeBOTTOM(FCG(P))
GMOD{F)=
LMOD(F}uPASS(FyjRET(FMU{GMOD(F')nGREF(Fr)}]
F'eCHILDRENS(F)
FiBOTTOM{FCG{P))
其中,RET (F)表示函数F的返回值取值区间,根据上式可得,程序P中所有函数的 GM0D可以按照FCG(P)的拓扑逆序的顺序迭代获得。根据以上定义,函数摘要信息中的后置信息可表示为FSI (F). P0ST_INF0 = GMOD(F)。函数特征信息包括函数对资源的分配及释放情况、以及可抛出的异常类型,它们 主要用于对资源泄漏故障模式的检测及对控制流信息的影响。若函数F内存在一条路径,返回由系统库函数创建的资源,则该函数F的特征为分 配返回资源 ALLOC (F) = [RES, ret] 若函数F内存在一条路径,返回由具有分配返回资源特征的函数所分配的资源, 则该函数F的特征为分配返回资源ALLOC(F) = [RES,ret]。若函数F内存在一条路径,将系统库函数创建的资源赋值给一个全局变量 global_var,则该函数的F特征为分配全局资源ALLOC (F) = [RES,global_var]。若函数F内存在一条路径,将具有分配返回资源特征的函数所分配的资源赋值给 一个全局变量global_var,则该函数的F特征为分配全局资源ALLOC (F) = [RES, global, var] o在函数F的所有路径中,都对由参数param传入的资源进行释放,则该函数的特征 为释放传入资源 RELEASE (F) = [RES, param]。在函数F的所有路径中,都对由全局变量globalvar标记的资源进行释放,则该函数的特征为释放全局资源RELEASE (F) = [RES, global_var] 0在一个异常处理结构T中,如果在子句try结构中应用throw方法抛出异常,则这 I匕异常称为T中子句t的显式异常,五砂= U throws(e)}。
est在一个异常处理结构T中,如果在子句catch结构中应用throw方法抛出异常,则 这些异常称为T中子句c的显式异常,五印"U^l throw(e)}。
eec在一个异常处理结构T中,如果在子句finally结构中应用throw方法抛出异常, 则这些异常称为T中子句f的显式异常,芯印&叫厂乃=°
^^ J在一个异常处理结构T中,如果子句try结构中在某种条件下, 由特定的函数可抛出一些异常,则这些异常称为T中子句t的隐式异常,
Im p lie it (T ,t) = [J E x c e p tio n{F )
F et在一个异常处理结构T中,如果子句catch结构中在某种条件下, 由特定的函数可抛出一些异常,则这些异常称为T中子句c的隐式异常,
Implicit (T ,c) = (J Exc ep tio n(F )
Fee0在一个异常处理结构T中,如果子句finally结构中在某种条件 下,由特定的函数可抛出一些异常,则这些异常称为T中子句f的隐式异常, Im p lie it(T , / ) = [J Exception{F )
F-fo一个单层异常处理结构T的显式抛出异常为
,Explicit(T,f),\fpath. Explicit (J\ f)本 0
0,Vpath, Explicit(T, /) = 0 八 Jump(f,path)Catch(Explicit(J\t)y)u Explicit(T,c)Kj Explicit(T,f\
3path, Explicit (T^ f) = 0 /\]Jump、f, path)一个单层异常处理结构T的隐式抛出异常为
Implicit(J\ f),/path, Explicit(T, /)弇 0 v Jump{f, path)
(Jmpl icit(J\ t) r^Catch{Jmplicit(T, t))) KjImplicitiJ, c) KjImplicitiT, f),
3path, Explicit{!T^ f)-0A -iJump{f, path)
V
j个多层异常处理结构T的显式抛出异常为
STE(T) =
STI(T) =
MTE(T) =
STE(T),Sub(T) = 0
Explicit(TJ)vj |J MTE{Tr),\fpath, Explicit^, /) ^ 0
reSub(TJ)
{Explicit{T,t)\J [J MTE(T')) n Catch(Explicit(T, t) u (J MTE(T'))u
reSub(T,t)T'€Sub(T,t)
Explicit (T,c)kj (J MTE{T)yjExplicit{T,f)kj |J MTE(T'),
T'eSub(T,c)T'eSub(TJ)
Bpath, Expl icit(T, /) = 0 a —Jump{f, path)
一个多层异常处理结构T的隐式抛出异常为 一个函数F的非异常处理结构中,如果在语句中应用throw方法抛出异常,则这些 异常称为函数F的附加显式异常/印 函数F的可抛出异常为 根据以上定义,函数摘要信息中的特征信息可表示为FSI (F). CHAR_INF0 = {ALLOC(F),RELEASE(F),Exception(F)}。函数前置信息是指函数F在被调用时受上下文的影响,主要包括其ANCESTORS (F) 内所有的函数对全局变量和类成员变量的更改。若存在函数F的一个直接调用者F' G PARANTS(F),如果在F、的入口 到F的所有路径上更改了若干外部变量V= {Vl,v2, ...,vn},则这些变量V及其取 值区间VAL(V)构成函数F对函数F、的一个直接关联集合,记做LASS0(F,F')= {[Vl, VAL(Vl)], [v2,VAL(v2) ],..., [vn, VAL(vn)]}0 函数 F 的所有直接关联集合为 如果从程序的入口到函数F的函数调用过程中,若干外部变量V= {Vl,v2,..., vn}被更改,其中包括所有直接或间接调用F的函数F' = ANCESTORS (F)的直接关联集 合,则这些变量v及其取值区间VAL(v)构成函数F的全局关联集合,记做GASSO(F),且有 根据上式,程序P中所有函数的GASS0可以按照FCG(P)的拓扑有序的顺序迭代获得。根据以上定义,函数摘要信息中的前置信息可表示为FSI(F).PRE_INF0 = GASS0(F)。以上所述为本发明所提出的函数摘要信息介绍,下面再对本发明所提出的函数摘 要信息在软件静态测试过程中的应用进行解释和进一步说明在软件缺陷的检测过程中以函数作为被分析单元,首先建立缺陷相关变量的状态 机实例,然后根据状态转换规则,在CFG(F)中应用每个节点N的IN(N)和0UT(N)分析状态机实例,判断是否会达到故障状态。如在分析过程中遇到函数调用时,还需要参考函数摘要 信息,应用约束信息、前置信息和特征信息来辅助进行缺陷判断。下面给出对应不同缺陷模式的检测方法1、检测空指针引用故障如果在函数F中的某条路径上存在一个为空的指针p,没有经过有效性判断就引 用它的内容,则会发生空指针引用的故障。对该类问题的检测过程如下首先为相关变量创建空指针引用状态机实例,这些相关变量包括函数内实例变量 INTRA_NPD (F) = {v | POINTER (v)八 v G VAR (LOCAL (F)) U VAR (LREF (F))}和函数间实例变 量 INTER_NPD (F) = {v | v G VAR(C0NS_NPD (F))},其中 LOCAL (F)表示 F 的本地变量。对函数F内非函数调用节点N的检测描述为
INTRA _NPD{F),NULL{p) eIN(N)aREF(N,p)^NPD(F,p)对调用函数F的节点N的检测描述为
3p,peINTER_NPD(F),,CONS _NPD(FyVAL{p)e(FSI(F).PRE _INFOuIN_ 八
REF(N,p)ACONS_NPD(F).COND(P)^NPD(F,P)其中NULL(p)表示指针p为空,^COA^ — A/PDC^y^LO)表示与函数F的NPD 约束信息中P的值相悖的情况,即指针P为空,REF(N, p)表示节点N中对指针p内容的引 用,C0NS_NPD (F). C0ND (p)表示函数F的NPD约束信息中p所对应的条件为真。2、检测变量未初始化故障如果在函数F的某条路径上使用一个变量V,并且v在使用前没有初始化,则可能 会导致程序内部处理错误。对该类问题的检测过程如下首先为相关变量创建变量未初始化状态机实例,这些相关变量包括函数内实例变 量 INTRA_UV(F) = {v|v G VAR (LOCAL (F)) U VAR (LREF (F))}和函数间实例变量 INTER_ UV (F) = {v|v G VAR (C0NS_UV(F))}。对函数F内非函数调用节点N的检测描述为
3v,v eINTRA—UV{F\NOT _INIT(y) &INQN)八 REFQN,v)。UV、F ,v)对调用函数F的节点N的检测描述为
3v,v&INTERJJV{F)^COmjW(F)yAUv)钱FSKJ^PRE _INF(XJlN{Ny) AREF{N,V)八
CONSJJV{F).CONOy) ^>UV(F,v)其中NOT_init(v)表示变量v未初始化,-nCOiv^—"rcF)yAL(v)表示与函数
F的UV约束信息中v的值相悖的情况,即变量v没有初始化,C0NS_UV(F).C0ND(v)表示函 数F的UV约束信息中v所对应的条件为真。3、检测错误使用指针故障如果在函数F中存在一个无效的指针p,没有经过有效性判断就引用它的内容,则
15会发生无法预知的错误。对该类问题的检测过程如下首先为相关变量创建错误使用指针状态机实例,这些相关变量包括函数内实例变 量 INTRA_WUP (F) = {p| POINTER (p) A p G VAR (LOCAL (F)) U VAR (LREF (F))}和函数间实 例变量 INTER_WUP (F) = {p | p G VAR (C0NS_WUP (F))}。对函数F内非函数调用节点N的检测描述为
3p, p & INTRA _WUP(JF\INVALID{p) eIN(N)八 REF(N, p)。WUP(F, p)对调用函数F的节点N的检测描述为
3p,peINTER_WUP(F),,CONS—WUP(F).VAL(pXFSI(F).PRE_INFCKJlN(N))A
REF(N,p)aCONS_WUP(F).COND(p)^WUP(F,p)其中INVALID (p)表示p为无效指针,C0NS_WUP (F). COND (p)表示函数F的WUP约 束信息中条件为真,"" CCWS^FfL/PC^J^LO)表示与函数F的WUP约束信息中P的值 相悖的情况,即P是一个无效的指针,它的无效性有多种情况,例如指针被释放后指向的空 间、指向的空间被释放、指针经过算术运算后要释放、指向无效的栈空间等等。4、检测非法计算故障在函数F中存在一些违背操作数v约束的运算操作,如除法分母为零、平方根操作 数为负数等,如果在运算前没有判断这些非法取值,则会发生非法计算异常。对该类问题的 检测过程如下首先为相关变量创建变量未初始化状态机实例,这些相关变量包括函数内实例变 量 INTRA_IA(F) = {v|v G VAR (LOCAL (F)) U VAR (LREF (F))}和函数间实例变量 INTER_ IA (F) = {v|v G VAR (C0NS_IA(F))}。对函数F内非函数调用节点N的检测描述为
3v,vGlNTRAJA(F),ILLEGAL(v)eIN(N)AREF(N,v)^IA(F,v)对调用函数F的节点N的检测描述为
3v,v&INTER_IA(F),~CONS_IA{F)miv)&(FSI、F).PREJNFCKjIN{Ny}AREF{N,v)/\
CONS_IA{F).CONOy) =>IA(F,v)其中ILLEGAL (v)表示变量v为非法值,C0NS_IA (F). COND (v)表示函数F的IA约 束信息中条件为真,表示与函数F的IA约束信息中V的值相悖 的情况,即变量V为非法值,如对于除法和取余运算的非法值为分母为零、平方根运算的非 法值为负数等。5、检测数组越界故障在函数F中一个数组a使用了下标V,如果对v的使用超过了 a定义时的范围,则 会导致程序内部处理错误。对该类问题的检测过程如下首先为相关变量创建数组越界状态机实例,这些相关变量包括函数内实例变量INTRA_00B (F) = {a | a G VAR (LOCAL (F)) U VAR (LREF (F))}和函数间实例变量 INTER_ 00B(F) = {a|a G VAR(C0NS_00B(F))}。对函数F内非函数调用节点N的检测描述为3a,aeINTRA_OOB(F),OUT_BOUND(a) eIN(N) => OOB{F,a)对调用函数F的节点N的检测描述为
3a, a e INTER _OOB(F),^CONS_OOB(F).VAL(a) g (FSI(F).CONS _INFO uIN(N)) a
CONS _ OOB(F).COND(a) => OOB(F,a)其中,0UT_B0UND (a)表示对数组a使用越界,C0NS_00B (F). COND (a)表示函数F的 00B约束信息中条件为真,表示与函数F的00B约束信息中a 的值相悖的情况,即对数组a使用越界。下面结合本发明具体实施例对本发明做进一步说明,以表1中的程序代码为例作 为本发明实施例中的被测源程序表1 被测源程序
1int 氺p,氺q ;
2int flag, vl ;
3f2(inta[]) {
4if (flag)
5p = new int[a[10]/\^1];
6else
7p = NULL ;
9}
10int*fl(int & v2){
11intb[10];
12f2 (b);
13vl = 1, v2 = 0 ;
14return new int [1];
15}
16int f() {
17int v2,r ;
18vl = 0, p = NULL ;
19q = fl(v2);
20if(flag)
21氺p = v2/vl ;
22if(p k)
23= vl/v2, r =;}
24return r ;
25}
采用现有软件测试工具中使用的算法对表1中的源程序进行测试,可发现如下软 件故障19行变量v2未初始化;21行变量p空指针引用;21行变量vl非法计算;23行变 量q空指针引用;23行变量p空指针引用;24行变量r未初始化。图1为本发明实施例应用跨函数分析的方法进行软件测试的流程示意图,如图1 所示,应用本发明中的函数摘要信息后再对表1进行软件测试,其过程包括如下步骤步骤101 分析项目源程序中所有函数间的调用关系,建立函数调用关系图。这里,以表1中的源程序为例,经过分析后得到几个函数间的调用关系图,所述函 数间的调用关系,如图2所示。其中,建立函数调用关系图的过程具体如下首先编译项目中的所有文件,若编译失败,则返回错误信息;若编译成功,则根据 编译后的类(class)文件,提取所有类型信息,所属类型信息包括程序中所有定义的类名 称、类中所有的成员变量及其类型、类中所有的成员方法及其返回类型;然后再顺序分析程 序中的所有函数或成员方法,若在其语法树中遇到其它函数或方法的使用,则在函数调用 图中添加相应的内容。待执行完后,再执行步骤102。步骤102 在函数调用关系图中确定当前节点,判断当前节点是否为最后一个节 点,若所述当前节点为最后一个节点,则执行步骤107 ;否则,执行步骤103。这里,所述确定当前节点具体为按照拓扑逆序取函数调用关系图中下一个节点 作为当前节点。步骤103 利用所述当前节点中的相关变量,如全局变量和参数变量等,生成约 束信息,然后执行步骤104。这里,所述生成约束信息的内容和格式随缺陷类型的不同而不同。所述约束信息 生成的具体过程如下步骤1031 提取当前节点中所有引用的全局指针变量及参数指针变量,分别对这 些变量作如下判断若存在一条从函数入口到引用指针变量内容的路径,且在引用内容前 未判断指针是否为空,则将该变量及路径信息加入到当前节点的空指针引用约束信息中, 然后执行步骤1032 ;步骤1032 当判断完所有的指针变量后,则提取当前节点中所有引用的全局指针 变量及参数指针变量,并分别对这些变量作如下判断若存在一条从函数入口到释放指针 内容的路径,且在释放内容前未判断指针是否变更,则将该变量及路径信息加入到当前节 点的内存泄露约束信息中;当判断完所有的指针变量后,执行步骤1033 ;步骤1033 提取当前节点中所有数组类型参数变量,分别对这些变量作如下判 断若存在一条从函数入口到数组下标引用的路径,则将引用下标的最大、最小值加入到当 前节点的数组越界约束信息中。当判断完所有的数组变量后,执行步骤1034 ;步骤1034 提取当前节点中所有全局变量及参数变量,分别对这些变量作如下判 断若存在一条从函数入口到引用变量内容的路径,且在引用内容前未对其赋值,则将该变 量及路径信息加入到当前节点的未初始化约束信息中。当判断完所有的变量后,执行步骤 1035 ;步骤1035 提取当前节点中所有引用的全局变量及参数变量,分别对这些变量作 如下判断若存在一条从函数入口到对该变量作算术运算的路径,且在使用其内容前未判 断其有效性,如分母不能为零、平方根不能为负等,则将该变量及路径信息加入到当前节点的非法计算约束信息中。当判断完所有的变量后,执行步骤104。所述调用关系图中的节点生成约束信息为FSI (f2) . C0NS_INF0 = { {paral
, vl [-max, -1] | [1, max] }, {flag: [-max, _1] | [1, max]}}FSI (fl) C0NS_INF0 = {}FSI (f). C0NS_INF0 = {}步骤104 读取函数调用关系图中所在节点对应的控制流图中的下一个节点作为 当前节点,若所述当前节点为最后一个节点,则执行步骤106 ;否则,执行步骤105。步骤105 应用已获得的函数后置信息,并根据当前节点所对应的语句类型对所 述节点的各变量进行区间运算,得到变量的新的区间取值,然后返回执行步骤104。这里,所述对节点的各变量进行区间运算前,需根据进入当前节点前的输入状态, 计算出经过当前节点的所有可能的输出状态,其生成过程步骤如下步骤1051 若当前节点为控制流图的入口节点,则该节点输入状态为空,输出状 态为当前节点的新增状态,则执行步骤104 ;否则执行步骤1052 ;步骤1052 若当前节点为控制流图的非分支节点或汇合节点,则该节点输入状态 为其所有前驱节点的输出状态相并,其输出状态为当前节点的输入状态减去其删减状态并 上新增状态,然后执行步骤104 ;否则执行步骤1053 ;步骤1053 若当前节点为控制流图的分支节点,则该节点输入状态为其前驱接 点的输出状态,输出状态为当前节点的输入状态与所有条件相交后的并集,然后执行步骤 104 ;否则,执行步骤1054 ;步骤1054 如果当前节点的前驱为控制流图的分支节点,则该节点输入状态为其 前驱节点的输出状态与该分支条件的交集,输出状态为当前节点的输入状态减去其删减状 态并上新增状态,然后执行步骤104 ;否则执行步骤1055 ;步骤1055 如果当前节点为控制流图的汇合节点,则该节点输入状态为其所有前 驱节点的输出状态的并集,输出状态等于其输入状态,然后执行步骤104。其中,以上步骤中,函数f的控制流图为图3、函数f2的控制流图为图4。将控制 流区间进行迭代后,得到如下运算结果f2. IN(N1) = {};f2. OUT(Nl) = {{flag: [-max, -1] | [1, max]}, {flag:
}}f2. IN(N2) = {flag: [-max, _1] | [1,max]}f2. OUT(N2) = {flag: [-max, _1] | [1,max],p:N0T_NULL,a:
,vl:UNKN0ff}f2. IN(N3) = {flag:
};f2. OUT(N3) = {flag:
, p:NULL}f2. IN(N4) = {{flag:
,p:NULL},{flag: [-max, _1] | [1,max],p:N0T_NULL, a:
,vl:UNKN0ff}}f2. OUT (N4) = {{flag:
,p:NULL},{flag: [-max,_1] | [1,max],p:N0T_NULL, a:
,vl:UNKN0ff}}fl. IN(N1) = {};fl. OUT(Nl) = {b:
}
fl. IN(N2) = {b:
};fl. OUT(N2) = {{flag:
, p:NULL, b:
}, {flag: [—max,_1] | [1,max],p:N0T_NULL, vl:UNKNOff,b:
}}fl. IN(N3) = {{flag:
, p:NULL, b:
}, {flag: [—max, _1] | [1,max],p:N0T_NULL,vl:UNKNOff, b:
}};fl. 0UT(N3) = {{flag:
, p:NULL, b:
, vl: [1,1], v2:
}, {flag: [-max, 一1][l,max],p:N0T_NULL,vl: UNKNOff, b:
, vl: [1,1], v2:
}};fl. IN(N4) = { {flag:
,p:NULL,b:
,vl : [1,1],v2:
}, {flag: [-max, 一1][l,max],p:N0T_NULL,vl: UNKNOff, b:
, vl: [1,1], v2:
}};fl. OUT(N4) = {{flag:
, p:NULL, b:
, vl: [1,1], v2:
, ret:N0T_ NULL},{flag:[-max, _1]|[1,max],p:N0T_NULL,vl:UNKNOff, b:
,vl: [1,1],v2:
, ret: N0T_NULL}};f. IN(N1) = {}f. OUT (Nl) = {v2:UNINIT, r:UNINIT}f. IN(N2) = {V2:UNINIT, r:UNINIT}f. OUT(N2) = {v2:UNINIT, r:UNINIT, vl:
, p:NULL}f. IN(N3) = {v2:UNINIT, r:UNINIT, vl:
, p:NULL}f. OUT(N3) = {{flag:
, p:NULL, vl: [1,1], v2:
, r:UNINIT, q:N0T_ NULL},{flag: [-max, _1] | [1, max], r: UNINIT, p: N0T_NULL, vl: [1,1], v2:
,q:N0T_NULL}}f. IN(N4) = {{flag:
, r:UNINIT, p:NULL, vl: [1,1], v2:
, q:N0T_ NULL},{flag:[-max, _1]|[1, max], r:UNINIT,p:N0T_NULL, vl:[1,1], v2:
,q:N0T_NULL}}f. OUT(N4) = {{flag: [-max, -1] | [1, max], r:UNINIT, p:N0T_NULL, vl: [1,1],v2:
, q:N0T_NULL},{flag:
, r:UNINIT, p:NULL, vl:[1,1], v2:
,q:N0T_NULL}}f. IN(N5) = {flag:[-max, -1] | [1,max],r:UNINIT,p:N0T_NULL,vl: [1,1], v2:
,q:N0T_NULL}f. OUT(N5) = {flag:[-max, -1] | [1, max], r:UNINIT, p:N0T_NULL, vl: [1,1], v2:
,q:N0T_NULL}f. IN(N6) = {{flag:[-max, -1] | [1, max], r:UNINIT, p:N0T_NULL, vl: [1,1], v2:
,
20
q:N0T_NULL},{flag:
,r:UNINIT, p:NULL, vl:[1,1], v2:
,q:N0T_NULL}}步骤106 结束对当前控制流图的遍历,为调用关系图中当前节点生成函数后置 信息和函数特征信息,然后返回执行步骤102。这里,将调用关系图的当前节点内所有可能对环境产生影响的变量及其发生条件 生成后置信息,所述后置信息的生成过程如下步骤1061 将当前节点可能的返回值及其相应条件加入到后置信息中,然后执行 步骤1062 ;步骤1062 将当前节点的指针型参数和引用型参数的可能区间及其相应条件加 入到后置信息中,然后再执行步骤1063 ;步骤1063 将当前节点所有调用的函数的后置信息中未被修改的部分加入到当 前节点的后置信息中;然后再执行步骤1064。所述为调用关系图中当前节点生成的函数后置信息如下FSI (f 2). P0ST_INF0 = {{flag:
, p:NULL}, {flag: [-max, -1] | [1, max], p:N0T_NULL, vl:UNKN0ff}}FSI(fl).P0ST_INF0 = {{flag:
, p:NULL, vl:[1,1], v2:
, ret:N0T_ NULL},{flag: [-max, _1] | [1,max],p:N0T_NULL,vl: [1,1], v2:
, ret :N0T_NULL}}进一步地,在所述步骤1061 1063的基础上,分析所述调用关系图的当前节点是 否为分配资源、释放资源或可抛出异常的类型,再生成函数的特征信息,其生成过程如下步骤1064:若在调用关系图中的当前节点中存在一条路径,返回由库函数或者 具有分配资源特征的函数分配的资源,或者将库函数或具有分配资源特征的函数分配的 资源赋值给全局变量,则当前节点的特征为分配资源,然后执行步骤1066 ;否则,执行步骤 1065 ;步骤1065 若在调用关系图中的当前节点的所有路径中,都存在由库函数或者 具有释放资源特征的函数来释放参数资源,或者由库函数或者具有释放资源特征的函 数来释放全局资源,则当前节点的特征为释放资源,其中,当前节点的可抛出异常包括 try-catch-finally结构内和try-catch-finally结构外等的显式及隐式抛出异常;然后 执行步骤102。所述为调用关系图中的当前节点生成函数特征信息如下FSI(f2). CHAR INFO = {[memory,p], [null, null], {}}FSI(f1). CHAR_INF0 = {[memory, ret], [null, null], {}}FSI(f). CHAR_INF0 = {[null, nullret], [null, null], {}}步骤107 按照拓扑顺序取函数调用关系图中的下一个节点作为当前节点,判断 该当前节点是否为最后一个节点,若所述当前节点为最后一个节点,则执行步骤109 ;否 则,执行步骤108。步骤108 为函数调用关系图中当前节点生成函数前置信息,然后返回执行步骤 107。这里,调用关系图当前节点入口到引用被调函数的所有路径中,所有可能对被调函数产生影响的变量及其发生条件构成被调函数的前置信息。所述生成函数前置信息的过程如下步骤1081 将当前节点中所有与被调函数的参数变量相关的变量区间及其相应 条件加入到被调函数的前置信息中,然后执行步骤1082 ;步骤1082 将当前节点的前置信息中没有被修改的部分加入到被调函数的前置 信息中,然后执行步骤107。所述为调用关系图中的节点生成前置信息如下FSI (f2). PRE_INF0 = {vl:
, p:NULL}FSI (f 1). PRE_INF0 = {vl:
, p:NULL}FSI (f). PRE_INF0 = {}当分析函数fl时,先为相关变量创建状态机实例,其中包括INTRA_00B(fl)= {b} ;INTER_00B(f2) = {paral} ;INTER_IA(f2) = {vj,然后独立分析每个状态机实例,与
普通工具检测结果对比如下 当分析函数f时,先为相关变量创建状态机实例,其中包括INTRA_UV(f) = {v2, r} ;INTRA_NPD(f) = {p,q} ;INTRA_IA(f) = {v2,vl},然后独立分析每个状态机实例,与普 通工具检测结果对比如下v2 e INTRA _UV(f),INIT(v2) e OUT(N3) ^ ^ UV(f,v2) : DEFECT (A, f,v2)r e INTRA _ UV(f), INIT(r) e IN(N9) ^ ^ UV(f, r): DEFECT{A,f,r)P e INTRA _ NPD{f), NOT _ NULL(p) e IN(N5) ^ ^NPD{f, p) : DEFECT {A J, p)p e INTRA _ NPD(f), NULL(p) e W(JV8) NPD{f, p) : DEFECT(A,f,p)q e INTRA _ NPD{f), NOT _ NULL(q) e IN(m) ^ ^NPD(J, q) : DEFECT {A, f,q)vl e INTRA _IA{f), ILLEGAL{v\) g IN(N5) -nIA(f, vl) : DEFECT {A, f,v\)v2 e INTRA_IA(f), ILLEGAL(v2) e IN(m) => IA(f,v2) : ^DEFECT{A,f,v2)步骤109 结束对当前函数调用关系图的遍历,输出程序中所有函数的摘要信息。这里,所述输出程序中所有函数的摘要信息,包括前置信息、约束信息、后置信息 以及函数特征信息等。在软件缺陷分析过程中,如果遇到函数调用时,这些函数摘要信息可 以作为被调函数的替代。运用本发明定义的函数摘要信息并结合本发明的跨函数分析方法,对一些开源软 件的源程序进行测试,其实验所测得的数据及结果如下为了便于计算,定义故障误报率的公式如下 其中,FPR(A,P)代表程序P应用软件缺陷测试系统(DTS,Defect TestingSystenOl.CK算法A)检测的故障误报率;DEFECT (F, v)表示函数F中的变量v发 生故障;五Cr(F,v)表示函数F中的变量v未发生故障;DEFECT (A,F,v)表示算法 A检测到函数F中变量v发生故障;表示算法A未检测到函数F中变量 v发生故障。定义故障增报率公式如下 其中,DER(A,B,P)代表对程序P进行测试时,软件缺陷测试系统(DTS) 2. 3 (算法 B)发现故障较DTS1.0 (算法A)发现故障的倍数;其中DEFECT (A,F,v)表示工具DTS1.0应 用算法A检测到函数F中变量V发生故障厂DEFECT(A,F,v)表示工具DTS1. 0不能检测 到函数F中变量v发生故障;DEFECT (B,F, v)表示工具DTS2. 3检测到函数F中变量v发生 故障厂DEFECT(B,F,v)表示工具DTS2. 3不能检测到函数F中变量v发生故障。实验1 以10个开源的Java程序为例,将没有应用函数摘要信息的测试软件 DTS1. 0与采用本发明方法的并应用函数摘要信息的测试软件DTS2. 3进行对比。其测试结 果对比情况如表2所示表2 :DTS1. 0和DTS2. 3的测试结果对比 从表2所示的测试结果对比情况可知,采用测试软件DTS1. 0的平均故障误报率为 61. 49%,而采用测试软件DTS2. 3的平均误报率仅为35. 53%,比前者降低了 25. 95%。另 外,使用DTS2. 3检测出的故障为DTS1. 0检测出故障的4. 811倍。实验2 仍以10个开源的Java程序为例,其中包括实验1中所用到的部分源程序。 将以上开源软件的源代码应用Klockwork公司的测试软件K8与采用本发明方法的测试软件DTS2. 3分别进行测试,所测试的结果中资源泄露类故障的测试结果对比如表3所示表3 :K8和DTS2. 3的测试结果对比 综合表3的测试结果可知,使用测试软件DTS2. 3报告的资源泄露缺陷数目平均为 采用K8的1. 682倍。以上所述,仅为本发明的较佳实施例而已,并非用于限定本发明的保护范围。
权利要求
一种应用跨函数分析的软件测试方法,其特征在于,该方法包括A、分析项目源程序中所有函数间的调用关系,建立函数调用关系图;B、在所述函数调用关系图中确定当前节点,判断当前节点是否为最后一个节点,若所述当前节点为最后一个节点,则执行步骤G;否则,执行步骤C;C、利用所述当前节点中的相关变量,生成约束信息,然后执行步骤D;D、读取所述函数调用关系图中所在节点对应的控制流图中的下一个节点作为当前节点,若所述当前节点为最后一个节点,则执行步骤F;否则,执行步骤E;E、应用已获得的函数后置信息,并根据当前节点所对应的语句类型对所述节点的各变量进行区间运算,得到变量的新的区间取值,然后返回执行步骤D;F、结束对当前控制流图的遍历,为调用关系图中当前节点生成函数后置信息和函数特征信息,然后返回执行步骤B;G、按照拓扑顺序取所述函数调用关系图中的下一个节点作为当前节点,若所述当前节点为最后一个节点,则执行步骤I;否则,执行步骤H;H、为所述函数调用关系图中当前节点生成函数前置信息,然后返回执行步骤G;I、结束对当前函数调用关系图的遍历,输出程序中所有函数的摘要信息。
2.根据权利要求1所述的方法,其特征在于,步骤A所述建立函数调用关系图的过程如下A1、编译项目源程序中的所有文件,若编译失败,则返回错误信息;若编译成功,则执行 步骤A2 ;A2、根据编译后的类class文件,提取所有类型信息,所属类型信息包括程序中所有定 义的类名称、类中所有成员变量及其类型、类中所有成员方法及其返回类型,然后执行步骤 A3 ;A3、再顺序分析程序中的所有函数或成员方法,若在其语法树中遇到其它函数或成员 方法的使用,则在函数调用图中添加相应的内容。
3.根据权利要求1所述的方法,其特征在于,步骤B所述确定函数调用关系图中的当前 节点,具体为按照拓扑逆序选取所述函数调用关系图中的下一个节点作为当前节点。
4.根据权利要求1所述的方法,其特征在于,步骤C所述利用当前节点中的相关变量生 成约束信息的过程具体为C1、提取当前节点中所有引用的全局指针变量及参数指针变量,分别对这些变量作如 下判断若存在一条从函数入口到引用指针变量内容的路径,且在引用内容前未判断指针 是否为空,则将该变量及路径信息加入到当前节点的空指针引用约束信息中,然后执行步 骤C2 ;C2、当判断完所有的指针变量后,则提取当前节点中所有引用的全局指针变量及参数 指针变量,并分别对这些变量作如下判断若存在一条从函数入口到释放指针内容的路径, 且在释放内容前未判断指针是否变更,则将该变量及路径信息加入到当前节点的内存泄露 约束信息中;然后执行步骤C3;C3、提取当前节点中所有数组类型参数变量,分别对这些变量作如下判断若存在一条 从函数入口到数组下标引用的路径,则将引用下标的最大、最小值加入到当前节点的数组越界约束信息中;执行步骤C4 ;C4、提取当前节点中所有全局变量及参数变量,分别对这些变量作如下判断若存在一 条从函数入口到引用变量内容的路径,且在引用内容前未对其赋值,则将该变量及路径信 息加入到当前节点的未初始化约束信息中;然后执行步骤C5 ;C5、提取当前节点中所有引用的全局变量及参数变量,分别对这些变量作如下判断若 存在一条从函数入口到对该变量作算术运算的路径,且在使用其内容前未判断其有效性, 则将该变量及路径信息加入到当前节点的非法计算约束信息中;其中,所述有效性判断包 括分母不能为零、平方根不能为负。
5.根据权利要求1所述的方法,其特征在于,所述步骤E进一步包括对所有节点的各 变量进行区间运算前,需根据进入当前节点前的输入状态,计算经过当前节点的所有可能 的输出状态,其过程如下E1、若当前节点为控制流图的入口节点,则该节点输入状态为空,输出状态为当前节点 的新增状态,则执行步骤D ;否则执行步骤E2 ;E2、若当前节点为控制流图的非分支节点或汇合节点,则该节点输入状态为其所有前 驱节点的输出状态相并,其输出状态为当前节点的输入状态减去其删减状态并上新增状 态,然后执行步骤D ;否则执行步骤E3 ;E3、若当前节点为控制流图的分支节点,则该节点输入状态为其前驱接点的输出状态, 输出状态为当前节点的输入状态与所有条件相交后的并集,然后执行步骤D;否则,执行步 骤E4 ;E4、如果当前节点的前驱为控制流图的分支节点,则该节点输入状态为其前驱节点的 输出状态与该分支条件的交集,输出状态为当前节点的输入状态减去其删减状态并上新增 状态,然后执行步骤D ;否则执行步骤E5 ;E5、如果当前节点为控制流图的汇合节点,则该节点输入状态为其所有前驱节点的输 出状态的并集,输出状态等于其输入状态。
6.根据权利要求1所述的方法,其特征在于,步骤F所述后置信息的生成过程为 F1、将当前节点可能的返回值及其相应条件加入到后置信息中,然后执行步骤F2 ; F2、将当前节点的指针型参数和引用型参数的可能区间及其相应条件加入到后置信息中,然后再执行步骤F3;F3、将当前节点所有调用的函数的后置信息中未被修改的部分加入到当前节点的后置 信息中。
7.根据权利要求1或6所述的方法,其特征在于,步骤F进一步包括,利用所述生成的 后置信息生成所述函数特征信息,其生成过程为F4、分析所述调用关系图的当前节点是否为分配资源、释放资源或可抛出异常的类型; 若在调用关系图中的当前节点中存在一条路径,返回由库函数或者具有分配资源特征的函 数分配的资源,或者将库函数或具有分配资源特征的函数分配的资源赋值给全局变量,则 当前节点的特征为分配资源,然后执行步骤F6 ;否则,执行步骤F5 ;F5、若在调用关系图中的当前节点的所有路径中,都存在由库函数或者具有释放资源 特征的函数来释放参数资源,或者由库函数或者具有释放资源特征的函数来释放全局资 源,则当前节点的特征为释放资源,其中,当前节点的抛出异常包括显式及隐式抛出异常。
8.根据权利要求1所述的方法,其特征在于,步骤H所述前置信息的生成过程为 HI、将当前节点中所有与被调函数的参数变量相关的变量区间及其相应条件加入到被 调函数的前置信息中,然后执行步骤H2 ;H2、将当前节点的前置信息中没有被修改的部分加入到被调函数的前置信息中。
全文摘要
本发明公开了一种应用跨函数分析的软件测试方法,解决软件静态测试中函数调用对区间精度的影响、对环境约束信息未充分利用以及由异常处理导致的控制流变更等问题。通过定义函数摘要信息及其前置信息、后置信息、约束信息和特征信息,对程序中不同类型的缺陷检测相应地规定了判定方法;而且在软件测试过程中通过收集函数摘要信息,并将其应用在控制流图的语句节点上和缺陷模式的判定过程中,在测试完成后输出被测程序中所有函数的摘要信息。通过实验证明,应用本发明方法的测试软件比现有测试软件的测试结果相比,具有更高的函数间分析准确度和更低的测试结果误报率和漏报率。
文档编号G06F11/36GK101894064SQ20091008454
公开日2010年11月24日 申请日期2009年5月21日 优先权日2009年5月21日
发明者宫云战, 杨朝红, 肖庆, 金大海, 陈俊亮 申请人:北京邮电大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1