soot icon indicating copy to clipboard operation
soot copied to clipboard

Potential issues in VTA, CHA, and simple-edges-bidirectional.

Open amordahl opened this issue 3 years ago • 0 comments

Hi,

I have discovered a few potential bugs across various configurations of SOOT. My methodology is as follows:

  1. Construct a hypothesis about the relationship between two configuration options (e.g., vta -> TRUE should be more precise than vta -> FALSE).
  2. Run these two configurations on various benchmark programs and construct a call graph.
  3. 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()

amordahl avatar Aug 26 '22 22:08 amordahl