Potential issues in VTA, CHA, and simple-edges-bidirectional.
Hi,
I have discovered a few potential bugs across various configurations of SOOT. My methodology is as follows:
- Construct a hypothesis about the relationship between two configuration options (e.g., vta -> TRUE should be more precise than vta -> FALSE).
- Run these two configurations on various benchmark programs and construct a call graph.
- Test the hypothesis by comparing the call graph edges (e.g., if the callgraph produced by vta -> TRUE has edges that are not in vta -> FALSE, then it violates the precision hypothesis, as more precision should only remove false positives).
So, for each report, I will make clear my hypothesis, and then the difference in behavior I found.
Thanks in advance for any feedback.
BTW, I ran each of these with cg.spark on-fly-cg:false,enabled:true, which as I understand uses CHA as the baseline call graph algorithm instead of SPARK.
Hypothesis: vta.TRUE should be as precise as vta.FALSE. Input: TC2.zip
// castclassapi/Demo.java
package castclassapi;
//import lib.annotations.callgraph.DirectCall;
class Demo {
public static void main(String[] args) throws Exception {
if (args.length == 0)
castToTarget(Target.class, new Target());
else
castToTarget(Demo.class, new Demo());
}
// @DirectCall(
// name = "toString", returnType = String.class, line = 18,
// resolvedTargets = "Lcastclassapi/Target;"
// )
static <T> void castToTarget(Class<T> cls, Object o) {
T target = cls.cast(o);
target.toString();
}
public String toString() { return "Demo"; }
}
Bug: The callgraph produced by vta.TRUE has various false positive call edges from the call to target.toString() in castclassapi.Demo.castToTarget that are not in the callgraph produced by vta.FALSE, such as:
- java.time.temporal.WeekFields.toString()
- java.security.spec.PSSParameterSpec.toString()
- java.lang.StackFrame.toString()
Hypothesis: rta.TRUE should be as precise as rta.FALSE Input: TC4.zip
// instanceofcheck/Demo.java
package instanceofcheck;
//import lib.annotations.callgraph.DirectCall;
class Demo{
public static void main(String[] args) throws Exception {
if (args.length == 0)
callIfInstanceOfTarget(new Target());
else
callIfInstanceOfTarget(new Demo());
}
// @DirectCall(
// name = "toString", returnType = String.class, line = 18,
// resolvedTargets = "Linstanceofcheck/Target;"
// )
static void callIfInstanceOfTarget(Object o) {
if (o instanceof Target)
o.toString();
}
public String toString() { return "Demo"; }
}
class Target {
public String toString() { return "Target"; }
}
Bug: The callgraph for rta.TRUE contains many false positive targets from instanceofcheck.Demo.callIfInstanceOfTarget(), such as
- java.time.YearMonth.toString()
- java.lang.Float.toString()
- java.net.InetSocketAddress.toString()
Hypothesis: simple-edges-bidirectional.TRUE should be as sound as simple-edges-bidirectional.FALSE Input: LRR1.zip
// lrr/Demo.java
package lrr;
//import lib.annotations.callgraph.DirectCall;
class Demo {
public static void verifyCall(){ /* do something */ }
public static void main(String[] args) throws Exception {
String className = (args.length % 2 == 0) ? "lrr.Left" : "lrr.Right";
Class.forName(className);
}
}
class Left {
static {
staticInitializerCalled();
}
// @DirectCall(name="verifyCall", line=22, resolvedTargets = "Llrr/Demo;")
static private void staticInitializerCalled(){
Demo.verifyCall();
}
}
class Right {
static {
staticInitializerCalled();
}
// @DirectCall(name="verifyCall", line=35, resolvedTargets = "Llrr/Demo;")
static private void staticInitializerCalled(){
Demo.verifyCall();
}
}
Bug: The callgraph produced by simple-edges-bidirectional.TRUE misses true positive edges, including:
- lrr.Left.staticInitializerCalled() -> lrr.Demo.verifyCall()
- lrr.Right.staticInitializerCalled() -> lrr.Demo.verifyCall()