南京大学 静态软件分析(static program analyzes)-- Datalog-Based Program Analysis 学习笔记


一、Motivation:Datalog-Based Program Analysis

声明式语言和指令式语言的区别

Datalog是一种声明式(Declarative)的编程语言,与之相对的另一种语言是命令式(Imperative)编程语言。

举一个例子说明说明两者之间的区别,

  • 命令式语言是直接告诉程序需要做哪些指令(how to do),典型的如C、JAVA
  • 声明式语言是告诉程序要得到什么结果(what to do),典型的如sql,声明式语言更加精炼

使用哪种语言去实现PTA?

1、使用Imperative(命令式)

若使用命令式实现PTA,实现复杂。

  • worklist数据结构是数组list还是链表,是先进先出还是先进后出?
  • 如何表示指针集合,hash集还是bit向量?
  • 如何关联PFG节点和指针?
  • 如何联系相关语句和其中的变量?

2、使用Datalog(声明式)

声明式PTA实现有以下优点:

  1. 简洁
  2. 可读性好
  3. 易于实现

二、Introduction to Datalog

Datalog:是声明式编程语言,是Prolog的子集,最初用于数据库,现在广泛应用于程序分析、网络定义、大数据、云计算等。

Datalog=Data+Logic(and,or,not)

  • Datalog没有副作用(没有赋值)
  • 没有控制流
  • 没有函数
  • 非图灵完备

Predicates (Data)

1、谓词Predicates

谓词(Predicates)是datalog中的一个主要组成部分,可以看作是数据所组成的一个表(table of data),谓词中的每一行都代表一个事实(fact)。例如:

  • (”Xiaoming“,18)是一个fact
  • (”Abal“,23)在该数据集中找不到,不是一个fact
  • Age是一个谓词、Person也可以是一个谓词,对应到SQL里就是某个数据集中的一列

谓词Predicate可以看作一系列陈述的集合,陈述某事情的事实(真假)。如

  • Age,表示一些人的年龄
  • Person,表示一些人的姓名

总体上,谓词可以分为两类,

  • EDB (extensional database):在程序运行前,这些数据已经给定
  • IDB (intensional database):这一类数据仅由规则推导得来

2、事实Fact

表示一个组合是否属于一种关系,比如

  • ("Xiaoming", 18)可以表示“Xiaoming的年龄是18岁”,但注意这个陈述不一定值为True。

3、原子Atoms

原子(Atoms)是Datalog中的基本元素,原子Atoms的基本格式是:P(X1, X2, ... , Xn)

  • P表示谓词名
  • Xi表示参数

比如Age("Xiaoming", 18)

形式化表述和例子如下:

Atoms可以分成两类:

  • Relational Atoms
  • Arithmetic Atoms

Datalog Rules (Logic) 

Datalog使用规则来进行推导(inference),总共有如下几种推导类型,

  • Logic And
  • Logic Or
  • Logic Not/Negation
  • Recursion

1、Logic And

定义如下:

当Body中的所有表达式都为True时,Head才为True,如: 

求解过程(Interpretation of Datalog Rules)是枚举Body中所有关系表达式的可能取值组合,进而得到新的predicate/table。例如: 

2、Logic Or

逻辑或有两种写法,

注意,逻辑与的优先级比逻辑或的优先级高。 

建议在书写程序时用括号明确地标识期望的运算优先级:H<-A,(B;C)

3、Logic Not/Negation 

4、Recursion 

Rule Safety 

Rule的安全性问题需要特别关注,注意看这两条Rules看起来有什么问题,

上面两条Rule都是非安全的,这里最核心的问题在于:

由于x有无限的取值能满足规则,所以生成的A是一个无限大的关系。因此上述两条规则是不安全的。在Datalog中,只接受安全的规则。

这里我们需要记住一个判定的准则:

  • 产生的数据必须有穷:如果规则中的每个变量至少在一个non-nageted relational atom中出现一次,那么这个规则是安全的。这实际上是借助已有的predicates(它们必定是有限的)来限制变量的取值范围。

类似地,还有这样的规则:

对应地有第二个准则:

  • 推导规则不能出现悖论(H和Bi间出现矛盾)不要把recursion和negation写在同一条规则里,即避免写出非A推导出A这样的循环悖论规则。  

