Learning-Based对象敏感指针分析策略

1.Introduction

作者提出了一种partial context-sensitive pointer analysis算法。artifact地址。

motivating example

请添加图片描述
这幅图中在对21行 A a = (A)c1.get(); 和 23行 B b = (B)c2.get(); 进行类型验证 (cast 是否会发生异常) 时需要准确分析出 a 指向object A1b 指向object B1。如果用context-insensitive方法分析,那么 C::set 方法中 data = e 可推导出 this.data 指向 {A1, B1},因此 a, b 都会指向 {A1, B1},会判定 cast 操作不安全。

通过context(object)-sensitive分析可以得出在context C1 下调用 C::set, this.data 指向 A1,在context C2 下调用指向 B1。但是如果全量context-sensitive分析 F1, F2 两个object之后也会展开,而并没有带来精度提升。因此需要一种选择性的context-sensitive策略。

之前的工作 [ 2 ] , [ 3 ] ^{[2],[3]} [2],[3]提出了object-allocation-graph (上述代码的OAG如下所示) 来描述object之间的context关系。前面示例的OAG如下图所示,F1, F2 的成员函数中分配了 A1, B1, C1, C2。而 C1, C2 的成员函数分配了 O

请添加图片描述

下图为policy推导出的选中进行context-sensitive分析的结点满足的条件:

  • 1.其所有前驱结点入变边数量在 [ 0 , ∞ ] [0, \infty] [0,],出边数量在 [ 2 , ∞ ] [2, \infty] [2,]

  • 2.其所有结点入变边数量在 [ 0 , ∞ ] [0, \infty] [0,],出边数量在 [ 0 , ∞ ] [0, \infty] [0,]

  • 3.其所有后继结点入变边数量在 [ 2 , ∞ ] [2, \infty] [2,],出边数量在 [ 0 , ∞ ] [0, \infty] [0,]

请添加图片描述
满足条件的object只有 C1, C2。因此对 C1, C2 所有成员函数调用进行context-sensitive分析。

2.Preliminaries

2.1.Baseline Pointer Analysis

Notation含义示例
V \mathbb{V} V程序变量集合A a 定义了一个 A 类型变量 a
H \mathbb{H} H堆分配点(allcation site)集合v = new C 新建了一个 C 类型的堆对象
M \mathbb{M} M方法(method)集合void main() { ... }main 方法
C \mathbb{C} C调用context定义为一个allocation sites序列
H C \mathbb{HC} HC堆context定义为一个allocation sites序列,和 H C \mathbb{HC} HC 等价
t h i s m this_m thism方法 m m mthis 变量
p a r a m m param_m paramm方法 m m m 的形参
r e t u r n m return_m returnm方法 m m m 的返回值
∥ \Vert (原文的符号打不出来)在一个序列后append一个元素,用来在context中添加一个allocation site s = < a 1 , . . . , a n > s = <a_1, ..., a_n> s=<a1,...,an>, s ∥ a ′ = < a 1 , . . . , a n , a ′ > s \Vert a^{'} = <a_1, ..., a_n, a^{'}> sa=<a1,...,an,a>
⌈ ⌉ k \lceil \rceil_{k} k取序列后 k k k 个元素 ⌈ ⟨ a 1 , a 2 , . . . , a n ⟩ ⌉ k = ⟨ a n − k + 1 , . . . , a n ⟩ \lceil⟨a_1, a_2, ... , a_n ⟩\rceil_{k} = ⟨a_{n−k+1}, ... , a_n ⟩ ⌈⟨a1,a2,...,ank=ank+1,...,an

在对象敏感分析中,调用context和堆context等价。

指令类型示例关键信息说明
Alloca v = n e w    C v = new \; C v=newC ( v a r , h e a p , i n M e t h ) (var, heap, inMeth) (var,heap,inMeth)变量(v), 堆对象(new C), 语句所处方法
Copy x = y x = y x=y ( t o , f r o m , i n M e t h ) (to, from, inMeth) (to,from,inMeth)from变量 y, to变量 x, 语句所处方法
Field Load x = y . f x = y.f x=y.f ( t o , f r o m , f l d , i n M e t h ) (to, from, fld, inMeth) (to,from,fld,inMeth)from变量 y, to变量 x, 加载的fld f, 语句所处方法
Field Store x . f = y x.f = y x.f=y ( t o , f l d , f r o m , i n M e t h ) (to, fld, from, inMeth) (to,fld,from,inMeth)from变量 y, to变量 x, 写入的fld f, 语句所处方法
Call x = y . m c a l l e e ( a r g ) x = y.m_{callee}(arg) x=y.mcallee(arg) ( r e t u r n , b a s e , c a l l e e , a r g , c a l l e r ) (return, base, callee, arg, caller ) (return,base,callee,arg,caller)return变量 x,base变量 y,callee函数 m,参数 arg,以及语句所处方法caller
分析输出映射关系说明
VarPtsTo V × C → ( H × H C ) \mathbb{V} \times \mathbb{C} \rightarrow (\mathbb{H} \times \mathbb{HC}) V×C(H×HC)将变量 v v v 映射到在context c c c 下所有所有指向的 (heap context, heap object) 对。
FldPtsTo H × H C × F → ( H × H C ) \mathbb{H} \times \mathbb{HC} \times \mathbb{F} \rightarrow (\mathbb{H} \times \mathbb{HC}) H×HC×F(H×HC)将heap object h h h 的field f f f ( h . f h.f h.f) 映射到在context h c hc hc 下的所有 (heap context, heap object) 对。
MethodCtx M → C \mathbb{M} \rightarrow \mathbb{C} MC将method m m m 映射到所有涉及到的context下

