“与操作语义之间的充分性、可靠性证明可检验模型是否准确。静态分析先以收集语义汇总程序点上的全部可达具体状态,再由抽象解释映到较粗但可计算的性质域。该路线通常在完备格上使用单调算子与Knaste…”
收集所有可能状态 ​
设程序点集合为
其中
若控制边
入口还要加入初始状态集合
与操作语义的关系 ​
操作语义定义一个具体配置怎样一步变成下一个配置。把配置写成
因此两者回答不同问题。小步语义可以展示
这一条执行怎样推进;收集语义则把所有可能到达
大步语义若只关联程序入口与最终结果,通常不足以直接给出中间程序点的集合。静态分析需要循环头、分支汇合等位置的信息,因而常以小步或控制流边语义为基础。
循环例子的固定点轨迹 ​
考虑
x := 0
while x < 3:
x := x + 1
return x
假设整数算术无溢出。初始化后到达循环头的状态集合从
此后再应用方程不产生新状态,故循环头的精确集合为
若只记录一次样例运行,仍会看到
汇合会遗忘路径关系 ​
考虑分支 if b then x:=0 else x:=1。汇合点的收集集合包含两类状态:一类满足
精确收集语义本身仍保留完整状态元组,因此没有丢掉相关性;丢失发生在后续选择的非关系抽象表示。把精确 concrete set 已经产生的路径汇合,与区间、符号等抽象域造成的精度损失混为一谈,会误判假警报来源。
另一方面,按程序点合并确实遗忘了到达路径的身份。若性质依赖“先经过认证节点才可访问资源”,可以把认证位加入状态,或采用 path-sensitive 分析;不在状态中的历史不会由集合收集自动恢复。
为何通常不可直接计算 ​
即使程序语句有限,整数、堆、栈或队列也可让
有限状态程序也可能有指数多状态。逐项枚举精确集合在理论上可行,在工程上仍会遭遇组合爆炸。收集语义的作用不是承诺一个高效表示,而是提供“静态分析究竟要包住什么”的语义标尺。
抽象域用可计算元素代表这些具体集合,抽象转移函数给出可靠外包络。可靠性要求不漏掉
参考资料
- Patrick Cousot and Radhia Cousot, “Abstract Interpretation: A Unified Lattice Model for Static Analysis,” POPL, 1977, pp. 238–252。
- Flemming Nielson, Hanne Riis Nielson, and Chris Hankin, Principles of Program Analysis, Springer, 1999, Chs. 1–2。
- Xavier Rival and Kwangkeun Yi, Introduction to Static Analysis, MIT Press, 2020, Chs. 2–4。