【软件分析/静态分析】chapter6 课程08 指针分析(Pointer Analysis)

🔗 课程链接:李樾老师和谭天老师的:

南京大学《软件分析》课程08(Pointer Analysis)_哔哩哔哩_bilibili


目录

第六章 指针分析(Pointer Analysis)

6.1 为什么需要指针分析

6.2 指针分析的基本概念

6.2.1 基础知识

6.2.2 例子

6.2.3 指针分析(Pointer Analysis)和别名分析(Alias Analysis)

6.2.4 指针分析的应用

6.3 指针分析的关键要素

 6.3.1 Heap Abstraction 堆抽象

6.3.2 Context Sensitivity 上下文敏感

6.3.3 Flow sensitivity 流敏感

6.3.4 Analysis Scope 分析范围

6.3.5 总结

6.4 指针分析关注的语句

6.4.1 分析什么?

6.4.2 关注的指针

6.4.3 关注的语句 ⭐


第六章 指针分析(Pointer Analysis)

6.1 为什么需要指针分析

        如下图所示的程序,如果用CHA对 int x = n.get() 进行分析,则会根据n的声明类型Number 进行resolve,Number有三个子类,所以就会有三个目标方法,如果在这个基础上进行常量传播分析,就会出现三个不同的return值返回给x,导致合并时将结果定为x=NAC,实际上这样是不准确的,CHA分析出来的3条路径中有2条都是假的,从而丢失了精度。

        

        如果我们用指针分析的方式对该程序进行分析,会根据n指向的对象new One()来建调用图,然后对new One 做dispatch,只得到One的get方法。如下图所示,这样分析的结果是准确的,没有false positive。

        

        指针分析可以很好的解决CHA引入假的调用边的问题。

6.2 指针分析的基本概念

6.2.1 基础知识

        指针分析主要有以下三方面的性质:

  • 一种基础的静态分析
    • 计算程序中的每个指针可以指向哪些内存的地址。
  • 对于OOP语言
    • 计算一个指针(variable or field)可以指向程序中的哪些对象
  • 看作是一个may-analysis
    • 计算每个变量指向哪些对象的时候是over-approximation的,会比实际指向的对象更多一点,可以看作是这样一个问题:“指针可能会指向哪些对象?”

论文出处:

William E.Weihl, "Interprocedural Data Flow Analysis in the Presence of Pointers,  Procedure Variables,  and Label Variables".POPL 1980.

现如今,指针分析仍是一个比较活跃的领域。

        指针分析对于不同的语言也是有所区别的,这里我们仍以OOP语言(object-oriented programs, 面向对象语言)为主 (主要是java)。

6.2.2 例子

        指针分析的主要问题:“Which objects a pointer can point to?”我们先通过一些例子感受一下指针分析。

        如下图,对左边的程序做指针分析,结果用右侧的指向关系(Points-to relations)来表示。

        

第1、2个:比较好理解,就是变量a 和x 所指向的new A 和new B

第3个的this为变量a调用A的setB时的,所以this,指向new A 

第4个:b 是变量a调用A的setB时声明的,是B类型的,所以指向new B

第5个:y是变量a调用getB之后的返回值this.b,即B类型的,所以指向newB

下边的new A.b 是class A 中 this.b,指向传入参数x的new B。

6.2.3 指针分析(Pointer Analysis)和别名分析(Alias Analysis)

这两个概念之间紧密相关但有所区别

  • 指针分析关注 “指针可以指向哪些对象?”
  • 别名分析关注 “程序中的两个指针是否会指向相同的对象?”

        假设两个指针,p和q,指向相同的对象,则称p和q互相之间为别名(aliases)

        如下图所示,p 和q  aliases,但是x和y不是。                
         

        别名信息可以通过指针分析的结果(points-to relations)推导出来。

6.2.4 指针分析的应用

        指针分析在很多方面有很多作用,例如:

  • 基础信息:调用图、别名信息、……
  • 编译优化:Virtual call inlining,……
  • bug 检测:空指针检测,……
  • 安全性分析:信息流分析,……
  • ……

        "Pointer analysis is one of the most fundamental static program analyses,on which virtually all others are built." 指针分析是最基本的静态程序分析之一,几乎所有其他程序都是建立在此基础上的。

        —— Point Analysis - Report from Dagstuhl Seminar 13162. 2013.

        