context-sensitive指针分析transfer rule如下,context-insensitive规则本质上就是将所有 h c t x hctx hctx 固定为常量。

指令规则
Alloca ( v a r ,    h e a p ,    i n M e t h ) ∈ A l l o c c t x    ∈    M e t h o d C t x ( i n M e t h ) h c t x = ⌈ c t x ⌉ m a x H ( h e a p ,    h c t x )    ∈    V a r P t s T o ( v a r ,    c t x ) \frac{(var, \; heap, \; inMeth) \in Alloc \quad ctx \; \in \; MethodCtx(inMeth) \quad hctx = \lceil ctx \rceil_{maxH}}{(heap, \; hctx) \; \in \; VarPtsTo(var, \; ctx)} (heap,hctx)VarPtsTo(var,ctx)(var,heap,inMeth)AllocctxMethodCtx(inMeth)hctx=ctxmaxH
Copy ( t o ,    f r o m ,    i n M e t h ) ∈ C o p y c t x    ∈    M e t h o d C t x ( i n M e t h ) V a r P t s T o ( f r o m ,    c t x )    ⊆    V a r P t s T o ( t o ,    c t x ) \frac{(to, \; from, \; inMeth ) \in Copy \quad ctx \; \in \; MethodCtx(inMeth)}{VarPtsTo(from, \; ctx) \; \subseteq \; VarPtsTo(to, \; ctx)} VarPtsTo(from,ctx)VarPtsTo(to,ctx)(to,from,inMeth)CopyctxMethodCtx(inMeth)
Field Load ( t o ,    f r o m ,    f l d ,    i n M e t h ) ∈ F l d L o a d c t x    ∈    M e t h o d C t x ( i n M e t h ) ( h e a p ,    h c t x )    ∈    V a r P t s T o ( f r o m ,    c t x ) F l d P t s T o ( h e a p ,    h c t x ,    f l d )    ⊆    V a r P t s T o ( t o , c t x ) \frac{(to, \; from, \; fld, \; inMeth) \in FldLoad \quad ctx \; \in \; MethodCtx(inMeth) \quad (heap, \; hctx) \; \in \; VarPtsTo(from, \; ctx)}{FldPtsTo(heap, \; hctx , \; fld ) \; \subseteq \; VarPtsTo(to, ctx)} FldPtsTo(heap,hctx,fld)VarPtsTo(to,ctx)(to,from,fld,inMeth)FldLoadctxMethodCtx(inMeth)(heap,hctx)VarPtsTo(from,ctx)
Field Store ( t o ,    f l d ,    f r o m ,    i n M e t h ) ∈ F l d S t o r e c t x    ∈    M e t h o d C t x ( i n M e t h ) ( h e a p ,    h c t x )    ∈    V a r P t s T o ( t o ,    c t x ) V a r P t s T o ( f r o m ,    c t x )    ∈    F l d P t s T o ( h e a p ,    h c t x ,    f l d ) \frac{(to, \; fld, \; from, \; inMeth) \in FldStore \quad ctx \; \in \; MethodCtx(inMeth) \quad (heap, \; hctx) \; \in \; VarPtsTo(to, \; ctx)}{VarPtsTo(from, \; ctx) \; \in \; FldPtsTo(heap, \; hctx, \; fld)} VarPtsTo(from,ctx)FldPtsTo(heap,hctx,fld)(to,fld,from,inMeth)FldStorectxMethodCtx(inMeth)(heap,hctx)VarPtsTo(to,ctx)
Call ( r e t u r n ,    b a s e ,    c a l l e e ,    a r g ,    c a l l e r )    ∈    C a l l c t x    ∈    M e t h o d C t x ( c a l l e r ) ( h e a p , h c t x )    ∈    V a r P t s T o ( b a s e , c t x ) c t x ′    =    ⌈ h c t x    ∥    h e a p ⌉ m a x K c t x ′    ∈    M e t h o d C t x ( c a l l e e ) V a r P t s T o ( a r g , c t x )    ⊆    V a r P t s T o ( p a r a m c a l l e e , c t x ′ ) ( h e a p , h c t x ) ∈ V a r P t s T o ( t h i s c a l l e e , c t x ′ ) V a r P t s T o ( r e t u r n c a l l e e , c t x ′ ) ⊆ V a r P t s T o ( r e t u r n ,    c t x ) \frac{(return, \; base, \; callee, \; arg, \; caller) \; \in \; Call \quad ctx \; \in \; MethodCtx(caller) \quad (heap, hctx) \; \in \; VarPtsTo(base, ctx) \quad ctx^{'} \; = \; \lceil hctx \; \Vert \; heap \rceil_{maxK}}{ctx^{'} \; \in \; MethodCtx(callee) \quad VarPtsTo(arg, ctx) \; \subseteq \; VarPtsTo(param_{callee}, ctx^{'}) \quad (heap, hctx ) \in VarPtsTo(this_{callee} , ctx^{'}) \quad VarPtsTo(return_{callee} , ctx^{′}) \subseteq VarPtsTo(return, \; ctx)} ctxMethodCtx(callee)VarPtsTo(arg,ctx)VarPtsTo(paramcallee,ctx)(heap,hctx)VarPtsTo(thiscallee,ctx)VarPtsTo(returncallee,ctx)VarPtsTo(return,ctx)(return,base,callee,arg,caller)CallctxMethodCtx(caller)(heap,hctx)VarPtsTo(base,ctx)ctx=hctxheapmaxK

