循环语句中变量抽象取值的迭代求精方法

文档序号:6440117阅读:305来源:国知局
专利名称:循环语句中变量抽象取值的迭代求精方法
技术领域
本发明涉及程序静态分析技术,尤其涉及一种在程序静态分析时,循环语句中变量抽象取值的迭代求精方法。
背景技术
程序测试是在一个可控的环境中分析或执行程序的过程,其根本目的是以尽可能少的时间和人力发现并改正程序中潜在的各种故障及缺陷,提高程序的质量。从是否需要运行被测程序,可以将程序测试方法分为两大类动态测试方法和静态测试方法;所谓动态测试,就是通过运行程序来检验程序的动态行为和运行结果的正确性;所述静态测试的基本特征是在对程序进行分析、检查和测试时不实际运行被测试的程序。动态测试和静态测试各有其优缺点,动态测试的优点是被发现的程序错误会非常直观的呈现出来;缺点是不同的测试用例发现错误的能力差别很大,因此对测试用例的设计要求高,另外,需要实际运行被测程序也对程序测试提出了较高的要求。静态测试优点是不需要设计测试用例,不需要实际运行被测程序,容易实现自动化测试;静态测试的缺点是测试发现的问题往往不能直接确定为程序错误,还需要通过人工分析进行确认,因此,静态测试也被称作静态分析。目前,通常采用数据流迭代分析方法对程序进行静态分析,所述数据流迭代分析是一种用来获取有关数据如何沿着程序执行路径流动的相关信息的技术,具体是指重复执行一组指令或一定步骤,在每次执行这组指令或这些步骤时,都从变量的原值推出它的一个新值。数据流迭代分析的基础是控制流图(Control Flow Graph,CFG),所述CTO是一种反应程序逻辑控制流程的有向图,是进行数据流迭代分析必不可少的基础数据结构。一个程序的CFG通常可表示为N,E,Entry, Exit,其中,N代表节点的集合,所述节点包括顺序节点、分支节点和汇合节点,其中,顺序节点对应程序中的顺序执行语句,具有1个前驱和1个后继;分支节点对应程序中的条件判断语句,具有两个或两个以上的后继,程序中的if、switch及循环语句中的条件判定语句均属于此类分支节点;汇合节点对应程序中各分支语句的退出节点,具有两个或两个以上的前驱,例如if语句块退出时的节点为if_out,它汇合了来自真假分支中的语句;循环语句头节点LoopHead汇合了来自直接前驱节点和循环回边节点中的数据流。E代表有向边的集合,其反映程序中语句间的控制流关系。Entry代表入口节点,该入口节点为函数的固定、唯一的入口节点,具有0个前驱和1个后继。Exit代表出口节点,该出口节点为函数的固定、唯一的退出节点,具有1个前驱和 0个后继。因此,概括的讲所述CFG是具有固定、唯一的入口节点和出口节点的有向图 ’为适应多入口和/或出口的程序,可以在CFG中添加统一的入口和/或出口节点。程序的执行可以从程序状态及状态转换的角度来理解,即将程序的执行看作是对程序状态的一系列转换;程序状态由程序中的所有变量的值组成,同时包括运行时刻栈的栈顶之下各个栈帧的相关值。当分析一个程序的行为时,必须考虑程序执行时可能采取的各种通过程序的流图的程序点序列(即为程序路径);然后从各个程序点上可能的程序状态中抽取出需要的信息,用以解决特定数据流分析问题。程序执行过程中,程序状态本质上由两个因素决定程序中各变量的当前取值 (这里的变量是广义上的变量,包括各种全局内存、栈内存和堆内存的内容)和程序执行的当前位置。基于程序状态的概念,程序的执行可以看作是程序状态的一系列转换过程。一条语句的执行把程序从一个状态转换到另一个状态,语句的语义可以看作是针对程序状态的转换函数,其输入状态和该语句之前的程序点相关联,而输出状态和该语句后的程序点相关联。当静态地分析一个程序的动态行为时,需要考虑程序执行时可能通过CFG的各种路径,然后根据分析问题的需要从各程序点上可能的程序状态中抽取需要的信息。一般来说,一个程序可能有无穷多条路径,路径的长度也没有上界。程序分析通常把每个程序点上可能出现的所有程序状态集合作为最根本的信息来源,但实际中无法精确地计算和表示每个程序点上的可能程序状态集合,不同的分析技术选择抽象掉无用的信息,保留有用的信肩、ο另外,在分析过程中用变量的区间来表示数据流信息,所以在生成CFG后需要基于该CFG生成区间信息,所述区间信息是区间运算得到的结果。所谓变量的区间,就是指变量的取值范围。区间运算的目的是对程序中出现的变量和表达式的取值范围进行跟踪,为进一步的程序分析提供精确的信息支持。Java中的变量有不同的类型,因此变量的区间也有不同的类型。实际的区间计算中,变量的取值信息可能会被以下语句所更新变量赋值语句、条件判断语句、循环判断语句等。对于赋值语句,它对变量的取值范围的影响是显然的。例如 i = i+3 ;假设i原来的取值范围为[1,5],则执行了该语句后i的取值范围为W,8]。程序中的条件判断也会影响变量取值范围。例如
if(i>=3){
}else{
}i原来的取值范围为[1,5],那么在if语句真分支上由于受到i > = 3条件取真的限定,则i的取值范围为[3,5],相应地在if假分支上受到i > = 3条件取假的限定,则 i的取值范围为[1,2]。控制流对于变量的区间起传递和汇合的作用。目前,对程序进行静态分析的过程通常包括如下步骤首先,生成程序的CFG。其次,在Entry初始化数据流集合。所谓数据流集合是对程序实际执行语义的抽象,它包括了函数形参、局部变量和全局变量的运行时动态取值信息。
最后,以此初始的数据流集合为基础,根据经典的数据流分析框架沿着控制流依次进行数据流迭代,分别计算CFG中每个节点的数据流^集合和数据流Out集合,直到每个节点的数据流状态稳定,就得到了每个控制流节点(即每条程序语句)处相关变量的抽象取值信息,即整个函数的数据流方程解。数据流迭代分析方法在进行循环语句中变量抽象取值计算时,由于程序中的循环语句存在变量,造成迭代次数未知,尤其是遇到特殊的循环(例如while(l)或f0r(i = 0 ; i < 100000000 ; i++)类似的循环)时,可能导致数据流迭代收敛缓慢,甚至不收敛,无法得到整个函数的数据流方程解,最终影响对程序进行静态分析。

