soot-oss / soot

Soot - A Java optimization framework
GNU Lesser General Public License v2.1
2.84k stars 708 forks source link

Soot reports a false positive edge in call graph #2061

Open kitty-1998 opened 4 months ago

kitty-1998 commented 4 months ago

Describe the bug

I used Soot RTA to construct a call graph and find a false positive. In the following program, Soot reports two edges in the call graph: (1) Main.main -> Thread1.run; (2) Main.main -> Thread2.run. However, the second edge is obviously a false positive as Thread2 class is never instantiated. Hence, RTA should not add this edge to CG based on its algorithm design.

Besides, when I used Soot CHA to construct the call graph, it does not report this false positive. It is confusing as CHA is more sound than RTA.

Input files

Main.java

public class Main {
    public static void main(String[] args) {
            Thread t = new Thread1();
            t.start();
        }
    }
}

Thread1.java

public class Thread1 extends Thread {
    public void run() {}
}

Thread2.java

public class Thread2 extends Thread {
    public void run() {}
}

Results

Soot RTA Edge: <Main: void main(java.lang.String[])> --> <Thread1: void run()> Soot RTA Edge: <Main: void main(java.lang.String[])> --> <Thread2: void run()> // false positive

To reproduce

Steps to reproduce the behavior: I used Soot 4.4.1 and the options are listed below:

Options.v().set_whole_program(true);
Options.v().set_soot_classpath(JAVA_BASE_DIRECTORY); 
Options.v().set_no_bodies_for_excluded(true);
List<String> classPaths = new ArrayList<>();
classPaths.add("PATH/TO/INPUTDIR");
Options.v().set_process_dir("Path/to/dir");
Options.v().process_dir();
Options.v().set_allow_phantom_refs(true);
Options.v().setPhaseOption("jb", "use-original-names:true");
Options.v().set_prepend_classpath(false);
Options.v().set_exclude(Constants.excludedClassList);
Scene.v().loadNecessaryClasses();

Transform transform = new Transform("cg.spark", null);
PhaseOptions.v().setPhaseOption("cg.spark", "on");
PhaseOptions.v().setPhaseOption("cg.spark", "rta:true");
PhaseOptions.v().setPhaseOption("cg.spark", "types-for-sites:true");
PhaseOptions.v().setPhaseOption("cg.spark", "on-fly-cg:false");
Map<String, String> phaseOptions = PhaseOptions.v().getPhaseOptions(transform);
SparkTransformer.v().transform(transform.getPhaseName(), phaseOptions);
PackManager.v().runPacks();