引言

众所周知,数据流分析是实现污点分析的一种常用技术

数据流分析分为过程内的数据流分析与过程间的数据流分析。前者是对一个方法体内的数据流分析,主要是基于CFG分析,不涉及方法调用;后者是基于不同方法间的数据流分析,主要是基于ICFG+CG分析,会涉及方法调用。

一、过程内数据流分析

1. CFG的构建

1.1.把程序转换为IR(此处采用3AC)表示

3地址码中的地址可能有如下的几种类型:

  • 名字(Name),包括

    • 变量(Variable)
    • 标签(Label)
      • 用于指示程序位置,方便跳转指令的书写
  • 字面常量(Literal Constant)
  • 编译器生成的临时量(Compiler-Generated Temporary)

每一种指令都有其对应的 3 地址码形式,一些常见的 3 地址码形式如下:(x, y, z是变量的地址)

x = y bop z  // bop 是双目操作符(Binary Operator),可以是算数运算符,也可以是逻辑运算符
x = uop y // uop 是单目操作符(Unary Operator),可能是取负、按位取反或者类型转换
x = y
goto L // goto 是无条件跳转,L 是标签(Label),是标记程序位置的助记符,本质上还是地址
if x goto L // if... goto 是条件跳转
if x rop y goto L // rop 是关系运算符(Relational Operator),运算结果一般为布尔值

1.2.找程序的Leader集合L,进而划分Basic Block

  • 程序入口
  • 跳转指令的目标指令
  • 跳转指令的下一条指令

(一个Leader到下一个Leader之前就是一个BB)

1.3.连接Basic Block

程序控制流的产生来源于两个地方:

  • 天然的顺序执行

    • 这是计算系统天然存在的一种控制流
  • 跳转指令
    • 这是人为设计添加的一种控制流

示例

二、过程间数据流分析

1.CG 方法调用图

1.1.Java中的方法调用类型

  • Static Call:调用静态方法 --> 编译时明确
  • Special Call:调用构造方法、私有方法、基类实例方法 --> 编译时明确
  • Virtual Call:调用其他实例方法 --> 运行时明确(多态,最常见)

所以在构建方法调用图时,最关键的是要处理好Virtual Call的情况

1.2.CG的构建方法

  • 类层级结构分析(Class Hierarchy Analysis,CHA)
  • 快速类型分析(Rapid Type Analysis,RTA)
  • 变量类型分析(Variable Type Analysis,VTA)
  • 指针分析(Pointer Analysis,k-CFA)

上面的四种方法自上而下精度(Precision)越来越高,但是效率(Efficiency)也越来越低。

本文只关注CHA的方式:

CHA

在方法调用点处,只关注caller的声明类型T及callee的方法签名sig,会把T及其子类中所有与sig匹配的方法都视为可能的目标方法,示例:

class A {
void foo() { ... }
} class B extends A { } class C extends B {
void foo() { ... }
} class D extends B {
void foo() { ... }
}

类层级结构如下:

现有以下代码片段:

void resolve() {
C c = ...;
c.foo();A a = ...;
a.foo();B b = new B();
b.foo();
}

CHA算法会对于每一个接收变量的声明类型本身及其子类关于调用点处的函数签名进行方法派发的操作,将所有找到的目标方法加入结果之中。因此,结果如下:

  • Resolve(c.foo()) = {C.foo()}
  • Resolve(a.foo()) = {A.foo(), C.foo(), D.foo()}
  • Resolve(b.foo()) = {A.foo(), C.foo(), D.foo()}

我们需要注意一下的是第三个调用点, A.foo() 也在其结果之内,因为对于 B 类本身的方法派发得到的结果是 A.foo()

并且,CHA的Resolve算法只关心声明类型,因此 new B() 其实并没有在算法中发挥作用,从而我们 Resolve(b.foo()) 产生了两个虚假(Spurious)的目标调用 C.foo()D.foo()

CG构建示例:

class A {
static void main() {
A.foo();
} static void foo() {
A a = new A();
a.bar();
} void bar() {
C c = new C();
c.bar();
}
} class B extends A {
void bar() { }
} class C extends A {
void bar() {
if (...) {
A.foo();
}
} void m() { }
}

CHA最终构建的CG如下:

在上述例子当中需要注意的是,虽然 A a = new A() ,但是解析 a.bar() 的目标方法时候,依旧会对 A 以及 A 的所有子类作 Dispatch ,故而会有3条从 a.bar() 出发的边

最后我们会发现存在一个不可达的方法(Unreachable Method) C.m() ,那么这个方法中的代码就是死代码(Dead Code,即在任何情况下控制流都不能到达的代码)。

CHA的应用:IDE中的目标方法提示

2.ICFG 过程间控制流图

2.1.ICFG的构建

ICFG要在CFG基础上添加call Edges(调用边)、return Edges(返回边)

ICFG = CFGs + call & return edges ,连接调用边和返回边的信息可以从调用图中获得。因此,过程间控制流图的精度取决于调用图的精度。

示例:

static void main() {
int a, b, c;
a = 6;
b = addOne(a);
c = b - 3;
b = ten();
c = a * b;
} static int addOne() {
int y = x + 1;
return y;
} static int ten() {
return 10;
}

构建的ICFG如下:

从上图可以看出,在构建ICFG时,仍然保留了Call-to-return edges(调用点到返回点的边),虽然实际程序运行过程不会走这条边,但是这条边可以传递callee方法不需要的数据,这样就避免了在目标方法中始终维护其不需要的数据,可以提高效率

公主号推荐

id:CodeAnalyzer,名称:CodeAnalyzer Ultra

开源仓库推荐

https://github.com/HaHarden/CPGPractise

