Click Here Return to Posts List
# Context Sensitive
## Example
```bash
void main(){
Number n1, n2, x, y;
n1 = new One();
n2 = new Two();
x = id(n1);
y = id(n2);
int i = x.get();
}
Number id(Number n){
return n;
}
interface Number{
int get();
}
class One implements Number{
public int get(){
return 1;
}
}
class Two implements Number{
public int get(){
return 2;
}
}
```
e.g.1
```bash
n1 -> o1
n2 -> o2
n -> o1,o2
x -> o1,o2
y -> o1,o2
x.get() -> NAC
y.get() -> NAC
```
对于常量传播来说,n1对应了o1,n2对应了o2,id类使n对应了o1,o2,再传到x,y中时他们分别都指向了o1和o2,在最终get的时候就会使得$1\cap 2$ = NAC
但是对于上下文敏感(动态分析)的时候,就会分开考虑,从而使x.get()返回正确的值1
e.g.2
```bash
n1 -> o1
n2 -> o2
id(n1):n -> o1
id(n2):n -> o2
x -> o1
y -> o1
x.get() -> 1
y.get() -> 2
```
## Context Sensitivity
Context Sensitivity models calling contexts by distinguishing different dataflows of different contexts to improve precision
### Call-Site sensitivity
The oldest and best-known context sensitivity strategy. It represent each context a chain of call site.
e.g.3
```bash
1.x = id(n1);
2.y = id(n2);
3.int i = x.get();
Number id(Number n){
return n;
}
```
method id has two context: 1 and 2.
### Cloning-Based Context Sensitivity
In Cloning-Based Context Sensitivity, each method and variable are qualified by context. for example in the e.g.2
In practice, JAVA and other OOPLs are **heap-sensitive**, so context sensitivity should also apply to heap abstraction, and each object should be qualified by context
e.g.4
```bash
n1 = new One();
n2 = new Two();
x1 = newX(n1);
x2 = newX(n2);
n = x1.f();
X newX(Number n){
X x = new X();
x.f = p;
return x;
}
class X{
Number f;
}
```
对于variable和method有CS,而heap没有时
|variable|Object|Note|
|:----:|:----:|:----:|
|n1|o1||
|n2|o2||
|3:p|o1||
|3:x|o8||
|x1|o8||
|4:p|o2|可以看到p和x作了区分|
|4:x|o8||
|x2|o8||
|o8.f|o1,o2|这里会出现问题|
|n|o1,o2||
heap也有CS时
|variable|Object|Note|
|:----:|:----:|:----:|
|n1|o1||
|n2|o2||
|3:p|o1||
|3:x|3:o8|这里作了区分|
|x1|3:o8||
|4:p|o2||
|4:x|4:o8||
|x2|4:o8||
|3:o8.f|o1|如此就规避了o8的多重指向|
|n|o1||
**IMPORTANT**:cs heap must based on context sensitivity
## Domain and Notations
Context $C$: c`,c``
Context-sensitive method $C \times M$: c:m
Context-sensitive variable $C \times V$: c:v
Context-sensitive object $C \times O$: c:o
Field F: f,g
Context-sensitive instance field $C \times O \times F$: c:o.f
Context-sensitive pointer $(C \times V) \cup (C \times O \times F)$
## Rules
1. new: $\frac{}{c:o_i \in pt(c:x)}$
2. assign 'x = y': $\frac{c:o_i \in pt(c:y)}{c:o_i \in pt(c:x)}$
3. store 'x.f = y': $\frac{c':o_i \in pt(c:x),c'':o_j \in pt(c:y)}{c'':o_j \in pt(c':o_i.f)}$
4. load 'y = x.f': $\frac{c':o_i \in pt(c:x),c'':o_j \in pt(c':o_i.f)}{c'':o_j \in pt(c:y)}$
5. call
## Algorithms
```bash
Build Pointer Flow Graph with Contxt Sensitive <-- mutual dependent --> Propagate points-to information on PFG with Context Sensitive
```
Edges in Graph represent the objects pointed by pointer x may flow to pointer y
|Statement|PFG Edges|
|:----:|:----:|
|x = new T()|N/A|
|x = y|c:x <- c:y|
|x.f = y|c':oi.f <- c:y|
|y = x.f|c:y <- c':oi.f|
|r = x.k(a1,...,an)|c:a1 -> c^T:m_1,c:a2 -> c^T:m_2,c:r <- c^T:m_ret|
The only difference between CI and CS is the specification of context
```bash
Solve(m_entry){
WL=[],PFG=[],S=[],RM=[],CG=[]
AddReachable([]:m_entry)
while(WL not empty){
remove top from WL
delta = pts - pt(n)
Propagate(n,delta)
if(n == variable c:x){
for each c‘:o_i in delta{
for each x.f = y in S{
addEdge(c:y,c’:o_i.f)
}
for each y = x.f in S{
addEdge(c‘:o_i.f,c:y)
}
ProcessCall(c:x,c’:o_i)
}
}
}
}
#Reachable
AddReachable(c:m){
if(c:m !in RM){
add c:m to RM
S = S combine S_M
for each i: x = new T() in S_M{
add to WL
}
for each x = y in S_M{
AddEdge(c:y,c:x)
}
}
}
#MethodCall
ProcessCall(c:x,c‘:o_i){
for each l: r = x.k(a1,...,an) in S{
m = Dispatch(o_i,k)
ct = Select(c,l,c’:o_i,m)
add to WL
if(c:l -> ct:m !in CG){
add c:l -> ct:m to CG
AddReachable(ct:m)
for each p_i of m{
AddEdge(c:a_i,ct:p_i)
}
AddEdge(ct:m_ret,c:r)
}
}
}
#Propagate
Propagate(n,pts){
if(pts not empty){
pt(n) = pt(n) & pts
for each n -> (s in PFG){
add to WL
}
}
}
# addEdge
addEdge(s,t){
if(s -> t not in PFG){
add s-> t to PFG
if(pt(s) not empty){
add to WL
}
}
}
```
## Context Sensitive Varient
### Call-site sensitivity
Select(caller context,call site,receive object with heap CS,callee site)
call-site **chain**
```text
Select(c,l,c‘:o,m)=[l1,l2,...,l]
where c = [l1,l2,...]
```
如果类中出现递归会是什么情况?
```bash
void main(){
a.foo()
}
void foo(){
foo()
}
```
对于foo来说,由于递归,其context会变为[2,6,6,6,...]无限重复下去,此时我们需要引入一个限制来避免这种情况
#### k-limiting context abstraction
set an upper bound k for length of context(method context and heap context use different bound)
e.g.
1-call-site:Select(c,l,c‘:o,m)=[l]
2-call-site:Select(c,l,c‘:o,m)=[l‘’,l] where c = [l’,l‘’]
### Object sensitivity
### Type sensitivity