首页 / 专利库 / 软件 / 控制流图 / 应用跨函数分析的软件测试方法

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

阅读:1025发布:2020-10-24

专利汇可以提供应用跨函数分析的软件测试方法专利检索,专利查询,专利分析的服务。并且本 发明 公开了一种应用跨函数分析的 软件 测试方法,解决软件静态测试中函数调用对区间 精度 的影响、对环境约束信息未充分利用以及由异常处理导致的控制流变更等问题。通过定义函数 摘要 信息及其前置信息、后置信息、约束信息和特征信息,对程序中不同类型的 缺陷 检测相应地规定了判定方法;而且在软件测试过程中通过收集函数摘要信息,并将其应用在 控制流图 的语句 节点 上和缺陷模式的判定过程中,在测试完成后输出被测程序中所有函数的摘要信息。通过实验证明,应用本发明方法的测试软件比现有测试软件的测试结果相比,具有更高的函数间分析准确度和更低的测试结果误报率和漏报率。,下面是应用跨函数分析的软件测试方法专利的具体信息内容。

1.一种应用跨函数分析的软件测试方法,其特征在于,该方法包括:
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所述前置信息的生成过程为:
H1、将当前节点中所有与被调函数的参数变量相关的变量区间及其相应条件加入到被调函数的前置信息中,然后执行步骤H2;
H2、将当前节点的前置信息中没有被修改的部分加入到被调函数的前置信息中。

说明书全文

技术领域

发明涉及软件自动化测试技术,尤其涉及一种应用跨函数分析的软件测试方法

背景技术

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

发明内容

