diff --git a/.gitbook/assets/DtoA.png b/.gitbook/assets/DtoA.png new file mode 100644 index 0000000..8a7ec90 Binary files /dev/null and b/.gitbook/assets/DtoA.png differ diff --git a/src/ch0/00-01-why-SPA.assets/PL.png b/.gitbook/assets/PL.png similarity index 100% rename from src/ch0/00-01-why-SPA.assets/PL.png rename to .gitbook/assets/PL.png diff --git a/.gitbook/assets/concurrentProgram.png b/.gitbook/assets/concurrentProgram.png new file mode 100644 index 0000000..b993b8e Binary files /dev/null and b/.gitbook/assets/concurrentProgram.png differ diff --git a/.gitbook/assets/harmonyOS.png b/.gitbook/assets/harmonyOS.png new file mode 100644 index 0000000..885b3a2 Binary files /dev/null and b/.gitbook/assets/harmonyOS.png differ diff --git a/.gitbook/assets/market.png b/.gitbook/assets/market.png new file mode 100644 index 0000000..63386c7 Binary files /dev/null and b/.gitbook/assets/market.png differ diff --git a/.gitbook/assets/mayMustSum.png b/.gitbook/assets/mayMustSum.png new file mode 100644 index 0000000..0072086 Binary files /dev/null and b/.gitbook/assets/mayMustSum.png differ diff --git a/README.md b/README.md index 469baf1..93576a5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,131 @@ -# Static-Program-Analysis-Book +# 简介 -[Gitbook在线阅读地址](https://ranger-nju.gitbook.io/static-program-analysis-book/) +[《静态程序分析》Gitbook在线阅读地址](https://ranger-nju.gitbook.io/static-program-analysis-book/) -[GitHub项目地址](https://github.com/RangerNJU/Static-Program-Analysis-Book) - ----- +[《静态程序分析》GitHub项目地址](https://github.com/RangerNJU/Static-Program-Analysis-Book) Getting started with static program analysis. Read this and start writing your first static program analyzer! 静态程序分析入门。阅读此书并着手编写你的第一个静态程序分析器吧! +# 这一《静态程序分析》教程对谁有用? + +学生,开发者,研究者……几乎所有当代生活者都能从中受益。 + +- 学习方向与程序有关的**学生。** + - 计算机方向的学生可以通过深入学习这一领域知识而为自己建立独特的学术和就业优势。 + - 其他方向的学生同样可以通过了解这一技术,了解静态分析软件能够为你提供怎样的功能和便利,以及如何更好地使用这些软件以保证你所关心的程序质量。 +- 工作内容与程序有关的**开发者。** + - 无论你希望更好地理解[Wiki](https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis)上众多的开源或是闭源的静态程序分析技术,还是希望自己开发一个适用于眼下工作内容的静态程序分析器以保证程序质量,了解静态程序分析都会有所帮助。 +- 研究领域与程序相关的**研究者。** 或许你希望微调研究方向,却因没有合适的入门材料而苦恼;或许你希望了解计算机领域的相关知识以期获得启发……这一教程可以作为你的入门材料或是闲暇读物。 +- 生活与程序相关的**每个人** + - 软件质量是信息化时代的重要议题之一,在这个时代生活与工作,你一定会遇到相关的问题。 + - 在大多数学校和企业中,没有开设该领域的课程。 + +# 什么是静态程序分析? + +## 静态程序分析在计算机科学领域中的定位 + + + +**静态程序分析**是**编程语言**中**应用**层面下的一个细分领域。它是一个非常重要的核心内容。 + +在理论部分,研究者考虑的是如何设计一个语言的语法和语义,如何设计语言的类型系统等等问题;有了语言的语法、语义和类型系统之后,我们需要支撑语言的运行。因此,在环境部分,研究者考虑的是如何为运行中的程序提供运行时环境——如何设计编译器,在运行时需要怎样的支持(如内存的分配管理)等等;应用部分则关注如何保证语言所写出程序的效率、安全性和可靠性,研究者们考虑如何对程序进行分析,验证和合成(如何自动合成一个程序)。 + +### 编程语言的分类 + +当今的计算机世界,面对这样一条恶龙: + +> 数十年来语言的核心没有变化,但软件的规模和复杂性增长迅速,如何保证程序的可靠性? + +尽管新的语言和特性层出不穷,但现在编程语言无非三大类 *(如果你对其中的某个语言不熟悉,可以到语言的官网或英文Wiki页面查看相关示例,也可以利用搜索引擎做初步的了解。本教程内容主要关注于针对命令式语言JAVA的分析。)* : + +* 命令式(C、C++、JAVA) +* 函数式([Scala](https://www.scala-lang.org/)、[Haskell](https://www.haskell.org/)) +* 逻辑式([Prolog](https://en.wikipedia.org/wiki/Prolog)) + +## 静态程序分析的应用 + + +静态程序分析即是屠龙的宝刀之一,这一技术可以处理以下问题(*以下概念只需要了解,重要的应用在后文中会详细讲解。*): + +1. 提高程序可靠性 + - Null pointer dereference, memory leak, etc. + - 空指针引用与内存泄漏等:几乎每个程序编写者都被这两个问题所困扰过 +2. 提高程序安全性 + - Private information leak, injection attack, etc. + - 隐私信息泄漏:TODO + - [注入攻击](https://en.wikipedia.org/wiki/Code_injection):这是网络安全中非常常见的议题。不熟悉的读者可以查看[W3School](https://www.w3schools.com/sql/sql_injection.asp)或[Wiki](https://en.wikipedia.org/wiki/SQL_injection)上关于SQL注入攻击的例子。 +3. 为编译优化提供基础技术 + - Dead code elimination, code motion, etc. + - [死代码消除](https://en.wikipedia.org/wiki/Dead_code_elimination):在编译器的机器无关优化环节,将不会对程序执行结果产生影响的代码(即死代码)删除。 + - [循环不变量的代码移动](https://en.wikipedia.org/wiki/Loop-invariant_code_motion):在编译器的机器无关优化环节,在保证不影响程序执行结果的情况下,将循环中的特定语句移动到循环外,使得程序运行时执行的语句数减少。更为详细的解释可以参考[StackOverFlow上的回答](https://stackoverflow.com/questions/5607762/what-does-code-motion-mean-for-loop-invariant-code-motion)。 +4. 有助于程序理解 + - IDE call hierarchy, type indication, etc. + - 为集成开发环境的功能提供帮助:当你使用VS 2019/Idea/Clion/Eclipse/Android Studio等等IDE时,将鼠标悬停在代码上,IDE能够动态地分析并提示你所悬停对象的相关信息,背后使用的技术就是静态程序分析。 + +## 静态程序分析的市场 + + + +- 在学术界,静态程序分析技术几乎可以应用于所有关于程序的研究方向。 +- 在工业界,国外的Google,IBM等大企业已经初步建立了自己的静态程序分析团队。国内的华为和阿里等企业也正在积极寻找静态程序分析方面的人才。 +- **无论你将来想在学术界还是工业界深入发展,学习这一领域的知识都能为你建立独特的优势。** + +## 静态程序分析与类似技术的对比 + +> Testing shows the presence, not the absence of bugs. --Edsger W. Dijkstra + +动态的软件测试和形式化语义的验证的作用与静态程序分析类似,这一部分对这三个细分方向做简单的对比。 + +### 静态程序分析 + +- 优点:在选定的精度下能够保证没有bug。这在教程中会详细介绍。 +- 缺点: + 1. 学术门槛相对高。目前国内高校只有北京大学和南京大学开设有关课程,且暂无教材。作为一门计算机专业的高年级选修课,入门和提高都较困难。 + 2. You tell me. + +### 动态软件测试 + +- 优点:在工程中被广泛应用,并且有效。实现简单,便于自动化。 + +- 缺点: + + 1. **无法保证没有bug。** 这是无法遍历所有可能的程序输入的必然结果。 + 2. 在当今的由多核与网络应用带来的**并发环境下作用有限。** 某个bug可能只在特定情况下发生,因而难以稳定地复现。如果你对并发程序的测试细节感兴趣,可以参考[《拧龙头法测试并发程序》](https://zhuanlan.zhihu.com/p/51341151)。(截图来自南京大学《形式化语义》课程资料) + + + +### 形式化语义验证 + +- 优点:由于用数学的方法对程序做了抽象,能够保证没有bug。 + +- 缺点: + + 1. 学术门槛较高,学习者必须有良好的数学基础才能入门。 + + 2. 验证代价较高,一般来说非常重要的项目会使用这一方式保证程序质量。甚至在操作系统这样重要的软件中,也并不一定会使用。(截图来自鸿蒙OS直播发布会) + + + +# 加入项目/How to contribute + +> 觉得有所帮助的话可以点个star支持哦。 + +欢迎希望添加更好的讲解资料或对教程内容进行扩充的小伙伴 `fork, modify, PR` 三连。 + +# 本地化/Localization + +## English + +If you wanna translate this project into English, I can proofread for you. All you need to do is `fork, modify, PR` . + +## 日本語 + +このプロジェクトを日本語に翻訳したい場合は、翻訳されたコンテンツの校正をお手伝いします. `fork, modify, PR` で始めましょう! + +# 其他相关项目 + +[《软件测试简介》Gitbook在线阅读地址](https://ranger-nju.gitbook.io/software-testing-intro) + +[《软件测试简介》GitHub项目地址](https://github.com/RangerNJU/Software-Testing-Intro) diff --git a/SUMMARY.md b/SUMMARY.md index 2870901..73af91d 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,15 +1,20 @@ # Table of contents -* [第零章-写在前面](src/ch0/README.md) - * [静态程序分析是啥玩应啊](src/ch0/00-01-why-SPA.md) - * [为什么是这本书?](src/ch0/00-02-why-this-book.md) - * [来源与版权信息](src/ch0/00-03-sources-and-license.md) -* [第一章-静态程序分析简介](src/ch1/README.md) - * [初见——静态分析是什么?](src/ch1/01-01-whats-spa.md) - * [中间表示——静态分析器的输入](src/ch1/01-02-ir.md) -* [第二章-数据流分析的理论与应用](src/ch2/README.md) - * [数据流分析](src/ch2/02-00-dataflow-analysis.md) - * [到达定值分析](src/ch2/02-01-reaching-def-analysis.md) - * [活跃变量分析](src/ch2/02-02-live-var-analysis.md) - * [可用表达式分析](src/ch2/02-03-available-exp-analysis.md) +* [简介](README.md) +* [第零章-写在前面](ch0/README.md) + * [为什么是这本书?](ch0/00-01-why-this-book.md) + * [来源与版权信息](ch0/00-02-sources-and-license.md) +* [第一章-静态程序分析简介](ch1/README.md) + * [初见——静态分析是什么?](ch1/01-01-whats-spa.md) + * [中间表示——静态分析器的输入](ch1/01-02-ir.md) +* [第二章-数据流分析——应用](ch2/README.md) + * [数据流分析](ch2/02-00-dataflow-analysis.md) + * [到达定值分析](ch2/02-01-reaching-def-analysis.md) + * [活跃变量分析](ch2/02-02-live-var-analysis.md) + * [可用表达式分析](ch2/02-03-available-exp-analysis.md) +* [第三章-数据流分析——理论](ch3/README.md) + * [数据流分析](ch3/03-00-dataflow-analysis.md) + * [到达定值分析](ch3/03-01-reaching-def-analysis.md) + * [活跃变量分析](ch3/03-02-live-var-analysis.md) + * [可用表达式分析](ch3/03-03-available-exp-analysis.md) diff --git a/ch0/00-01-why-this-book.md b/ch0/00-01-why-this-book.md new file mode 100644 index 0000000..75a1744 --- /dev/null +++ b/ch0/00-01-why-this-book.md @@ -0,0 +1,39 @@ +# 为什么是这本书? + +> 这里的《静态程序分析》跟别处的有什么不同? + +## 为什么应该读这本书? + +**1. 当前,中英文社区都缺乏这一领域的入门材料。** + +**2. 本书将试图通过理论和实践的结合介绍这一领域。** + +### 中文社区 + +在搜索引擎上搜索相关中文关键词,你会发现结果靠前的答案都是与某南的李老师相关的课程在B站上公开视频的笔记,其中有不少写得很好,**但并非面向一般学习者开发者的教程**。这两者有重要的区别: + +* 笔记:**面向自己复习**使用,只要自己回顾时能迅速pick up当时理解到的重点,就是一份好的笔记。 +* 教程:**面向他人学习**使用,一份好教程能让学习者迅速把握领域中的重点,并且为学习者的进一步应用打下基础。 + +### 英文社区 + +在搜索引擎上搜索英文关键词,你应该能搜索到国际上的大牛们的教材式的PDF文件和相关论文,或是开源的静态分析程序。但同样**缺乏教程**。大多数材料要么艰涩难懂要么太过粗浅。根据粗略的访问与调查,目前业界中主要还是大型的、国际化的、有前瞻视野的企业重视这一技术的发展应用,而中小企业则对其并不了解或认为静态程序分析技术仍不成熟。 + +### 理论与实践的结合 + +本书将同时涉及理论和实践,这主要是受到了《The Rust Programming Language》的启发。 + +### 本书写作的目标 + +能让大多数有一定编程经历,已经修过本科计算机相关基础课程的大四及以上同学: + +1. 在阅读本书时能较为轻松地理解理论 +2. 能够自主完成一个简单的程序实现 +3. (任何人都)能在阅读过程中接触计算机不同领域的小知识 + +## 为什么要写这本书? + +* 最主要的动力还是老师现场授课时我感受到的passion +* 这是一个少有人涉足的领域,写这方面的内容很符合我的性格 +* 我从开源社区中获益颇多,找到了合适的机会也希望能为开源社区(尤其是中文社区)作出自己的贡献 + diff --git a/ch0/00-02-sources-and-license.md b/ch0/00-02-sources-and-license.md new file mode 100644 index 0000000..876a2d0 --- /dev/null +++ b/ch0/00-02-sources-and-license.md @@ -0,0 +1,13 @@ +# 来源与版权信息 + +## 资料来源 + +本入门教程主要内容基于南京大学《软件分析》课程。 + +[PASCAL研究组主页](https://pascal-group.bitbucket.io/teaching.html) + +## 版权信息 + +教程文字部分遵循CC BY-NC-SA许可协议。 + +图片部分若无特殊说明,均出自课程资料,使用已获作者同意。 diff --git a/ch0/README.md b/ch0/README.md new file mode 100644 index 0000000..92d4d65 --- /dev/null +++ b/ch0/README.md @@ -0,0 +1,5 @@ +# 第零章简介 + +记录一些你在继续阅读之前可能需要了解的信息。 + +如果这是你第一次了解“静态程序分析”,你应该先查看[Github上的简介](https://github.com/RangerNJU/Static-Program-Analysis-Book)。 \ No newline at end of file diff --git a/ch1/01-01-whats-spa.md b/ch1/01-01-whats-spa.md new file mode 100644 index 0000000..c5751b1 --- /dev/null +++ b/ch1/01-01-whats-spa.md @@ -0,0 +1,140 @@ +# 初见——静态分析是什么? + +> 静态程序分析是指**不编译**出二进制代码通过测试用例对程序进行测试,仅通过**静态地**分析程序得到程序**不平凡**的性质的过程。 + +## 静态程序分析的抽象定义与诠释 + +### 定义 + +> Static analysis analyzes a program P to reason about its behaviors and determines whether it satisfies some properties before running P. + +- Does P contain any private information leaks? +- Does P dereference any null pointers? +- Are all the cast operations in P safe? +- Can v1 and v2 in P point to the same memory location? +- Will certain assert statements in P fail? +- Is this piece of code in P dead (so that it could be eliminated)? + +即:对一个程序P,静态程序分析在运行P之前分析它的行为并确认它是否满足某些性质。例如: + +- P会导致隐私信息泄漏吗? +- P中会不会有空指针被解引用? +- P中的所有cast操作(掌握JAVA或C++的读者应该熟悉这一操作)都是安全的吗? +- P中的两个指针是否会指向同一个内存地址? +- P中某个特定的断言会失败吗? +- P中的某部分代码是死代码吗? + +### 诠释 + +> Ensure \(or get close to\) soundness, while making good trade-offs between analysis precision and analysis speed. + +在分析精度和速度之间做平衡的同时,保证(或近似)soundness。*(对于soundness这个词,有很多种不同的翻译方式,如可靠性、安全性等。)*通常来说,分析的精度要求越高,分析的速度就会越慢。类似的trade-off在计算机世界非常常见。 + +## 静态程序分析的具体解释 + +静态程序分析技术中最重要的两个技术,分别是Abstraction(抽象)和Over-Approximation(过近似) + +### Abstraction + + + +**抽象是将值从Concrete Domain(具体域)映射到Abstract Domain(抽象域)的过程,也即将具体值映射为抽象值。** + +例如,在上图中: + +- Concrete Domain中变量的值可以是具体的数值,也可能是某种表达式或函数的返回值。 +- Abstract Domain中变量的值分为五类: + 1. 正 + 2. 负 + 3. 零 + 4. unknown(未知),通常表达为正的T,读作top + 5. undefined(未定),通常表达为上下颠倒的T,读作bottom + +关于unknown和undefined: + +- unknown(未知):根据表达式或函数返回决定,程序运行时会有具体的正负零数值,但运行前只通过该表达式无法确定。如应用C语言中的三目运算符(TODO:加Link)`x = flag ? 1 : -1`中x的值就是unknown的。 +- undefined(未定)程序运行时会遇到错误,并产生未定义行为(TODO:加Link)。如许多语言中divided by zero(除数为零)通常会触发异常/硬件错误,此时如`a=b/0`中a的值就是undefined的。 + +### Over-approximation + +**过近似主要是指对抽象值进行操作时的思想。** + +继续上面的例子,具体来说操作可以分为两类:Data flow(数据流)和Control flow(控制流): + +#### Data flow + +(TODO-加图) + +* 两个正数相加为正数 +* ... +* 正数和负数相加,结果为unknown/top。**这是因为运行前只知道表达式的正负号,无法确定结果是正负零中的任何一个,但程序运行时会有具体的数值。** +* unknown/top除以0,结果为undefined。**这是因为会触发未定义行为。** + +#### Control flow + +在程序执行过程中往往会有分支结构,如果x的值在两个分支中分别被赋抽象正值和抽象负值,那么合并时x抽象值应该是五类中的哪一种呢? + +对于分支合并时的x,**运行前只知道抽象值的正负号,无法确定结果是哪一种,但程序运行时会有具体的数值**。无论是抽象为正还是负都无法准确描述x合并后的状态,所以x合并后的抽象值是unknown/top。 + +## Rice‘s Theorem与静态程序分析目标 + +### Rice's Theorem + +> Any non-trivial property of the behavior of programs in a r.e. language is undecidable. (TODO:加中文) + +(TODO:加中文) 这句话中有很多很难的词汇,接下来一一解释: + +* non-trivial properties ~= interesting properties ~= the properties related with run-time behaviors of programs +* r.e. \(recursively enumerable\) 递归可枚举语⾔: recognizable by a Turing-machine +* There is no such approach to determine whether P satisfies such non-trivial properties, i.e., giving exact answer: Yes or No +* 故不存在 perfect \(sound & complete\) static analysis + +### 两个重要概念:Sound与Complete + +> 思考: 作为一个开发者,你使用静态分析器分析自己的代码时,哪种情况更让你觉得糟糕? +> +> * 静态分析器**没有分析出代码错误**的部分。 +> * 静态分析器**判断代码正确的部分为错**的部分。 + +Over- and under-approximations are both for safety of analysis. + +sound: 报出所有问题 may analysis: outputs information that may be true \(over-approximation\) \(safe=over\) + +complete: 报出的问题都是对的 must analysis: outputs information that must be true \(under-approximation\) \(safe=under\) + +### 实际应用中静态分析器的设计目标 + +(TODO:加图) **实际应用中往往没有办法做到完美。因而需要妥协。** + +需要静态分析器能在可接受的时间内给出精度满足要求的解。为此: + +妥协 soundness \(false negatives 可能漏报\) + +妥协 completeness \(false positives 可能误报\) \(⼤多数情况的分析,因为 soundness 很重要\) + +## 再讲五块钱的? + +### 关于未定义行为 + +- [未定义行为](https://en.wikipedia.org/wiki/Undefined_behavior)在Wiki上的解释: + +> In computer programming, undefined behavior (UB) is the result of executing a program whose behavior is prescribed to be unpredictable, in the language specification to which the computer code adheres. + +- 一个经典的未定义行为例子: + + ```c++ + int a[7]; + ... + int j = 0; + + //输出结果根据编译器实现不同而不同 + std::cout << a[j++] + a[j] + ``` + +### 关于trade-off + +- [存储器层次结构](https://en.wikipedia.org/wiki/Memory_hierarchy):cache-memory-disk-network的经典结构,正是当代计算机设计者们对价格、读写速度和存储容量的典型trade-off。 +- 段页式内存管理:分段和分页方式的存储管理各有其特点,而段页式存储管理将两种方式结合,优缺点互补。 + +### 关于判定问题中经常用到的术语 + diff --git a/ch1/01-02-ir.md b/ch1/01-02-ir.md new file mode 100644 index 0000000..3dce6e3 --- /dev/null +++ b/ch1/01-02-ir.md @@ -0,0 +1,70 @@ +# 中间表示——静态分析器的输入 + +## 从编译器的组件谈起 + +一个典型的编译器分成一下几个部分: + +* Scanner:读入源代码,借助正则表达式完成词法分析,输出Tokens或报告错误的词法输入。如`goouojd`并是一个有效的英文单词,就会被报告为错误。 +* Parser:读入Tokens,通过上下文无关文法完成语法分析,构建抽象语法树或报告错误的语法输入。如`Like your hair I`就不符合英语语法,会被报告为错误。 +* Type Checker:读入抽象语法树,以属性文法进行语义分析并检查类型兼容性等,输出Decorated AST或报告错误的语义。如`Apples eat you`在语法上正确,但不可能有苹果会吃人,这是语义上的错误。 +* Translater:读入Decorated AST,通过遍历Decorated AST将树型IR(AST)翻译为线型IR(通常是三地址码的形式)。然后可以**通过静态分析**进行机器无关的代码优化。 +* Code Generator:读入线型IR,并根据指定的CPU指令集将机器无法直接执行的IR转换为机器可直接执行的机器代码。 + +### AST与IR的比较 + +AST: + +* high-level and closed to grammar structure +* usually language dependent +* suitable for fast type checking +* lack of control flow information + +即: + +* 更接近于语法规定的结构 +* 通常与语言有关 +* 适于快速类型检查 +* 没有控制流信息 + +IR: + +* low-level and closed to machine code +* usually language independent +* compact and uniform +* contains control flow info +* usually considered as the basis for static analysis + +即: + +* 更接近于机器码 +* 通常与语言无关 +* 紧凑而通用 +* 包含控制流信息 +* 通常被视为静态分析的基础 + +**总的来说,线型IR更适合静态分析。线型IR没有固定的定义,实际使用中常用三地址码。** + +~~在计算机领域,直接用英文常常更容易将概念表达清楚,如果有读者认为有更好的翻译,可以联系作者(邮箱或github issue都可以)~~ + +### 三地址码 + +> Definition: Each 3AC contains at most 3 addresses \(name, constant, temporary\) + +定义:每一条三地址码最多包含3个地址(地址包括程序员显式定义的有名字变量,常量和临时变量) 一些形式 + +TBD + +### 其他预备内容 + +举例说明: +Data/Method/Call Graph + +invoke specail:构造函数,super等使用 +virtual:其他的Class Method +interface:2 plus checking +static:静态方法调用 + +Java7 中引入dynamic cast? + +SSA->只需要记住FreshName和Phi-Function + diff --git a/ch1/README.md b/ch1/README.md new file mode 100644 index 0000000..2e226ec --- /dev/null +++ b/ch1/README.md @@ -0,0 +1,9 @@ +# 第一章-静态程序分析简介 + +在这一部分中,将正式地介绍: + +- 什么是静态程序分析(下简称为静态分析) +- 这一技术有什么样的应用 +- 为什么它值得我们去学习与研究 +- + diff --git a/src/ch2/02-00-dataflow-analysis.md b/ch2/02-00-dataflow-analysis.md similarity index 100% rename from src/ch2/02-00-dataflow-analysis.md rename to ch2/02-00-dataflow-analysis.md diff --git a/ch2/02-01-reaching-def-analysis.md b/ch2/02-01-reaching-def-analysis.md new file mode 100644 index 0000000..2629d9c --- /dev/null +++ b/ch2/02-01-reaching-def-analysis.md @@ -0,0 +1,4 @@ +# 到达定值分析 + +TBD + diff --git a/ch2/02-02-live-var-analysis.md b/ch2/02-02-live-var-analysis.md new file mode 100644 index 0000000..3018285 --- /dev/null +++ b/ch2/02-02-live-var-analysis.md @@ -0,0 +1,4 @@ +# 活跃变量分析 + +TBD + diff --git a/src/ch2/02-03-available-exp-analysis.md b/ch2/02-03-available-exp-analysis.md similarity index 53% rename from src/ch2/02-03-available-exp-analysis.md rename to ch2/02-03-available-exp-analysis.md index 12dd58f..9d0b62f 100644 --- a/src/ch2/02-03-available-exp-analysis.md +++ b/ch2/02-03-available-exp-analysis.md @@ -1,18 +1,15 @@ -# 数据流分析之可用表达式分析 +# 可用表达式分析 ## 定义 -> An expression x op y is available at program point p if (1) all paths from the entry to p must pass through the evaluation of x op y, and (2) after the last evaluation of x op y, there is no redefinition of x or y. +> An expression x op y is available at program point p if \(1\) all paths from the entry to p must pass through the evaluation of x op y, and \(2\) after the last evaluation of x op y, there is no redefinition of x or y. ## 理解定义:一个tricky的例子 1. 按照直觉来说,c处不是,但是按照定义来说是。但是实际上运行时只会走一条分支。 - -2. 回顾: -must->under-approximation->报出来的全都是真的。不允许误报,但允许漏报 -may->不允许漏报,但允许误报 -重新理解这个例子。 +2. 回顾: must->under-approximation->报出来的全都是真的。不允许误报,但允许漏报 may->不允许漏报,但允许误报 重新理解这个例子。 PS. 如何记住边界条件设置谁?设置是空还是满?对余下所有块的初始化是空还是满(一个巧妙的方法是判断may/must后,如果条件汇合时是交集,一般开始时大多数块初始化为满。) 一个经常迷惑的问题:先gen先kill?根据定义就解决所有问题2 + diff --git a/ch2/README.md b/ch2/README.md new file mode 100644 index 0000000..5457a2b --- /dev/null +++ b/ch2/README.md @@ -0,0 +1,2 @@ +# 第二章-数据流分析的理论与应用 + diff --git a/ch3/README.md b/ch3/README.md new file mode 100644 index 0000000..2b612e3 --- /dev/null +++ b/ch3/README.md @@ -0,0 +1,181 @@ +# 第三章-数据流分析——理论 + +帮助理解之前所数的数据流分析技术,让你在将来review的时候更有效率。忘记了也能自己推导出大概。 + +## 基础(Recall离散数学) + +### Yet Another(Math Instead of Program) View to Iterative Algorithm + +Forward:根据IN求OUT +May:Merge时求并,初始化为bottom + +文字描述->符号化描述。 + +*下标:Node,上标:迭代次数。最后i和i+1的结果一致。* + +右下角引出不动点(数学定义)。 + +- 有解性(一定有解) +- 解的唯一性(假设取得了最好的) + - 最大最小不动点? +- 什么时候算法给出解? + +**这是数十年来程序分析的问题精华。接下来我们接触一些必要的数学。** + +偏序: (能够容忍不可比较性) + +用例子记忆。 + +poset(偏序集) + +- 自反 +- 反对称 +- 传递 + +Lattice(格)之图。 + + +正式介绍Lattice之前,介绍两个概念:上下界。 + +注意:*上下界不需要是集合S中的元素。* + +例子。 + +定义一个least upper bound(lub or join),即最小上界。类似地定义最大下界。 + +例子。 + +属性: +1. join和meet不一定有。 +2. 有则唯一。( 证明-反证法。) + +定义Lattice: 任取两个元素,都有join和meet就是lattice。 + +定义Semilattice:join和meet有且只有一个。 + +定义Complete Lattice:任何一个子集都有join和meet。 + +top和bottom。 + +性质:有穷则complete,反之不行(Recall Ex1) + +程序通常是有限的(表达式,变量等是有限的)。因此,在数据流分析中主要关注Complete Lattice。 + +定义Product Lattice:新的集合,新的关系和join和meet。 + +性质: + +1. A product lattice is a lattice +2. If a product lattice L is a product of complete lattices, then L is also complete + +Lattice上数据流分析的框架: + +例子。 + +总结:Data flow analysis can be seen as iteratively applying transfer functions and meet/join operations on the values of a lattice. + +基础已备。回顾开头的三个问题: + +回顾单调性(和高中数学定义一致)。 + +**不动点定理** + +前提: Complete Lattice/Function is Monotonic/Lattice is Finite. + +效果:给出了固定的求不动点的方法。 + +证明: +1. 存在 +2. 最小 + +存在-f(bottom)中的元素一定在L中,由bottom的定义,这个式子自然成立。 *微积分:单调有界必收敛。* + +最小-从bottom开始和从任意一个x开始都满足关系。 + +#### 喜闻乐见的五块钱 + +从PL与数学的证明(T的不同方向)讲起。 + +通过清晰地定义问题的相关因素,缩小问题。 + +1. 重新定义问题的Scope(上下文敏感指针分析可以跑得必非上下文敏感指针分析更快)。 +2. 科研任务/工作任务需要通过沟通缩小Scope。 + +### Relate Iterative Algorithm to Fixed-Point Theorem + +上节课的Product Lattice。 + +Transfer Function**应该被设计为**是单调的。 +join和meet都可以被证明是单调的。 + +回答问题: +1. Yes。因为不动点原理。 +2. Yes。因为推理出来... + +何时能达到不动点? +首先定义高度。 + +提示:每个node一次一步,一个node最坏情况下走h步。所有node最坏情况下要走$h*k$步。 + +所以算法快慢与程序的规模和Lattice Domain有关。 + +### May and Must Analyses, a Lattice View + +相当于总结上文。 +TODO:从前三节课程的理解到一张图解释 + +所有分析过程一定从不安全的结果向安全但没有意义的结果推进, +以reaching definition为例子,每个块被初始化为全0,代表没有definition可以reach到特定程序点。 +Truth的位置在Safe和Unsafe中间,越接近Safe,精度就越低。 + +问题:为什么一定能越过Truth达到Fixed Point呢? +是否Safe是由Transfer Function和Mering的策略决定的,也就是由设计算法的人决定的。 + + + +### Meet/Join-Over-All-Paths Solution(MOP) + +> 我们的结论有多准? + +Meet:一旦数据流汇聚了,如何处理? + +PL基础小知识: +程序中的汇聚从何而来?<-分支和循环结构 +- 分支:if,switch,try catch, exception, promise(JS) ... +- 循环:while, do while, for ... + +这是分析精度的标杆。 + +### Iterative Algorithm vs MOP + +IA:在每次第一次汇聚的时候就等一等,先merge。不需要枚举,运算量更小,结果没那么准。 +MOP:没必要等,在最后一次汇聚的时候才merge。因为要枚举Path,运算量更大,结果更准。 + +关于精度,有一个简单的证明。(前提是F满足单调性)。 + +如果F满足分配律(高中数学)。那么MOP和我们的IA一样准。 + +好消息!当join/meet使用set union/intersection时(之前举过的三个例子都是可分配的)。 + +### 单调性与不动点 + +### 函数的可分布性 + +### Constant Propagation + +> Given a variable x at program point p, determine whether x is guaranteed to hold a constant value at p. 在程序点P指定一个变量X,判断X是否在这点是一个常量。 + +Undefine->Constant->NotAConstant + +下划线表示PL领域的通配符。 + + +other -> 两个UNDEF;一个UNDEF一个Constant=>不能是NAC:例如x+y,x第一次是UNDEF,第二次是14,y一直都是2,则两次的结果一次是NAC一次是常量=>这个Transfer Funtion不满足单调性。 + +## Worklist Algorithm + +作为IA的优化版本,懂了IA之后WA很容易懂。 + +IA适合性质的分析与证明,工作中使用的往往是WA。 + +WA为什么快->IA为什么慢-> \ No newline at end of file diff --git a/src/ch0/00-01-why-SPA.md b/src/ch0/00-01-why-SPA.md deleted file mode 100644 index d73eeed..0000000 --- a/src/ch0/00-01-why-SPA.md +++ /dev/null @@ -1,35 +0,0 @@ -# 为什么你需要了解静态程序分析 - -## 定位 - -**静态程序分析**是**编程语言**中**应用**层面下的一个细分领域。 - -![](00-01-why-SPA.assets/PL.png) - -(TODO:举一些具体的例子) - -当今编程语言可以主要分为三大类 -- 命令式(C、C++、JAVA) -- 函数式(Scale、Haskell) -- 逻辑式(Prolog、SQL) - -*之后的内容主要关注于针对命令式语言的分析。* - -当今**编程语言**这个分支下,面临这样一条恶龙:`数十年来语言的核心没有变化,但软件的规模和复杂性增长迅速,如何保证程序的可靠性?` - -## 应用 - -静态程序分析即是屠龙的宝刀之一,掌握并应用这一技术,能够: - -1. 提高程序可靠性——Null pointer dereference, memory leak, etc.(空指针引用与内存泄漏等) -2. 提高程序安全性——Private information leak, injection attack, etc.(隐私信息泄漏与注入攻击等) -3. 为编译优化提供基础技术——Dead code elimination, code motion, etc.(死代码消除和代码向循环外移动等) -4. 有助于程序理解——IDE call hierarchy, type indication, etc.(为集成开发环境的功能提供帮助) - -## 市场 - -在学术界,静态程序分析技术几乎可以应用于所有关于程序的研究方向。 - -在工业界,国外的Google,IBM等大企业已经初步建立了自己的静态程序分析团队。国内的华为和阿里等企业也正在寻找静态程序分析方面的人才。 - -(TODO:添加更为详细的例子) \ No newline at end of file diff --git a/src/ch0/00-02-why-this-book.md b/src/ch0/00-02-why-this-book.md deleted file mode 100644 index 3cc75b5..0000000 --- a/src/ch0/00-02-why-this-book.md +++ /dev/null @@ -1,39 +0,0 @@ -# 为什么是这本书? - -> 你说的静态程序分析似乎有点儿用处,那么哪里可以学到呢? - -## 为什么应该读这本书? - -**1. 当前的中英文社区都缺乏这一领域的入门材料。** - -**2. 本书将带领读者,通过理论和实践的结合了解这一领域。** - -### 中文社区 - -在搜索引擎上搜索相关中文关键词,你会发现结果靠前的答案都是与某南的李老师相关的课程在B站上公开视频的笔记,其中有不少写得很好,**但并非面向一般学习者开发者的教程**。这两者有重要的区别: - -- 笔记:**面向自己**复习使用,只要自己回顾时能迅速pick up当时理解到的重点,就是一份好的笔记。 -- 教程:**面向学习者**使用,一份好教程能让学习者迅速把握领域中的重点,并且为学习者的进一步应用打下基础。 - -### 英文社区 - -在搜索引擎上搜索英文关键词,你应该能搜索到国际上的大牛们的教材式的PDF文件和相关论文,或是开源的静态分析程序。但同样**缺乏教程**。大多数材料要么艰涩难懂要么太过粗浅。根据粗略的访问,我也了解到业界认为静态程序分析技术仍不成熟。 - -### 理论与实践的结合 - -本书将同时涉及理论和实践,这主要是受到了《The Rust Programming Language》的启发。 - -### 本书写作的目标 - -能让大多数有一定编程经历,已经修过本科计算机基础课程的大四及以上学力(不是学历)的同学: - -1. 在阅读本书时能较为轻松地理解理论 -2. 能够自主完成原型实现 -3. 能在阅读过程中接触CS不同领域的小知识 - -## 为什么要写这本书? - -- 最主要的动力还是老师现场授课时我感受到的passion -- 这是一个少有人涉足的领域,写这方面的内容很符合我的性格 -- 我从开源社区中获益颇多,找到了合适的机会也希望能为开源社区(尤其是中文社区)作出自己的贡献 -- 人类发展的历史重要的两部分是传承和发展。领域先锋发展探索,亦需要有人将新的知识传播开来 diff --git a/src/ch0/00-03-sources-and-license.md b/src/ch0/00-03-sources-and-license.md deleted file mode 100644 index d73168a..0000000 --- a/src/ch0/00-03-sources-and-license.md +++ /dev/null @@ -1,13 +0,0 @@ -# 来源与版权信息 - -## 资料来源 - -本入门教程基于南京大学《软件分析》课程。 - -[PASCAL研究组主页](https://pascal-group.bitbucket.io/teaching.html) - -## 版权信息 - -教程文字部分遵循CC BY-NC-SA许可。 - -图片部分若无特殊说明,均为课程Slides的一部分,本书中使用这些图片已获Slides作者同意。 diff --git a/src/ch0/README.md b/src/ch0/README.md deleted file mode 100644 index 8d694ad..0000000 --- a/src/ch0/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# 写在前面 - -记录一些你在决定认真阅读本书之前需要了解的信息。 diff --git a/src/ch1/01-01-whats-spa.md b/src/ch1/01-01-whats-spa.md deleted file mode 100644 index 6664dc5..0000000 --- a/src/ch1/01-01-whats-spa.md +++ /dev/null @@ -1,107 +0,0 @@ -# 静态程序分析是什么 - -> 静态程序分析是指**不编译**出二进制代码通过测试用例对程序进行测试,仅通过**静态地**分析程序得到程序**不平凡**的性质的过程。 - - -## 静态程序分析的抽象定义与诠释 - -### 一句话定义(TODO:中文翻译) - -> Static analysis analyzes a program P to reason about its behaviors and determines whether it satisfies some properties befo re running P. - -### 一句话诠释(TODO:中文翻译) - -> Ensure (or get close to) soundness, while making good trade-offs between analysis precision and analysis speed. - -在分析精度和速度之间做平衡的同时,保证(或近似)soundness。 - -## 静态程序分析的具体解释 - -静态程序分析技术中最重要的两个技术,分别是Abstraction(抽象)和Over-Approximation(过近似) - -### Abstraction - -**抽象是将值从Concrete Domain(具体域)映射到Abstract Domain(抽象域)的过程。** - -举个例子:(TODO:加图) - -Concrete Domain中,变量的值可以是具体的值,也可能是某种表达式或函数的返回值。 - -Abstract Domain中,变量的值分为五类: - -- 正 -- 负 -- 零 -- unknown(未知):根据表达式或函数返回决定,程序运行时会有具体的正负零数值,但运行前只通过该表达式无法确定。如应用C语言中的三目运算符(TODO:加Link)`x = flag ? 1 : -1`中x的值就是unknown的。 -- undefined(未定):程序运行时会遇到错误,并产生未定义行为(TODO:加Link)。如许多语言中divided by zero(除数为零)通常会触发异常/硬件错误,此时如`a=b/0`中a的值就是undefined的。 - -其中unknown通常表达为正的T,读作top;undefined通常表达为上下颠倒的T,读作bottom。 - -### Over-approximation - -**过近似主要是指对抽象值进行操作时的思想。** - -继续上面的例子,具体来说操作可以分为两类:Data flow(数据流)和Control flow(控制流): - -#### Data flow - -(TODO-加图) - -- 两个正数相加为正数 -- ... -- 正数和负数相加,结果为unknown/top。**这是因为运行前只知道表达式的正负号,无法确定结果是正负零中的任何一个,但程序运行时会有具体的数值。** -- unknown/top除以0,结果为undefined。**这是因为会触发未定义行为。** - -#### Control flow - -在程序执行过程中往往会有分支结构,如果x的值在两个分支中分别被赋抽象正值和抽象负值,那么合并时x抽象值应该是五类中的哪一种呢? - -对于分支合并时的x,**运行前只知道抽象值的正负号,无法确定结果是哪一种,但程序运行时会有具体的数值**。无论是抽象为正还是负都无法准确描述x合并后的状态,所以x合并后的抽象值是unknown/top。 - - -## Rice‘s Theorem与静态程序分析目标 - -### Rice's Theorem - -> Any non-trivial property of the behavior of programs in a r.e. language is undecidable. -(TODO:加中文) - -(TODO:加中文) -这句话中有很多很难的词汇,接下来一一解释: -- non-trivial properties ~= interesting properties ~= the properties related with run-time behaviors of programs -- r.e. (recursively enumerable) 递归可枚举语⾔: recognizable by a Turing-machine -- There is no such approach to determine whether P satisfies such non-trivial properties, i.e., giving exact answer: Yes or No -- 故不存在 perfect (sound & complete) static analysis - -### 两个重要概念:Sound与Complete - -> 思考: 作为一个开发者,你使用静态分析器分析自己的代码时,哪种情况更让你觉得糟糕? -> -> - 静态分析器**没有分析出代码错误**的部分。 -> - 静态分析器**判断代码正确的部分为错**的部分。 - -Over- and under-approximations are both for safety of analysis. - -sound: 报出所有问题 may analysis: outputs information that may be true (over-approximation) (safe=over) - -complete: 报出的问题都是对的 must analysis: outputs information that must be true (under-approximation) (safe=under) - - -### 实际应用中静态分析器的设计目标 - -(TODO:加图) -**实际应用中往往没有办法做到完美。因而需要妥协。** - -需要静态分析器能在可接受的时间内给出精度满足要求的解。为此: - -妥协 soundness (false negatives 可能漏报) - -妥协 completeness (false positives 可能误报) (⼤多数情况的分析,因为 soundness 很重要) - -## 再讲五块钱的? - -### 关于未定义行为(TODO:加Link和解释) - -### 关于程序测试与分析(TODO:加程序分析的LINK和对比) - -### 关于判定问题中经常用到的术语 diff --git a/src/ch1/01-02-ir.md b/src/ch1/01-02-ir.md deleted file mode 100644 index d0f9032..0000000 --- a/src/ch1/01-02-ir.md +++ /dev/null @@ -1,51 +0,0 @@ -# 中间表示——静态分析的输入 - -## 从编译器的组件谈起 - -一个典型的编译器分成一下几个部分: -- Scanner:读入源代码,借助正则表达式完成词法分析,输出Tokens或报告错误的词法输入。如`goouojd`并是一个有效的英文单词,就会被报告为错误。 -- Parser:读入Tokens,通过上下文无关文法完成语法分析,构建抽象语法树或报告错误的语法输入。如`Like your hair I`就不符合英语语法,会被报告为错误。 -- Type Checker:读入抽象语法树,以属性文法进行语义分析并检查类型兼容性等,输出Decorated AST或报告错误的语义。如`Apples eat you`在语法上正确,但不可能有苹果会吃人,这是语义上的错误。 -- Translater:读入Decorated AST,通过遍历Decorated AST将树型IR(AST)翻译为线型IR(通常是三地址码的形式)。然后可以**通过静态分析**进行机器无关的代码优化。 -- Code Generator:读入线型IR,并根据指定的CPU指令集将机器无法直接执行的IR转换为机器可直接执行的机器代码。 - -### AST与IR的比较 - -AST: -- high-level and closed to grammar structure -- usually language dependent -- suitable for fast type checking -- lack of control flow information - -即: -- 更接近于语法规定的结构 -- 通常与语言有关 -- 适于快速类型检查 -- 没有控制流信息 - -IR: -- low-level and closed to machine code -- usually language independent -- compact and uniform -- contains control flow info -- usually considered as the basis for static analysis - -即: -- 更接近于机器码 -- 通常与语言无关 -- 紧凑而通用 -- 包含控制流信息 -- 通常被视为静态分析的基础 - -**总的来说,线型IR更适合静态分析。线型IR没有固定的定义,实际使用中常用三地址码。** - -~~在计算机领域,直接用英文常常更容易将概念表达清楚,如果有读者认为有更好的翻译,可以联系作者(邮箱或github issue都可以)~~ - -### 三地址码 - -> Definition: Each 3AC contains at most 3 addresses (name, constant, temporary) - -定义:每一条三地址码最多包含3个地址(地址包括程序员显式定义的有名字变量,常量和临时变量) -一些形式 - -TBD \ No newline at end of file diff --git a/src/ch1/README.md b/src/ch1/README.md deleted file mode 100644 index fa58dfb..0000000 --- a/src/ch1/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# 入门指南 - -在这一部分中,将介绍什么是静态程序分析(下文将简称为静态分析),这一技术有什么样的应用,为什么它值得我们去学习与研究。 - diff --git a/src/ch2/02-01-reaching-def-analysis.md b/src/ch2/02-01-reaching-def-analysis.md deleted file mode 100644 index b430fdb..0000000 --- a/src/ch2/02-01-reaching-def-analysis.md +++ /dev/null @@ -1,4 +0,0 @@ -# 数据流分析之到达定值分析 - -TBD - diff --git a/src/ch2/02-02-live-var-analysis.md b/src/ch2/02-02-live-var-analysis.md deleted file mode 100644 index a733705..0000000 --- a/src/ch2/02-02-live-var-analysis.md +++ /dev/null @@ -1,4 +0,0 @@ -# 数据流分析之活跃变量分析 - -TBD - diff --git a/src/ch2/README.md b/src/ch2/README.md deleted file mode 100644 index 152d806..0000000 --- a/src/ch2/README.md +++ /dev/null @@ -1 +0,0 @@ -# 数据流分析的理论与应用