CN107704382A - 面向Python的函数调用路径生成方法和系统 - Google Patents
面向Python的函数调用路径生成方法和系统 Download PDFInfo
- Publication number
- CN107704382A CN107704382A CN201710802398.4A CN201710802398A CN107704382A CN 107704382 A CN107704382 A CN 107704382A CN 201710802398 A CN201710802398 A CN 201710802398A CN 107704382 A CN107704382 A CN 107704382A
- Authority
- CN
- China
- Prior art keywords
- function
- node
- nodes
- model
- python
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3668—Software testing
- G06F11/3672—Test management
- G06F11/3676—Test management for coverage analysis
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/362—Software debugging
- G06F11/3624—Software debugging by performing operations on the source code, e.g. via a compiler
Abstract
本发明实施例提供一种面向Python的函数调用路径生成方法和系统,方法包括:获取Python源代码的抽象语法树,遍历抽象语法树以获取其中的关键信息;根据提取到的关键信息,结合Python语言的控制结构特性,构建对应的函数调用关系模型,并以树形结构进行存储,记录函数间的调用关系,以生成函数调用关系模型;其中所述函数调用关系模型中的每一个节点代表源代码中的一个函数,如果一个节点存在孩子节点,则该孩子节点代表分支;如果一个节点不存在分支,则代表顺序执行的函数;其中所述函数调用关系模型中的兄弟节点与父节点是并列关系,在源代码中表示多分支结构。
Description
技术领域
本发明涉及计算机软件技术领域,具体涉及一种面向Python的函数调用路径生成方法和系统。
背景技术
随着Python的兴起,越来越多的程序员和研究员选择Python作为Web应用、游戏开发和科学计算等的首选语言。在互联网技术和大数据技术发展迅速的时代,Python作为一种面向对象的解释型计算机程序设计脚本语言,以其良好的可读性,可交互性,通用性,可移植性,可扩展性,可维护性以及可嵌入性等特征,吸引了众多软件开发者,成为了众多脚本语言中的佼佼者。近年来Python已成为最受欢迎的编程语言之一,逐渐成为科学计算、Web应用和游戏开发之首选语言。因此对Python程序的测试,也显得越来越重要。Python目前已存在基本测试框架,是面向过程内基于语句级别的,测试粒度较小,在测试大规模程序时,其测试路径会随着程序的复杂性呈指数增长,导致软件测试成本过高。面向函数调用路径的测试方法将函数调用和代码的逻辑结构相结合,将代码分析粒度提升到函数级,在避免路径大规模增长的同时又保证了软件测试的充分性[2]。
目前国内针对Python程序源代码的分析方面的研究相对较少,而国外在该方面的研究已经存在一些,包括控制流分析、数据流分析[3]等静态分析方法的研究,以及一些动态分析工具如cProfile等。但是针对Python的测试方法研究较少,对其抽象语法树的研究也相对较少。
发明内容
针对现有技术中针对Python语言的测试方法和工具不足导致对Python语言支持不好的问题,本发明实施例要解决的技术问题是提出一种面向Python的函数调用路径生成方法和系统,至少部分的解决现有技术中存在的问题。
为了解决上述问题,本发明实施例提出了一种面向Python的函数调用路径生成方法,包括:
步骤1、获取Python源代码的抽象语法树,即AST;
步骤2、遍历抽象语法树AST以获取抽象语法树AST中的关键信息;
步骤3、根据提取到的关键信息,根据Python语言的控制结构特性构建对应的函数调用关系模型,并以树形结构进行存储,记录函数间的调用关系、;其中所述函数调用关系模型中的每一个节点代表源代码中的一个函数,如果一个节点存在孩子节点,则该孩子节点代表分支;如果一个节点不存在分支,则代表顺序执行的函数;其中所述函数调用关系模型中的兄弟节点与父节点是并列关系,在源代码中表示多分支结构。
其中,所述步骤1具体为:
步骤11、将程序源代码解析为语法分析树Parse Tree;
步骤12、将语法分析树通过以下方法转化为抽象语法树AST:
根据程序源代码以及对应的的文法规则,将程序源代码转化为抽象语法树AST;其中所述抽象语法树AST为一个对象列表,每个对象包含多个子列表或者其他对象的引用;其中每个列表或子列表包含任意数量的节点,每个节点代表一条语句代码及其对应的行号和偏移量,而这些节点是标准库中AST模块的类实例。
其中,所述步骤2具体为:
步骤21、将每一个类型的操作封装在一个独立的对象访问者Visitor中,将此访问者Visitor对象传递给当前访问的节点,具体包括:
建立抽象访问者,所述抽象访问者基于Python的反射机制构建,且为每个节点提供通用的入口函数visit();
建立具体访问者,所述具体访问者提供函数visit_xxx()以实现节点访问的详细操作,该具体访问者针对不同语句的角色提供不同的函数visit_xxx();其中所述函数visit_xxx()可以包括基于函数定义的函数visit_FunctionDef()、基于If语句的函数visit_If();
建立通用访问者,所述通用访问者提供通用访问者的函数generic_visitor();
其中,所述抽象访问者、具体访问者、通用访问者都以节点对象作为入口参数;
步骤22、从抽象语法树AST的根节点开始,利用抽象访问者来进行转发;如果转发存在明确的具体访问者,则调用具体访问者的函数visit_xxx(),就直接进行访问;如果不存在明确的具体访问者角色,则调用通用访问者的函数generic_visitor();
步骤23、获取每一行源代码的行号以及缩进量,记为
(row,col)ClassName:FunctionName;
其中row为函数定义所在的行,col为缩进量,ClassName为函数所属的类,FunctionName为函数名。
其中,所述步骤3具体中,如果建立的函数调用关系模型包括分支关系模型,则所述步骤3包括:
对于缺省型语法结构,其语法结构为if<布尔表达式>:<语句F1>;则在建立函数调用关系模型时补全一个空节点,建立Begin节点—F1节点—空节点的函数调用关系模型;其中Begin节点即根节点,F1节点为左分支,空节点为F1节点的右分支;
对于标准型语法结构,其语法结构为if<布尔表达式>:<语句F1>else:<语句F2>;则如果if-else各自的语句中都包含函数的调用,建立Begin节点—F1节点—F2节点的函数调用关系模型;其中Begin节点即根节点,F1节点为左分支,F2节点为F1节点的右分支;;如果if-else各自的语句存在一方没有函数的调用,在建立模型时补全空节点,并建立Begin节点—F1节点—空节点的函数调用关系模型;如果if-else都不包含函数的调用,那么关系模型则不存在,对if-else内部的语句不做处理;
对于多分支语法结构:其语法结构为if<布尔表达式>:<语句F1>elif<布尔表达式>:<语句F2>else:<语句F3>;则建立Begin节点—F1节点—F2节点—F3节点的函数调用关系模型;其中Begin节点即根节点,F1节点为左分支,F2节点为F1节点的右分支,F3节点为F2节点的右分支;如果其中由一个分子不存在函数调用,则该分支对应的节点为空节点。
其中,所述步骤3具体中,如果建立的函数调用关系模型包括循环关系模型,则所述步骤3包括:
对于while语句,其语法结构为while<布尔表达式>:<语句>[else:<语句>];则表示程序要么执行要么不执行,则该语句循环一次和零次;
对于for语句,其语法结构为for<迭代参数>in<序列>:<语句>[else:<语句>],则表示该语法结构至少会执行一次,即循环一次;如果for结构中存在else语句块,则每次迭代都会执行else的语句块;建立顺序结构的函数调用关系模型;
对于break和continue语句,则函数调用的路径中循环结构按执行一次处理,因此构建出的break和continue语句的关系模型相同。
其中,所述步骤3具体中,如果建立的函数调用关系模型包括递归关系模型,即源代码中存在递归关系,即函数A调用函数B,而函数B又调用函数A,则所述步骤3具体包括:
如果检查到函数A的父节点是函数B,且检查到函数B的父节点是函数A,此时函数B又是函数A的孩子节点时,则路径中存在递归调用;函数A不用继续扩展,继续下一个函数的模型构建。
其中,所述步骤3还包括:以关键信息列表为输入,构建局部和全局函数调用关系模型;具体包括:
对于全局函数调用关系模型的生成,首先遍历模型列表获取标识为Begin-Start的节点的作为程序的入口点,从入口点的模型开始,将每一个函数的局部函数调用关系模型插入到全局的函数调用关系模型中,插入的这个模型的叶子结点的左孩子指向被替代的那个函数的左孩子节点。
同时,本发明实施例还提出了一种面向Python的函数调用路径生成系统,包括:
获取单元,用于获取Python源代码的抽象语法树,即AST;
抽取单元,用于遍历所述抽象语法树AST以获取抽象语法树AST中的关键信息;
模型建立单元,用于根据提取到的关键信息,根据Python语言的控制结构特性构建对应的函数调用关系模型,并以树形结构进行存储,并记录函数间的调用关系以生成函数调用关系模型;其中所述函数调用关系模型中的每一个节点代表源代码中的一个函数,如果一个节点存在孩子节点,则该孩子节点代表分支;如果一个节点不存在分支,则代表顺序执行的函数;其中所述函数调用关系模型中的兄弟节点与父节点是并列关系,在源代码中表示多分支结构。
本发明的上述技术方案的有益效果如下:上述技术方案提出了一种面向Python的函数调用路径生成方法和系统,以基于抽象语法树的方法实现对Python函数调用路径的静态提取。上述技术方案从Python编译过程中提取到的抽象语法树(Abstract Syntax Tree,AST)作为基础,解析提取关键信息,提取函数调用关系,构建函数调用关系模型,生成函数调用路径。实验表明,该方法能够较为准确地生成Python程序的函数调用路径,在一定程度上避免了测试路径的爆炸式增长问题,为面向覆盖的测试用例自动生成以及软件缺陷定位提供了一定的技术支撑。
附图说明
图1为Python语言编译过程的示意图;
图2为Python程序的运行过程的示意图;
图3为sub函数抽象语法树文本示意图;
图4为AST中信息节点存储格式的示意图;
图5为本发明实施例中函数调用关系模型示意图;
图6为Python中缺省语法结构示意图;
图7为Python中标准语法结构示意图;
图8为Python中多分支语法结构示意图;
图9为循环结构中break和continue的程序示意图;
图10为循环结构中break和continue的模型示意图;
图11为实验源代码;
图12为分支结构提取示意图;
图13和图14为提取出的抽象语法树的关键信息、函数词典、关键信息的示意图;
图15为test_WHILE()函数示意图;
图16为采用for标准结构的函数示意图;
图17和图18为图15和图16获得的关键信息示意图;
图19为If–局部函数关系调用路径图;
图20为If-全局函数调用路径图;
图21为While-全局函数调用路径图;
图22为For–全局函数调用路径图;
图23为综合实验源代码提取函数调用路径图;
图24为关键信息示意图;
图25为分析结果图;
图26a、图26b、图26c为全局函数调用路径可视化效果图。
具体实施方式
为使本发明要解决的技术问题、技术方案和优点更加清楚,下面将结合附图及具体实施例进行详细描述。
1.路径覆盖生成技术
路径覆盖的核心是用最少的测试用例,发现程序中最多的错误。最小测试用例集合应能够覆盖程序中所有的路径。为达到路径覆盖,必须确切地知道被测试程序的路径数目,以便安排测试计划、分配测试资源,并对实际测试所达到的覆盖率做出评估,以决定是否结束测试工作。路径覆盖是一种唯一考虑到同一程序中不同判定之间组合关系的覆盖测试方法,它要求程序中的每条可能路径至少执行一次。路径覆盖的覆盖规则严格,测试彻底。然而,当程序规模较大时,由于程序逻辑关系复杂,路径数随分支数指数级增加,路径数量过于庞大导致完全的路径测试无法完成。
面向函数调用路径(Function Calling Paths,FCP)的思想是在回归测试和路径覆盖测试的基础上发展起来的,不仅简化了面向基路径的测试问题,使得面向基路径的测试工作量大幅度减少,而且将面向路径的自动化测试变成了可能。
考虑到面向过程的程序语言的结构特性,分支循环的复杂性,以及对热点路径(包括递归路径、不可达路径)的处理,已经实现基于函数调用路径的自动化白盒测试工具Regression Test C版。该工具通过静态分析与动态执行的方法,生成C语言的全部带有控制逻辑的静态函数调用路径。
考虑到面向对象语言的语法特点,使用面向过程的函数调用路径生成方法明显会增大工作量。因此研究人员提出了一种基于Soot的面向Java语言函数调用生成方法,利用开源Java编译优化框架Soot生成三地址文件,设计多态唯一性静态分析算法和组合算法生成函数调用关系图。
到目前为止,研究人员先后提取了C、C++、Java、C#版本的函数调用路径,但方法不能通用,且因Python语言的语法灵活多变,之前并没有对其进行相关研究。在Python编译过程中,抽象语法树详细记录了程序中函数间的依赖关系,为生成Python的函数调用路径提供了分析基础和帮助。
2.Python语言相关
2.1Python编译和执行
本质上Python和Java、C#是一样的,三者的程序执行原理都可以用两个词概括——虚拟机、字节码。Python有一个非常核心的组件,被称为解释器(interpreter)。当通过“python my-test.py”执行一个特定的Python程序时,解释器会立即被激活,进而执行python程序。但在真正开始执行之前,Python的解释器还要进行编译.py文件的工作。编译的过程和标准的编译过程无异,如图1所示,基本分为三个步骤:
(1)将程序源代码解析为语法分析树(Parse Tree)。
(2)将语法分析树转化为抽象语法树(Abstract Syntax Tree,AST)。
(3)将抽象语法树转化为字节码(Byte Code)。
编译的主要结果是产生一组Python的字节码.pyc文件,然后将编译的结果交给Python的虚拟机,由虚拟机按照顺序一条一条地执行,从而完成对Python虚拟机的执行动作。其运行过程如图2所示。
2.2Python抽象语法树
在计算机科学中,抽象语法树(Abstract Syntax Tree,AST)作为程序的一种良好的中间表示,不仅能够适应很多变成语言的语法结构,而且还能达到对源程序进行预处理的目的。抽象语法树可以理解为源代码的抽象语法结构的树状表现形式,树上的每个节点都表示源代码中的一种结构,代表一个类型的语句。
基于Python的抽象语法树文法中大约包含了67条文法规则,规则左边是非终结符,对应为抽象语法树的复合节点;规则中不属于非终结符号集合的符号称为终结符号,对应的是叶子节点或是某种属性值。
Python的抽象语法树AST可表示为一个对象列表,每个对象包含多个子列表或者其他对象的引用。每个列表或子列表包含任意数量的节点,每个节点都代表一条语句代码及其对应的行号和偏移量,这些节点是标准库中AST模块的类实例。使用标准库中AST模块可将python程序源代码转化成抽象语法树。举例说明,图3是一段简单的python源代码及其获取抽象语法树的过程。从图中可看出通过使用AST模块的parse()方法,得到抽象语法树的对象expr_ast。通过调用ast.dump()方法查看expr_ast的具体内容。
抽象语法树详细记录了sub函数的操作信息,Module父结点,表示代码的整体,其body中包含了一个函数定义FunctionDef,其中包含了函数名name、参数列表args、变量名Name和函数主体body。函数主体包含了一个单独的Return结点,结点中含有一个Sub()运算。
由此可以看出,本发明实施例中提出的以抽象语法树作为提取函数调用路径的基础数据,不仅节省扫描及解析源代码的时间开销,而且可以保证代码理解的准确性。
2.关键信息提取:已知每个AST对象都包含了源代码中的所有执行信息,信息量巨大,其中有些信息是不需要的,而有些信息是需要重点关注的。因此在对Python源代码的分析过程中,是不必去分析一颗完整的抽象语法树的,去掉不必要的信息对后继的程序分析有很大帮助。那么,如何在这些海量数据中提取到所需的关键信息,即与函数和控制流相关的信息,是提取函数调用关系过程中的重要环节。
2.1、基于抽象语法树的遍历:
在遍历抽象语法树的过程中,可能会涉及多个操作,这些操作大多要求对不同的节点进行不同处理。如果将所有操作分散到各个不同节点类中,在导致程序的可读性和可理解性变差的同时,如果需要增加新的操作,就需要重新编译所有节点类,会造成程序混乱等现象。
根据Python抽象语法树的结构可知,AST是一个深度嵌套的树形结构,为避免上述遍历过程中可能出现的现象和问题,以及Python的递归深度限制给遍历带来的不确定影响,本发明实施例采用非递归的访问者(Visitor)模式,实现抽象语法树的遍历。通过将每一个类型的操作封装在一个独立的对象Visitor中,将此Visitor对象传递给当前访问的节点,当一个节点接受该访问者时,该节点会向访问者发送一个包含自身类型信息的请求。在发送请求的同时将该节点本身作为一个参数,访问者将对该节点执行某一类操作。
在遍历过程中,涉及到以下几个角色:
抽象访问者(Visitor)角色:也可叫做访问者工厂,该工厂根据Python的反射机制构建,为每个节点提供通用的入口方法visit(),以节点对象作为入口参数。
具体访问者(Concrete Visitor)角色:实现节点访问的详细操作,方法结构为visit_xxx(),如visit_FunctionDef()和visit_If(),这两种方法分别代表两种角色,前者是基于函数定义,后者是基于If语句。
通用访问者(Generic Visitor)角色:该角色提供通用的访问方法generic_visitor()。
三种角色均以节点对象作为入口参数。
Visitor的遍历可理解为,对每一个节点来说,通过访问者工厂的转发,如果存在明确的具体访问者角色visit_xxx(),就直接进行访问;如果不存在明确的具体访问者角色,则访问generic_visitor()。
遍历算法1如下所示:
2.2、基于抽象语法树的关键信息提取:
以抽象语法树遍历算法为辅助,实现基于抽象语法树的关键信息提取。Visitor首先从抽象语法树的根节点进行遍历,在遍历过程中,假设节点类型为FunctionDef,如果存在visit_FunctionDef类型的函数,则调用该函数;如果不存在则调用generic_visitor函数。每个与函数调用关系和控制流相关的节点类型都有专用的类型处理函数,如果不存在,则通过调用generic_visitor进行处理。具体算法见算法2。
由于Python语法中的缩进就是python表示语句块的唯一方法,因此抽象语法树中的每一个节点都有行号和偏移量两个属性,提供了可以唯一标识语句块的序列对儿。所以,对于获取到的关键信息,统一采用如图4所示的格式进行存储。
其中,row表示该函数定义的所在行,col表示缩进列,ClassName表示函数所属的类,FunctionName表示函数名称,如(2,4)Calculate:add(self,x,y),表示add函数属于Calculate类,从第2行第4列开始定义。根据Python的函数定义规则,由于函数可在类内和类外进行定义,所以ClassName可缺省,如(1,0)main(),表示main函数从第一行第0列开始定义。
至此,繁琐的抽象语法树文本转换成能够生成函数调用关系所需的关键信息列表。
3.函数调用关系模型的构建
根据提取到的关键信息,结合Python语言的控制结构特性,构建对应的函数调用关系模型,并以树形结构进行存储,记录函数间的调用关系,函数调用关系模型如图5所示。
模型中的每个节点代表一个函数,孩子节点代表分支,如果不存在分支,则代表顺序执行的函数,兄弟节点与父节点是并列关系,在程序中表示多分支结构。
Python语言包含了常见的控制关键字,但是却又与其他语言存在显著差异。常见的控制结构如while、for、if、if-else等结构。没有switch-case结构,取而代之的是if-elif+-else;没有do-while结构,对于循环来说,Python为其提供一个else语句块作为辅助。
3.1、关系模型分析:
对于顺序结构,在语句中一般显示为先后顺序,即先执行的在前且后执行的在后,构建模型时较为容易,这里不再赘述。
3.1.1分支关系模型:
Python中的分支结构,大致可分为三种语法结构,缺省型、标准型以及多分支型。
缺省语法结构:
if<布尔表达式>:<语句>
这种语法结构由于没有else,表示要么执行要么不执行,在构建关系模型时,会自动补全一个空节点。如图6所示:
标准语法结构:
if<布尔表达式>:<语句F1>else:<语句F2>
这种语法结构满足if条件时执行if语句块,否则执行else语句块。如果if-else各自的语句中都包含函数的调用,其关系模型如图7所示。如果if-else各自的语句存在一方没有函数的调用,其关系模型如图6所示。如果if-else都不包含函数的调用,那么关系模型则不存在,对if-else内部的语句不做处理。
多分支语法结构:
if<布尔表达式>:<语句F1>elif<布尔表达式>:<语句F2>else:<语句F3>
这种语法结构在关系模型中存在一个节点多个兄弟节点,如果存在一个分支处不存在函数调用,则该分支为空节点,如图8所示。
3.1.2循环关系模型:
对于循环结构,采用Z路径覆盖思想,对循环机制进行简化,减少路径数量,使覆盖这些有限路径成为可能,简化循环机制指的是无论循环的形式及实际执行循环体的次数多少,只考虑循环一次和零次情况,即只考虑执行时进入循环体一次和跳过循环体这两种情况,在函数调用路径中的形式也只考虑这两种情况。
while语法结构:
while<布尔表达式>:<语句>[else:<语句>]
这种语法结构与if–else的结构类似,表示程序要么执行要么不执行,结合Z路径覆盖思想,只考虑循环一次和零次即可。
for语法结构:
for<迭代参数>in<序列>:<语句>[else:<语句>]
这种语法结构在python中至少会执行一次,为减少路径数量,只需循环一次即可,与while结构不同,如果for结构中存在else语句块,则每次迭代都会执行else的语句块,与顺序结构类似。
break和continue结构:
循环结构中break和continue结构经常会被用到,break是直接跳出循环,而continue是跳出本次循环,进行下一次循环。但在函数调用的路径中循环结构按执行一次处理,所以在构建关系模型时,二者的模型是相同的。且在循环结构中二者的出现一般伴随if结构。示例程序和模型见图9和图10。
3.1.3递归关系模型
对于代码中的递归问题,采用递归扩展验证的方法,举例说明如A调用B,B又调用A,当验证到第三个A函数是否要扩展时,调用A的是B,查看A的父节点,A的父节点是B,B又是A的孩子节点时,可判定路径中存在递归调用,从而A不用继续扩展,继续下一个函数的模型构建。
3.2函数调用关系模型的构建算法
以关键信息列表为输入,构建局部函数调用关系模型,算法3如下。
根据算法3,获取到局部函数调用关系模型列表,通过组合方法,构建全局函数调用关系模型。
对于全局函数调用关系模型的生成,首先遍历模型列表获取标识为Begin-Start的作为程序的入口点,从入口点的模型开始,将每一个函数的函数调用关系模型插入到全局的函数调用关系模型中,插入的这个模型的叶子结点的左孩子指向被替代的那个函数的左孩子节点,算法4如下。
至此,全局函数调用关系模型构建完成。通过遍历分析全局函数调用关系模型,即可获得带有函数具体信息的函数调用路径。
4.实验与评测:实验内容分为两个部分:验证关键信息提取的完整性和准确性。验证函数调用路径抽取算法的合理性和有效性。以下分别以三种基本程序结构和一个综合实例为实验数据,采用上述一系列算法,通过关键信息提取、建模实现对源代码的函数调用路径提取。
4.1关键信息的提取
以图11中的实验源代码作为基础,分别对顺序、分支以及循环的函数调用执行关键信息抽取算法,并与人工分析进行对比,实现对关键信息抽取算法的完整性和准确性进行评估。如图11所示,该段源代码实现简单加减乘除功能,定义Cal计算类,分别定义了加(add)减(sub)乘(minus)除(div)函数,以及提示(warn)函数和显示(show)函数。
首先对分支结构进行提取,如图12,test_IF()函数采用if-elif+-else结构,通过提取抽象语法树的关键信息(算法1和算法2),函数字典和关键信息分别如图13和图14所示。
分别对While和For循环结构进行关键信息抽取,如图15定义test_WHILE()函数采用while-else结构,如16定义函数采用for标准结构,其关键信息列表分别如图17和图18所示。
根据上述基于程序基本结构的函数字典和关键信息的提取结果,可以看出,前文提出的基于抽象语法树的关键信息提取算法是较为完备的,准确性良好。
4.2函数调用路径生成
对前文提到的test_IF()构建局部函数调用关系模型(算法3),获取各个函数的函数调用关系,见图19。通过重组局部函数调用关系模型,合成全局函数调用关系模型(算法4),获取全局函数调用关系,实验结果如图20。
从图20中的信息可知,代码段中存在4条函数调用路径,这与代码段的分支结构对应。从测试结果可看出,测试程序准确的提取了代码段的函数调用路径。
根据上述算法,经过构建、重组、合成全局函数调用关系模型,获取while和for循环结构的全局函数调用路径。
由while和for循环结构生成的函数调用路径结果可知,对于while结构,程序要么执行循环体要么则不执行,对于for结构,循环体至少会执行一次。
通过扩展main方法,构建综合实例,提取函数调用路径,源代码和分析结果如图23-25所示。
为了使实验的结果更加直观,设计并实现全局函数调用路径可视化,效果见图26a、图26b、图26c所示。
实验根据程序语言中的三种基本结构,分别对函数调用路径提取方法的有效性和合理性进行验证,通过上述两方面的实验,得到如下结论:本发明实施提出的面向Python的函数调用路径自动生成方法具有较高的准确性和良好的完备性。
本发明实施例提出了一种基于抽象语法树的python函数调用路径生成方法,通过python编译过程中的获取中间信息,得到函数间的依赖关系信息,设计基于抽象语法树的关键信息提取算法,构建基于关键信息的函数调用关系模型,获取函数调用关系,得到函数调用路径,生成函数调用路径图。
实验表明,该算法可行,能够较好的实现python程序的函数调用路径提取,基本达到预期效果,为基于Python的面向覆盖的测试用例自动生成以及缺陷定位提供了一定的技术支撑。
本发明实施例的参考文献如下,本发明将这些参考文献全文引用在此:
[1]范浩杰.面向Python程序源代码的分析与编译优化研究[D].北京信息科技大学,2015.
[2]张志华,牟永敏.基于函数调用的路径覆盖生成技术研究[J].电子学报,2010,38(8):1808-1811.
[3]David A.Schmidt.Modular,parsing-based,flow analysis of dictionarydata structures in scripting languages[J].Kansas State University technicalreport,2010,(2):36-42
[4]张志华,牟永敏.基于函数调用的路径覆盖生成技术研究[J].电子学报,2010,38(8):1808-1811.
[5]Zheng Y,Mu Y,Zhang Z.Research on the static function call pathgenerating automatically[C]//The IEEE International Conference on InformationManagement and Engineering.IEEE,2010:405-409.
[6]朱绪利,牟永敏,张志华.基于Soot控制流图的函数调用路径分析[J].数据通信,2012(4):26-29.
[7]陈儒.Python源码剖析[M].电子工业出版社,2008.
[8]刘巧红,单贵.Python语言整数运算实现机制分析与性能评估[J].计算机系统应用,2011,20(2):169-172.
[9]廖兴,尹俊文,蔡放.基于Java语言的抽象语法树的创建与遍历[J].长沙大学学报,2004,18(4):50-53.
[10]夏辉,宋昕,王理.基于Z路径覆盖的测试用例自动生成技术研究[J].现代电子技术,2006,29(6):92-94.
[11]刘万春,李顺华,朱玉文.基于改进的Z路径覆盖策略的路径生成算法[J].计算机工程与设计,2005,26(12):3327-3330.]
[12]Zhang D,Sui J,Gong Y.Large scale software test data generationbased o n collective constraint and weighted combination method[J].vjesnik,2017,24(4):1041-1049.
[13]Zhang D,Jin D,Gong Y,et al.Research of alarm correlations basedon sta tic defect detection[J].vjesnik,2015,22(2):311-318.
以上所述是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明所述原理的前提下,还可以作出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。
Claims (7)
1.一种面向Python的函数调用路径生成方法,其特征在于,包括:
步骤1、获取Python源代码的抽象语法树,即AST;
步骤2、遍历抽象语法树AST以获取抽象语法树AST中的关键信息;
步骤3、根据提取到的关键信息,根据Python语言的控制结构特性构建对应的函数调用关系模型,并以树形结构进行存储,记录函数间的调用关系、;其中所述函数调用关系模型中的每一个节点代表源代码中的一个函数,如果一个节点存在孩子节点,则该孩子节点代表分支;如果一个节点不存在分支,则代表顺序执行的函数;其中所述函数调用关系模型中的兄弟节点与父节点是并列关系,在源代码中表示多分支结构。
2.根据权利要求1所述的面向Python的函数调用路径生成方法,其特征在于,所述步骤1具体为:
步骤11、将程序源代码解析为语法分析树Parse Tree;
步骤12、将语法分析树通过以下方法转化为抽象语法树AST:
根据程序源代码以及对应的的文法规则,将程序源代码转化为抽象语法树AST;其中所述抽象语法树AST为一个对象列表,每个对象包含多个子列表或者其他对象的引用;其中每个列表或子列表包含任意数量的节点,每个节点代表一条语句代码及其对应的行号和偏移量,而这些节点是标准库中AST模块的类实例。
3.根据权利要求1所述的面向Python的函数调用路径生成方法,其特征在于,所述步骤2具体为:
步骤21、将每一个类型的操作封装在一个独立的对象访问者Visitor中,将此访问者Visitor对象传递给当前访问的节点,具体包括:
建立抽象访问者,所述抽象访问者基于Python的反射机制构建,且为每个节点提供通用的入口函数visit();
建立具体访问者,所述具体访问者提供函数visit_xxx()以实现节点访问的详细操作,该具体访问者针对不同语句的角色提供不同的函数visit_xxx();其中所述函数visit_xxx()可以包括基于函数定义的函数visit_FunctionDef()、基于If语句的函数visit_If();
建立通用访问者,所述通用访问者提供通用访问者的函数generic_visitor();
其中,所述抽象访问者、具体访问者、通用访问者都以节点对象作为入口参数;
步骤22、从抽象语法树AST的根节点开始,利用抽象访问者来进行转发;如果转发存在明确的具体访问者,则调用具体访问者的函数visit_xxx(),就直接进行访问;如果不存在明确的具体访问者角色,则调用通用访问者的函数generic_visitor();
步骤23、获取每一行源代码的行号以及缩进量,记为
(row,col)ClassName:FunctionName;
其中row为函数定义所在的行,col为缩进量,ClassName为函数所属的类,FunctionName为函数名。
4.根据权利要求1所述的面向Python的函数调用路径生成方法,其特征在于,所述步骤3具体中,如果建立的函数调用关系模型包括分支关系模型,则所述步骤3包括:
对于缺省型语法结构,其语法结构为if<布尔表达式>:<语句F1>;则在建立函数调用关系模型时补全一个空节点,建立Begin节点—F1节点—空节点的函数调用关系模型;其中Begin节点即根节点,F1节点为左分支,空节点为F1节点的右分支;
对于标准型语法结构,其语法结构为if<布尔表达式>:<语句F1>else:<语句F2>;则如果if-else各自的语句中都包含函数的调用,建立Begin节点—F1节点—F2节点的函数调用关系模型;其中Begin节点即根节点,F1节点为左分支,F2节点为F1节点的右分支;;如果if-else各自的语句存在一方没有函数的调用,在建立模型时补全空节点,并建立Begin节点—F1节点—F2节点的函数调用关系模型;如果if-else都不包含函数的调用,那么关系模型则不存在,对if-else内部的语句不做处理;
对于多分支语法结构:其语法结构为if<布尔表达式>:<语句F1>elif<布尔表达式>:<语句F2>else:<语句F3>;则建立Begin节点—F1节点—F2节点—F3节点的函数调用关系模型;其中Begin节点即根节点,F1节点为左分支,F2节点为F1节点的右分支,F3节点为F2节点的右分支;如果其中由一个分子不存在函数调用,则该分支对应的节点为空节点。
5.根据权利要求4所述的面向Python的函数调用路径生成方法,其特征在于,所述步骤3具体中,如果建立的函数调用关系模型包括循环关系模型,则所述步骤3包括:
对于while语句,其语法结构为while<布尔表达式>:<语句>[else:<语句>];则表示程序要么执行要么不执行,则该语句循环一次和零次;
对于for语句,其语法结构为for<迭代参数>in<序列>:<语句>[else:<语句>],则表示该语法结构至少会执行一次,即循环一次;如果for结构中存在else语句块,则每次迭代都会执行else的语句块;建立顺序结构的函数调用关系模型;
对于break和continue语句,则函数调用的路径中循环结构按执行一次处理,因此构建出的break和continue语句的关系模型相同。
6.根据权利要求4所述的面向Python的函数调用路径生成方法,其特征在于,所述步骤3具体中,如果建立的函数调用关系模型包括递归关系模型,即源代码中存在递归关系,即函数A调用函数B,而函数B又调用函数A,则所述步骤3具体包括:
如果检查到函数A的父节点是函数B,且检查到函数B的父节点是函数A,此时函数B又是函数A的孩子节点时,则路径中存在递归调用;函数A不用继续扩展,继续下一个函数的模型构建。
其中,所述步骤3还包括:以关键信息列表为输入,构建局部和全局函数调用关系模型;具体包括:
对于全局函数调用关系模型的生成,首先遍历模型列表获取标识为Begin-Start的节点的作为程序的入口点,从入口点的模型开始,将每一个函数的局部函数调用关系模型插入到全局的函数调用关系模型中,插入的这个模型的叶子结点的左孩子指向被替代的那个函数的左孩子节点。
7.一种面向Python的函数调用路径生成系统,其特征在于,包括:
获取单元,用于获取Python源代码的抽象语法树,即AST;
抽取单元,用于遍历所述抽象语法树AST以获取抽象语法树AST中的关键信息;
模型建立单元,用于根据提取到的关键信息,根据Python语言的控制结构特性构建对应的函数调用关系模型,并以树形结构进行存储,并记录函数间的调用关系以生成函数调用关系模型;其中所述函数调用关系模型中的每一个节点代表源代码中的一个函数,如果一个节点存在孩子节点,则该孩子节点代表分支;如果一个节点不存在分支,则代表顺序执行的函数;其中所述函数调用关系模型中的兄弟节点与父节点是并列关系,在源代码中表示多分支结构。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201710802398.4A CN107704382B (zh) | 2017-09-07 | 2017-09-07 | 面向Python的函数调用路径生成方法和系统 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201710802398.4A CN107704382B (zh) | 2017-09-07 | 2017-09-07 | 面向Python的函数调用路径生成方法和系统 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN107704382A true CN107704382A (zh) | 2018-02-16 |
CN107704382B CN107704382B (zh) | 2020-09-25 |
Family
ID=61172264
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201710802398.4A Active CN107704382B (zh) | 2017-09-07 | 2017-09-07 | 面向Python的函数调用路径生成方法和系统 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN107704382B (zh) |
Cited By (10)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110515823A (zh) * | 2018-05-21 | 2019-11-29 | 百度在线网络技术(北京)有限公司 | 程序代码复杂度评估方法和装置 |
WO2020056585A1 (zh) * | 2018-09-18 | 2020-03-26 | 西门子股份公司 | 用于程序文件编写和运行处理的方法及装置、系统 |
CN111858322A (zh) * | 2020-07-10 | 2020-10-30 | 中国科学技术大学 | 一种Python语言特征自动识别系统和方法 |
CN111881028A (zh) * | 2020-07-23 | 2020-11-03 | 深圳慕智科技有限公司 | 一种基于模型代码语法分析的神经网络自动生成方法 |
CN112348688A (zh) * | 2020-11-26 | 2021-02-09 | 德联易控科技(北京)有限公司 | 车险风控分析方法、装置、终端设备及存储介质 |
CN112463149A (zh) * | 2020-12-07 | 2021-03-09 | 中国科学院软件研究所 | 一种面向软件定义卫星的可复用代码库构建方法与装置 |
CN112506780A (zh) * | 2020-12-10 | 2021-03-16 | 零氪科技(北京)有限公司 | 一种问题追踪的方法、系统、电子设备及存储介质 |
CN112704874A (zh) * | 2020-12-21 | 2021-04-27 | 北京信息科技大学 | 一种3d游戏中的哥特式场景自动生成的方法和装置 |
CN112783720A (zh) * | 2021-01-05 | 2021-05-11 | 广州品唯软件有限公司 | 拓扑结构图生成方法、装置、计算机设备和展示系统 |
CN113721896A (zh) * | 2021-06-25 | 2021-11-30 | 中债金科信息技术有限公司 | 一种金融欺诈建模语言的优化处理方法及装置 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101017458A (zh) * | 2007-03-02 | 2007-08-15 | 北京邮电大学 | 基于源代码静态分析的软件安全代码分析器及其检测方法 |
WO2008130769A2 (en) * | 2007-04-20 | 2008-10-30 | Microsoft Corporation | Runtime translation from late-bound to early-bound expression |
CN103473171A (zh) * | 2013-08-28 | 2013-12-25 | 北京信息科技大学 | 一种基于函数调用路径的覆盖率动态跟踪方法及装置 |
CN106020848A (zh) * | 2016-06-07 | 2016-10-12 | 北京信息科技大学 | 面向c#的函数调用路径生成方法 |
-
2017
- 2017-09-07 CN CN201710802398.4A patent/CN107704382B/zh active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101017458A (zh) * | 2007-03-02 | 2007-08-15 | 北京邮电大学 | 基于源代码静态分析的软件安全代码分析器及其检测方法 |
WO2008130769A2 (en) * | 2007-04-20 | 2008-10-30 | Microsoft Corporation | Runtime translation from late-bound to early-bound expression |
CN103473171A (zh) * | 2013-08-28 | 2013-12-25 | 北京信息科技大学 | 一种基于函数调用路径的覆盖率动态跟踪方法及装置 |
CN106020848A (zh) * | 2016-06-07 | 2016-10-12 | 北京信息科技大学 | 面向c#的函数调用路径生成方法 |
Non-Patent Citations (3)
Title |
---|
ZHENG Y: "research on the static function call path generating automatically", 《2010 2ND IEEE INTERNATIONAL CONFERENCE ON INFORMATION MANAGEMENT AND ENGINEERING》 * |
张志华 等: "基于函数调用的路径覆盖生成技术研究", 《电子学报》 * |
陈璐 等: "Android应用安全缺陷的静态分析技术研究", 《计算机工程与应用》 * |
Cited By (13)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN110515823A (zh) * | 2018-05-21 | 2019-11-29 | 百度在线网络技术(北京)有限公司 | 程序代码复杂度评估方法和装置 |
WO2020056585A1 (zh) * | 2018-09-18 | 2020-03-26 | 西门子股份公司 | 用于程序文件编写和运行处理的方法及装置、系统 |
CN111858322B (zh) * | 2020-07-10 | 2022-01-11 | 中国科学技术大学 | 一种Python语言特征自动识别系统和方法 |
CN111858322A (zh) * | 2020-07-10 | 2020-10-30 | 中国科学技术大学 | 一种Python语言特征自动识别系统和方法 |
CN111881028A (zh) * | 2020-07-23 | 2020-11-03 | 深圳慕智科技有限公司 | 一种基于模型代码语法分析的神经网络自动生成方法 |
CN112348688A (zh) * | 2020-11-26 | 2021-02-09 | 德联易控科技(北京)有限公司 | 车险风控分析方法、装置、终端设备及存储介质 |
CN112463149A (zh) * | 2020-12-07 | 2021-03-09 | 中国科学院软件研究所 | 一种面向软件定义卫星的可复用代码库构建方法与装置 |
CN112506780A (zh) * | 2020-12-10 | 2021-03-16 | 零氪科技(北京)有限公司 | 一种问题追踪的方法、系统、电子设备及存储介质 |
CN112704874A (zh) * | 2020-12-21 | 2021-04-27 | 北京信息科技大学 | 一种3d游戏中的哥特式场景自动生成的方法和装置 |
CN112704874B (zh) * | 2020-12-21 | 2023-09-22 | 北京信息科技大学 | 一种3d游戏中的哥特式场景自动生成的方法和装置 |
CN112783720A (zh) * | 2021-01-05 | 2021-05-11 | 广州品唯软件有限公司 | 拓扑结构图生成方法、装置、计算机设备和展示系统 |
CN112783720B (zh) * | 2021-01-05 | 2023-05-19 | 广州品唯软件有限公司 | 拓扑结构图生成方法、装置、计算机设备和展示系统 |
CN113721896A (zh) * | 2021-06-25 | 2021-11-30 | 中债金科信息技术有限公司 | 一种金融欺诈建模语言的优化处理方法及装置 |
Also Published As
Publication number | Publication date |
---|---|
CN107704382B (zh) | 2020-09-25 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN107704382A (zh) | 面向Python的函数调用路径生成方法和系统 | |
US10831456B1 (en) | External code integrations within a computing environment | |
US8701081B2 (en) | Hardware specific code generation | |
CN102243608B (zh) | 基于全局数据结构描述的软件安全测试方法 | |
CN109739494B (zh) | 一种基于Tree-LSTM的API使用代码生成式推荐方法 | |
CN112199086A (zh) | 自动编程控制系统、方法、装置、电子设备及存储介质 | |
CN103914379B (zh) | 故障自动注入与故障检测的方法及其系统 | |
US6990438B1 (en) | Method and apparatus for observability-based code coverage | |
CN110196720B (zh) | 一种Simulink生成动态链接库的优化方法 | |
Schiewe et al. | Advancing static code analysis with language-agnostic component identification | |
CN107515739A (zh) | 提高代码执行性能的方法及装置 | |
CN111435312B (zh) | 应用程序管理方法、装置及电子设备 | |
Su et al. | MDD: A unified model-driven design framework for embedded control software | |
Rieger et al. | Challenges and Opportunities of Modularizing Textual Domain-Specific Languages. | |
CN109947644A (zh) | 基于模型抽取的安全协议javascript语言实施的分析方法及装置 | |
Lee et al. | A New Integrated Software Development Environment Based on SDL, MSC, and CHILL for Large‐scale Switching Systems | |
CN107577476A (zh) | 一种基于模块划分的安卓系统源码差异性分析方法、服务器及介质 | |
Panyala et al. | On the use of term rewriting for performance optimization of legacy HPC applications | |
Mezei et al. | The dynamic sensor data description and data format conversion language. | |
CN111538504A (zh) | 基于Solidity智能合约的语法信息提取方法、设备和存储介质 | |
Eilertsen | Making software refactorings safer | |
CN111078548A (zh) | 测试用例解析方法、装置、存储介质及验证平台 | |
CN110110299A (zh) | 文本变换方法、装置以及服务器 | |
CN116738900B (zh) | 知识产权块的代码转换装置和方法 | |
Grigorev et al. | String-embedded language support in integrated development environment |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |