关于我

静态程序分析基础

静态程序分析基础

静态程序分析基础(Static Program Analysis,简称Static Analysis)

PL与静态分析

编程语言( PL,Programming Languages),静态分析属于PL下面的Application下的一个分支

静态程序分析编程语言应用层面下的一个细分领域,它是一个非常重要的核心内容:

img

在理论部分,考虑的是如何设计一个语言的语法和语义,如何设计语言的类型系统等等问题;有了语言的语法、语义和类型系统之后,我们需要支撑语言的运行。因此,在环境部分,需要考虑如何为运行中的程序提供运行时环境——如何设计编译器,在运行时需要怎样的支持(如内存的分配管理)等等;应用部分则关注如何保证语言所写出程序的效率、安全性和可靠性,主要考虑如何对程序进行分析,验证和合成(如何自动合成一个程序)

现在编程语言无非三大类:

那么考虑一个问题:

数十年来语言的核心没有变化,但软件的规模和复杂性增长迅速,如何保证程序的可靠性?

这个时候就引出了我们的静态程序分析

静态程序分析

静态程序分析的用处很多:

  • 提高程序可靠性:比如避免内存泄漏、空指针引用等
  • 提高程序安全性:避免隐私信息泄漏、避免注入攻击
  • 编译优化:死代码消除、循环不变量的移动
  • 程序理解:例如使用IDE时,将鼠标悬停在代码上,IDE能够动态地分析并提示你所悬停对象的相关信息,背后使用的技术就是静态程序分析

一句话概括,在程序运行之前了解它的行为、安全性等信息

在应用安全(SDL)领域,SAST学习的基础也是静态程序分析

这里有两个术语,sound和truth

  • sound:可以理解为无漏报
  • truth:可以理解为无误报

没有一个完美的的SAST工具能够实现0漏报与0误报,往往只能妥协一个来换取另一个,而绝大多数都是妥协truth,来保证sound

两个词来概括静态分析:抽象(abstract)+过近似(over-approximation):

  • 抽象:比如代码里变量可能取值无限多,我们把它归成几个集合(比如“正/负/零/unknown/undefined”),这就是抽象

  • 过近似:

    • 以语义判断为例,a=9,b=-1,本来a+b=8,但是分析时是抽象为 正数+负数 所以判断结果不是正数,而是unknown(如果用这个思路分析负数的数组引用错误,就会导致误报)

    • 以控制流判断为例,有如下代码:

      x = 1;
      if(input)
      	y = 10;
      else
      	y = -1;
      z = x + y;
      

      那么他的control flow如下:

      flowchart TD B[x = 1] -->D[y = 10] B[x = 1] -->E[y = -1] D --> F[z = x + y] E --> F

      那么按照前面的思路来判断正负,流程就是这样:

      flowchart TD B[x = 1] -->D[y = 正] B[x = 1] -->E[y = 负] D --> F[y = unknown] E --> F F --> G[z = unknown]

      这里左边路径的y=正,右边的y=负,而流程会合并(merging)于是y合并后为unknown,所以最终的z=unknown

总结

静态程序分析是在不运行程序的前提下,通过对程序语义进行抽象和过近似来推断其可能行为的一类技术,核心目标是提升程序的安全性、可靠性和可维护性。由于程序状态和执行路径在理论上是无限的,静态分析必须在 sound(不漏报)与 truth(不误报) 之间取舍,现实中的工具通常选择牺牲精度来保证覆盖率。这也是误报不可避免的根本原因。理解这一点,有助于正确看待 SAST 工具的能力边界,并在规则设计与结果分析中做出理性的工程判断

Created by Yuy0ung. Powered by GitHub Page.