本文首先阐述有界模型检查(Bounded Model Checking)和 k-induction 的基本概念,然后介绍使用了 k-induction 的工具 CPAChecker、ESBMC 和 2LS。
Bounded Model Checking
模型检查的基本概念是将程序看作一个状态迁移系统
有界模型检查(Bounded Model Checking, BMC)是一种基于 SAT/SMT 求解器的模型检查方法。它通过检查系统在
其中
BMC 是一种下近似方法,适用于寻找反例,但不能证明系统的正确性。比如程序:
x = 0;
y = 0;
while (x < 10) {
x++;
y++;
}
assert(y > 10);对其进行
x_0 = 0;
y_0 = 0;
// g_0 <=> x_0 < 10
x_1 = x_0 + 1;
y_1 = y_0 + 1;
// g_1 <=> x_1 >= 10
x_2 = ite(g_0, x_1, x_0);
y_2 = ite(g_0, y_1, y_0);
assert(y_2 > 10);将上述 SSA 形式的程序转化为 SMT 公式,得到:
把这个公式交给 SMT 求解,得到 SAT,说明不存在长度为 1 的反例路径。假设我们预设的
k-induction 扩展了 BMC 的能力,通过增加一个归纳步骤来证明程序的正确性。
k-induction
k-induction 包含两个步骤:基步骤和归纳步骤。
基步骤与 BMC 类似,检查程序从初始状态
形式化地,定义:
Base case:
Induction step:
归纳步骤的前提不包含
x = 1;
y = 1;
while (x < 10) {
x++;
y++;
}
assert(x == y);初始情况下,
x_0 = 1;
y_0 = 1;
assert(x_0 == y_0);将上述 SSA 形式的程序转化为 SMT 公式,得到:
把这个公式交给 SMT 求解,得到 UNSAT,说明不存在长度为 1 的反例路径。对于归纳步骤(
havoc(x_0);
havoc(y_0);
assume(x_0 == y_0); // 归纳假设
// g_0 <=> x_0 < 10
x_1 = ite(g_0, x_0 + 1, x_0);
y_1 = ite(g_0, y_0 + 1, y_0);
assert(x_1 == y_1); // 需要证明对应地,将归纳步骤转成 SMT 可满足性检查:
该公式 UNSAT,说明归纳步骤成立。因此该程序确实是正确的。
上述例子通过
如果对于更加复杂的程序或更加复杂的性质,需要逐步增大
CPAChecker
CPAChecker 的整体架构如图:
CPAChecker 在 A Unifying View on SMT-Based Software Verification 中给出了在 Configuarble Program Analysis 中进行 k-induction 的算法。
以下面的程序为例:
base:
induction:
ESBMC v6.0
在 ESBMC v6.0 的论文中使用了不太相同的记号,不过目标相同:
ESBMC v6.0 提出使用区间分析加强不变式合成。在 k-induction 之前进行静态分析,过近似地估计变量的可能取值范围,实现一种 rectangular invariant 生成(例如
2LS for Program Analysis
2LS 的核心算法是 k-induction k-invariant (kIkI) 算法。算法流程如图:
和 ESBMC 的思路不同,2LS 在 k-induction 的过程中合成 template-based invariant。
k-invariant 的合成基于抽象解释。
具体化函数
定义路径条件:
类似 CEGAR 的思路,从
如果上面的公式 SAT,说明找到了一个反例,那么利用反例的结果增强原先的抽象域,表示为用
Lam4Inv
题外话:
LLM Meets Bounded Model Checking: Neuro-symbolic Loop Invariant Inference