发明内容
有鉴于此,本发明的主要目的在于提供一种循环语句中变量抽象取值的迭代求精方法,能够解决循环语句中变量抽象取值迭代计算收敛速度慢或不收敛的问题。为达到上述目的,本发明的技术方案是这样实现的本发明公开了一种循环语句中变量抽象取值的迭代求精方法,所述方法包括根据控制流图CFG进行数据流迭代,得到上次迭代区间LastDomain ;根据循环头节点LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain ;将 LastDomain 禾口 ThisDomain 进行力口宽 Widening 操作。较佳的,所述根据CFG进行数据流迭代,得到上次迭代区间LastDomain为根据CFG进行数据流迭代,得到LoopHead的循环语句的直接前驱I^reHeadNode 的区间和循环回边性质的前驱PostHeadNode的区间,将所述I^reHeadNode的区间和 PostHeadNode的区间取并集得到上次迭代区间LastDomain。较佳的,所述根据LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain为,根据LoopHead的循环条件进行循环语句块的数据流迭代,生成新PostHeadNode 的区间,将上次迭代得到的I^reHeadNode的区间与新PostHeadNode区间取并集,得到本次迭代区间ThisDomain。较佳的,所述将LastDomain和ThisDomain进行Widening操作之后,该方法还包括判定与LastDomain相比Widening后的区间发生改变时,将Widening后的区间作为新的 LastDomain ;重复根据LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间 ThisDomain,将 LastDomain 和 ThisDomain 进行 Widening 操作的步骤。较佳的,所述将LastDomain和ThisDomain进行Widening操作之后,该方法还包括判定与LastDomain相比Widening后的区间没有发生改变,将Widening后的区间记为中间迭代区间hterDomain,作为收窄Narrowing操作的输入;按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain ;判断与InterDomain相比ThisDomain是否发生改变,如果发生变化,将InterDomain与ThisDomain执行Narrowing操作;如果没有发生变化,数据流迭代终止。较佳的,所述按循环条件进行循环语句块的数据流迭代,得到本次迭代区间 ThisDomain 为按循环条件进行循环语句块的数据流迭代,得到I^eHeadNode的区间与 PostHeadNode的区间,将所述PreHeadNode的区间和PostHeadNode的区间取并集得到本次迭代区间ThisDomain。较佳的,所述将InterDomain与HiisDomain执行Narrowing操作之后,该方法还包括将Narrowing后的区间记为新的InterDomain ;重复按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain, 判断与InterDomain相比ThisDomain是否发生改变的步骤。由上可知,本发明循环语句中变量抽象取值的迭代求精方法,将抽象解释理论中的加宽Widening算子应用于数据流迭代方法,使得循环语句数据流迭代可以快速收敛,提高得到整个函数的数据流方程解的效率;将抽象解释理论中的收窄Narrowing算子应用于数据流迭代方法,又能使得到的数据流方程解更加接近精确解,有利于循环内部的变量区间检查及循环后变量的区间运算。