有鉴于此,本发明的主要目的在于提供一种应用跨函数分析的软件测试方法,以降低软件静态测试过程中函数调用对区间计算精度的影响,提高函数间分析的准确度、降低测试结果的误报率和漏报率。
为达到上述目的,本发明的技术方案是这样实现的:
一种应用跨函数分析的软件测试方法,该方法包括:
A、分析项目源程序中所有函数间的调用关系,建立函数调用关系图;
B、在所述函数调用关系图中确定当前节点,判断当前节点是否为最后一个节点,若所述当前节点为最后一个节点,则执行步骤G;否则,执行步骤C;
C、利用所述当前节点中的相关变量,生成约束信息,然后执行步骤D;
D、读取所述函数调用关系图中所在节点对应的控制流图中的下一个节点作为当前节点,若所述当前节点为最后一个节点,则执行步骤F;否则,执行步骤E;
E、应用已获得的函数后置信息,并根据当前节点所对应的语句类型对所述节点的各变量进行区间运算,得到变量的新的区间取值,然后返回执行步骤D;
F、结束对当前控制流图的遍历,为调用关系图中当前节点生成函数后置信息和函数特征信息,然后返回执行步骤B;
G、按照拓扑顺序取所述函数调用关系图中的下一个节点作为当前节点,若所述当前节点为最后一个节点,则执行步骤I;否则,执行步骤H;
H、为所述函数调用关系图中当前节点生成函数前置信息,然后返回执行步骤G;
I、结束对当前函数调用关系图的遍历,输出程序中所有函数的摘要信息。
其中,步骤A所述建立函数调用关系图的过程如下:
A1、编译项目源程序中的所有文件,若编译失败,则返回错误信息;若编译成功,则执行步骤A2;
A2、根据编译后的类class文件,提取所有类型信息,所属类型信息包括程序中所有定义的类名称、类中所有成员变量及其类型、类中所有成员方法及其返回类型,然后执行步骤A3;
A3、再顺序分析程序中的所有函数或成员方法,若在其语法树中遇到其它函数或成员方法的使用,则在函数调用图中添加相应的内容。
步骤B所述确定函数调用关系图中的当前节点,具体为:
按照拓扑逆序选取所述函数调用关系图中的下一个节点作为当前节点。
步骤C所述利用当前节点中的相关变量生成约束信息的过程具体为:
C1、提取当前节点中所有引用的全局指针变量及参数指针变量,分别对这些变量作如下判断:若存在一条从函数入口到引用指针变量内容的路径,且在引用内容前未判断指针是否为空,则将该变量及路径信息加入到当前节点的空指针引用约束信息中,然后执行步骤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所述前置信息的生成过程为:
H1、将当前节点中所有与被调函数的参数变量相关的变量区间及其相应条件加入到被调函数的前置信息中,然后执行步骤H2;
H2、将当前节点的前置信息中没有被修改的部分加入到被调函数的前置信息中。
本发明所提供的应用跨函数分析的软件测试方法,具有以下优点:
本发明提出的跨函数分析的软件测试方法,在现有的静态测试中的区间计算和函数间分析技术的基础上,扩展函数摘要信息在基于缺陷模式的软件测试中的具体内容,完善了函数内的区间迭代技术,将函数副作用及其分支条件计算到迭代公式中,从而在缺陷判定过程中充分利用所述函数摘要信息,大幅提高了函数间分析的准确度即提高测试结果的准确性、降低了测试结果中的误报率和漏报率。
附图说明
图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)是一个四元组(POST_INFO,PRE_INFO,CONS_INFO,CHAR_INFO),其中POST_INFO表示函数F执行后对上下文的影响,PRE_INFO表示函数F执行前受上下文的影响,CONS_INFO表示函数执行前对环境的约束,CHAR_INFO是函数F的特征信息,用于在静态分析的过程中辅助缺陷状态的判断。
下面分别说明函数摘要信息中的相关内容。函数约束信息是指函数对其调用者的约束,由相关变量的取值区间和达到该取值区间的条件构成。在静态分析的过程中,当处理到调用函数F的语句时,需要参考FSI(F).CONS_INFO判断是否发生故障。对应不同类型的缺陷,函数摘要信息中的约束信息内容也有所不同,下面分别说明。
1、空指针引用(NPD)约束信息:
在函数F中存在一个外部指针p,如果没有判断是否为空就引用它的内容,则会发生空指针引用的异常。指针p的约束值以及达到其内容引用语句的条件,构成函数F中指针p的空指针引用约束信息,记做CONS_NPD(F,p)={VAL(p)=NOT_NULL,COND(p)},其中COND(p)={[c1,VAL(c1)],[c2,VAL(c2)],...,[cn,VAL(cn)]}为到达引用指针p处的条件,由一些相外部量的取值区间构成。
函数F中所有具有这种特性指针的约束信息,构成函数F的空指针引用约束信息,记做CONS_NPD(F),且有其中POINTER(v)表示变量v为指针类型,NULL_NOTSURE(v)表示无法确定指针变量v是否为空。
2、未初始化变量(UV)约束信息:
在函数F中使用一个外部变量v,如果在使用该变量前没有初始化,则会导致程序内部处理错误。变量v的约束值以及达到其内容使用语句的条件,可以构成函数F中变量v的未初始化约束信息,记做CONS_UV(F,v)={VAL(v)=INIT,COND(v)}。
函数F中所有具有这种特性的变量的约束信息,构成函数F的未初始化约束信息,记做CONS_UV(F),且有其中REF(v)表示变量v的内容被使用,DEF_NOTSURE(v)表示无法确定在使用变量v前是否对其内容定义。
3、误用指针(WUP)约束信息
在函数F中存在一个外部指针p,如果没有经过有效性判断就引用它的内容,则会发生无法预知的错误。指针p的约束值以及达到其内容引用语句的条件,可以构成函数F中指针p的错误使用指针约束信息,记做CONS_WUP(F,p)={VAL(p)=VALID,COND(p)}
函数F中所有具有这种特性的指针的约束信息,构成函数F的错误使用指针约束信息,记做CONS_WUP(F),且有其中VALID_NOTSURE(p)表示无法确定指针变量p是否有效。
4、非法计算(IA)约束信息
在函数F中存在一些可能违背操作数v约束的运算操作,如除法分母为零、平方根操作数为负数等,如果在运算前没有判断这些非法取值,则会发生非法计算异常。相关变量v的约束值以及达到其非法计算位置的条件,可以构成函数F  中变量v  的非法计算约束信息,记做CONS_IA(F,v)={VAL(v)=LEGAL,COND(v)}
函数F中所有具有这种特性的变量的约束信息,构成函数F的非法计算约束信息,记做CONS_IA(F),且有其中ARITHMETIC(v)表示变量v参与算术运算,ILLEGAL_NOTSURE(v)表示无法确定变量v在算术运算中的合法性。
5、数组越界(OOB)约束信息
在函数F的形参中使用一个数组a,如果对其使用的下标超过了定义时的范围,则会导致程序内部处理错误。数组a的约束取值范围以及达到其内容使用语句的条件,构成函数F中变量a的数组越界故束信息,记做CONS_OOB(F,a)={VAL(a)=[LOW,UP],COND(a)},其中LOW和UP分别表示函数内部使用数组a下标的最小值和最大值。
函数F中所有具有这种特性的数组的约束信息,构成函数F的数组越界约束信息,记做CONS_OOB(F),且有其中ARRAY(a)表示a为数组,BOUND_NOTSURE(a)表示无法确定数组a的有效边界。
通过前面的描述,函数摘要信息中的约束信息可表示为:FSI(F).CONS_INFO=CONS_NPD(F)∪CONS_UV(F)∪CONS_WUP(F)∪CONS_IA(F)∪。CONS_OOB(F)
在常见的缺陷检测算法中,对大多数缺陷模式需要获取控制流信息,如空指针引用故障、资源泄露故障、内存不当使用故障和变量未初始化故障等。在考虑函数副作用影响的同时,应用函数内控制流区间迭代技术,既可以计算出进入和退出节点N时的所有可能状态,又可以通过矛盾状态排除不可达路径。
如果函数F的控制流图CFG(F)的一个节点N中声明了若干局部变量V={v1,v2,...,vn},则这些变量V及其初始取值区间VAL(V)构成节点N的进入作用域变量集合,记做IS(N)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}(vi∈N)。
如果函数F的控制流图CFG(F)中的一个节点N退出了若干局部变量V={v1,v2,...,vn}的作用域,则这些变量V构成节点N的退出作用域变量集合,记做OS(N)={v1,v2,...,vn}(vi∈N)。
如果函数F的控制流图CFG(F)中的一个节点N引用了若干外部变量V={v1,v2,...,vn},则这些变量V及其取值区间VAL(V)构成节点N的本地引用集合,记做LREF(N)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}(vi∈N)。
如果函数F的控制流图CFG(F)中的一个节点N调用了若干函数,则这些函数的全局使用集合构成节点N的全局引用集合,记做
如果函数F的控制流图CFG(F)中的一个节点N修改了若干变量V={v1,v2,...,vn}的值,则这些变量V及其修改后的取值区间VAL(V)构成节点N的本地更改集合,记做LMOD(N)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}(vi∈N)
如果函数F的控制流图CFG(F)中的一个节点N调用了若干函数,则这些函数的全局更改集合构成节点N的全局更改集合,记做GMOD(N)=FNGMOD(F).
如果函数F的控制流图CFG(F)中的一个节点N的后继节点数量大于1,即SUM(NEXT(N))>1,则该节点为若干条件分支的分流节点,记做DIFF(N)。如果CFG(F)中的一个节点N的前驱节点数量大于1,即SUM(PRED(N))>1,则该节点为若干条件分支的合流节点,记做CONF(N)。
如果N′∈NEXT(N),则满足从节点N到N′的变量及其取值区间构成条件满足集合,记做CON(N,N′)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}(vi∈N)。
如果函数F的控制流图CFG(F)中的一个节点N新产生或改变了相关变量的取值区间,则这些变量V及其取值区间VAL(V)构成节点N的更新变量区间集合,记做GEN(N)={IS(N)∪LREF(N)∪GREF(N)∪LMOD(N)∪GMOD(N)}。
如果函数F的控制流图CFG(F)中的一个节点N注销或改变了相关变量的取值区间,则这些变量V构成节点N的消除变量区间集合,记做KILL(N)={OS(N)∪VAR(LMOD(N))∪VAR(GMOD(N))}。
在CFG(F)中的某个节点N执行前,相关变量V={v1,v2,...,vn}及其取值区间VAL(V)构成通过节点N前的所有可能状态集合,记做IN(N),且有

