7

假设我的库中有两种方法:

void com.somepackage.SomeClass.someSink(String s)

int com.someotherpackage.SomeOtherClass.someSource(int i)

第一种方法用作数据接收器,而第二种方法在我的代码中用作数据源。类型参数int, String仅作为示例给出,实际情况可能会有所变化。

我想在一些满足下面给出的特定模式的代码中检测这些方法的使用:

  1. 一些数据(比如x)是由源生成的
  2. 一些数据(比如y)是使用一系列转换生成的f1(f2(... fn(x))
  3. y被送到水槽。

只要从为接收器生成数据的函数到从源接收数据的函数之间存在一系列调用,转换可以是任意函数。这些函数也可以采用任何其他参数,并将用作黑盒。

扫描可以在源或字节码级别。有哪些工具可用于此类分析?

更喜欢使用 Java API 的非基于 IDE 的工具。

[编辑:] 澄清更多,someSink并且分别是类中someSource的任意方法名称。它们可能是也可能不是,并且可能采用任意数量的参数(我应该能够定义)。参数的类型也不是任意的。唯一的要求是该工具应该扫描出现模式的代码和输出行号。所以该工具可能以这种方式工作:SomeSomeSomeOtherClassstatic

  • 从用户处获取接收器和源名称(类和方法名称的完全限定名称)。
  • 静态扫描代码并找到所有使用给定接收器和源的地方
  • 检查是否存在通过一系列操作(运算符、方法)直接或间接将源输出的某些数据提供给接收器的路径。
  • 忽略那些不存在此类路径的源/汇,并输出剩余的源/汇(如果有)。

示例输出:

MyClass1.java:12: value1 = com.someotherpackage.SomeOtherClass.someSource(...)
MyClass2.java:23: value2 = foo(value1, ...)
MyClass3.java:3: value3 = bar(value2)
MyClass4.java:22: com.somepackage.SomeClass.someSink(value3, ...)

注意:如果一个函数不带参数但对数据有一些副作用也需要考虑。(示例a = source(); void foo(){ c = a+b }; foo(); sink(c)是需要捕获的模式。)

4

2 回答 2

4

在做了一些研究之后,我发现煤烟最适合这种任务。Soot 比 PQL 等其他开源替代品更成熟。

于 2012-07-26T07:05:34.283 回答
2

那么 source 和 sink 方法的作用仅仅是 x 起源于源方法(某处)并在目标方法中(某处)被消耗?您如何表征“x”,或者您只是想要所有具有此属性的 x?

假设您已经在源方法中确定了一个特定的 x,您是否 a) 坚持通过方法调用将 x 传递给目标方法[这将使目标方法成为您的调用链中的最后一个调用],或者可以是其中之一中间值被复制?b) 坚持每个函数调用只有一个参数?

我们已经为大型 C 系统做了类似的事情。问题是将分配的变量跟踪到其他函数中的用途,无论它们在哪里,包括表示不同但意图相同的值(“抽象副本”;如果我使用,字符串“1.0”抽象地等同于整数 1字符串最终作为一个数字;“int_to_string”是一个“抽象复制”函数,它将一种表示形式的值转换为另一种表示形式的等效值。)。

为此,我们需要对每个函数进行到达定义分析(“来自特定赋值的值到哪里去?”),以及“抽象副本”到达分析,确定标记为“的特殊函数消耗到达值的位置抽象副本”,以及该抽象副本功能的结果到达的位置。然后“x 到达 z”和“x 到达 f(x) 到达 z”的传递闭包计算 x 可以去的地方。

我们使用DMS Software Reengineering Toolkit完成了这项工作,它提供了通用解析和流分析机制,以及 DMS 的C Front End,它实现了 C 的特定到达和抽象复制到达计算。DMS 有一个Java 前端,它计算到达定义; 有人会添加抽象复制到达逻辑并重新实现传递闭包代码。

于 2012-05-07T03:27:45.910 回答