icexu 发表于 2020-7-23 17:01:39

什么是静态代码分析?什么是中间表示

什么是静态代码分析?
静态代码分析是指在不实际执行程序的情况下,对代码语义和行为进行分析,由此找出程序中由于错误的编码导致异常的程序语义或未定义的行为。通俗的说,静态代码分析就是在代码编写的同时就能找出代码的编码错误。你不需要等待所有代码编写完毕,也不需要构建运行环境,编写测试用例。它能在软件开发流程早期就发现代码中的各种问题,从而提高开发效率和软件质量。
静态代码分析现在面临最大的难题是什么?
现代软件系统规模越来越大,代码行数从数万或数十万行规模增长到数千万行;系统复杂度也越来越高,从传统的单机系统变为分布式系统,同构系统变为异构系统;而且软件开发的编程语言也从使用单一的语言发展为多种语言协同开发。这些变化都对SAST工具带来了巨大挑战。
SAST工具首先必须要有能同时检测多种语言代码及其互操作的能力,例如要检测Android应用程序的漏洞,SAST除了要能支持检测C/C++和Java语言外,还必须支持JNI,才能有效的检测Byte Code和Native Code互操作导致的各类问题。
此外对静态程序分析工具还有这些维度的评价指标:
一是漏报率和误报率;漏报率或误报率过高会导致SAST工具的实用性和有效性显著降低,无法有效提高软件开发效率和软件质量。
二是检测规则是否容易扩展及按用户特定需求定制;除了支持常见的工业安全编码标准外,SAST工具应该还能支持用户自定义的编码规范和业务逻辑规则。
三是分析所需的时间和资源占用;如果SAST工具一次扫描所需的时间太长或者占用内存资源太大,将难以和程序员日常的开发工作和流程整合,进而无法起到提高开发效率和软件质量的目的。
在编译器技术领域,什么是抽象语法树 (AST)?
抽象语法树是程序源代码结构的树状表示。程序源代码经过词法分析器(Lexer)得到各种不同种类的单词(Token),再由语法分析器(Parser)分析和语法检查后得到抽象语法树(AST)。抽象语法树的根节点表示整个程序,内部节点是抽象语法结构或者单词。AST的核心在于它能与输入源代码中的各个语法元素一一对应。对于 附图1 的C语言源代码,它对应的AST如 附图2 所示。
什么是中间表示(IR)?
IR是编译系统或程序静态分析系统的核心,它是源程序在编译器或者静态分析器的内部表示,所有的代码分析,优化和转换工作都是基于中间表示进行的。IR一般由AST经过类型检查和规范化后转换而来。对编译器来说,它在中间表示上做完分析和优化工作后,将中间表示转换为其他语言源代码或者汇编/目标语言。
而静态分析工具则会在中间表示上进行语义或未定义的行为分析,然后结合各种预定义规则或者用户自定义规则检测源代码的各种漏洞或缺陷。
在现代编译器和静态分析工具中,通常会使用控制流图(Control Flow Graph,CFG)来表示程序的控制流,使用静态单赋值(Static Single Assignment,SSA)来表示程序中数据的使用-定义链(Use-Def Chain),这两个关键数据结构都是AST中没有的。对于附图1 的C语言源代码,它对应的IR如 附图3 所示。
查找源代码缺陷时,为什么在IR级别上进行静态代码分析比在AST级别上准确性更高?
根据前面的描述,对AST进行类型检查和规范化,即可转换为IR。AST上适合做一些代码规范的检查,例如标识符命名规范检查或常见的编码惯用法检查,AST上的检查一般使用图模式匹配的方法。
而IR上能进行更深层次的流敏感分析,过程间分析,上下文敏感分析和对象敏感分析等等,从而实现各种更高难度的程序漏洞检查。相比IR,AST有这些明显的劣势:AST不能很好的表示控制流和数据流,AST做为输入源代码的树状表示,它本身就缺乏表示控制流和控制流的方式。AST是非规范化的,相同语义的结构如果写法不同,它们在AST上的表示也会不同。例如C语言中使用for、while和if/goto表达的循环结构,它们的AST是不一样的;而转换为IR后产生的控制流图是一样的。规范化使得对程序语义的分析更容易,使得检测精确度更高。

页: [1]
查看完整版本: 什么是静态代码分析?什么是中间表示