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
的精确性,并进一步降低误报率。提高精确性
上周我们提到,要提高精确性可能要涉及到对判断语义的理解。目前打算的实现方式是这样的:
首先对现在的 slicing 进行改写,目前的 slicing 是
Unit
的集合,现在打算将 slicing 改为 从Object
到Set<Unit>
的映射,即map<Object, Set<Unit>>
。根据我们寻找 slicing 的算法,我们知道:
Callsite
的依赖通常是一系列Unit
。而IfStmt
的依赖则是它所使用的两个变量的依赖语句。对于IfStmt
,若其中一个变量是某个方法的返回值,那么我们将对该方法的所有语句进行遍历,对其中使用“特殊字串”(如android.os.Build$VERSION: int SDK_INT
等)定义的变量及使用过它的 IfStmt 语句(及其依赖)进行递归查找,并以Value
->Set<Unit>
的映射存储。即,我们构造的 slicing 将是如下的形式:这样,在
canHandleIssue
的时候,我们采用以下启发式方式来检测是否能够被处理:使用现在的方式,即检测其 slicing 中是否包含相应的字符串。
将对语义进行解析:上面提到,IfStmt 的依赖一般是 IfStmt 使用的变量的定义语句,因此,我们将:
我们将按照上述提到的 IfStmt 的检测方式对每条使用该 Value 的 IfStmt 进行检测。
降低误报率
关于误报率,这几天在测试的时候发现,(我)目前的实现还是有提高误报率的操作,是在
computeCallsite
的时候:我们知道,callgraph 是程序的静态表示,其中并不包含控制流信息,因此利用我们寻找到的仅仅针对某个 acpair.api 的 callsites 并不能精确地告诉我们该 acpair 在某个 callsite 处是否被 fix。说起来可能很费力,举个例子:
上面的代码中,
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。
总结