ICSE‘22 Precise Divide-By-Zero Detection with Affirmative Evidence 数值除零bug检测

请添加图片描述

上文 PLDI’21 并发检测 提到了港科大团队怎么利用VFG (Value Flow Graph)进行并发程序的bug检测。今天要讨论的是ICSE’22, 它利用VFG进行数值程序分析,检测程序中可能出现的除零bug。

最近在研究这个技术,把这篇文章看了好几遍,但是在实现时仍然存在状态数爆炸的问题。跪了… …

1. 简介

一般提到数值程序分析,可能会想到抽象解释,八面体,polyhedra 抽象域 … 国防科大陈老师 … 放上链接,数值程序分析:https://www.bilibili.com/video/BV1bR4y1u7bV

当然还有利用符号分析[1],符号执行[2]等技术去检测数值相关的bug。

作者提出的方法是利用VFG上的数据依赖,控制依赖,以及节点间的运算关系传播符号值以及该符号值所依赖的条件,最后交给约束求解器去判断

  • 节点的符号值满足“等于0” ^ 该符号值下的条件可满足。

作者通过研究2011年以来的CVE数据库,通过手动研究其中的123个除零bug,总结出一个经验:实际的除零错误的代码特征常常会是这样的:

  • Source Evidence:代码中存在的Source Evidence,存在两种值可以进行传播
    • 显式的0字面量;这个很显然,传播值到divisor,会发生divide-by-zero
    • 输入的污点值;这种也很显然,传播用户可控的输入例如v:=atoi(argv[1]),会发生divide-by-zero
  • Bound Evidence:这种是作者总结的经验,如果程序中存在x cmp y (cmp是比较运算符比如<, <=, >, >= 等等),可以认为发现了一个Bound Evidence,这样在计算约束时,可以认为存在这样的条件约束: (x == y)。作者的实验表明,利用Bound Evidence能够能到比较好的精度。

Bound Evidence其实是作者通过分析CVE缺陷,总结出来的程序员的编码经验。

2. 一个例子

作者只考虑intra-procedural的除零错误。然后拿抽象解释符号执行做对比。

针对如下示例代码,作者不考虑top-fun;get_step函数默认它第二个参数就是固定的除零点,所以分析的时候只考虑move函数。
请添加图片描述
可以看到20, 25,26,27行分别是可能存在的除零点,实际真实存在的是27行。

2.1 方法1. 抽象解释

利用抽象解释的polyhedra abstract domain (关系型抽象域),分析15~18行的时候,有两个抽象:
请添加图片描述
然后在两条路径的交汇处将两个抽象进行meet:Abs1 meet Abs2 = {diff >= -1},可以看到抽象解释虽然说是Sound的,但是会导致20行误报。(因为diff的真实值要么为-1,要么为1+dx-dy >=1 )

2.2 方法2. 符号执行

利用符号执行,它会去穷举所有路径,其中,在第20行的状态状态为:
请添加图片描述

它能够证明20行不存在除零错误。但是在25~27行,由于入参dx, dy是under-constrained,所以都会报出错误。(但实际上25,26行不应该报出)

2.3 方法3. 作者的方法

除零点从静态分析的角度而言要满足 pc ^ Q

  • C1: 存在可行执行路径P到达除法指令 (pc表示路径P的路径条件)
  • C2: 该除法指令的divisor变量v可能等于零 (Q表示v = 0)

作者通过研究得到通过evidence-based方式检测的经验:

  • C1*: 如果C1和C2成立
  • C2*: 下面其中一个条件成立
    • divisor存在source-evidence,也就是说存在污点
    • pc关联了bound-evidence,使得v一定等于0

C1*成立表示基本的检测方法,C2 * 表示经验总结出来的方法。

作者利用Guarded Symbolic Value Set用于表示变量的值,以及该值成立的条件。例如,对于diff变量,它的value set可以表示成:
请添加图片描述

针对diff的value set,很显然可以推测20行不存在除零错误。

针对25~27行,利用evidence-based方法:

  • source-evidence:很显然,代码中不存在source点
  • bound-evidence:在25行存在dx,dy比较,21行存在dx,dy,d之间的比较。所以得到bound-evidence:dx = dy, dx = d, dy = d

利用得到的bound-evidence作为额外的约束强制更新value set。对于dz,可以简化成:
请添加图片描述
很显然,dz求解出来可以为0。所以27行检测出除零。而针对25,26行,由于不存在evidence能够推到出dx, dy为0。这样就减少了误报。

2.4 总结

