Skip to content
This repository has been archived by the owner on Mar 7, 2022. It is now read-only.

weekly report: 2017.11.29-2017.12.05 #10

Closed
connglli opened this issue Dec 12, 2017 · 0 comments
Closed

weekly report: 2017.11.29-2017.12.05 #10

connglli opened this issue Dec 12, 2017 · 0 comments

Comments

@connglli
Copy link
Owner

周报

2017.11.29 ~ 2017.12.05

回想上周,我们本周的关注点只有一个:如何提高 canHandleIssue 的精确性,并进一步降低误报率。

提高精确性

上周我们提到,要提高精确性可能要涉及到对判断语义的理解。目前打算的实现方式是这样的:

首先对现在的 slicing 进行改写,目前的 slicing 是 Unit 的集合,现在打算将 slicing 改为 从 ObjectSet<Unit> 的映射,即 map<Object, Set<Unit>>

根据我们寻找 slicing 的算法,我们知道:

slice = "dependents of a Callsite" + 
        "dependents of some IfStmts"

Callsite 的依赖通常是一系列 Unit。而 IfStmt 的依赖则是它所使用的两个变量的依赖语句。对于 IfStmt,若其中一个变量是某个方法的返回值,那么我们将对该方法的所有语句进行遍历,对其中使用“特殊字串”(如 android.os.Build$VERSION: int SDK_INT 等)定义的变量及使用过它的 IfStmt 语句(及其依赖)进行递归查找,并以 Value -> Set<Unit> 的映射存储。即,我们构造的 slicing 将是如下的形式:

slicing = {
  Callsite: dependent Units of Callsite,
  IfStmt1: 2 definition Units of 2 variables used by IfStmt1,
  Value1:  Units which defines or uses Value1, and Value1 is a value used by some IfStmt,
  ...
}

这样,在 canHandleIssue 的时候,我们采用以下启发式方式来检测是否能够被处理:

  • Callsite

使用现在的方式,即检测其 slicing 中是否包含相应的字符串。

  • IfStmt

将对语义进行解析:上面提到,IfStmt 的依赖一般是 IfStmt 使用的变量的定义语句,因此,我们将:

假设该 IfStmt 使用的两个 expr 为 e1 和 e2:
  1. 若 ei(i = 1,2) 为常量,且为 0 或者 1,且 ej(j != i,j = 1,2)
     为变量,令 ej 的定义语句为 dj:
    1.1. 若 dj 包含方法调用语句,且该调用语句的参数部分(一般是个数字)满足我们的
      acpair(在最大最小值之间),我们认为该处被 fix。
  2. 若 ei(i = 1,2) 为常量,且不为 0 也不为 1,且 ej(j != i,j = 1,2)
    为变量,令 ej 的定义语句为 dj:
    2.1. 若 dj 包含相应的字符串,且 ei 对应的常量满足我们的 acpair,我们认为该处
      被 fix。
  3. 对其他任何情况,我们都认为该 IfStmt 不能 fix 此处。

上述提到的两种 fix 方式一般对应于以下两种 fix 方式:

1.1 if (Xxx.isCompatible(11)) { ... }

2.1 if (os.Build.VERSION.SDK_INT > 11) { ... }

我们将随着测试用例的增加进一步扩展对 IfStmt 的检测

  • Value

我们将按照上述提到的 IfStmt 的检测方式对每条使用该 Value 的 IfStmt 进行检测。

降低误报率

关于误报率,这几天在测试的时候发现,(我)目前的实现还是有提高误报率的操作,是在 computeCallsite 的时候:

我们知道,callgraph 是程序的静态表示,其中并不包含控制流信息,因此利用我们寻找到的仅仅针对某个 acpair.api 的 callsites 并不能精确地告诉我们该 acpair 在某个 callsite 处是否被 fix。说起来可能很费力,举个例子:

private void _acpair_check_getActionBar() {
  ActionBar actionBar = getActionBar();
  actionBar.setTitle("123");
}

private void directCheck() {
  if (Build.VERSION.SDK_INT > 11) {
    _acpair_check_getActionBar();
  }
}

上面的代码中,getActionBar 在 api < 11 的时候是个 FIC issue,无论是利用 callgraph 还是像 Lili 一样一条一条语句地进行检测,我们最终找到的 callsite 都是第 2 行,即 _acpair_check_getActionBar 会调用 getActionBar,而对第 2 行的代码利用我们目前的方式进行 slicing 的时候实际上并不能追溯到 directCheck 方法(或许真正的 SDG 可以追溯到,因为 SDG 里面包含了控制流和数据流信息),所以利用 fic-finder 在进行检测的时候会报告第 2 行有个 FIC issue 没有被 fix,但显然这是一个 FP(因为第 7 行已经 fix 掉了)。

不知道 Lili 的实现里有没有可能这种会误报的情况。目前我考虑的针对这种问题的解法也跟之前提到的 IfStmt 寻找类似,即寻找 K 层调用,不光寻找某个 acpair.api 的 caller(我们暂称为 acpair.api 的 direct caller ),还要寻找 acpair.api.direct_caller 的 caller(我们暂称为 acpair.api 的 1-indirect-caller),一直找到 acpair.api 的 K-indirect-caller。

总结

  1. 上面的所有思考是这周在一遍进行测试的时候一边想到的,现在还没有转换为代码,其中应该也有一些问题,Lili 和 许老师 先看下,讨论一下其中可能存在的问题并进行修正后再转换为代码。
  2. 我已经提前把代码转换到了安卓,因为在做纯 java 的时候对一些 fix 方式还是不是很好模拟。代码在 j2a 分支
@connglli connglli changed the title weekly report: 2017.11.22-2017.12.05 weekly report: 2017.11.29-2017.12.05 Mar 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant