Bit-Vector框架(1) — Reaching Definition Analysis

Bit-Vector框架(1)——Reaching Definition Analysis

y := 1
x <= 0
x > 0
y := x * y
x := x - 1
q0
qx
q1
q2
q3
图2.1 阶乘函数的程序图表示

以下是4个Bit-Vector Framework的数据流分析经典例子。

  • Reaching Definition Analysis(本文):变量/数组在哪里最新被定义它们的值
  • Live Variables Analysis:变量/数组在重新被定义之前(或者程序结束之前),是否被使用
  • Available Expressions Analysis:哪些表达式之前已经被计算过,当再次进行计算时能够得到相同的值
  • Very Busy Expressions Analysis:哪些表达式在哪些点被计算后,程序结束前仍然被计算,并且计算的结果相等。

1. Reaching Definitions

1.1 Reaching Definition简介

RD分析求解的信息

  • 求解程序图中的每个节点处,变量/数组最后一次的可能被定义/修改的地方。

例子(图2.1 中的q1处)

  • 变量y可能被修改的行为有两处:q0 -> q1q2 -> q3
  • 变量x则为:q3 -> q1? -> q0 (x可能没有被修改,我们用? -> q0表示)

RD求解信息的用途

  • 编译优化 和 程序理解

  • 连接变量被定义的地方被使用的地方

  • 验证安全属性

  • 检查变量是否被合适地初始化,进而知道程序可能存在某种形式的可被攻击的缺陷

例如,下图是一个最简单的检测PHP程序中XSS代码缺陷的例子:

Def -> Use
HTTP GET -> echo
XSS攻击信息流传播路径
$a = $_GET['info']
echo $a
1.2 分析结果的定义

Q = { 程 序 图 所 有 节 点 的 集 合 } , 图 示 Q = { q 0 , q x , q 1 , q 2 , q 3 } A c t = { 程 序 中 所 有 语 句 行 为 的 集 合 } , 图 示 A c t = { y : = 1 , x < = 0 , x > 0 , y : = x ∗ y , x : = x − 1 } E d g e = { 程 序 中 所 有 边 的 端 点 以 及 它 们 上 行 为 的 集 合 } , 图 示 E d g e = { ( q 0 , y : = 1 , q 1 ) , ( q 1 , x < = 0 , q x ) , ( q 1 , x > 0 , q 2 ) , ( q 2 , y : = x ∗ y , q 3 ) , ( q 3 , x : = x − 1 , q 1 ) } V a r = { 程 序 中 所 有 简 单 变 量 的 集 合 } , 图 示 V a r = { x , y } A r r = { 程 序 中 所 有 数 组 变 量 的 集 合 } , 图 示 A r r = { } 定 义 三 元 组 : ( x , q s , q t ) ,    ( A , q s , q t ) 其 中   : ( q s , q t ) ∈ E d g e      x ∈ V a r      A ∈ A r r \begin{aligned} Q&=\{程序图所有节点的集合\}, \\ 图示Q&=\{q_0,q_x,q_1,q_2,q_3\} \\ \\ Act&=\{程序中所有语句行为的集合\},\\ 图示Act&=\{y:=1,x<=0,x>0,y:=x*y,x:=x-1\} \\ \\ Edge&=\{程序中所有边的端点以及它们上行为的集合\}, \\ 图示Edge&=\{(q_0,y:=1,q_1),(q_1,x<=0,q_x),(q_1,x>0,q_2),(q_2,y:=x*y,q_3),(q_3,x:=x-1,q_1)\}\\ \\ Var&=\{程序中所有简单变量的集合\}, \\ 图示Var&= \{x,y\}\\ \\ Arr&=\{程序中所有数组变量的集合\}, \\ 图示Arr&=\{\} \\ \\ 定义三元组&: (x, q_s, q_t), \ \ (A, q_s, q_t) \\ 其中& \ :(q_s, q_t) \in Edge \\ & \ \ \ \ x \in Var \\ & \ \ \ \ A \in Arr \end{aligned} QQActActEdgeEdgeVarVarArrArr={},={q0,qx,q1,q2,q3}={},={y:=1,x<=0,x>0,y:=xy,x:=x1}={},={(q0,y:=1,q1),(q1,x<=0,qx),(q1,x>0,q2),(q2,y:=xy,q3),(q3,x:=x1,q1)}={},={x,y}={},={}:(x,qs,qt),  (A,qs,qt) (qs,qt)Edge    xVar    AArr