6.3 指针分析的关键要素

        指针分析是一个非常复杂的系统,有两个关键指标:精度(precision)和速度(efficiency),不同的因素影响着系统的这两个性能。针对不同的需求,指针分析需要做不同的取舍,为了取得比较好的平衡,就需要关注这些不同的因素,这里选择了4个对指针分析最关键的要素:

        

 6.3.1 Heap Abstraction 堆抽象

1. 解决的问题:How to model heap memory? 如何对程序中的堆内存进行建模?

        因为在程序动态执行时,如果程序中有循环或者递归,堆的对象的数量,理论上是无穷的。如果静态分析去处理无穷的对象,那就不能终止了。

        为了确保终止,提出了堆抽象技术,动态地将无穷的具体对象 抽象为 方便静态分析的有限的抽象对象(finite abstract object)。

        如下图所示,左边的原点表示动态时候产生的对象,随着程序的运行可能会产生无穷无尽的对象,使用堆抽象技术,会把这些动态产生的对象进行抽象,把具有某些共性的对象抽象成一个对象,通过这种抽象的方式限制静态分析处理的对象的个数,从而保证终止。

        

对抽象技术本身是一个很复杂的技术,有很多分支,出自于2016年的一篇文章,大概有两大流派,store based model,和storeless model,还有他们的混合。在本文的指针分析中,我们只学习store based model中的Allocation sites(调用点的抽象)

        

2.  Allocation-Sites Abstraction(调用点的抽象)

        Allocation-Sites Abstraction 是目前最常用的堆抽象技术。其主要思想如下:

  • 将动态对象建模的方式抽象成创建点
  • 每一个allocation site 创建一个抽象对象,来表示其分配的动态的时候创建的所有具体对象

        如下所示,假设这里有一个循环的程序,第2行有个创建点,这个循环动态的时候,会创建三次,也就是创建3个对象,如中间的Dynamic execution,用o_{2} 表示一个创建点,下标表示创建点所在的位置。如果采用allocation-sites abstraction 技术,来对这个程序的堆进行建模时,会抽象为一个对象,用着一个对象来表示所有具体的对象。

        

        通过这样的处理方式,一定可以保证抽象对象的个数是有限的,因为一个程序中allocation sites的个数是有限的。

6.3.2 Context Sensitivity 上下文敏感

1. 解决问题:How to model calling contexts? 指针分析的过程中,如何对调用上下文进行建模?

        通常有两种选择,上下文敏感 vs 上下文不敏感

        上下文敏感的思想:在做静态分析的时候,会模拟动态的上下文的方式,将一个方法的不同上下文区分开来进行分析,对同一个方法有多个上下文的情况,就会对每一个上下文分别进行分析。

        

         如上图所示,对于不同的调用foo,采用上下文敏感的方法,会分开上下文1 和上下文2 ,这样a.foo(x)的 实参就只会传入上下文1中的 p。对于上下文不敏感的情况,不会将不同上下文区分开,会将不同上下文中的数据流全都混在一起。每个方法只有一个上下文,这样可能会丢失精度。

        上下文敏感是一个非常有用的技术,对于提升指针分析的精度非常显著,在后续的课程中,也会有更详细的讲述。这里我们先从简单的上下文不敏感的技术学起。

6.3.3 Flow sensitivity 流敏感