2.2.Parameterization

Parametric Object Sensitivity: 前面分析规则中对context深度的处理涉及到计算 m a x K maxK maxK 值。作者定义了一个 C o n t e x t A b s t r a c t i o n : H → [ 0 , m a x K ] ContextAbstraction: H \rightarrow [0, maxK] ContextAbstraction:H[0,maxK] 函数将heap object映射到context深度。

Parametric Heap Abstraction: 堆抽象有2种方式, allocation-based以及type-based。allocation-based为每一个 new 调用点分配一个object,type-based为每个class type分配一个object。分析出来的 VarPtsToFldPtsTo 集合会调整如下,作者定义了一个 H e a p A b s t r a c t i o n HeapAbstraction HeapAbstraction 函数,如果 H e a p A b s t r a c t i o n ( h e a p ) = = a l l o c HeapAbstraction(heap) == alloc HeapAbstraction(heap)==alloc,那么object为allocation-site,反之,为 t y p e o f ( h e a p ) typeof(heap) typeof(heap)

  • VarPtsTo : V × C → ( ( H + T ) × H C ) \mathbb{V} \times \mathbb{C} \rightarrow ((\mathbb{H} + \mathbb{T}) \times \mathbb{HC}) V×C((H+T)×HC)

  • FldPtsTo : ( H + T ) × H C × F → ( ( H + T ) × H C ) (\mathbb{H} + \mathbb{T}) \times \mathbb{HC} \times \mathbb{F} \rightarrow ((\mathbb{H} + \mathbb{T}) \times \mathbb{HC}) (H+T)×HC×F((H+T)×HC)

3.Graphick

graphick的策略由feature描述,feature为一个 ( p r e v , ( [ a , b ] , [ c , d ] ) , s u c c ) (prev, ([a, b], [c, d]), succ) (prev,([a,b],[c,d]),succ) 3元组。interval pair ( [ a , b ] , [ c , d ] ) ([a, b], [c, d]) ([a,b],[c,d]) 表示被选中的node入边数量在 [ a , b ] [a, b] [a,b] 之间出边数量在 [ c , d ] [c, d] [c,d] 之间。 p r e v prev prev s u c c succ succ 为interval序列,描述前驱和后继结点入边和出边数量。

策略由一组参数 ∏ = < F 1 , F 2 , . . . F k > \prod = <F_1, F_2, ... F_k> =<F1,F2,...Fk> 组成, F i F_i Fi 包含一组feature。策略会给OAG上每一个结点赋予一个degree j j j,如果被 F 1 F_1 F1 选中,那么 j = 1 j = 1 j=1,被 F k F_k Fk 选中,那么 j = k j = k j=k。如果同时被多个feature选中,那么取最大值。degree j j j 表示进行 j-context-sensitive分析。作者的insight大概在于OAG上不同pattern(比如自身入度多少,出度多少;前驱后继入度、出度)的node应该用不同的上下文敏感度进行分析。具体多少无法人工指定需要学习。策略的学习需要训练样本(也就是几个程序),学习的核心包含一个Learning Minimal Abstraction函数和一个Learning a Set of Features函数。