SAST-数据流分析方法-理论的更多相关文章

  1. 黑盒测试用例设计方法&理论结合实际 -> 正交试验法

    一. 概念 依据Galois理论,从大量的(实验)数据(测试例)中挑选适量的,有代表性的点(例),从而合理地安排实验(测试)的一种科学实验设计方法.类似的方法有:聚类分析方法,因子方法方法等. 二. ...

  2. 黑盒测试用例设计方法&理论联系实际-> 功能图法

    一. 概念 功能图由状态迁移图和布尔函数组成.状态迁移图用状态和迁移来描述.一个状态指出数据输入的位置(或时间),而迁移则指明状态的改变.同时要依靠判定表或因果图表示的逻辑功能.例,一个简化的自动出纳 ...

  3. 黑盒测试用例设计方法&理论结合实际 -> 因果图法

    一. 概念 因果图法是一种利用图解法分析输入的各种组合情况,从而设计测试用例的方法,它适合于检查程序输入条件的各种组合情况 二. 因果图法的应用 等价类划分法和边界值分析方法都是着重考虑输入条件,但没 ...

  4. 黑盒测试用例设计方法&理论结合实际 -> 错误推断法

    一 概念 基于经验和直觉推测程序中所有可能存在的各种错误, 从而有针对性的设计测试用例的方法. 二 错误推断法的应用  基本思想:列举出程序中所有可能有的错误和容易发生错误的特殊情况,根据他们选择测试 ...

  5. 黑盒测试用例设计方法&理论结合实际 -> 边界值分析法

    一. 概念 边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法.通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界. 二. 边界值分析法的应用 根据大量的测 ...

  6. 黑盒测试用例设计方法&理论结合实际 -> 等价类划分

    一. 概念 等价类划分法是把程序的输入域划分成若干部分(子集),然后从每个部分中选取少数代表性数据作为测试用例.每一类的代表性数据在测试中的作用等价于这一类中的其他值. 二. 等价类划分的应用 等价类 ...

  7. 黑盒测试用例设计方法&理论结合实际 -> 场景法

    一概念 现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流.这种在软件设计方面的思想也可以引入到软件测试中,可以比较生动地描绘出事件 ...

  8. 黑盒测试用例设计方法&理论结合实际 -> 判定表驱动法

    一. 概念 判定表是分析和表达多逻辑条件下执行不同操作的情况的工具. 二. 判定表驱动法的应用 判定表的优点: a. 能够将复杂的问题按照各种可能的情况全部列举出来,简明并避免遗漏.因此,利用判定表能 ...

  9. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  10. [置顶] Oracle学习路线与方法

    还没有整理好.... 1.学习路线 Oracle官方文档:2 Day DBA-->2 Day+Performance Tuning Guide--->Administrator's Gui ...

随机推荐

  1. 【ACM专项练习#01】基本输入输出,如何加减

    关于ACM,牛客其实也有专门的模拟练习:https://ac.nowcoder.com/acm/contest/5657#question 做这个也可以 关于while(cin>>n) 在 ...

  2. 【Java复健指南03】递归思想

    [递归] 递归重要规则 1.执行一个方法时,就创建一个新的受保护的独立空间(栈空间) 方法的局部变量是独立的,不会相互影响,比如n变量 如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用 ...

  3. Taurus.MVC WebMVC 入门开发教程5:表单提交与数据验证

    前言: 在本篇 Taurus.MVC WebMVC 入门开发教程的第五篇文章中,我们将学习如何处理表单提交和进行数据验证. 这是 Web 开发中非常重要的一部分,因为它涉及到用户输入数据的处理和有效性 ...

  4. 求求你别再用OkHttp调用API接口了,快来试试这款HTTP客户端库吧

    引言 在日常业务开发中,我们时常需要使用一些其他公司的服务,调用第三方系统的接口,这时就会涉及到网络请求,通常我们可以使用HttpClient,OkHttp等框架去完成网络请求.随着RESTful A ...

  5. 【Azure Batch】在中国区批处理服务(Mooncake Batch Account)上实验自动池(Auto Pool)的创建/删除

    问题描述 在Azure Batch的介绍文档中,提出了自动池的概念, 它可以在任务完成后,自动删除Pool资源,详细介绍:https://docs.azure.cn/zh-cn/batch/nodes ...

  6. 「实操」结合图数据库、图算法、机器学习、GNN 实现一个推荐系统

    本文是一个基于 NebulaGraph 上图算法.图数据库.机器学习.GNN 的推荐系统方法综述,大部分介绍的方法提供了 Playground 供大家学习. 基本概念 推荐系统诞生的初衷是解决互联网时 ...

  7. CPack 入门指南

    背景 CPack 是 CMake 2.4.2 之后的一个内置工具,用于创建软件的二进制包和源代码包. CPack 在整个 CMake 工具链的位置. CPack 支持打包的包格式有以下种类: 7Z ( ...

  8. 11 .Codeforces Round 891 (Div. 3)E. Power of Points(推公式+前缀和优化)

    E. Power of Points 题解参考 #include <bits/stdc++.h> #define int long long #define rep(i, a, b) fo ...

  9. 定义pod的hosts文件(HostAliases)

    通过HostAliases 向 Pod /etc/hosts 文件添加条目 当 DNS 配置以及其它选项不合理的时候,通过向 Pod 的 /etc/hosts 文件中添加条目, 可以在 Pod 级别覆 ...

  10. [置顶] tomcat处理请求导致页面出现ERR_CONNECTION_RESET错误解决方案

    现象: 浏览器发送请求到servlet,servlet处理时间太久,所以导致chrome浏览器出现ERR_CONNECTION_RESET错误 解决方案: 在相应servlet执行最后添加一句代码: ...