1. 解决问题:How to model control flow? 如何对程序的控制流进行建模?

        与上下文敏感类似,通常也有两种做法:控制流敏感 vs 控制流不敏感:

        流敏感的基本思想:流敏感分析中,会尊重程序中语句执行的顺序,为了实现这一点,流敏感分析在程序中的每一点(每个语句上),都维护着一对指向关系的映射。到目前位置,我们学到的数据流分析都是流敏感的。

        对于流不敏感的方法,会将程序当作一群无序语句的集合,因此会对整个程序维护一个指向关系的映射。

        ​​​​​

        如上图所示的程序中,如果是流敏感的方法中,在每一条语句之后,都会记录当前程序的指向关系。如果是流不敏感的方法,只会对整个程序维护一组指向关系的映射。例如说c.f 就可能会指向x或者y,如果不考虑顺序,s也会指向x和y,显然,这个s指向y是一个虚假信息,降低了准确性。

        流敏感对于不同语言的效果是不一样的,通常,对于C是非常有效的,但是对于Java,目前还没有证据可以表示,流敏感分析会比流非敏感分析的效率好很多。目前Java的主流都是流不敏感的,因为其更简单。所以本课程所学习的也是流不敏感的,也就是只维护一组指向信息。

6.3.4 Analysis Scope 分析范围

1. 解决问题:Which parts of program should be analyzed? 应该分析程序中的哪些部分?

        可以分为两类:whole-program(整体分析/全程序分析),demand-driven(需求驱动)

  • whole-program(整体分析): 会分析整个程序中的所有指向关系,其结果对所有可能的应用提供信息。
  • demand-driven(需求驱动分析): 针对特定需求计算指向关系,其结果只满足特定的应用。

       

         如上图所示,如果是全程序分析,就会把所有变量的指向关系都计算出来;如果我们感兴趣的点就只有第5行,就可以进行需求驱动分析,只需要分析第四行即可,有这个z 的信息就可以分析第五行的z.bar()了。

        如果需求很明确,可以采用需求驱动分析,这样可以更快地得到结果,但是demand-driven的方式也没有那么美好,因为这个方法虽然只需要部分结果,但是也要求这个结果是safe的,可能还是会对程序绝大部分进行分析后,才能解出正确结果,速度可能并没有快非常多。此外,需求驱动分析只能满足特定的clients,如果有多个clients,然后对每个需求都进行分析,他们之间可能会有重复的部分,可能并没有比全程序分析快。本课程中采用全程序分析。

6.3.5 总结

        如下图所示,便是这四种因素,choice列提供具体的方法,红色为本课程会学习的技术。

        

简单总结如下:

堆抽象:针对对象,采用allocation-site抽象的方法,为每个调用点创建一个抽象对象;

上下文敏感:针对上下文,先学习上下文不敏感,后续会再学习上下文敏感的方法;

流敏感分析:针对控制流,为了减小开销,采用不敏感的;

分析范围:针对分析范围,选择全程序分析。

6.4 指针分析关注的语句

6.4.1 分析什么?

        现在的语言拥有很多类型,例如 if else, switch case, for/while/do while, continue/break…他们不会直接修改某些指针的值,所以我们在做指针分析的时候,很多语句是不需要处理的。

        我们只关注影响指针指向的语句pointer-affecting statements

6.4.2 关注的指针

Local variable 本地变量
Static field 静态字段C.f 有时候会看作global variable,跟处理variable是类似的
Instance field 实例字段x.f 建模成一个由x所指向的object,并加上field f
Array element 数组array[i] 

忽略数组下标、长度,不同位置的数据统一指向一个单独的field

        注意:对于数组而言,因为其每个索引具体指向的对象很难分析出来。所以静态分析的通用做法就是:忽略数组的下标、长度信息,让数据统一指向一个单独的field,例如说arr,将array[i]指向的信息全部抽象映射到array.arr中,取的时候,也直接取array.arr。如下图所示:

        

        在实际的分析中,学会分析 instance filed  也就会 array element了,且static field处理方法与variable类似,所以在后续的学习中,我们将会重点关注第1、3个指针。

6.4.3 关注的语句 ⭐

        接下来,我们将会重点关注影响指针分析的这5种语句:

Newx = new T()创建对象
Assignx = y赋值语句
Storex.f = y

往instance field中存值

Loady = x.f往instance field中取值
Callr = x.k(a, ……)方法调用

注意:

1. 在程序中,这种 x.f 的操作,也可能是很复杂的访问内存的指针表达式,例如 x.f.g.h = y。 我们在做指针分析的时候,对于所有这种memory-accesses的方式,都是一样的,我们会引入临时变量,将其分解成3地址码的形式,进行简化,如下图所示,如果很长就多引入几个中间变量:
        