在CFG(F)中的某个节点N执行后,相关变量V={v1,v2,...,vn}及其取值区间VAL(V)构成通过节点N后的所有可能状态集合,记做OUT(N),且有

根据上式,函数F中所有节点的IN和OUT可以按照CFG(F)的拓扑有序的顺序迭代获得。
函数后置信息用来确定函数的副作用,即函数执行后对上下文的影响,包括函数及其内部嵌套调用的函数对全局变量和类成员变量的更改、指针及引用型参数的变更对其调用者的影响、以及函数的返回值对其调用者的影响。
如果函数F中使用了若干外部变量V={v1,v2,...,vn},则这些变量V及其取值区间VAL(V)构成函数F的本地引用集合,记做LREF(F)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}。
如果函数F中使用了若干外部变量V={v1,v2,...,vn},并且其中包括程序P中所有直接或间接调用F的函数F′=ANCESTORS(F)中使用的外部变量,则这些变量V及其取值区间VAL(V)构成函数F的全局引用集合,记做GREF(F),且有
GREF(F)=LREF(F),FTOP(FCG(P))LREF(F)[FPARENTS(F)GREF(F)],FTOP(FCG(P)).
根据上式可得,程序P中所有函数的GREF可以按照FCG(P)的拓扑有序的顺序迭代获得。
如果函数F中使用了若干外部变量V={v1,v2,...,vn},并且其中包括程序P中所有被函数F直接或间接调用的函数F′=DESCENDENTS(F)中使用的外部变量,则这些变量V及其取值区间VAL(V)构成函数F的全局使用集合,记做GUSE(F),且有
根据上式可得,程序P中所有函数的GUSE可以按照FCG(P)的拓扑逆序的顺序迭代获得。
如果函数F更改了若干外部变量V={v1,v2,...,vn},则这些变量V及其取值区间VAL(V)构成函数F的本地更改集合,记做LMOD(F)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}。
如果函数F中的形参列表中出现指针变量或者引用变量,这些变量及其取值区间构成函数F的可更改参数集合,记做PARA(F)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}。而函数F中所有被调函数的PARA(F’),构成函数F的参数更改集合,记做PASS(F),且有PASS(F)=FCHILDRENS(F)PARA(F).
如果函数F更改了若干外部变量v,其中包括F直接或间接调用的函数F′=DESCENDENTS(F)中更改的外部变量,则这些变量v及其取值区间VAL(v)构成函数F的全局更改集合,记做GMOD(F),且有GMOD(F)=LMOD(F)PASS(F)RET(F),FBOTTOM(FCG(P))LMOD(F)PASS(F)RET(F)[FCHILDRENS(F){GMOD(F)GREF(F)}]FBOTTOM(FCG(P)).
其中,RET(F)表示函数F的返回值取值区间,根据上式可得,程序P中所有函数的GMOD可以按照FCG(P)的拓扑逆序的顺序迭代获得。
根据以上定义,函数摘要信息中的后置信息可表示为:FSI(F).POST_INFO=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]。
在函数F的所有路径中,都对由参数param传入的资源进行释放,则该函数的特征为释放传入资源RELEASE(F)=[RES,param]。
在函数F的所有路径中,都对由全局变量global_var标记的资源进行释放,则该函数的特征为释放全局资源RELEASE(F)=[RES,global_var]。
在一个异常处理结构T中,如果在子句try结构中应用throw方法抛出异常,则这些异常称为T中子句t的显式异常,
在一个异常处理结构T中,如果在子句catch结构中应用throw方法抛出异常,则这些异常称为T中子句c的显式异常,
在一个异常处理结构T中,如果在子句finally结构中应用throw方法抛出异常,则这些异常称为T中子句f的显式异常,
在一个异常处理结构T中,如果子句try结构中在某种条件下,由特定的函数可抛出一些异常,则这些异常称为T中子句t的隐式异常,Implicit(T,t)=FtException(F).
在一个异常处理结构T中,如果子句catch结构中在某种条件下,由特定的函数可抛出一些异常,则这些异常称为T中子句c的隐式异常,Implicit(T,c)=FcException(F).
在一个异常处理结构T中,如果子句finally结构中在某种条件下,由特定的函数可抛出一些异常,则这些异常称为T中子句f的隐式异常,Implicit(T,f)=FfException(F).
一个单层异常处理结构T的显式抛出异常为

