模型检测与符号执行技术

1.模型检测( Model Checking)

模型检测是一种很重要的自动验证技术,主要思想是先建立待测系统的有限状态模型,然后用算法穷尽检测模型中的状态,判断其是否满足待测属性。若不满足,则根据反馈信息判断具体系统中是否确实存在违反此属性的执行路径(即反例路径)。 

模型检测依赖的是对程序行为空间的自动化遍历。遍历也就意味着穷尽搜索,所以一开始模型检测技术主要检查的对象是用有穷状态机(Finite State Machine)描述的系统模型。那么检测什么呢?总得有个什么叫对什么叫不对的标准吧。在模型检测领域,一般我们验证的是某个模型是否满足给定的形式化规约(Formal Specification)。有了系统的模型,有了检测的规约,这两者就 构成了模型检测技术的输入

模型检测技术将自动化的去对系统模型的状态空间进行显式地遍历或者符号化地不动点(fix point)计算来判断该模型的行为是否满足规约的要求,比如会不会出现温度超过A,或者颜色跳错了等。当检查结束时,如果未出现反例,则这个模型对于此规约而言一定是正确的;而如果检查中出现反例,该技术会给出一个具体的执行轨迹,告诉你模型是怎么一步步执行并最终违反了你给出的规约。 

由于模型检测技术需要对状态空间做一个穷尽的搜索,所以当系统状态空间过大的时候,该技术的处理能力就会遇到一定问题。说直白一点,如果将这个系统背后可能的状态一个个列出来就能把你电脑内存吃干净甚至于都放不下的话,你还想在上面做搜索,你的计算机一定要哭着臣妾做不到,分分钟死给你看了。 

所以,科学家们提出了各种各样的包括符号模型检测(Symbolic Model Checking),偏序约减(Partial Oder Reduction),状态抽象(Abstraction)等在内的一系列优化技术来压缩状态的表达,缩减要验证的空间,提高遍历的效率。随着相关技术的逐步发展,模型检测也终于从实验室走向了应用,在电路设计,协议设计等领域发挥了巨大的作用。

 

2.符号执行(Symbolic Execution)

2.1 定义

符号执行 是一种程序分析技术,它可以通过分析程序来得到让特定代码区域执行的输入。顾名思义,使用符号执行分析一个程序时,该程序会使用符号值作为输入,而非一般执行程序时使用的具体值。在达到目标代码时,分析器可以得到相应的路径约束,然后通过约束求解器来得到可以触发目标代码的具体值。

2.2 目标

软件测试中的符号执行主要目标是: 在给定的探索尽可能多的、不同的程序路径(program path)。对于每一条程序路径,(1) 生成一个具体输入的集合(主要能力);(2) 检查是否存在各种错误,包括断言违规、未捕获异常、安全漏洞和内存损坏。

2.3 经典符号执行技术

符号执行的主要思想就是将输入(input)用符号来表征而不是具体值,同时将程序变量表征成符号表达式。因此,程序的输出就会被表征成一个程序输入的函数,即fun(input)。在软件测试中,符号执行被用于生成执行路径(execution path)的输入。在具体的执行过程中,程序在特定的输入上运行,并对单个控制流路径进行了探索。因此,在大多数情况下,具体的执行只能在对相关财产进行近似分析的情况下进行。相反,符号执行可以同时探索程序在不同输入下可能采用的多种路径。这为可靠的分析铺平了道路,可以对检查的属性产生强有力的保证。关键思想是允许程序采用符号而不是具体的输入值。

执行路径(execution path):一个true和false的序列seq={p0,p1,…,pn}。其中,如果是一个条件语句,那么pi=ture则表示这条条件语句取true,否则取false。
执行树(execution tree):一个程序的所有执行路径则可表征成一棵执行树。

例如,图1中的函数testme()有三个执行路径,形成了图2所示的执行树。


å¨è¿éæå¥å¾çæè¿°

                                                                       图1

å¨è¿éæå¥å¾çæè¿°

                                                                       图2

 

3条不同的执行路径构成了一棵执行树。三组输入{x=0,y=1},{x=2,y=1},{x=30,y=15}覆盖了所有的执行路径。

符号状态(symbolic state):符号执行维护一个符号状态e,它将变量映射到符号表达式。
符号路径约束(symbolic path constraint):符号路径约束PC,它是符号表达式上无量词的一阶公式。

符号执行后的结果如下图所示:e和PC都在符号执行过程中更新。 在沿着程序的执行路径的符号执行结束时,使用约束求解器来求解PC以生成具体的输入值。如果程序在这些具体的输入值上执行,它将采用与符号执行完全相同的路径并以相同的方式终止。例如,图1中代码的符号执行以空符号状态开始,符号路径约束为true。执行过程中的状态如图中红色部分所示。

2.4 混合执行(Concolic Execution)

最早将实际执行和符号执行结合起来的是2005年发表的DART[5],全称为“Directed Automated Random Testing”,以及2005年发表的CUTE[6],即“A concolic unit testing enginefor C”。

Concolic执行维护一个实际状态和一个符号化状态:实际状态将所有变量映射到实际值,符号状态只映射那些有非实际值的变量。Concolic执行首先用一些给定的或者随机的输入来执行程序,收集执行过程中条件语句对输入的符号化约束,然后使用约束求解器去推理输入的变化,从而将下一次程序的执行导向另一条执行路径。简单地说来,就是在已有实际输入得到的路径上,对分支路径条件进行取反,就可以让执行走向另外一条路径。这个过程会不断地重复,加上系统化或启发式的路径选择算法,直到所有的路径都被探索,或者用户定义的覆盖目标达到,或者时间开销超过预计。

我们依旧以上面那个程序的例子来说明。Concolic执行会先产生一些随机输入,例如{x=22, y=7},然后同时实际地和符号化地执行程序。这个实际执行会走到第7行的else分支,符号化执行会在实际执行路径生成路径约束x_{0} \ne 2 y_{0}。然后concolic执行会将路径约束的连接词取反,求解x_{0} = 2 y_{0}得到一个测试输入{x=2, y=1},这个新输入就会让执行走向一条不同的路径。之后,concolic执行会在这个新的测试输入上再同时进行实际的和符号化的执行,执行会取与此前路径不同的分支,即第7行的then分支和第8行的else分支,这时产生的约束就是(x_{0}=2y_{0})\wedge (x_{0}\leq y_{0}+10),生成新的测试输入让程序执行没有被执行过的路径。再探索新的路径,就需要将上述的条件取反,也就是(x_{0}=2y_{0})\wedge (x_{0}> y_{0}+10),通过求解约束得到测试输入{x=30, y=15},程序会在这个输入上遇到ERROR语句。如此一来,我们就完成了所有3条路径的探索。

这个过程中,我们从一个实际输入{x=22, y=7}出发,得到第一个约束条件x_{0} \ne 2 y_{0},第一次取反得到x_{0} = 2 y_{0},从而得到测试输入{x=2, y=1}和新约束(x_{0}=2y_{0})\wedge (x_{0}\leq y_{0}+10);第二次取反得到(x_{0}=2y_{0})\wedge (x_{0}> y_{0}+10),从而求解出测试输入{x=30, y=15}。

å¨è¿éæå¥å¾çæè¿°

注意在这个搜索过程中,其实concolic执行使用了深度优先的搜索策略。

 

参考:https://www.testwo.com/article/683

           https://blog.csdn.net/omnispace/article/details/80248252

           https://blog.csdn.net/wcventure/article/details/86773290

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值