Contents
  1. 1. 静态分析
    1. 1.1. 定义
    2. 1.2. 完美的静态分析
    3. 1.3. Rice定理(Rice Theorem)
    4. 1.4. 妥协的静态分析
  2. 2. 数据流分析
    1. 2.1. 数据流分析的主要内容
    2. 2.2. 数据抽象
    3. 2.3. 中间表示
      1. 2.3.1. 特点
    4. 2.4. 控制流图
      1. 2.4.1. 基块Basic Block
    5. 2.5. 数据流分析 (过程内分析)
      1. 2.5.1. 转移函数(Transfer Function)
      2. 2.5.2. 控制流处理方法(Control-Flow Handlings)
    6. 2.6. 讨论

静态分析(Static Analysis) 是指在实际运行程序P之前,通过分析静态程序P本身来推测程序的行为,并判断程序是否满足某些特定的 性质(Property)。数据流分析作为静态分析的一种,可以解决程序分析中的一些问题,如存活变量分析。

静态分析

定义

静态分析(Static Analysis) 是指在实际运行程序P之前,通过分析静态程序P本身来推测程序的行为,并判断程序是否满足某些特定的 性质(Property)

性质(Property)

  • 程序P是否会产生私有信息泄漏(Private Information Leak),或者说是否存在访问控制漏洞(Access Control Venerability);
  • 程序P是否有空指针的解引用(Null Pointer Dereference)操作,更一般的,是否会发生不可修复的运行时错误(Runtime Error);
  • 程序P中的类型转换(Type Cast)是否都是安全的;
  • 程序P中是否存在可能无法满足的断言(Assersion Error);
  • 程序P中是否存在死代码(Dead Code, 即控制流在任何情况下都无法到达的代码);

完美的静态分析

满足以下两个条件:

  • 完整性(Soundness):真相一定在S给出的答案中;
  • 正确性(Completeness):S给出的答案一定在真相中;

Rice定理(Rice Theorem)

对于使用 递归可枚举(Recursively Enumerable) 的语言描述的程序,其任何 有价值(Non-trivial) 的性质都是无法完美确定的。

  • 关于递归可枚举,其含义是存在某个计算函数(可以是图灵机),能够将这种语言中的所有合法字符串枚举出来。这个概念有些抽象,不必深究,暂时只需要知道,目前我们所能想到的所有的编程语言都是递归可枚举语言。
  • 关于有价值,我们认为,如果一种性质是所有的程序都满足的或者都不满足的,那么这种性质是没有价值的,除此之外的性质是有价值的。简单理解就是和程序运行时的行为相关的,让我们感兴趣的性质,就是有价值的性质。

妥协的静态分析

  • 完整性(Soundness)=> 饱和估计(Overapproximate) => 分析结果存在False Positive => 这种分析称为Must Analysis
  • 正确性(Completeness)=> 保守估计(Under-approximation)=> False Negative => May Analysis

sound_completeness

数据流分析

数据流分析(Data Flow Analysis, DFA) 是指分析数据在程序中是怎样流动的。后文将详细介绍如下内容:

  • 分析的对象:数据=基于抽象的特定数据

  • 分析的基础:控制流图CFG

  • 分析的行为:流动。不同的流动使用不同的处理方式。

    • 在CFG的点(Node)内流动,即程序基块内部的数据流;=> 转移函数(Transfer Function)
    • 在CFG的边(Edge)上流动,即由基块间控制流触发的数据流。=> 控制流处理方法(Control-Flow Handlings),通常称为汇集操作
  • 分析的方式:安全估计(Safe-Approximation)

    • 饱和估计(Over-Approximation)=> 可能性分析(May Analysis)
    • 保守估计(Under-Approximation)=> 必然性分析(Must Analysis)

    根据需求确定哪种是安全的。例如,编译优化通常使用必然性分析,如果优化了不应该优化的内容会导致程序错误。

数据流分析的主要内容

  1. 数据抽象(Data Abstraction)
  2. 流安全估计策略——饱和估计或者保守估计
  3. 转移函数(Transfer Function)、控制流处理方法(Control-Flow Handlings)

数据抽象

程序中的值有很多,但我们关心的只有和Non-trivial性质相关的值。比如考虑除0错误,只需要判断变量的值是否为0,其他的我们并不需要关心。

《举例:区分程序中所有变量的正负情况》

如下图,将变量值抽象成几类符号。然而,这样简单的抽象并不能解决全部的情况,对于未知的数据,我们定义为Unknown.

data_abstract

中间表示