2. 对于方法调用,上篇文章中提到了三种不同的调用方式,这里我们重点关注最复杂的virtual call的情况

         


🦄写在后边:

本文主要介绍了静态分析领域的重要技术,指针分析,的一些基本概念,以及指针分析的关键要素,并介绍了后续我们会在指针分析中重点关注的变量、指针、语句等。关于指针分析的核心内容将在下篇文章中进行介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14807.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

惊!ChatGPT处理文章仅需一秒钟,提取大纲、重写不在话下!

前言 在上篇文章中,我们实现了批量抓取到微信公众号文章的链接地址,那么这篇文章将继续为大家介绍,如何根据链接爬取到文章内容,并且利用chantGPT对文章进行处理。 爬取文章内容 我们已经有了很多文章的链接,这些链…

C# 使用HttpListener时候异常(此平台不支持此操作:System.PlatformNotSupportedException)

C# 使用HttpListener时候异常(此平台不支持此操作:System.PlatformNotSupportedException) 代码: HttpListener listener new HttpListener(); 错误: System.PlatformNotSupportedException: Operation is not su…

(四)Kafka 消费者

文章目录 1. Kafka 消费者相关概念消费者和消费者组(1)横向伸缩消费者(2)横向伸缩消费者组 分区再平衡再均衡的类型(1)主动再均衡(2)协作再均衡(增量再均衡) …

Kubernetes对象深入学习之二:细说schema.ObjectKind

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 在前文咱们对对象体系有了大概了解,接下来就要按照前面换分的三个知识区域逐个深入学习,今天从最简单的对象类型开始 runtime.Object…

C语言 数组

1. 数组的地址 1.1 一维数组的地址 int a[5];(1) &a[0]第0个元素的地址a第0个元素的地址&a整个一维数组的地址 (2)&a[0] a &a; (3) &a[0] 1跳过一个数组元素a …

Gradio库中的Model3D模块:实时上传和展示3D模型

❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…

如何与ChatGPT愉快地聊天

原文链接:https://mp.weixin.qq.com/s/ui-O4CnT_W51_zqW4krtcQ 人工智能的发展已经走到了一个新的阶段,在这个阶段,人工智能可以像人一样与我们进行深度的文本交互。其中,OpenAI的ChatGPT是一个具有代表性的模型。然而&#xff0…

chatGPT之100个例子-从体验到精通

简介 本博文演示了100个chatGPT在各行各业的使用例子,全部看完有助于培养chatGPT解决问题的思维。 在人工智能时代,智能软件并不会淘汰人类,淘汰人类的是会使用人工智能的人! 我们直接使用openAI官方chatGPT,生动演示了chatGPT的一些妙用! 请仔细看完,一定会有收获! 每…

构建工具——webpack、vite

文章目录 构建工具Webpack使用步骤配置文件(webpack.config.js)插件(plugin) ViteVite 也是前端的构建工具使用命令构建配置文件:vite.config.js 构建工具 当我们习惯了在 node 中编写代码的方式后,在回到…

Jenkins 配置用户角色和权限

1、配置条件: 1)已安装Jenkins,当前案例使用版本:2.319.3 2)已成功进入Jenkins,并新建用户:dev_java 2、安装插件【系统管理-插件管理-搜索-可选插件】:Role-based Authoriz…

多元分类预测 | Matlab基于麻雀算法优化深度置信网络(SSA-DBN)的分类预测,多特征输入模型,SSA-DBN分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab基于麻雀算法优化深度置信网络(SSA-DBN)的分类预测,多特征输入模型,SSA-DBN分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程…

【计算机视觉 | 目标检测 | 图像分割】arxiv 计算机视觉关于目标检测和图像分割的学术速递(7 月 7 日论文合集)

文章目录 一、检测相关(5篇)1.1 Contextual Affinity Distillation for Image Anomaly Detection1.2 Noise-to-Norm Reconstruction for Industrial Anomaly Detection and Localization1.3 MMNet: Multi-Collaboration and Multi-Supervision Network for Sequential Deepfake…