程序分析与验证中的近似思想
在程序分析和验证中,最核心的概念当数近似(Approximation)。程序分析中的近似可以分为上近似(过近似,Over-approximation)和下近似(Under-approximation)。我们将程序在执行过程中,所有可能出现的状态视为一个集合,称为程序的实际状态集合,记为C。一般而言,集合C是难以获得和准确描述的,而直接在C上进行分析是困难的,其代价也非常高。因此,我们需要使用近似思想,在一个更加“简洁”的集合上进行分析,从而提高效率。在下近似分析中,会在一个C的子集U中进行分析;而在上近似分析中,则会在一个C的超集O中进行分析。
为了保证分析的正确性(Soundness),下近似分析一般只用于找错(证伪,Falsification),但无法用于证明(Verification)。这是因为,在实际状态集C的子集U中寻找到的可达错误状态,一定也是C中的可达错误状态。反之,U中不存在可达错误状态却不能说明C中亦不存在可达错误状态。软件测试可以视为一种下近似分析;软件有界模型检测(BMC)也是一种下近似分析。
相对而言,上近似分析则一般只用于证明,而不直接用于找错。这是因为在实际状态集C的超集O中不存在可达的错误状态,那么C中一定也不存在可达错误状态。反之,O中存在可达的错误状态,却不能说明C中亦存在可达的错误状态。一般基于抽象的方法,比如静态分析中的各类基于抽象解释的分析算法,程序验证中的谓词抽象、路径抽象等等,都是上近似分析;引入不变式也是一种上近似。
需要注意的是,上近似与下近似不能混用,否则将导致分析结果不正确(Unsound)。这是因为分析过程中必须维持分析的集合和实际状态集合之间的子集或超集关系。一旦混用,则无法明确得到这一关系,从而有可能使得找错不准,证明也不正确。
值得注意的是,很多验证工具和算法能够同时实现证明和找错,例如参加程序验证大赛(SV-COMP)的工具,基本上都支持对安全属性(Safety Property)的证明和证伪。这其中的原因很简单,一般而言,这些工具都是基于上近似验证算法的(CBMC是基于下近似,但是它的证明方法比较特殊)。但是,这些验证算法会对在集合O中寻找到的可达错误状态(错误路径)进行检验(Validate),以确定所寻找到的错误状态是实际状态集合C中可达的。
例如,在基于反例制导的抽象精化的谓词分析(CEGAR-PA)算法中,就会对当前精度(Precision,谓词集合)下的抽象状态空间(集合O)中,所寻找到的可达错误状态的路径,使用SMT编码进行检验。倘若路径真实可达,则寻找到了一个真反例(真实的错误路径)。而反之若路径不可达(Infeasible),则寻找到了一个伪反例(Spurious Counter-example)。这说明当前的抽象不够精确,需要精化。基于对找到的伪反例进行插值分析,可以得到一系列能证明该路径不可达的谓词,作为新增的谓词,加入到精度集合中,从而消去该伪反例,精化抽象空间。
转载自https://zhuanlan.zhihu.com/p/377410186
浙公网安备 33010602011771号