三元组(x, qs, qt),(A, qs, qt)表示变量x或者数组A最新被定义可能是通过一条边为(qs,act,qt)上的act行为所定义/修改的。我们允许让qs为?, 表示x或者A仍然保持初值不变

RD映射程序图中每个节点到形如三元组<x, qs, qt>或者<A, qs, qt>的集合。并且qs可能为?。RD函数的形式化定义为:
R D : Q → P o w e r S e t (   ( V a r ∪ A r r ) × Q q ×   Q ) 其 中 : Q q = { ? } ∪ Q \begin{aligned} RD &: Q \rightarrow PowerSet(\ (Var\cup Arr) \times Qq \times \ Q) \\ 其中&: Qq = \{?\} \cup Q \end{aligned} RD:QPowerSet( (VarArr)×Qq× Q):Qq={?}Q
如果关心平行边的话,可以考虑:
R D : Q → P o w e r S e t ( ( V a r ∪ A r r ) × Q q × A c t × Q ) RD:Q \rightarrow PowerSet( (Var \cup Arr) \times Qq \times Act \times Q ) RDQPowerSet((VarArr)×Qq×Act×Q)
我们并不关心平行边。所以不予考虑。

1.3 路径上定义了什么
1.3.1 定义程序单个行为的语义函数

首先分析对于每个行为act,数组/变量会被怎么定义/修改:
D e f ( x : = a ) = { x } D e f ( A [ a 1 ] : = a 2 ) = { A } D e f ( c ? x ) = { x } D e f ( c ? A [ a ] ) = { A } D e f ( c ! a ) = { } D e f ( b ) = { } D e f ( s k i p ) = { } \begin{aligned} &Def(x := a) &= &\{x\} \\ &Def(A[a_1] := a_2) &= &\{A\} \\ &Def(c?x) &= &\{x\} \\ &Def(c?A[a]) &= &\{A\} \\ &Def(c!a) &= &\{\} \\ &Def(b) &= &\{\} \\ &Def(skip) &= &\{\} \\ \end{aligned} Def(x:=a)Def(A[a1]:=a2)Def(c?x)Def(c?A[a])Def(c!a)Def(b)Def(skip)======={x}{A}{x}{A}{}{}{}
其中,对于数组元素的修改,我们近似地认为修改数组整体。

接着我们分析对于一条路径,数组/变量会被怎么定义/修改。

1.3.2 一条路径上变量x的定义函数