Execution of Datalog Programs

Datalog的两大重要特性:

  • 单调性。因为事实(facts)不会被删除的。
  • 必然终止。
    • 事实的数量是单调的。
    • 由Rule Safety,所能得到的IDB的大小也是有限的。

三、Pointer Analysis via Datalog

了解了Datalog的基本语法和性质,我们就可以用它来实现声明式的指针分析算法。

关于声明式的指针分析算法,三个重要的部分如下:

  • EDB: pointer-relevant information that can be extracted from program syntactically
  • IDB: pointer analysis results
  • Rules: pointer analysis rules

Datalog Model for Pointer Analysis-EDB&IDB

1、基本语句(New、Assign、Store、Load)

我们首先需要对前四条语句建模。输入的EDB代表了4个存储相应类型语句的table,输出为Variable和Field的指向关系。

举一个例子说明怎么对指针分析中的基本语句建模为EDB,

2、Method Calls语句

处理This

对于基于Datalog的PTA,首先,我们需要引入新的EDB和IDB:

  • EDB:
    • VCall(方法调用)
    • Dispatch(表格的形式表达找到的函数)
    • ThisVar(储存变量)
  • IDB:
    • Reachable(可达方法)
    • CallGraph

处理Parameters 

接下来要处理参数的传递,与之前类似,需要引入新的EDB和IDB:

  • EDB:
    • Argument(调用语句行号,参数标号和参数本身)
    • Parameter(被调用方法,参数标号和参数本身)
  • IDB:空

对应用Datalog书写的规则如果用自然语言描述,就是处理行号l处对m的调用时,根据形参和实参的信息,将实参已经有的指向关系传递给形参数。

处理返回值

引入新的EDB和IDB:

  • EDB:
    • 方法的返回值
    • 在调用点处的接收返回值的变量
  • IDB:空 

Sum up

以上三个部分总结起来,就能得到以下的Datalog Rules。

Datalog Model for Pointer Analysis-Rules 

对于New,创建语句推导出指针对对象的指向

对于Assign,赋值语句和指向信息推导出新的指向信息

对于Store,x和y的指向信息和Store语句推导出域指向信息

对于Load,Load语句、x的指向信息和域指向信息推导出y的指向信息

  • Body代表前提(红线)
  • Head代表结论(蓝线)

An Example

根据Datalog算法和Datalog的执行规则,分析下面这段代码,给出推导结束后的IDB。

如前面所属,EDB已知,

处理new语句,

处理assign语句,

处理store语句,

处理load语句,

最终IDB结果如下:

Whole-Program Pointer Analysis

综上,得到全程序的分析算法如下。

值得一提的是,在VarPointsTo(x,o)规则中,添加Reachable(m)跳过不可达方法中的对象。而其他规则不需要加这一条件,则是因为它们都有VarPointsTo规则作为Body的一部分。

四、Taint Analysis via Datalog

Datalog Model

使用Datalog进行污点分析,需要用户提供Source和Sink。输出被标记的数据可能流到的Sink方法。 

  • DB:
    • Source(m : M):source函数
    • Sink(m : M):sink函数
    • Taint(l : S, t : T):关联调用点和调用点处的污点数据
  • IDB:
    • TaintFlow(t : T, m : M):识别出的污染流处理规则(source和sink的处理):

Datalog Rules

  • 对于source,首先找到一条调用边,它是source,取出返回值接收变量r,以及调用点关联的污点数据t;推导出r指针指向污点数据t。
  • 对于sink,首先找到一条调用边,它是sink,取出形参(不关心哪个形参),形参指向的污点数据以及确认的污染数据t(不关心t来源于哪一行);推导出污染数据t会传给sink函数m,得到一条污染流。

五、Datalog的优缺点

  • 优点:
    • 简洁可读
    • 易于实现
    • 得益于已有的成熟的优化引擎,速度快
  • 缺点:
    • 表达能力受限,非图灵完备,有的情况处理不了(比如有的时候需要中途去掉一些sinks,Datalog就无法实现;表达单个存在很容易,但表达同时满足多个存在比较困难,通常需要双重否定)
    • 不能完全控制性能(底层已经实现了,无法再进行优化)

相关