图1为本发明循环语句中变量抽象取值的迭代求精方法第一实施例的流程示意图;图2为示例程序片断的CFG ;图3为本发明循环语句中变量抽象取值的迭代求精方法第二实施例的流程示意图;图4为本发明循环迭代求精的流程结果示意图。
具体实施例方式本发明公开的循环语句中变量抽象取值的迭代求精方法的第一实施例,如图1所示,所述方法包括步骤101、根据CFG进行数据流迭代,得到上次迭代区间LastDomain ;具体的,根据CFG进行数据流迭代,得到LoopHead的循环语句的直接前驱 PreHeadNode的区间和循环回边性质的前驱PostHeadNode的区间,将所述PreHeadNode的区间和PostHeadNode的区间取并集得到上次迭代区间LastDomain。步骤102、根据循环头节点LoopHead的循环条件进行循环语句块的数据流迭代, 得到本次迭代区间HiisDomain ;具体的,根据LoopHead的循环条件进行循环语句块的数据流迭代,生成新 PostHeadNode的区间,将上次迭代得到的PreHeadNode的区间与新PostHeadNode区间取并集,得到本次迭代区间ThisDomain。步骤103、将 LastDomain 和 ThisDomain 进行加宽 Widening 操作。由上可知,采用上述技术方案能够使循环语句数据流迭代快速收敛,提高得到整个函数的数据流方程解的效率。可选的,所述将LastDomain和ThisDomain进行加宽Widening操作之后,还包括 判断与LastDomain相比Widening后的区间是否发生改变,如果发生变化,将Widening后的区间作为新的LastDomain,重复步骤102和步骤103的操作,直到与LastDomain相比 Widening后的区间没有发生改变数据流迭代终止,此时各控制流节点所关联的数据流信息即为循环迭代求精的结果,结束本次流程。可选的,所述将LastDomain和ThisDomain进行加宽Widening操作之后,还包括判定与LastDomain相比Widening后的区间没有发生改变,将Widening后的区间记为中间迭代区间hterDomain,作为收窄Narrowing操作的输入;按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain ;具体的,按循环条件进行循环语句块的数据流迭代,得到I^reHeadNode的区间与PostHeadNode 的区间,将所述I^reHeadNode的区间和PostHeadNode的区间取并集得到本次迭代区间 ThisDomain0判断与InterDomain相比ThisDomain是否发生改变,如果发生变化,将 InterDomain与ThisDomain执行Narrowing操作;如果没有发生变化,数据流迭代终止,此时各控制流节点所关联的数据流信息即为循环迭代求精的结果,结束本次流程。可选的,所述将InterDomain与HiisDomain执行Narrowing操作之后,还包括将Narrowing后的区间记为新的InterDomain ;重复按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain 和判断与InterDomain相比ThisDomain是否发生改变的步骤。由上可知,采用上述技术方案能使得到的数据流方程解更加接近精确解,有利于循环内部的变量区间检查及循环后变量的区间运算。下面以将本发明应用于一个程序片断为例,对本发明进行详细的介绍。所述程序片断如下
void fun(){ Li: inti=l,j=l; L2: while(i<100){ L3: i++; L4: j++;
L5: } }其中,Ll处的代码行为循环语句的直接前驱I^reHeadNode,L2处的代码行为循环头节点LoopHead,L5处代码行为循环回边性质的前驱PostHeadNode。 所述程序片断的CFG如图2所示。图2中的Func_Head_fun_0中的FuncJfead为函数的Entry,fun为函数名,O为节点序号;相似的,Func_0ut_fun_6中的Func_0ut为函数的Exit,6为节点序号。
CFG的每条边按其分析次序都有相应的编号,如图1中箭头线上的0、1、3和4。如果是分支边,则根据其真假条件分别命名为T或F序号,如图1中箭头线上的T_2、F_5。根据每条程序语句的语义特征,为出口、入口节点之外的其他节点都生成了不同的前缀名称,例如声明语句为decl_Stmt、while循环头节点为whilejiead,普通语句为 stmt,所有节点后边都附有节点序号。图3为本发明循环语句中变量抽象取值的迭代求精方法第二实施例的流程示意图,如图所示,所述方法包括以下步骤步骤301、根据CFG进行数据流迭代,得到LoopHead的I^reHeadNode的区间和 PostHeadNode的区间,将所述PreHeadNode的区间和PostHeadNode的区间取并集得到上次迭代区间LastDomain0具体的,从函数的Entry,即图1中的FimcJfead节点开始进行数据流迭代,初始区间为空,对LoopHead进行数据流汇聚h,到达Ll后,区间变为U [1,1] j [1,1]}。由于 L5处尚未进行过迭代,此时LoopHead节点的数据流区间为{i :[1,1] j [1,1]}。LoopHead 节点始终保存有两类区间,一类是当前迭代的基础,另一类是迭代后更新的区间,前者即为 LastDomain,后者为ThisDomain,通过对比迭代前后两个区间是否发生变化,来进行加宽或收窄操作,以及判断迭代是否应该终止。步骤302、根据LoopHead的循环条件进行循环语句块的数据流迭代,生成新 PostHeadNode的区间,将上次迭代得到的PreHeadNode的区间与新PostHeadNode区间取并集,得到本次迭代区间ThisDomain。具体的,将LoopHead的初始区间{i :[1,1] j [1,1]},根据循环条件(i < 100) 拆分为真假分支真分支为U:[1,1] j:[i,i]},假分支为空区间。真分支经过L3、L4迭代后得到区间{i :[2,2] j :[2,2]}与Ll处的区间U :[1,1] j :[1,1]}合并得到U :[1,2] j :[1,2]},作为本次迭代区间ThisDomain。步骤303、将 LastDomain 和 ThisDomain 进行加宽 Widening 操作。具体的,将LastDomain和ThisDomain进行通过加宽算子▽进行Widening操作。 所述widening算子为[a 1, b 1 ] V[a2 ,b2 ]=[L1,L2]If (a2 < al)then Ll =-⑴;else Ll = al ;If (b2 > bl)then L2 = + ⑴;else L2 = bl ;例如口V [1,10]=[1,10][1,10] V [l,ll]=[l,+ oo][Ι,+ οο] V
=[-oo,+oo]因此,LastDomain = {i :[1,1] j : [1,1] },ThisDomain = {i : [1,2] j:[l,2]},二者加宽后的区间为U:[i,⑴]j:[i,^]}。步骤304、判断与LastDomain相比Widening后的区间是否发生了改变;如果与 LastDomain相比Widening后的区间没有变化,则表示数据流迭代稳定,进入步骤305 ;如果与LastDomain相比,Widening后的区间有变化,进行步骤309。很明显,本例在加宽操作后区间发生了变化,因此进行步骤309的运算;将 LastDomain更新为{i:[l,⑴]j:[l,⑴]}后,再次进入步骤302迭代根据循环条件while (i< 100),真分支中数据流为U :[1,99] j [1,⑴]},经过L3、L4语句迭代后更新为 U: [2,100] j [2,- ]};将此迭代结果与Ll处区间合并得到新的ThisDomain= {i:[l, 100] j]} JfLastDomain= {i:[l,⑴]j [1,①]}与其加宽操作后,得到新的区
间仍然为U [1,①]j [1,- ]},表示迭代稳定,进入步骤305。 步骤305、将Widening后的区间记为中间迭代区间InterDomain,作为收窄 Narrowing操作的输入。具体地,InterDomain = {i :[1,°° ] j]}。步骤306、按循环条件进行循环语句块的数据流迭代,得到I^eHeadNode的区间与 PostHeadNode的区间,将所述PreHeadNode的区间和PostHeadNode的区间取并集得到本次迭代区间ThisDomain。具体地,ThisDomain= {i :[1,100] j:[l,⑴]}。步骤307、判断与InterDomain相比ThisDomain是否发生了改变;如果与 InterDomain相比ThisDomain没有变化,则表示数据流迭代稳定,进入步骤310 ;如果与 InterDomain相比ThisDomain有变化,进入步骤308。明显地,进行收窄操作后区间发生了变化,因此进入步骤308。PM 308, InterDomain 与 ThisDomain ^Mf NarrowingNarrowingB^ 区间记为新的hterDomain,进入步骤306。具体的,将 InterDomain 与 ThisDomain 通过 narrowing 算子 Δ 进行 Narrowing 操作,所述narrowing算子Δ为[al, bl] Δ [a2, b2] = [Li, L2]If (al =-⑴)then Ll = a2 ;else Ll = MIN(al, a2);If (bl = + ⑴)then L2 = b2 ;else L2 = MAX (bl, b2);例如[-c ,+ ①]Δ [- c ,101] = [- c ,101][- c ,101] Δ
=
Δ
=
具体的,将Narrowing之后的区间U [1,100] j :[1,⑴]}作为新的 InterDomain,进入步骤306 ;根据循环条件(i < 100)拆分为真假分支真分支中,U :[1, 99] j :[1,⑴]},经过L3、L4迭代后得到区间U :[2,100] j [2,-]};与Ll处区间合并得至丨J ThisDomain = {i [1,100] j [1, 00 ]},将 InterDomain 与 ThisDomain 进行 narrowing 后区间仍为{i [1,100]」[1,^]},表示迭代稳定。步骤309,将Widening后的区间作为新的LastDomain,进入步骤302。步骤310,数据流迭代终止,此时各控制流节点所关联的数据流信息即为循环迭代求精的结果,结束本次流程。Exit即FimC_0ut节点得到的数据流方程解中的i为100,与循环迭代的精确解完全一致;j的区间为[1,⑴],相对于保守数据流方程解有所扩大。所谓的精确解指的真实的程序执行语义,通过观察程序片断,在循环退出节点i 的值是100,与分析结果完全一致;而j的精确值也是100,但由于执行加宽及收窄运算,导致了精度损失,因此最终得到j的区间[1,⑴]是保守解,即它对真实程序语义扩大化了。下面的表一和表二给出了整体的分析步骤,为了简化,表中只对变量i的区间进行了记录,L3、L4语句处区间为取L2处真分支条件运算的结果(表一)
权利要求
1.一种循环语句中变量抽象取值的迭代求精方法,其特征在于,所述方法包括根据控制流图CRi进行数据流迭代,得到上次迭代区间LastDomain ;根据循环头节点LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间 ThisDomain ;将 LastDomain 禾口 ThisDomain 进行力口宽 Widening 操作。
2.根据权利要求1所述的方法,其特征在于,所述根据CFG进行数据流迭代,得到上次迭代区间LastDomain为根据Cre进行数据流迭代,得到LoopHead的循环语句的直接前驱I^reHeadNode的区间和循环回边性质的前驱PostHeadNode的区间,将所述PreHeadNode的区间和PostHeadNode 的区间取并集得到上次迭代区间LastDomain。
3.根据权利要求2所述的方法,其特征在于,所述根据LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain为,根据LoopHead的循环条件进行循环语句块的数据流迭代,生成新PostHeadNode的区间,将上次迭代得到的I^reHeadNode的区间与新PostHeadNode区间取并集,得到本次迭代区间 ThisDomain0
4.根据权利要求1所述的方法,其特征在于,所述将LastDomain和HiisDomain进行 Widening操作之后,该方法还包括判定与LastDomain相比Widening后的区间发生改变时,将Widening后的区间作为新的 LastDomain ;重复根据LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间 ThisDomainJf LastDomain 和 ThisDomain 进行 Widening 操作的步骤。
5.根据权利要求1所述的方法,其特征在于,所述将LastDomain和HiisDomain进行 Widening操作之后,该方法还包括判定与LastDomain相比Widening后的区间没有发生改变,将Widening后的区间记为中间迭代区间hterDomain,作为收窄Narrowing操作的输入;按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain ;判断与hterDomain相比ThisDomain是否发生改变,如果发生变化,将hterDomain 与ThisDomain执行Narrowing操作;如果没有发生变化,数据流迭代终止。
6.根据权利要求5所述的方法,其特征在于,所述按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain为按循环条件进行循环语句块的数据流迭代,得到I^reHeadNode的区间与PostHeadNode 的区间,将所述I^reHeadNode的区间和PostHeadNode的区间取并集得到本次迭代区间 ThisDomain0
7.根据权利要求5所述的方法,其特征在于,所述将InterDomain与ThisDomain执行 Narrowing操作之后,该方法还包括将Narrowing后的区间记为新的hterDomain ;重复按循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain,判断与hterDomain相比ThisDomain是否发生改变的步骤。
全文摘要
本发明提供了一种循环语句中变量抽象取值的迭代求精方法,所述方法包括根据控制流图CFG进行数据流迭代,得到上次迭代区间LastDomain;根据循环头节点LoopHead的循环条件进行循环语句块的数据流迭代,得到本次迭代区间ThisDomain;将LastDomain和ThisDomain进行加宽Widening操作。采用本发明公开的技术方案能够解决循环语句中变量抽象取值迭代计算收敛速度慢或不收敛的技术问题。
文档编号G06F11/36GK102495800SQ20111040017
公开日2012年6月13日 申请日期2011年12月5日 优先权日2011年12月5日
发明者宫云战, 王思岚, 肖庆, 赵云山, 金大海 申请人:北京邮电大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1