【南大软件分析-学习笔记】Lecture 11 & 12-Point Analysis-Context Sensitivity
0. 前言
接下来开始学习上下文敏感(context sensitivity)的指针分析,上下文敏感的指针分析相比前面所学的上下文不敏感的指针分析具有更高的精度,也是目前 Java 指针分析中做有效的分析方式。
1. Introduction
1.1 C.I.
导致 C.I. 精确度较差的主要原因有以下几个:
- 在程序的动态执行中,一个方法可能在不同的调用上下文(calling context)中被调用多次;
- 在不同的调用上下文中,方法中的变量可能会指向不同的对象;
- 在 C.I. 指针分析中,不同上下文中的对象通过返回值或方法或副作用被混到一起传播到程序各处,导致了虚假数据流。
1.2 C.S.
上下文敏感的指针分析通过把不同数据流下的不同上下文区分开来保证精度。
1.2.1 call-site sensitivity (call-string)
最常见的一种上下文敏感方式是 call-site sensitivity,它把每一个方法的每一个上下文用一个调用点链(a chain of sites)表示,它对程序动态运行时的调用栈进行抽象。
例如,在下面这段代码中,对于方法 id(Name) 而言,它就有两个不同的上下文 [1] 和 [2]。
x = id(n1);
y = id(n2);
int i = x.get();
Number id(Number n) {
return n;
}
使用其它变量表示的上下文敏感将会在第四节中进行介绍。
1.2.2 Cloning-Based Context Sensitivity
最直观的一种上下文敏感的实现方式是 cloning-based context sensitivity,在程序中,每个方法和变量都会带有一个或多个上下文。针对代码中的一个方法或变量,我们为每个上下文克隆了一个该方法或变量,从而将它们区分开来。
还是上面那段代码,使用 cloning-based context sensitivity 的 PFG 如下图所示:
1.2.3 Context-Sensitive Heap
面向对象的程序(例如java)往往是 heap-intensive 的,在实际中,为了提高分析的精度,我们往往也会对堆抽象(heap abstraction)做上下文敏感处理,也就是说,抽象对象也将带有 heap context,在基于 allocation-site 的堆抽象基础上,上下文敏感的堆抽象将提供粒度更细的堆模型:
同样的,C.S 的堆抽象之所以能提高准确性,也是因为:
- 在程序的动态执行中,一个 allocation site 可能在不同的调用上下文中创建多个对象;
- 在同一个 site 创建的不同对象可能是由不同的数据流控制的,例如,将不同的值(值可能来自不同的方法调用)存储到对象的域中。
因此,在指针分析中,在没有 heap context 时,合并不同上下文的数据流到一个抽象对象可能会导致精确度降低,必须要把位于同一 allocation size 但不同上下文的对象区分开才能提高准确度,下面两个例子就分别展示了对方法、变量应用上下文敏感处理,但不对堆进行上下文敏感处理以及对只对堆进行上下文敏感处理而不对方法、变量应用上下文敏感处理导致的分析结果。
2. Rules
2.1 Domain and Notations
首先还是来看一下在上下文敏感中用到的一些表示:
2.2 Rules
其中,\(select\) 函数用于为目标方法 \(m\) 根据 call site 处的信息选取对应的上下文,具体如何选择在第四节中介绍,\(c^t\) 是 callee 的上下文。
3. Algorithms
算法如下:
4. Context Sensitivity Variants
接下来介绍三种上下文敏感处理常用的方式:
- call-site sensitivity
- object sensitiivity
- type sensitivity
先再来关注一下 select 函数吧:
其中,\(c\) 是 caller context,\(l\) 是 call site,\(c':o_i\) 是带有堆上下文的消息接受对象(即调用某个对象的方法)。
4.1 call-site sensitivity
call-site sensitivity 使用调用点链表示上下文,在调用方法时,将当前调用点加入 caller context 的末尾,得到 callee context:
它本质上是对调用栈的抽象。为了保证分析终止并避免上下文过多,通常采用 \(k\)-limiting,只保留调用链中最后 \(k\) 个调用点,称为 \(k\)-call-site sensitivity(或 \(k\)-CFA)。例如,1-call-site 的 callee context 为 \([l]\)。方法上下文和堆上下文可以使用不同的 \(k\)。
4.2 object sensitivity
object sensitivity 使用对象链表示上下文,在调用方法时,将消息接收对象的 allocation site 加到其 heap context 的末尾,得到 callee context:
同样可以使用 \(k\)-limiting,1-object sensitivity 的 callee context 即为 \([o_i]\)。与 call-site sensitivity 相比,两者的精度在理论上不可比较,但在面向对象语言中,object sensitivity 通常具有更高的精度和效率。
4.3 type sensitivity
type sensitivity 使用类型链表示上下文,在调用方法时,将包含接收对象 allocation site 的类型加入其 heap context 的末尾:
注意,\(\text{InType}(o_i)\) 是包含 allocation site 的类型,而不是被创建对象的类型。例如,在类 X 中执行 new Y(),对应的 \(\text{InType}\) 为 X。
type sensitivity 是对 object sensitivity 更粗粒度的抽象:它将同一类型中不同的 allocation site 合并。在相同的 \(k\) 下,type sensitivity 的精度不高于 object sensitivity,但通常具有更高的效率。

浙公网安备 33010602011771号