下面定义:对于一条路径Pi 和一个变量x,我们定义Pi如下:
P i =   q 0 , a 1 , q 1 , a 2 , q 2 , . . . , q n − 1 , a n , q n 其 中 , n ≥ 0 q i ∈ Q , 0 ≤ i < n a j ∈ A c t , 1 ≤ j ≤ n \begin{aligned} Pi = &\ q_0, a_1, q_1, a_2, q_2, ..., q_{n-1}, a_n,q_n \\ 其中,&n \geq 0 \\ &q_i \in Q, 0 \leq i < n\\ &a_j \in Act, 1 \leq j \leq n \end{aligned} Pi= q0,a1,q1,a2,q2,...,qn1,an,qnn0qiQ,0i<najAct,1jn
定义一条路径上变量x的Def函数为:
D e f ( P i , x ) = { ( x , q i − 1 , q i ) 如 果 x ∈ D e f ( a i ) , 并 且 ∀ j > i : x ∉ D e f ( a j ) ( x , ? , q 0 ) 如 果 ∀ j : x ∉ D e f ( a j ) Def(Pi,x)= \begin{cases} (x,q_{i-1},q_{i})& 如果x\in Def(a_i),并且\forall j>i:x\notin Def(a_j) \\ (x,?,q_0) & 如果\forall j:x\notin Def(a_j) \end{cases} Def(Pi,x)={(x,qi1,qi)(x,?,q0)xDef(ai),j>i:x/Def(aj)j:x/Def(aj)
上面对变量x的Def函数的意思很简单:

  • 在一条路径结束,x会被路径上最后一个定义它的程序行为来定义;
  • 如果路径中不存在任何定义x的点,那么它保持着最初的值,对应的定义点就是(x,?,q0)。
1.3.3 一条路径上数组A的定义函数

而对于数组变量,Def(Pi, A)函数的定义为:
D e f ( P i , A ) = {   ( A , ? , q 0 )   }   ∪   {   ( A , q i − 1 , q i )    ∣    A ∈ D e f ( a i ) } Def(Pi, A) = \{\ (A, ?, q_0)\ \} \ \cup \ \{\ (A,q_{i-1},q_i) \ \ | \ \ A \in Def(a_i) \} \\ Def(Pi,A)={ (A,?,q0) }  { (A,qi1,qi)    ADef(ai)}
对数组A的Def函数的意思也很容易理解:

  • 数组A仍然有部分元素保持最初的值,也就是数组仍然可以被认为被定义在程序的开始处:(A, ?, q0)
  • 路径Pi上每次对A的定义我们都可以认为是数组A的定义点
1.3.4 总结

综上,对于一条路径Pi,它的定义函数为:
D e f ( P i ) = {   D e f ( P i , x )   ∣   x ∈ V a r   }   ∪   ⋃ A ∈ A r r D e f ( P i , A ) Def(Pi) = \{\ Def(Pi, x)\ |\ x\in Var \ \} \ \cup \ \bigcup_{A\in Arr}Def(Pi, A) Def(Pi)={ Def(Pi,x)  xVar }  AArrDef(Pi,A)
也就是说,一条路径的定义函数为:对变量和数组的定义之和

通过上面的函数概念,我们现在可以重新定义Reaching Definition Analysis:

对于程序图上的每个节点q,我们想求解出所有可能的,从q0到q的路径上产生的定义,之和。其中q0为程序的入口点,q为除q0外所有的程序点。

而我们知道,因为程序存在循环的情况,静态分析的情况下很多时候是求解不出所有的执行路径。但是,存在一些路径,它们已经能够足够地给出程序点的所有可能的定义。能够总结出程序点的所有路径的定义的最小(least)分析结果,我们也称之为 MOP解(Merge Over Paths solution)

1.4 RD分析的约束

1.3是通过将所有路径的定义结果进行merge合并,这并不是一种有效的计算正确的RD分析的方法。因为很多时候我们静态地并不能够分析出所有的可能执行路径,所以很难将所有路径的结果进行merge。

为了改进上述方法。现在,我们定义一个约束系统,RD必须满足,之后我们会给出算法来求解这些约束。

程序图
提取出RD分析的约束
求解约束
RD分析结果集

在定义约束系统之前,我们先定义一下约束系统中的约束因子:KILL和GEN

对于程序图中每条边(qs, a, qt),我们定义所谓的对定义的KILL函数和GEN函数:

aKILL(q s _s s, a, q t _t t)GEN(q s _s s, a, q t _t t)解释
x := a{x} × \times × Q ? _? ? × \times × Q{x, q s _s s, q t _t t}1. 此边会Kill掉所有定义x的点;并在此边上生成x的定义
A[a1] := a2{}{A, q s _s s, q t _t t}2. 保守分析,不Kill掉数组;但是会在边上生成A的定义
c?x{x} × \times × Q ? _? ? × \times × Q{x, q s _s s, q t _t t}同1
c?A[a]{}{A, q s _s s, q t _t t}同2
c!a{}{}没有赋值的语义,与Kill和Gen没关系
b{}{}同上
Skip{}{}同上

KILL,GEN的目的是为RD分析的约束服务。现在我们定义约束:

  • 对于程序图上的每条边edge(qs, a, qt​),必须满足:

∀ ( q s , a , q t )   ∈   E d g e R D ( q t )   ⊇   (   R D ( q s ) − K I L L ( q s , a , q t )   )   ∪   G E N ( q s , a , q t ) \begin{aligned} \forall (q_s, a, q_t)\ &\in \ Edge\\ RD(q_t) \ &\supseteq \ (\ RD(q_s) -KILL(q_s, a, q_t)\ ) \ \cup \ GEN(q_s, a, q_t) \end{aligned} (qs,a,qt) RD(qt)  Edge ( RD(qs)KILL(qs,a,qt) )  GEN(qs,a,qt)

  • 对于程序入口节点 q 0 _0 0 ,必须满足:

R D ( q 0 )   =   ( V a r   ∪   A r r )   ×   ( ? )   ×   { q 0 } RD(q_0) \ = \ (Var \ \cup \ Arr ) \ \times \ (?) \ \times \ \{q_0\} RD(q0) = (Var  Arr) × (?) × {q0}

前者表示:从边(qs, a, qt)的一端qs传递过来的RD信息可能会通过该边的a行为kill掉部分定义。于此同时a行为又会产生定义。约束条件中存在一个子集的概念,也就是说,无论qt的前驱节点是哪个qs,右侧求出的集合一定是RD(qt)的子集。因此,可以这么认为:对qt的所有前驱qs,求解右侧的集合运算,并将这些计算结果并集,就会得到RD(qt)。

后者表示:所有变量/数组有初始值。被定义的地方为一条虚拟边 ? -> q0 ,这是求解约束的初始状态

与MOP的定义类似,我们通过上面的约束系统,来重新定义Reaching Definition Analysis:

Reaching Definition Analysis就是要根据约束来求解出每个程序点的RD函数值,上述约束条件要在任何时候(等同于任何执行路径)都满足

1.5 求解约束

输 入 : 集 合 Q 包 含 程 序 图 中 所 有 节 点 ; 初 始 节 点 q 0 ; 边 集 合 E 输 出 : R D : R e a c h i n g   D e f i n i t i o n   A n a l y s i s 分 析 的 赋 值 定 义 结 果 函 数 ; 给 定 一 个 程 序 点 q , R D ( q ) 表 示 可 能 有 哪 些 定 义 可 达 程 序 点 q 算 法 : 对 于 所 有 q ∈ ( Q − { q 0 } ) , 令 R D ( q ) : = { } R D ( q 0 ) : = ( V a r   ∪   A r r )   ×   { ? }   ×   { q 0 } W h i l e   仍 然 存 在 ( q s , a , q t ) ∈ E , 使 得   R D ( q t ) ⊉ (   R D ( q s ) − K I L L ( q s , a , q t )   )   ∪   G E N ( q s , a , q t )              那 么 令   R D ( q t )   : =   R D ( q t )   ∪   (   R D ( q s ) − K I L L ( q s , a , q t )   )   ∪   G E N ( q s , a , q t ) \begin{aligned} 输入:&集合Q包含程序图中所有节点;初始节点q_0;边集合E \\ 输出:&RD: Reaching \ Definition \ Analysis分析的赋值定义结果函数;给定一个程序点q,RD(q)表示可能有哪些定义可达程序点q \\ 算法:& \\ &对于所有q \in (Q- \{q_0\}),令RD(q):=\{\} \\ &RD(q_0) := (Var \ \cup \ Arr) \ \times \ \{?\} \ \times \ \{q_0\} \\ &While \ 仍然存在(q_s,a,q_t) \in E,使得 \ RD(q_t)\not\supseteq(\ RD(q_s)-KILL(q_s,a,q_t)\ ) \ \cup \ GEN(q_s,a,q_t) \\ &\ \ \ \ \ \ \ \ \ \ \ \ 那么令 \ RD(q_t) \ := \ RD(q_t) \ \cup \ (\ RD(q_s)-KILL(q_s,a,q_t)\ ) \ \cup \ GEN(q_s,a,q_t) \end{aligned} Qq0ERD:Reaching Definition Analysisq,RD(q)qq(Q{q0})RD(q):={}RD(q0):=(Var  Arr) × {?} × {q0}While (qs,a,qt)E使 RD(qt)( RD(qs)KILL(qs,a,qt) )  GEN(qs,a,qt)             RD(qt) := RD(qt)  ( RD(qs)KILL(qs,a,qt) )  GEN(qs,a,qt)

算法的核心就在于while循环迭代,直至约束系统达到稳定状态。

核心想法就是,如果对于程序点q,仍然存在其它程序点的新的赋值定义流到q,那么就将新的赋值定义合并到程序点q。

对每个程序点都如此操作,最终能够通过上述约束等式,求解出每个程序点赋值定义可达的解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值