一个单层异常处理结构T的隐式抛出异常为

一个多层异常处理结构T的显式抛出异常为

一个多层异常处理结构T的隐式抛出异常为

一个函数F的非异常处理结构中,如果在语句中应用throw方法抛出异常,则这些异常称为函数F的附加显式异常,
函数F的可抛出异常为:

根据以上定义,函数摘要信息中的特征信息可表示为:FSI(F).CHAR_INFO={ALLOC(F),RELEASE(F),Exception(F)}。
函数前置信息是指函数F在被调用时受上下文的影响,主要包括其ANCESTORS(F)内所有的函数对全局变量和类成员变量的更改。
若存在函数F的一个直接调用者F`,F′∈PARANTS(F),如果在F`的入口到F的所有路径上更改了若干外部变量V={v1,v2,...,vn},则这些变量V及其取值区间VAL(V)构成函数F对函数F`的一个直接关联集合,记做LASSO(F,F′)={[v1,VAL(v1)],[v2,VAL(v2)],...,[vn,VAL(vn)]}。函数F的所有直接关联集合为
如果从程序的入口到函数F的函数调用过程中,若干外部变量V={v1,v2,...,vn}被更改,其中包括所有直接或间接调用F的函数F′=ANCESTORS(F)的直接关联集合,则这些变量v及其取值区间VAL(v)构成函数F的全局关联集合,记做GASSO(F),且有
根据上式,程序P中所有函数的GASSO可以按照FCG(P)的拓扑有序的顺序迭代获得。
根据以上定义,函数摘要信息中的前置信息可表示为:FSI(F).PRE_INFO=GASSO(F)。
以上所述为本发明所提出的函数摘要信息介绍,下面再对本发明所提出的函数摘要信息在软件静态测试过程中的应用进行解释和进一步说明:
软件缺陷的检测过程中以函数作为被分析单元,首先建立缺陷相关变量的状态机实例,然后根据状态转换规则,在CFG(F)中应用每个节点N的IN(N)和OUT(N)分析状态机实例,判断是否会达到故障状态。如在分析过程中遇到函数调用时,还需要参考函数摘要信息,应用约束信息、前置信息和特征信息来辅助进行缺陷判断。
下面给出对应不同缺陷模式的检测方法:
1、检测空指针引用故障
如果在函数F中的某条路径上存在一个为空的指针p,没有经过有效性判断就引用它的内容,则会发生空指针引用的故障。对该类问题的检测过程如下:
首先为相关变量创建空指针引用状态机实例,这些相关变量包括函数内实例变量INTRA_NPD(F)={v|POINTER(v)∧v∈VAR(LOCAL(F))∪VAR(LREF(F))}和函数间实例变量INTER_NPD(F)={v|v∈VAR(CONS_NPD(F))},其中LOCAL(F)表示F的本地变量。
对函数F内非函数调用节点N的检测描述为:

对调用函数F的节点N的检测描述为:


其中NULL(p)表示指针p为空,表示与函数F的NPD约束信息中p的值相悖的情况,即指针p为空,REF(N,p)表示节点N中对指针p内容的引用,CONS_NPD(F).COND(p)表示函数F的NPD约束信息中p所对应的条件为真。
2、检测变量未初始化故障
如果在函数F的某条路径上使用一个变量v,并且v在使用前没有初始化,则可能会导致程序内部处理错误。对该类问题的检测过程如下:
首先为相关变量创建变量未初始化状态机实例,这些相关变量包括函数内实例变量INTRA_UV(F)={v|v∈VAR(LOCAL(F))∪VAR(LREF(F))}和函数间实例变量INTER_UV(F)={v|v∈VAR(CONS_UV(F))}。
对函数F内非函数调用节点N的检测描述为:

对调用函数F的节点N的检测描述为:


其中NOT_INIT(v)表示变量v未初始化,表示与函数F的UV约束信息中v的值相悖的情况,即变量v没有初始化,CONS_UV(F).COND(v)表示函数F的UV约束信息中v所对应的条件为真。
3、检测错误使用指针故障
如果在函数F中存在一个无效的指针p,没有经过有效性判断就引用它的内容,则会发生无法预知的错误。对该类问题的检测过程如下:
首先为相关变量创建错误使用指针状态机实例,这些相关变量包括函数内实例变量INTRA_WUP(F)={p|POINTER(p)∧p∈VAR(LOCAL(F))∪VAR(LREF(F))}和函数间实例变量INTER_WUP(F)={p|p∈VAR(CONS_WUP(F))}。
对函数F内非函数调用节点N的检测描述为:

对调用函数F的节点N的检测描述为:


其中INVALID(p)表示p为无效指针,CONS_WUP(F).COND(p)表示函数F的WUP约束信息中条件为真,表示与函数F的WUP约束信息中p的值相悖的情况,即p是一个无效的指针,它的无效性有多种情况,例如指针被释放后指向的空间、指向的空间被释放、指针经过算术运算后要释放、指向无效的栈空间等等。
4、检测非法计算故障
在函数F中存在一些违背操作数v约束的运算操作,如除法分母为零、平方根操作数为负数等,如果在运算前没有判断这些非法取值,则会发生非法计算异常。对该类问题的检测过程如下:
首先为相关变量创建变量未初始化状态机实例,这些相关变量包括函数内实例变量INTRA_IA(F)={v|v∈VAR(LOCAL(F))∪VAR(LREF(F))}和函数间实例变量INTER_IA(F)={v|v∈VAR(CONS_IA(F))}。
对函数F内非函数调用节点N的检测描述为:

对调用函数F的节点N的检测描述为:


其中ILLEGAL(v)表示变量v为非法值,CONS_IA(F).COND(v)表示函数F的IA约束信息中条件为真,表示与函数F的IA约束信息中v的值相悖的情况,即变量v为非法值,如对于除法和取余运算的非法值为分母为零、平方根运算的非法值为负数等。
5、检测数组越界故障
在函数F中一个数组a使用了下标v,如果对v的使用超过了a定义时的范围,则会导致程序内部处理错误。对该类问题的检测过程如下:
首先为相关变量创建数组越界状态机实例,这些相关变量包括函数内实例变量INTRA_OOB(F)={a|a∈VAR(LOCAL(F))∪VAR(LREF(F))}和函数间实例变量INTER_OOB(F)={a|a∈VAR(CONS_OOB(F))}。
对函数F内非函数调用节点N的检测描述为:
a,aINTRA_OOB(F),OUT_BOUND(a)IN(N)OOB(F,a)
对调用函数F的节点N的检测描述为:


其中,OUT_BOUND(a)表示对数组a使用越界,CONS_OOB(F).COND(a)表示函数F的OOB约束信息中条件为真,表示与函数F的OOB约束信息中a的值相悖的情况,即对数组a使用越界。
下面结合本发明具体实施例对本发明做进一步说明,以表1中的程序代码为例作为本发明实施例中的被测源程序:
表1:被测源程序
1:int  *p,*q;
2:int flag,v1;
3:f2(inta[]){
4:        if(flag)
5:                p=new int[a[10]/v1];
6:        else
7:                p=NULL;
9:    }
10:  int*f1(int & v2){
11:          intb[10];
12:          f2(b);
13:          v1=1,v2=0;
14:          return new int[1];
15:    }
16:    int f(){
17:          int v2,r;
18:          v1=0,p=NULL;
19:          q=f1(v2);
20:          if(flag)
21:                  *p=v2/v1;
22:          if(p||q)
23:                  {*p=v1/v2,r=*q;}
24:          return r;
25:    }
采用现有软件测试工具中使用的算法对表1中的源程序进行测试,可发现如下软件故障:19行变量v2未初始化;21行变量p空指针引用;21行变量v1非法计算;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).CONS_INFO={{para1:[0,10],v1:[-max,-1]|[1,max]},{flag:[-max,-1]|[1,max]}}
FSI(f1).CONS_INFO={}
FSI(f).CONS_INFO={}
步骤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(N1)={{flag:[-max,-1]|[1,max]},{flag:[0,0]}}
f2.IN(N2)={flag:[-max,-1]|[1,max]}
f2.OUT(N2)={flag:[-max,-1]|[1,max],p:NOT_NULL,a:[0,10],v1:UNKNOW}
f2.IN(N3)={flag:[0,0]};
f2.OUT(N3)={flag:[0,0],p:NULL}
f2.IN(N4)={{flag:[0,0],p:NULL},{flag:[-max,-1]|[1,max],p:NOT_NULL,a:[0,10],v1:UNKNOW}}
f2.OUT(N4)={{flag:[0,0],p:NULL},{flag:[-max,-1]|[1,max],p:NOT_NULL,a:[0,10],v1:UNKNOW}}
f1.IN(N1)={};
f1.OUT(N1)={b:[0,9]}
f1.IN(N2)={b:[0,9]};
f1.OUT(N2)={{flag:[0,0],p:NULL,b:[0,9]},{flag:[-max,-1]|[1,max],
p:NOT_NULL,v1:UNKNOW,b:[0,9]}}
f1.IN(N3)={{flag:[0,0],p:NULL,b:[0,9]},{flag:[-max,-1]|[1,max],
p:NOT_NULL,v1:UNKNOW,b:[0,9]}};
f1.OUT(N3)={{flag:[0,0],p:NULL,b:[0,9],v1:[1,1],v2:[0,0]},{flag:[-max,-1]|
[1,max],p:NOT_NULL,v1:UNKNOW,b:[0,9],v1:[1,1],v2:[0,0]}};
f1.IN(N4)={{flag:[0,0],p:NULL,b:[0,9],v1:[1,1],v2:[0,0]},{flag:[-max,-1]|
[1,max],p:NOT_NULL,v1:UNKNOW,b:[0,9],v1:[1,1],v2:[0,0]}};
f1.OUT(N4)={{flag:[0,0],p:NULL,b:[0,9],v1:[1,1],v2:[0,0],ret:NOT_NULL},
{flag:[-max,-1]|[1,max],p:NOT_NULL,v1:UNKNOW,b:[0,9],v1:[1,1],
v2:[0,0],ret:NOT_NULL}};
f.IN(N1)={}
f.OUT(N1)={v2:UNINIT,r:UNINIT}
f.IN(N2)={V2:UNINIT,r:UNINIT}
f.OUT(N2)={v2:UNINIT,r:UNINIT,v1:[0,0],p:NULL}
f.IN(N3)={v2:UNINIT,r:UNINIT,v1:[0,0],p:NULL}
f.OUT(N3)={{flag:[0,0],p:NULL,v1:[1,1],v2:[0,0],r:UNINIT,q:NOT_NULL},
{flag:[-max,-1]|[1,max],r:UNINIT,p:NOT_NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL}}
f.IN(N4)={{flag:[0,0],r:UNINIT,p:NULL,v1:[1,1],v2:[0,0],q:NOT_NULL},
{flag:[-max,-1]|[1,max],r:UNINIT,p:NOT_NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL}}
f.OUT(N4)={{flag:[-max,-1]|[1,max],r:UNINIT,p:NOT_NULL,v1:[1,1],
v2:[0,0],q:NOT_NULL},{flag:[0,0],r:UNINIT,p:NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL}}
f.IN(N5)={flag:[-max,-1]|[1,max],r:UNINIT,p:NOT_NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL}
f.OUT(N5)={flag:[-max,-1]|[1,max],r:UNINIT,p:NOT_NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL}
f.IN(N6)={{flag:[-max,-1]|[1,max],r:UNINIT,p:NOT_NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL},{flag:[0,0],r:UNINIT,p:NULL,v1:[1,1],v2:[0,0],
q:NOT_NULL}}
步骤106:结束对当前控制流图的遍历,为调用关系图中当前节点生成函数后置信息和函数特征信息,然后返回执行步骤102。
这里,将调用关系图的当前节点内所有可能对环境产生影响的变量及其发生条件生成后置信息,所述后置信息的生成过程如下:
步骤1061:将当前节点可能的返回值及其相应条件加入到后置信息中,然后执行步骤1062;
步骤1062:将当前节点的指针型参数和引用型参数的可能区间及其相应条件加入到后置信息中,然后再执行步骤1063;
步骤1063:将当前节点所有调用的函数的后置信息中未被修改的部分加入到当前节点的后置信息中;然后再执行步骤1064。
所述为调用关系图中当前节点生成的函数后置信息如下:
FSI(f2).POST_INFO={{flag:[0,0],p:NULL},{flag:[-max,-1]|[1,max],p:NOT_NULL,v1:UNKNOW}}
FSI(f1).POST_INFO={{flag:[0,0],p:NULL,v1:[1,1],v2:[0,0],ret:NOT_NULL},
{flag:[-max,-1]|[1,max],p:NOT_NULL,v1:[1,1],v2:[0,0],ret:NOT_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_INFO={[memory,ret],[null,null],{}}
FSI(f).CHAR_INFO={[null,nullret],[null,null],{}}
步骤107:按照拓扑顺序取函数调用关系图中的下一个节点作为当前节点,判断该当前节点是否为最后一个节点,若所述当前节点为最后一个节点,则执行步骤109;否则,执行步骤108。
步骤108:为函数调用关系图中当前节点生成函数前置信息,然后返回执行步骤107。
这里,调用关系图当前节点入口到引用被调函数的所有路径中,所有可能对被调函数产生影响的变量及其发生条件构成被调函数的前置信息。
所述生成函数前置信息的过程如下:
步骤1081:将当前节点中所有与被调函数的参数变量相关的变量区间及其相应条件加入到被调函数的前置信息中,然后执行步骤1082;
步骤1082:将当前节点的前置信息中没有被修改的部分加入到被调函数的前置信息中,然后执行步骤107。
所述为调用关系图中的节点生成前置信息如下:
FSI(f2).PRE_INFO={v1:[0,0],p:NULL}
FSI(f1).PRE_INFO={v1:[0,0],p:NULL}
FSI(f).PRE_INFO={}
当分析函数f1时,先为相关变量创建状态机实例,其中包括INTRA_OOB(f1)={b};INTER_OOB(f2)={para1};INTER_IA(f2)={v1},然后独立分析每个状态机实例,与普通工具检测结果对比如下:


OUT_BOUND(b)IN(N)OOB(f1,b) :DEFECT(A,f1,b)
当分析函数f时,先为相关变量创建状态机实例,其中包括INTRA_UV(f)={v2,r};INTRA_NPD(f)={p,q};INTRA_IA(f)={v2,v1},然后独立分析每个状态机实例,与普通工具检测结果对比如下:
v2INTRA_UV(f),INIT(v2)OUT(N3)UV(f,v2):DEFECT(A,f,v2)
rINTRA_UV(f),INIT(r)IN(N9)UV(f,r):DEFECT(A,f,r)
pINTRA_NPD(f),NOT_NULL(p)IN(N5)NPD(f,p):DEFECT(A,f,p)
pINTRA_NPD(f),NULL(p)IN(N8)NPD(f,p):DEFECT(A,f,p)
qINTRA_NPD(f),NOT_NULL(q)IN(N8)NPD(f,q):DEFECT(A,f,q)
v1INTRA_IA(f),ILLEGAL(v1)IN(N5)IA(f,v1):DEFECT(A,f,v1)
v2INTRA_IA(f),ILLEGAL(v2)IN(N8)IA(f,v2):DEFECT(A,f,v2)
步骤109:结束对当前函数调用关系图的遍历,输出程序中所有函数的摘要信息。
这里,所述输出程序中所有函数的摘要信息,包括前置信息、约束信息、后置信息以及函数特征信息等。在软件缺陷分析过程中,如果遇到函数调用时,这些函数摘要信息可以作为被调函数的替代。
运用本发明定义的函数摘要信息并结合本发明的跨函数分析方法,对一些开源软件的源程序进行测试,其实验所测得的数据及结果如下:
为了便于计算,定义故障误报率的公式如下:

其中,FPR(A,P)代表程序P应用软件缺陷测试系统(DTS,Defect TestingSystem)1.0(算法A)检测的故障误报率;DEFECT(F,v)表示函数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发生故障;表示工具DTS1.0不能检测到函数F中变量v发生故障;DEFECT(B,F,v)表示工具DTS2.3检测到函数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倍。
以上所述,仅为本发明的较佳实施例而已,并非用于限定本发明的保护范围。
高效检索全球专利

专利汇是专利免费检索,专利查询,专利分析-国家发明专利查询检索分析平台,是提供专利分析,专利查询,专利检索等数据服务功能的知识产权数据服务商。

我们的产品包含105个国家的1.26亿组数据,免费查、免费专利分析。

申请试用

分析报告

专利汇分析报告产品可以对行业情报数据进行梳理分析,涉及维度包括行业专利基本状况分析、地域分析、技术分析、发明人分析、申请人分析、专利权人分析、失效分析、核心专利分析、法律分析、研发重点分析、企业专利处境分析、技术处境分析、专利寿命分析、企业定位分析、引证分析等超过60个分析角度,系统通过AI智能系统对图表进行解读,只需1分钟,一键生成行业专利分析报告。

申请试用

QQ群二维码
意见反馈