专利名称:基于模块分解技术的软件缺陷检测系统的复杂性分析方法
技术领域:
本发明涉及软件测试技术,尤其涉及一种基于模块分解技术的软件缺陷检测系统(DTS,Defect Testing System)的复杂性分析方法,以发现该缺陷检测系统的性能瓶颈, 对提高缺陷检测效率及并发执行多个测试任务提供理论依据。
背景技术:
静态的程序分析技术通过对源代码进行分析,毋须动态执行程序即可得到程序的语义信息。完备的程序分析技术通过对程序语义的抽象(over-approximation),可以应用于缺陷查找、类型检查、编译优化等的过程。但对程序语义的抽象带来的负面影响则是增大了计算量,导致分析效率下降。基于区间运算的缺陷检测系统是抽象解释理论的一种典型应用,它通过将源程序构建为语法树(AST),然后访问AST节点生成符号表信息,从而得到变量及函数的作用域、 类型信息。进一步地,再通过遍历函数控制流图,对每个控制流节点进行数据流迭代,得到每个函数的抽象取值信息(以离散的区间域来表示);根据此抽象取值信息可以进行缺陷状态机迭代,如果有错误(error)状态发生,则表示程序中存在某种类型的缺陷。通过上述对静态缺陷检测系统的功能描述不难发现,其中的某些步骤复杂度较高,有可以成为影响软件性能的瓶颈;而某些步骤与上下文分析环境(Context)依赖性不大的,则可通过采用改进的分析技术来提高分析效率。
发明内容
有鉴于此,本发明的主要目的在于提供一种基于模块分解技术的软件缺陷检测系统的复杂性分析方法,通过对每个分析子模块的内部分析单元的复杂性进行分析,统计得出DTS的复杂性分布情况,克服现有复杂性分析评估方法不够系统全面、对影响系统复杂性的关键技术分析不足等缺点,以检出和解决DTS性能瓶颈以及优化分布式(并行化)缺陷检测任务。为达到上述目的,本发明的技术方案是这样实现的
一种基于模块分解技术的软件缺陷检测系统的复杂性分析方法,该分析方法包括
A、根据所述缺陷检测系统DTS缺陷检测原理,将该分析方法的流程包括由前端输入预处理模块完成的前端输入预处理步骤、由预分析模块完成预分析的步骤、由正式分析模块完成正式分析的步骤;
B、对所述的前端输入预处理模块、预分析模块和正式分析模块的内部所有分析单元, 按其调用顺序及依赖关系依次分析其复杂度,得到每个分析单元复杂性分布的性质和规律;
C、根据步骤B的分析结果,统计得出整个DTS系统的复杂性分布情况。其中,将步骤B所述前端输入预处理模块、预分析模块和正式分析模块分别进一步分为将所述前端输入预处理模块分为载入缺陷状态机单元、源文件收集单元和程序转换单元;
将所述预分析模块分为全局函数调用关系生成单元和文件分析次序解析单元;以及将正式分析模块分为线程分析单元和缺陷检测结果输出单元。其中,步骤C所述得出整个DTS系统的复杂性分布情况的过程,包括对前端预输入处理模块的分析单元进行复杂度分析,具体如下
Cl、将待测试的程序源文件载入缺陷状态机单元,根据预先配置的待扫描缺陷状态机类型,读入对应的状态机描述XML文件;复杂度取决于待扫描缺陷状态机种类数 Num (fsm);
C2、收集待进行缺陷检测的源文件,如果以工程为单位进行检测,则根据工程配置文件搜索待分析源文件;否则,直接搜索待扫描目录,收集所有待检测源文件;复杂度取决于待分析源文件数量Num(srcFiles);
C3、根据待测源文件的类型执行程序转换,具体为通过程序转换单元,根据待检测源文件类型,调用相应的编译器进行预处理,得到预处理后的中间文件,作为后续分析的输入;
如果是JAVA语言,需要调用JVM将源文件(.Java)编译为字节码文件(.class);其复杂度取决于JVM的编译器效率;
如果是C或CPP语言,需要调用相应的编译器(gcc,cl)将源文件(.c,.cpp)预处理为中间文件(.i);其复杂度取决于编译器的效率;
最后,将该类不可控分析单元的复杂度标记为0(⑴)。步骤C所述得出整个DTS系统的复杂性分布情况的过程,对预分析模块的分析单元进行复杂度分析,具体如下
C4、通过全局函数调用关系生成单元,首先进行预分析,生成全局函数调用关系,然后按字母顺序遍历所有源文件,查找所有需要分析的函数并建立全局函数表,保存函数间调用关系;同时,还能够根据需要生成库函数摘要;
C5、利用文件分析次序解析单元,根据所述全局函数表及调用关系,对文件调用关系进行拓扑排序,最终的文件分析次序为拓扑排序的逆序;该分析单元的复杂度取决于全局函数表中的函数个数Num(Proc)及每个函数调用其他函数的平均次数NumQ^ocCall),得出该分析单元的复杂度Num(Proc) *Num(ProcCal 1)。步骤C所述得出整个DTS系统的复杂性分布情况的过程,对正式分析模块的分析单元进行复杂度分析,具体如下
C6、利用线程分析单元,根据上述步骤C5中得到的文件分析次序,为每个文件依次生成分析线程,同时检测线程执行过程中是否出现异常以便及时结束线程;
C7、通过缺陷检测结果输出单元,将所述步骤C6的输出检测结果写入数据库中;其复杂度取决于待分析文件数Num(srCFiles)及每个文件的平均缺陷数Num(IP),复杂度依赖于 Num(srcFiles) *Num(IP)。根据全局函数调用关系生成单元的原理,将所述步骤C4分为五个子分析单元,然后对每个子单元的复杂度分析,具体包括
C41、语法树生成包括词法分析及语法分析两个阶段词法分析复杂度取决于源文件的平均行数NunKsrcFileLines),语法分析的复杂度取决于源文件的语法复杂程度,均为不可控的;其语法树生成单元的复杂度为NunKsrcFileLines);
C42、作用域和声明分析单元为单个文件生成SourceFil必cope, ClassScope, MethodScope及LocalScope作用域层次关系,及每个作用域下的变量声明集合 VariableNamesDeclarations 禾口函数声明集合 MethodNameDeclarations,并且为每个变量及函数创建类型信息;其复杂度主要依赖于语法树中相关节点的数量,若其与文件行数成正比,则本分析单元复杂度为Num(srcFiIeLines);
C43、表达式类型分析单元为程序中的各种表达式生成类型信息,为后续的区间分析及缺陷模式计算提供类型支持;本分析单元的复杂度也依赖于语法树中相关节点的数量,若其与文件行数成正比,则本分析单元复杂度为NunKsrcFileLines);
C44、标志符出现分析单元将所有标识符的出现与其正确的声明相关联,并且将这种关联关系添加到具体的作用域中,以方便后续的文件内函数调用关系生成;标识符的出现分为变量使用和函数调用,本分析单元的复杂度取决于程序中变量和函数的声明及使用数量 Num(Var)+Num(Proc);
C45、函数调用关系分析单元遍历程序中所有函数定义节点 (ASTFimctionDefinition),查找该函数作用域中的所有函数调用,为当前函数定义节点生成“一对多”的调用关系,随着遍历的进行生成函数调用关系图;本分析单元复杂度主要依赖于每个文件中函数平均个数Num(ftx)C),及每个函数调用其他函数的平均个数 Num(ProcCall),其复杂度为 Num(Proc) * Num(ProcCall);
所述的全局函数调用关系生成单元,其复杂度为Num(srcFiles)* (Num(srcFileLines) + Num(Var) + Num(Proc))。 根据线程分析单元的检测原理,将所述步骤C6进一步分为十个子分析单元,对每个子单元的复杂度分析步骤为
C61 C64、其复杂度分析过程与C41 C44的类似;
C65、利用控制流图生成单元遍历语法树相关节点,分别生成控制流图节点和边; 所述控制流图中节点与边的数量为等数量级的,且节点数主要取决于源代码行数;本分析单元的复杂度主要依赖于语法树中相关节点的数量及程序代码行数,复杂度为 Num (srcFiIeLines);
C66、定义使用分析单元为变量的声明及使用位置生成关联关系,能够为相关模式提供数据依赖分析的支持;首先根据步骤C62 C64的分析结果,按作用域层次关系依次初始化每个变量出现的定义或使用信息,并将此初始化定义使用信息绑定到对应的控制流节点, 然后基于步骤C65生成的控制流图,进行流敏感的定义使用信息迭代;定义使用信息迭代的复杂度取决于控制流节点数及每次迭代的复杂度,迭代复杂度取决于每个控制流节点上变量出现的个数(与程序中变量总数成正比);本分析单元的复杂度为NunKsrcFileLines)* Num(Var);
C67、文件内函数调用关系生成单元的分析原理与步骤C66类似,也是通过作用域层次关系得到文件内的函数调用关系,并创建函数调用关系图;其复杂度取决于Num(Proc);
C68、解析函数分析次序单元与步骤C45类似;其复杂度取决于函数及函数调用的个数 Num (Proc);C69、区间分析单元以函数为单位(Num(Proc)),依次遍历控制流图进行数据流方程迭代在控制流入口节点将所有外部区间信息初始化,后续节点首先对前驱节点的数据流信息进行继承或汇聚,然后根据当前节点关联语法树节点的类型进行区间运算;若平均每个函数的控制流节点数为Num(VexNode),每个节点区间运算的复杂度为O (IntervalAnalysis),则对单个函数进行区间分析的复杂度为O(Num(VexNode)* IntervalAnalysis);在控制流出口节点,根据配置是否进行函数间分析,为当前函数计算其函数摘要,包括后置条件与前置约束,后置条件需要计算所有return语句的区间信息并取并集,其复杂度决定于Num(VexNode),前置条件需要查询AST上某种类型的节点,复杂度与Num(ASTNode)有关;得到该区间分析单元的总复杂度为=Num(Proc) * (Num(srcFiIeLines)* IntervalAnalysis);
C70、缺陷自动机分析单元根据步骤A载入的状态机类型,根据每种类型状态机的创建条件生成状态机实例集合如果是非流敏感的状态机实例,则直接在语法树上进行状态迭代,检测该类型的缺陷;将所有流敏感的状态机实例集合置于函数控制流入口节点处, 然后根据控制流顺序对每个状态机实例的缺陷状态进行状态条件更新,如果发生状态迁移且为error状态则上报一个相应类型的缺陷,否则状态自动迁移到end状态表示自动机将自动销毁;如果为路径敏感的缺陷状态迭代方法,则状态条件需要重新通过区间运算计算生成(OantervalAnalysis));每个函数创建的状态机实例数为Num(FSiOnstances), 每个控制流节点关联的缺陷状态实例数为与其成正比,每个状态条件迁移与否的计算量为O (FSMTransition),则路径敏感的缺陷自动机分析复杂度为Num (Proc) * (Num(FSMInstances) * O(FSMTransition) * O(IntervalAnalysis) )) ; 陷自动机分析复杂度为 Num(Proc) * (Num(FSMInstances) * O(FSMTransition))); 得到所述正式分析模块的复杂度为Num(srcFiles) * (Num(srcFiIeLines) * Num(Var) +Num(Proc)*Num(srcFiIeLines)(IntervalAnalysis)0所述的缺陷检测系统的总复杂度为Num(fsm) +Num(srcFiles) * (Num(srcFiles) * (Num(srcFileLines)氺Num(Var)+Num(Proc)*Num(srcFileLines))。所述的缺陷检测系统具有多项式复杂度,影响其分析效率的因子,主要包括 Num(fsm), O(IntervalAnalysis)和O (FSMTransition),且部分影响因子是待测程序的复杂度,如 Num(Proc),Num(ProcCall), Num(Var)决定的。所述缺陷检测系统中的各模块及分析单元的复杂性较高且可并发执行;将每个文件的语法树、符号表等信息进行缓存,当后续分析需要时直接获取,能够进一步降低该分析过程的复杂度。本发明所提供的基于模块分解技术的软件缺陷检测系统的复杂性分析方法,具有以下优点
采用该分析方法,通过对静态缺陷检测系统进行模块分解,并对每个模块及其子分析单元进行全面、系统的复杂度分析,尤其对影响DTS复杂性的关键技术如数据流迭代框架、 区间运算、缺陷状态自动机迭代进行了分析,分析得出的复杂度较高的单元意味着系统性能瓶颈,并对分析算法中无依赖关系的模块可以通过并行分析技术进行优化。克服了现有复杂性分析评估方法不够系统全面、对影响系统复杂性的关键技术分析不足等缺点,还为发现并解决DTS性能瓶颈、优化分布式(并行化)缺陷检测任务提供了可行的技术路线。
图1为本发明基于模块分解技术的软件缺陷检测系统的复杂性分析流程及模块分解过程示意图2为本发明所述全局函数调用关系生成单元的子分析单元执行分解过程示意图; 图3为本发明所述线程分析单元的子分析单元分解过程示意图。
具体实施例方式下面结合附图及本发明的实施例对本发明的软件缺陷检测系统的复杂性分析方法作进一步详细的说明。本发明基于模块分解技术的缺陷检测系统(DTS)的复杂性分析方法,包括 步骤一,根据软件DTS的缺陷检测原理,可将其分析流程利用抽象为逻辑上彼此独
立的三个模块(Module)(即前端输入预处理模块(Input Preprocessor )、预分析模块 (Pre-Analysis)和正式分析模块(Formal Analysis))来完成,即由前端输入预处理模块 (Input Pr印rocessor)完成前端输入预处理步骤、由预分析模块(Pre-Analysis)完成预分析的步骤、由正式分析模块(Formal Analysis)完成正式分析的步骤。步骤二,对所述的每个模块的内部所有分析单元(Unit)的调用顺序及依赖关系依次分析其复杂度,得到每个分析单元复杂性分布的性质和规律。步骤三,根据上述步骤二的分析结果,进一步统计得出整个缺陷检测系统的复杂性分布情况。将所述各模块进一步分为如下分析单元(Unit),具体如下
将所述输入预处理模块分为载入缺陷状态机单元、源文件收集单元和程序转换单
元;
将所述预分析模块分为全局函数调用关系生成单元和文件分析次序解析单元; 将所述正式分析模块分为线程分析单元和缺陷检测结果输出单元。图1为本发明基于模块分解技术的软件缺陷检测系统的复杂性分析流程及模块分解过程示意1、对前端预输入处理模块的分析单元进行复杂度分析,具体包括 步骤11、将待测试的程序源文件载入缺陷状态机单元,根据预先配置的待扫描缺陷状态机类型,读入对应的状态机描述XML文件;复杂度取决于待扫描缺陷状态机种类数 Num (fsm);
步骤12、收集待进行缺陷检测的源文件,如果以工程为单位进行检测,则根据工程配置文件搜索待分析源文件;否则,直接搜索待扫描目录,收集所有待检测源文件;复杂度取决于待分析源文件数量Num(srcFiIes);
步骤13、根据待测源文件的类型执行程序转换,具体为
通过程序转换单元,根据待检测源文件类型,调用相应的编译器进行预处理,得到预处理后的中间文件,作为后续分析的输入;如果是JAVA语言,需要调用JVM (Java虚拟机)将源文件(.java)编译为字节码文件(.class);其复杂度取决于JVM的编译器效率。如果是 C或CPP语言,需要调用相应的编译器(gcc,cl)将源文件(.c,.cpp)预处理为中间文件(.i),其复杂度取决于编译器的效率。因此,本分析单元的复杂度是不可控的,本发明中将此类不可控分析单元的复杂度标记为0(⑴),并且此类复杂度不计入最终的复杂度统计结
果ο2、对预分析模块的分析单元进行复杂度分析的过程,包括步骤14 步骤15 具体如下
步骤14、通过全局函数调用关系生成单元,首先进行预分析,生成全局函数调用关系, 然后按字母顺序遍历所有源文件,查找所有需要分析的函数(用户自定义函数)并建立全局函数表,保存函数间调用关系。同时,还可根据需要生成库函数摘要。步骤15、利用文件分析次序解析单元,根据所述全局函数表及调用关系,对文件调用关系进行拓扑排序,最终的文件分析次序为拓扑排序的逆序;该分析单元的复杂度取决于全局函数表中的函数个数Num(Proc)及每个函数调用其他函数的平均次数 Num(ProcCall),因此本分析单元的复杂度取决于二者之积Num(Proc) *Num(ProcCall)。3、对正式分析模块的分析单元进行复杂度分析的过程,包括步骤16 步骤17 具体如下
步骤16、利用线程分析单元,根据上述步骤15中得到的文件分析次序,为每个文件依次生成分析线程,同时监测线程执行过程中是否出现异常(如分析超时,内存溢出等)以便及时结束线程。步骤17、最后,再通过缺陷检测结果输出单元,将所述步骤16的输出检测结果,并将其写入数据库中。其复杂度取决于待分析文件数NunKsrcFiles)及每个文件的平均缺陷数 Num(IP),因此复杂度依赖于 Num(srcFiles)*Num(IP)。图2为本发明所述全局函数调用关系生成单元(预分析模块)的子分析单元执行分解过程示意图,如图2所示,步骤14中5个子分析单元的每个子单元的复杂度分析过程,包括
步骤141、语法树生成包括词法分析及语法分析两个阶段词法分析的复杂度取决于源文件的平均行数NunKsrcFileLines),语法分析的复杂度取决于源文件的语法复杂程度, 均为不可控的。因此,其语法树生成单元的复杂度为NunKsrcFileLines)。步骤142、作用域和声明分析单元为单个文件生成SourceFil必cope, ClassScope, MethodScope及LocalScope作用域层次关系,及每个作用域下的变量声明集合 VariableNamesDeclarations 禾口函数声明(定义)集合 MethodNameDeclarations,并且为每个变量及函数创建类型信息。由于本步骤所生成的信息是遍历语法树的相关节点(变量声明为ASTDeclaraion节点,函数声明为ASTFunctionDeclaration节点)得到的,因此复杂性主要依赖于语法树中相关节点的数量。假定其与文件行数成正比,则本分析单元复杂度为 Num(srcFiIeLines)。步骤143、表达式类型分析单元为程序中的各种表达式生成类型信息,为后续的区间分析(生成该表达式运算后的区间类型)及缺陷模式计算(确定某表达式的类型是否允许某种操作,如移位,与O比较等)提供类型支持。与步骤142类似,本分析单元的复杂度也依赖于语法树中相关节点的数量,因此复杂度为NunKsrcFileLines)。步骤144、标志符出现分析单元将所有标识符的出现与其正确的声明相关联,并且将这种关联关系添加到具体的作用域中,以方便后续的文件内函数调用关系生成;标识符的出现分为变量使用和函数调用,因此本分析单元的复杂度取决于程序中变量和函数的声明及使用数量 Num (Var) +Num (Proc)。步骤145、函数调用关系分析单元遍历程序中所有函数定义节点 (ASTFimctionDefinition),查找该函数作用域中的所有函数调用(出现),为当前函数定义节点生成“一对多”的调用关系,随着遍历的进行便生成了函数调用关系图。该分析单元的复杂度主要依赖于每个文件中函数平均个数Num(ftx)C),及每个函数调用其他函数的平均个数 Num(ProcCall),因此复杂度为 Num(Proc) * Num(ProcCall)。故,步骤14中所述的全局函数调用关系生成单元其复杂度为Num(SrcFileS)* (Num(srcFileLines)+ Num(Var) + Num(Proc))。图3为本发明所述线程分析单元(正式分析模块)的子分析单元分解过程示意图, 根据线程分析单元的检测原理,该线程分析单元(正式分析模块)又分为10个子分析单元, 每个子单元的复杂度分析过程,分别为
步骤16广步骤164的复杂度分析与步骤14中步骤141 步骤144子分析单元的分析方法类似,这里不再赘述。步骤165、利用控制流图生成单元遍历语法树相关节点,分别生成控制流图节点和边;控制流图中节点与边的数量是等数量级的(边e与节点η的关系为e=n-l),且节点数主要取决于源代码行数(除while,if, try-catch外,其他语句基本上与节点为1:1关系)。 因此本分析单元的复杂度主要依赖于语法树中相关节点的数量及程序代码行数(仍然假设二者是正比关系),则复杂度为NunKsrcFileLines)。步骤166、定义使用分析单元为变量的声明及使用位置生成关联关系,可以为相关模式提供数据依赖分析的支持(如变量使用前有多次定义的缺陷模式);首先根据步骤 162 步骤164的分析结果,按作用域层次关系依次初始化每个变量出现的定义或使用信息,并将此初始化定义使用信息绑定到对应的控制流节点,然后基于步骤165生成的控制流图,进行流敏感的定义使用信息迭代;定义使用信息迭代的复杂度取决于控制流节点数及每次迭代的复杂度,迭代复杂度取决于每个控制流节点上变量出现的个数(与程序中变量总数成正比),因此本分析单元的复杂度为Num(srcFiIeLines)* Num(Var)。步骤167、文件内函数调用关系生成单元的分析原理与步骤166类似,也是通过作用域层次关系得到文件内的函数调用关系,并创建函数调用关系图,因此复杂度取决于 Num(Proc)。步骤168、解析函数分析次序单元与步骤145类似,复杂度取决于函数及函数调用的个数 Num (Proc)。步骤169、区间分析单元以函数为单位(Num(Proc)),依次遍历控制流图进行数据流方程迭代在控制流入口节点将所有外部区间信息初始化(参数,全局变量),后续节点首先对前驱节点的数据流信息进行继承(顺序节点)或汇聚(分支合并节点),然后根据当前节点关联语法树节点的类型进行区间运算(新数据流生成Gen及旧数据流更新Update或删除 Kill)。假设平均每个函数的控制流节点数为Num(VexNode),每个节点区间运算的复杂度为0 antervalAnalysis),则对单个函数进行区间分析的复杂度为0(Num(VexNode)* IntervalAnalysis) 0在控制流出口节点,根据配置是否进行函数间分析,为当前函数计算其函数摘要,包括后置条件(生成返回值区间信息,及对全局变量的数据流影响)与前置约束(根据步骤11中载入的状态机类型,创建调用当前函数时的前置约束),后置条件需要计算所有return语句的区间信息并取并集,复杂度决定于Num(VexNode),前置条件一般来说需要查询AST上某种类型的节点,复杂度与Num(ASTNode)有关。因此,区间分析单元的总复杂度为:Num(Proc) * (Num(srcFiIeLines) * IntervalAnalysis)。步骤170、缺陷自动机分析单元根据步骤11中载入的状态机类型(分为文件作用域与函数作用域,或者流敏感与非流敏感),根据每种类型状态机的创建条件生成状态机实例集合如果是非流敏感的状态机实例,则直接在语法树上进行状态迭代,检测该类型的缺陷;将所有流敏感的状态机实例集合置于函数控制流入口节点处,然后根据控制流顺序对每个状态机实例的缺陷状态进行状态条件更新,如果发生状态迁移且为错误(error)状态, 则上报一个相应类型的缺陷,否则状态自动迁移到结束(end)状态,表示自动机将自动销毁。特殊情况下,如果为路径敏感的缺陷状态迭代方法,则状态条件需要重新通过区间运算计算生成(OantervalAnalysis))。每个函数创建的状态机实例数为 Num(FSMhstances),每个控制流节点关联的缺陷状态实例数为与其成正比,每个状态条件迁移与否的计算量为O(FSMTransiti0n),则路径敏感的缺陷自动机分析复杂度为 Num(Proc) * (Num(FSMInstances) * O(FSMTransition) * O(IntervalAnalysis) )),非路径敏感的缺陷自动机分析复杂度为Num (Proc) * (Num (FSMInstances) * O(FSMTransition)))。因此,步骤F正式分析模块的总复杂度为
Num(srcFiles) *(Num(srcFiIeLines)*Num(Var)+Num (Proc) *Num(srcFiIeLines)(IntervalAnalysis)。所以,整个缺陷检测的复杂度为Num(fsm)+Num(srcFiles)*(Num(srcFiles) * (Num(srcFiIeLines)^Num(Var)+Num(Proc)*Num (srcFiIeLines))。本发明所提供的基于模块分解技术的软件缺陷检测系统的复杂性分析方法表明,该缺陷检测系统具有多项式复杂度,影响其效率的因子很多,且部分影响因子是待测程序的复杂度决定的(例如Num(Proc),Num(ProcCall), Num(Var)等)。对组成多项式的各项因子分析发现,可控的复杂度影响因子包括Num (fsm),O (IntervalAnalysis), O(FSMTransiti0n),在设计相应的区间运算算法及缺陷迭代判断时应考虑如何提高其效率。基于上述模块分解技术的复杂度分析方法也可以看出,各模块及分析单元的复杂性较高且可以并发进行,如拓扑排序后得到的文件依赖关系图及函数调用关系图,由于我们的算法是按照自底向上进行单文件或单函数分析的,因此在依赖图中出度为O (叶子节点)的文件或函数可以并发检测,且该类型的文件或函数检测完毕后,又会生成新的叶子节点,从而可以用上述算法继续进行并发检测。通过对整个的分析流程观察可以发现,语法树、符号表是整个缺陷检测的基础,因此可以考虑将每个文件的此类信息进行缓存(例如,缓存到本地硬盘文件系统中),当后续分析需要时直接可以获取,从而进一步降低复杂度。
以上所述,仅为本发明的较佳实施例而已,并非用于限定本发明的保护范围。
权利要求
1.一种基于模块分解技术的软件缺陷检测系统的复杂性分析方法,其特征在于,该分析方法包括A、根据所述缺陷检测系统DTS缺陷检测原理,将该分析方法的流程包括由前端输入预处理模块完成的前端输入预处理步骤、由预分析模块完成预分析的步骤、由正式分析模块完成正式分析的步骤;B、对所述的前端输入预处理模块、预分析模块和正式分析模块的内部所有分析单元, 按其调用顺序及依赖关系依次分析其复杂度,得到每个分析单元复杂性分布的性质和规律;C、根据步骤B的分析结果,统计得出整个DTS系统的复杂性分布情况。
2.根据权利要求1所述的基于模块分解技术的缺陷检测系统的复杂性分析方法,其特征在于,将步骤B所述前端输入预处理模块、预分析模块和正式分析模块分别进一步分为将所述前端输入预处理模块分为载入缺陷状态机单元、源文件收集单元和程序转换单元;将所述预分析模块分为全局函数调用关系生成单元和文件分析次序解析单元;以及将正式分析模块分为线程分析单元和缺陷检测结果输出单元。
3.根据权利要求1所述基于模块分解技术的软件缺陷检测系统的复杂性分析方法,其特征在于,步骤C所述得出整个DTS系统的复杂性分布情况的过程,包括对前端预输入处理模块的分析单元进行复杂度分析,具体如下Cl、将待测试的程序源文件载入缺陷状态机单元,根据预先配置的待扫描缺陷状态机类型,读入对应的状态机描述XML文件;复杂度取决于待扫描缺陷状态机种类数 Num (fsm);C2、收集待进行缺陷检测的源文件,如果以工程为单位进行检测,则根据工程配置文件搜索待分析源文件;否则,直接搜索待扫描目录,收集所有待检测源文件;复杂度取决于待分析源文件数量Num(srcFiles);C3、根据待测源文件的类型执行程序转换,具体为通过程序转换单元,根据待检测源文件类型,调用相应的编译器进行预处理,得到预处理后的中间文件,作为后续分析的输入;如果是JAVA语言,需要调用JVM将源文件(.java)编译为字节码文件(.class);其复杂度取决于JVM的编译器效率;如果是C或CPP语言,需要调用相应的编译器(gcc,cl)将源文件(.c,.cpp)预处理为中间文件(.i);其复杂度取决于编译器的效率;最后,将该类不可控分析单元的复杂度标记为0(⑴)。
4.根据权利要求1所述的基于模块分解技术的软件缺陷检测系统的复杂性分析方法, 其特征在于,步骤C所述得出整个DTS系统的复杂性分布情况的过程,对预分析模块的分析单元进行复杂度分析,具体如下C4、通过全局函数调用关系生成单元,首先进行预分析,生成全局函数调用关系,然后按字母顺序遍历所有源文件,查找所有需要分析的函数并建立全局函数表,保存函数间调用关系;同时,还能够根据需要生成库函数摘要;C5、利用文件分析次序解析单元,根据所述全局函数表及调用关系,对文件调用关系进行拓扑排序,最终的文件分析次序为拓扑排序的逆序;该分析单元的复杂度取决于全局函数表中的函数个数Num(Proc)及每个函数调用其他函数的平均次数NumQ^ocCall),得出该分析单元的复杂度Num(Proc) *Num(ProcCal 1)。
5.根据权利要求1所述的基于模块分解技术的软件缺陷检测系统的复杂性分析方法, 其特征在于,步骤C所述得出整个DTS系统的复杂性分布情况的过程,对正式分析模块的分析单元进行复杂度分析,具体如下C6、利用线程分析单元,根据上述步骤C5中得到的文件分析次序,为每个文件依次生成分析线程,同时检测线程执行过程中是否出现异常以便及时结束线程;C7、通过缺陷检测结果输出单元,将所述步骤C6的输出检测结果写入数据库中;其复杂度取决于待分析文件数Num(srCFiles)及每个文件的平均缺陷数Num(IP),复杂度依赖于 Num(srcFiles) *Num(IP)。
6.根据权利要求4所述基于模块分解技术的软件缺陷检测系统的复杂性分析方法,其特征在于,根据全局函数调用关系生成单元的原理,将所述步骤C4分为五个子分析单元, 然后对每个子单元的复杂度分析,具体包括C41、语法树生成包括词法分析及语法分析两个阶段词法分析复杂度取决于源文件的平均行数NunKsrcFileLines),语法分析的复杂度取决于源文件的语法复杂程度,均为不可控的;其语法树生成单元的复杂度为NunKsrcFileLines);C42、作用域和声明分析单元为单个文件生成SourceFil必cope, ClassScope, MethodScope及LocalScope作用域层次关系,及每个作用域下的变量声明集合 VariableNamesDeclarations 禾口函数声明集合 MethodNameDeclarations,并且为每个变量及函数创建类型信息;其复杂度主要依赖于语法树中相关节点的数量,若其与文件行数成正比,则本分析单元复杂度为Num(srcFiIeLines);C43、表达式类型分析单元为程序中的各种表达式生成类型信息,为后续的区间分析及缺陷模式计算提供类型支持;本分析单元的复杂度也依赖于语法树中相关节点的数量,若其与文件行数成正比,则本分析单元复杂度为NunKsrcFileLines);C44、标志符出现分析单元将所有标识符的出现与其正确的声明相关联,并且将这种关联关系添加到具体的作用域中,以方便后续的文件内函数调用关系生成;标识符的出现分为变量使用和函数调用,本分析单元的复杂度取决于程序中变量和函数的声明及使用数量 Num(Var)+Num(Proc);C45、函数调用关系分析单元遍历程序中所有函数定义节点 (ASTFimctionDefinition),查找该函数作用域中的所有函数调用,为当前函数定义节点生成“一对多”的调用关系,随着遍历的进行生成函数调用关系图;本分析单元复杂度主要依赖于每个文件中函数平均个数Num(Proc),及每个函数调用其他函数的平均个数 Num(ProcCall),其复杂度为 Num(Proc) * Num(ProcCall);所述的全局函数调用关系生成单元,其复杂度为Num(srcFiles)* (Num(srcFileLines) + Num(Var) + Num(Proc))。
7.根据权利要求5所述基于模块分解技术的软件缺陷检测系统的复杂性分析方法,其特征在于,根据线程分析单元的检测原理,将所述步骤C6进一步分为十个子分析单元,对每个子单元的复杂度分析步骤为C61 C64、其复杂度分析过程与C41 C44的类似;C65、利用控制流图生成单元遍历语法树相关节点,分别生成控制流图节点和边; 所述控制流图中节点与边的数量为等数量级的,且节点数主要取决于源代码行数;本分析单元的复杂度主要依赖于语法树中相关节点的数量及程序代码行数,复杂度为 Num (srcFiIeLines);C66、定义使用分析单元为变量的声明及使用位置生成关联关系,能够为相关模式提供数据依赖分析的支持;首先根据步骤C62 C64的分析结果,按作用域层次关系依次初始化每个变量出现的定义或使用信息,并将此初始化定义使用信息绑定到对应的控制流节点, 然后基于步骤C65生成的控制流图,进行流敏感的定义使用信息迭代;定义使用信息迭代的复杂度取决于控制流节点数及每次迭代的复杂度,迭代复杂度取决于每个控制流节点上变量出现的个数(与程序中变量总数成正比);本分析单元的复杂度为NunKsrcFileLines)* Num(Var);C67、文件内函数调用关系生成单元的分析原理与步骤C66类似,也是通过作用域层次关系得到文件内的函数调用关系,并创建函数调用关系图;其复杂度取决于Num(Proc);C68、解析函数分析次序单元与步骤C45类似;其复杂度取决于函数及函数调用的个数 Num (Proc);C69、区间分析单元以函数为单位(Num(Proc)),依次遍历控制流图进行数据流方程迭代在控制流入口节点将所有外部区间信息初始化,后续节点首先对前驱节点的数据流信息进行继承或汇聚,然后根据当前节点关联语法树节点的类型进行区间运算;若平均每个函数的控制流节点数为Num(VexNode),每个节点区间运算的复杂度为O (IntervalAnalysis),则对单个函数进行区间分析的复杂度为O(Num(VexNode)* IntervalAnalysis);在控制流出口节点,根据配置是否进行函数间分析,为当前函数计算其函数摘要,包括后置条件与前置约束,后置条件需要计算所有return语句的区间信息并取并集,其复杂度决定于Num(VexNode),前置条件需要查询AST上某种类型的节点,复杂度与Num(ASTNode)有关;得到该区间分析单元的总复杂度为=Num(Proc) * (Num(srcFiIeLines)* IntervalAnalysis);C70、缺陷自动机分析单元根据步骤A载入的状态机类型,根据每种类型状态机的创建条件生成状态机实例集合如果是非流敏感的状态机实例,则直接在语法树上进行状态迭代,检测该类型的缺陷;将所有流敏感的状态机实例集合置于函数控制流入口节点处, 然后根据控制流顺序对每个状态机实例的缺陷状态进行状态条件更新,如果发生状态迁移且为error状态则上报一个相应类型的缺陷,否则状态自动迁移到end状态表示自动机将自动销毁;如果为路径敏感的缺陷状态迭代方法,则状态条件需要重新通过区间运算计算生成(OantervalAnalysis));每个函数创建的状态机实例数为Num(FSiOnstances), 每个控制流节点关联的缺陷状态实例数为与其成正比,每个状态条件迁移与否的计算量为O (FSMTransition),则路径敏感的缺陷自动机分析复杂度为Num (Proc) * (Num(FSMInstances) * O(FSMTransition) * O(IntervalAnalysis) )) ; 陷自动机分析复杂度为 Num(Proc) * (Num(FSMInstances) * O(FSMTransition)));得到所述正式分析模块的复杂度为Num(srcFiles) * (Num(srcFiIeLines) *Num(Var) +Num(Proc)*Num(srcFiIeLines)(IntervalAnalysis)0
8.根据权利要求7所述基于模块分解技术的软件缺陷检测系统的复杂性分析方法,其特征在于,所述的缺陷检测系统的总复杂度为Num(fsm) +Num(srcFiles)*(Num(srcFiles) 氺(Num(srcFileLines)氺Num(Var)+Num(Proc)*Num(srcFileLines))。
9.根据权利要求7所述基于模块分解技术的软件缺陷检测系统的复杂性分析方法, 其特征在于,所述的缺陷检测系统具有多项式复杂度,影响其分析效率的因子,主要包括 Num(fsm), O(IntervalAnalysis)和0 (FSMTransition),且部分影响因子是待测程序的复杂度,如 Num(Proc),Num(ProcCall), Num(Var)决定的。
10.根据权利要求7所述基于模块分解技术的软件缺陷检测系统的复杂性分析方法, 其特征在于,所述缺陷检测系统中的各模块及分析单元的复杂性较高且可并发执行;将每个文件的语法树、符号表等信息进行缓存,当后续分析需要时直接获取,能够进一步降低该分析过程的复杂度。
全文摘要
本发明公开一种基于模块分解技术的软件缺陷检测系统(DTS)的复杂性分析方法,包括A,根据所述DTS缺陷检测原理,将该分析方法的流程包括由前端输入预处理模块完成的前端输入预处理步骤、由预分析模块完成预分析的步骤、由正式分析模块完成正式分析的步骤;B,对所述的前端输入预处理模块、预分析模块和正式分析模块的内部所有分析单元,按其调用顺序及依赖关系依次分析其复杂度,得到每个分析单元复杂性分布的性质和规律;C,根据步骤B的分析结果,统计得出整个DTS系统的复杂性分布情况。采用本发明,通过对每个模块内部的分析单元的复杂性分析,统计得出DTS的复杂性分布情况,克服了现有复杂性分析方法不够系统全面等的缺点。
文档编号G06F11/36GK102521126SQ20111039821
公开日2012年6月27日 申请日期2011年12月5日 优先权日2011年12月5日
发明者宫云战, 肖庆, 赵云山, 金大海 申请人:北京邮电大学