中间表示通常作为静态分析的语言基础,便于进行分析,便于构建控制流图。

特点

  • 低层次,和机器代码相接近
  • 通常和具体的语言无关,主要和运行语言的机器(物理机或虚拟机)有关
  • 简单通用
  • 包含程序的控制流信息

控制流图

cfg-demo.2a9e5799

控制流图由Basic Block作为结点,以跳转语句作为边。

基块Basic Block

基块就是满足如下性质的最长指令序列:

  • 程序的控制流只能从首指令进入
  • 程序的控制流只能从尾指令流出

数据流分析 (过程内分析)

转移函数(Transfer Function)

转移函数定义了如何计算不同的语句的抽象数据的值。

在实际应用中,通常使用集合表示抽象数据,集合的内容表示了抽象数据的状态。在目标语句之前,程序的数据状态表示为In,在目标语句之后,程序的数据状态表示为Out。

对于语句S,转移函数 f 表示为
$$
Out[S] = f_S(In[S])
$$
《举例:区分程序中所有变量的正负情况》

如下图所示,为针对该问题设计的转移函数。对于加法运算,如果两个正数变量相加,被赋值的变量也是正数。根据抽象出的数据状态,我们可以枚举出加法运算的所有情况,从而构造出加法运算的转移函数,以此类推构造出除法。

transfor_func

如下图所示为一个特定语句的分析样例。对于a=x+y语句,有In = ('x':'+','y':'+'),可以推断出a一定为正数,所以计算出Out = ('x':'+','y':'+','a':'+')

transfor_func_exmp

控制流处理方法(Control-Flow Handlings)

定义了如何计算控制流交汇的抽象数据的值。定义交汇时的运算为汇集 (meet,符号记作)。

对于一条语句而言,控制流的流向通常有以下几种情况:

  • 输入为1条,输出为1条。这种情况为Basic Block内部的语句流向。
  • 输入为1条,输出为2条。这种情况为分支语句,导致控制流分叉。
  • 输入为多条,输出为1条。这种情况为跳转语句的指向语句,需要进行汇集操作。

汇集操作分为两类:

  • 并集。通常会导致分析结果的饱和估计(Over-Approximation),最终导致May Analyze
  • 交集。通常会导致分析结果的保守估计(Under-Approximation),最终导致Must Analyze

《举例:区分程序中所有变量的正负情况》

以下图的分析为例,对于分支导致y出现正负两种状态,在汇集时如果使用交集,则将y定义为Undefine(对应空)。如果使用并集,则将y定义为Unknown(对应全)

meet_exmp2

处理方法根据分析时采用的数据流向分为两类:

  • 正向分析:符合正常的程序执行顺序,计算函数满足:In[S] = ∧ Out[S_pre]
  • 反向分析:与正常的程序执行顺序相反,计算函数满足:Out[S] = ∧ In[S_suc]

讨论

静态分析具有很多分析方法和实际应用,而数据流分析只是静态分析的一小部分。

静态分析还有很多其他的分析方式:控制流分析、污点分析、无效代码分析等等

还有很多应用场景:

  1. 编译器优化:死亡代码消除,代码移动
  2. 程序可靠性:空指针引用,内存泄露
  3. 程序安全性:隐私信息泄露,注入攻击
  4. 系统理解:IDE调用层次结构,类型指示

对于软件分析而言,静态分析也只是其中一类,并且因为静态带来的局限性,其存在很多无法解决的问题。另一种分析方式,动态分析,则通过执行程序的方式,获取动态信息,并以此提高分析的准确性。

同样,动态分析也有很多分析方式:指针分析、符号执行等等。

这里不在过多赘述,可以移步到 南京大学 李樾、谭添 老师在b站发布的软件分析课程视频. 也是本文作者的学习视频(文中用了很多视频中的图)

Contents
  1. 1. 静态分析
    1. 1.1. 定义
    2. 1.2. 完美的静态分析
    3. 1.3. Rice定理(Rice Theorem)
    4. 1.4. 妥协的静态分析
  2. 2. 数据流分析
    1. 2.1. 数据流分析的主要内容
    2. 2.2. 数据抽象
    3. 2.3. 中间表示
      1. 2.3.1. 特点
    4. 2.4. 控制流图
      1. 2.4.1. 基块Basic Block
    5. 2.5. 数据流分析 (过程内分析)
      1. 2.5.1. 转移函数(Transfer Function)
      2. 2.5.2. 控制流处理方法(Control-Flow Handlings)
    6. 2.6. 讨论