(1).Learning Minimal Abstraction

指针分析的目标是能够尽可能以最少的代价验证程序中的 cast 操作是否会fail。文中有一个公式 p r o v e d ( F P ( a ) ) = p r o v e d ( F P ( k ) ) proved(F_P(a)) = proved(F_P(k)) proved(FP(a))=proved(FP(k)),左边表示基于策略对每个OAG结点赋予的degree进行敏感性分析能够达到的精度(能够验证may-cast-fail的数量),右边表示用精度最高的敏感性分析(每个OAG结点都采用最大值 k k k-context-sensitive分析)。学习的目标就是学到minimal abstraction来分配degree。算法如下,概括一下就是一个搜索算法,复杂度为 k ⋅ 2 ∣ C P ∣ k · 2^{|C_P|} k2CP ∣ C P ∣ |C_P| CP 可以理解是OAG的结点数量。

请添加图片描述
(2).Learn a Set of Feature

给每个degree j j j 学习一组feature F j F_j Fj。过程如下面Algo3所描述。

请添加图片描述

学习单个feature过程如Algo4描述,其中 S c o r e ( f , C ) = ∑ P ∈ P ∣ C ∩ γ G P ( P ) ( f ) ∣ ∑ P ∈ P ∣ γ G P ( P ) ( f ) ∣ Score(f , C) = \frac{\sum \textit{P} \in P | C \cap \gamma_{G_P}(P)(f)|}{\sum \textit{P} \in P | \gamma_{G_P}(P)(f)|} Score(f,C)=PPγGP(P)(f)PPCγGP(P)(f),大概意思是如果策略选中的node都在 C C C 中,那么score为1;当开始选中 C C C 之外的node,score开始下降。这里需要人工指定一个阈值 θ \theta θ。具体过程太复杂了,就不展开了。

请添加图片描述

4.Evaluation

  • RQ1: Graphick与baseline策略比较性能如何?

  • RQ2: learning开销如何?超参数 θ \theta θ 对Graphick性能有什么影响?

  • RQ3: 学习到的策略能看出什么insight?

作者基于Doop实现Graphick。对于精度:

  • 1.cast-fail分析,作者跟随之前的work采用may-fail分析,也就是只要存在fail的可能就报错。

  • 2.作者拿polymorphic call sites和call-edges的数量作为额外精度指标,理论上数量越少精度越高。

每次分析作者设定超时时间3 hours,对于 θ \theta θ,作者从0.1到0.9每个0.1取值(总共9个)。对于每个feature,作者限定最多选择3 node。

对于benchmark,作者从decapo选择10个(luindex, lusearch, antlr, pmdm , chart, eclipse, fop, bloat, xalan, and jython),以及从之前工作选择7个 (pmds , jedit, briss, soot, findbugs, JPC, checkstyle)。

这里先放出RQ1的部分结果。RQ2的跳过。

baseline:

  • Scaler: 基于OAG的人工制定的object-sensitivity策略。

  • Zipper: 基于PFG的人工制定的object-sensitivity策略。

  • Data:一种learning-based object-sensitivity策略。

  • 2objH: 2-object-sensitivity、1-context sensitivity heap。默认精度上限,开销最大。

  • Insens: 不敏感的分析,精度下限,开销最小。

作者选择3个程序作为训练集,1个验证集,剩下13个测试集。效果如下:

请添加图片描述

RQ3: 作者限制最大上下文敏感度是2,学习的策略总共包含了197个feature,总共包含68个2-object-sensitivity feature,29个2-type-sensitivity feature, 以及100个1-type-sensitivity feature。下图列出了几个top-5 feature,portion表示它们选择的precision-critical nodes的占比,score表示得分。

请添加图片描述

参考文献

[1].Minseok Jeon, Myungho Lee, and Hakjoo Oh. 2020. Learning graph-based heuristics for pointer analysis without handcrafting application-specific features. Proc. ACM Program. Lang. 4, OOPSLA, Article 179 (November 2020), 30 pages.

[2].Yue Li, Tian Tan, Anders Mùller, and Yannis Smaragdakis. 2018b. Scalability-first Pointer Analysis with Self-tuning Context-sensitivity. In Proceedings of the 2018 26th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering (Lake Buena Vista, FL, USA) (ESEC/FSE 2018). ACM, New York, NY, USA, 129-140.

[3].Tian Tan, Yue Li, and Jingling Xue. 2016. Making k-Object-Sensitive Pointer Analysis More Precise with Still k-Limiting. In Static Analysis, Xavier Rival (Ed.). Springer Berlin Heidelberg, Berlin, Heidelberg, 489-510.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值