针对第一个问题,Lili 也提到很难对这种 API 进行定位,尤其是一些编译优化的存在使得底层代码变动的更大,比如直接使用常量折叠与常量计算把一些高级 API 里才会用到的常量直接利用字面量替换了进去。这种很难进行捕捉。因此这两种暂时进行了 @WARNING 提示。
代码中暂时以 TODO 的形式留下了:
case ApiField.TAG: {
// TODO I have no idea how to get the callsite of a specific field
System.out.println("@WARNING: Model of @field is not supported by now");
// ApiField apiField = (ApiField) model.getApi();
// SootField sootField = scene.getField(apiField.getSiganiture());
break;
}
/**
* Backward slicing algorithm.
*
* we find the backward slicing of a unit by:
* 1. get the corresponding pdg, which describes the unit's method
* 2. find the corresponding PDGNode srcNode, which contains the unit
* 3. find all the dependent PDGNodes of srcNode
* 4. get all the units of each dependent PDGNode
*
*/
private Set<Unit> runBackwardSlicingFor(Callsite callsite);
对检测 Issue 是否会得到解决做了初步判断,主要是根据 Context 给出的条件对 Jimple Stmt 进行判断,判断其是否会进行相关的环境判断(如 api level,devices)等,但现在的判断非常不精确,仅仅会检查其是否会对 os.Build 进行调用,具体的值判断还需要对 Stmt 进行分析,个人觉得这也是一个难点。由于针对不同的 API 会有不同的检测方式,甚至对同一种 API 也会有多种检测方式和实现方式,即使利用 slicing 恐怕也难以进行。还需进一步思考。目前这部分判断在:
/**
* Check whether the stmt can handle the specific issue
*
*/
public boolean canHandleIssue(ApiContext model, Unit unit) {
// we only parse Jimple
if (!(unit instanceof Stmt) || !((Stmt) unit).containsFieldRef()) {
return false;
}
//
// TODO CHECK
// I don;t know exactly what FieldRef of a Stmt is!!!
// what if a Stmt contains more than one SootField?
//
Stmt stmt = (Stmt) unit;
SootField field = stmt.getFieldRef().getField();
String siganiture = field.getSignature();
if (model.needCheckApiLevel() || model.needCheckSystemVersion()) {
return Strings.contains(siganiture,
"android.os.Build.VERSION_CODES",
"android.os.Build.VERSION.SDK_INT",
"android.os.Build.VERSION.SDK");
}
if (model.hasBadDevices()) {
return Strings.contains(siganiture,
"android.os.Build.BOARD",
"android.os.Build.BRAND",
"android.os.Build.DEVICE",
"android.os.Build.PRODUCT");
}
return false;
}
In essence, the PDG nodes represent (within them) either CFG nodes or Region nodes.
直接认为该 DOC 是正确的(DOC 太乱,都不敢相信其正确性),因此做了如下实现:
/**
* In javaDoc of Soot, the following information are mentioned:
*
* This class(PDGNode) defines a Node in the Program Dependence
* Graph. There might be a need to store additional information
* in the PDG nodes. In essence, the PDG nodes represent (within
* them) either CFG nodes or Region nodes.
*
* So we simply considered that as only CFGNODE and REGION are allowed
*/
private Iterator<Unit> unitIteratorOfPDGNode(PDGNode n) {
Iterator<Unit> iterator = null;
PDGNode.Type type = n.getType();
// get iterator
if (type.equals(PDGNode.Type.CFGNODE)) {
iterator = ((Block) n.getNode()).iterator();
} else if (type.equals(PDGNode.Type.REGION)) {
iterator = ((Region) n.getNode()).getUnitGraph().iterator();
} else {
System.out.println("Only REGION and CFGNODE are allowed");
}
return iterator;
}
canHandleIssue
boolean canHandleIssue(ApiContext model, Unit unit) 目前实现过于简单,上面也提到过,是个难点。
周报
这周的工作相比前几周有了些进展,但问题还未完全解决。这次的周报还是主要汇报这周的工作进展,同时理一下目前仍然存在需要讨论的问题。
问题解决
首先说上周提到的三个问题:
上周提出这三个问题后 Lili 很快给出了解答,非常感谢!针对 Lili 的回答我也对代码进行了修改:
针对第一个问题,Lili 也提到很难对这种 API 进行定位,尤其是一些编译优化的存在使得底层代码变动的更大,比如直接使用常量折叠与常量计算把一些高级 API 里才会用到的常量直接利用字面量替换了进去。这种很难进行捕捉。因此这两种暂时进行了 @WARNING 提示。
代码中暂时以
TODO
的形式留下了:针对第二个问题,也是困扰了我一段时间的问题,Lili 的实现中直接使用了 Block 对应的 Units,而并未定位到具体的 Unit,这在分析的准确性上也不会影响,接受 Lili 的建议,这里我也直接这样做了。这部分代码的相关逻辑主要是这样(注释部分):
针对第三个问题,由于目前对 SDG 的了解不是很多,因此暂时还未实现。
进展
进展一
这周在稍微有点头绪后,先把整个代码需要运行起来的其他部分完成了,也就是 PubSub 模式的 Tracker/Issue。代码集中在 tracker 包下。
进展二
对检测 Issue 是否会得到解决做了初步判断,主要是根据 Context 给出的条件对 Jimple Stmt 进行判断,判断其是否会进行相关的环境判断(如 api level,devices)等,但现在的判断非常不精确,仅仅会检查其是否会对
os.Build
进行调用,具体的值判断还需要对 Stmt 进行分析,个人觉得这也是一个难点。由于针对不同的 API 会有不同的检测方式,甚至对同一种 API 也会有多种检测方式和实现方式,即使利用 slicing 恐怕也难以进行。还需进一步思考。目前这部分判断在:进展三
各部分到目前为止已经搭建好了,而且每部分也都有了基础的实现代码,接下来就到遗留问题了!
遗留问题
照常,对问题进行解释与说明:
SDG
SDG 构建还未进行,上面提到了。
unitIteratorOfPDGNode
Set<Unit> runBackwardSlicingFor(Callsite callsite)
依赖于方法Iterator<Unit> unitIteratorOfPDGNode(PDGNode n)
,该方法做了如下假设:假设
PDGNode
的类型仅有CFGNODE
和REGION
两种,因为 Soot 的 javaDOC 中有这么几句:直接认为该 DOC 是正确的(DOC 太乱,都不敢相信其正确性),因此做了如下实现:
canHandleIssue
boolean canHandleIssue(ApiContext model, Unit unit)
目前实现过于简单,上面也提到过,是个难点。心声
:(
本来以为代码写起来会很简单,没想到会有这么多需要了解的知识点和( Soot 给挖的)坑。:)
还是需要继续学习。希望推荐代码静态分析相关的课程(慕课,Stanford,Coursera)!感觉网上的资料并不多,有些论文也确实难懂。:)
在使用 Soot 的过程中,看了下 WALA,是 IBM 出的,应该是一个 IBM 的大工程项目,对 SDG、Slicer 的支持也比较好。由于是 IBM 的软件工程项目,所以代码质量和文档质量还是信得过的,而且还有对 Javascript 进行静态分析的支持,在 Javascript 大行其道的今天,感觉以后使用 WALA 也会成为必选。现在开发中客户端( Android/iOS )项目转无线端( H5/Javascript )的非常多,感觉这也是一个研究点,对 Javascript 的分析与编译(Babel 和 Webpack 做的非常好)也应该是一个重点。