作者讨论的是intra-procedural的除零错误,所以如果divisor依赖了函数的入参,那么这个参数在进行约束求解时就是under-constrained,不受约束的,那么交给约束求解器求解,能够生成满足的条件。这是不考虑调用上下文的,所以这也是under-constrained symbolic execution的限制。作者的方法就是根据被检测函数的一些经验性的代码特征(evidence),强制增加一些约束,从而降低一些误报。

3. 技术实现

上文提到,作者给每个变量生成一个Guarded Symbolic Value Set。

{ (值1, 条件1), {值2, 条件2}, ... }

3.1 怎么计算Guarded Symbolic Value Set

Demand-driven方式的符号分析

  • 输入是程序和一个感兴趣的点的变量

  • 输出是Guarded Symbolic Value Set
    请添加图片描述

  • 先构建VFG,方法就是PLDI’18 Pinpoint [3]提到的方法,这里不详细展开

  • 然后在图上找到相关感兴趣的点n

  • 为点n生成约束

    • 从n开始得到节点n的逆后序遍历集合 (加快约束迭代)
    • 遍历这个集合,构建节点间的依赖关系
  • 依赖关系建立好之后, 求解符号依赖关系

    • 根据依赖关系,自顶向下传播符号值,直到传播的符号值达到稳定状态

一个问题,怎么传播符号值?

这是示例代码的vfg,表示数据依赖关系,控制依赖关系。
请添加图片描述
构建约束规则:
请添加图片描述
初始化规则:

  • Init-var初始化变量节点一个未知符号值,cond表示节点的控制依赖条件
  • Init-op初始化运算节点一个未知符号值,条件为true
  • init-cst初始化常量节点的符号值,条件为cond

传播规则:

  • operation:针对v1 op v2,把v1的value set和v2的value set进行operation。

    • 组合:把值进行符号运算,然后条件logical and起来
    • 请添加图片描述
  • variable: 一个节点n可能有多个数据依赖, 每个数据依赖上存在路径条件,n自己又有控制依赖条件。将这些数据依赖的guarded value set进行组合。

    • 其中trans定义如下,就是把数据依赖的value set逻辑与上这条数据依赖边上的条件。然后把得到的所有数据依赖值进行合并。最后再把最终结果与n的控制依赖条件给logical and起来。
    • 请添加图片描述
    • 请添加图片描述
    • 上面规则(3)里面的c1^c2改为 c1 v c2
  • bound-evi: 之前说过,如果存在比较运算,那么将两个value set进行合并,并传播到各自的value set。

另外还有一条规则用于传播污点:
请添加图片描述

3.2 求解

请添加图片描述

4. 实验

有关soundnes

  • 展开cfg和cg上的循环一次
  • Value Set可能会比较大,设置阈值为20,超过的以未知值代替

实验环境

  • 2个20核 Intel® Xeon® CPU E5-2698 v4@2.20GHz
  • 256GB内存
  • Ubintu-16.04

相关数据:https://github.com/yiyuaner/ICSE-2022-Wit-data

实验测试集合12个流行的开源项目,代码量从3w到1kw行
请添加图片描述

作者做对照实验:不传播evidence,和传播evidence做对比
请添加图片描述

实现结果:

请添加图片描述

拿3个开源工具做对比

  • Crab: numberic abstract interpretation
  • Clang Static Analyzer: local symbolic execution
  • Infer: Separation logical and bi-abduction
    请添加图片描述

具体的比较数据可以看原文…

[1] Lian Li, Cristina Cifuentes, and Nathan Keynes. 2010. Practical and Effective Symbolic Analysis for Buffer Overflow Detection. In Proceedings of the Eighteenth ACM SIGSOFT International Symposium on Foundations of Software Engineering (Santa Fe, New Mexico, USA) (FSE ’10). Association for Computing Machinery, New York, NY, USA, 317–326. https://doi.org/10.1145/1882291.1882338

[2] Wei Le and Mary Lou Soffa. 2008. Marple: A Demand-Driven Path-Sensitive Buffer Overflow Detector. In Proceedings of the 16th ACM SIGSOFT International Symposium on Foundations of Software Engineering (Atlanta, Georgia) (SIGSOFT ’08/FSE-16). Association for Computing Machinery, New York, NY, USA, 272–282. https://doi.org/10.1145/1453101.1453137

[3] Qingkai Shi, Xiao Xiao, Rongxin Wu, Jinguo Zhou, Gang Fan, and Charles Zhang. 2018. Pinpoint: Fast and Precise Sparse Value Flow Analysis for Million Lines of Code. In Proceedings of the 39th ACM SIGPLAN Conference on Pro**gramming Language Design and Implementation (Philadelphia, PA, USA) (PLDI**2018). Association for Computing Machinery, New York, NY, USA, 693–706.https://doi.org/10.1145/3192366.3192418

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值