Skip to content

Commit

Permalink
Merge pull request #1074 from soot-oss/1064-feature-make-jimplebasedi…
Browse files Browse the repository at this point in the history
…nterproceduralcfg-configurable

user can pass a CallGraph or it uses  CHA as defaul
  • Loading branch information
swissiety authored Oct 1, 2024
2 parents 8a01dcb + dc383ff commit 4954992
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sootup.callgraph.CallGraph;
import sootup.callgraph.CallGraphAlgorithm;
import sootup.callgraph.ClassHierarchyAnalysisAlgorithm;
import sootup.core.graph.StmtGraph;
import sootup.core.jimple.common.stmt.Stmt;
Expand All @@ -56,7 +55,6 @@ public class JimpleBasedInterproceduralCFG extends AbstractJimpleBasedICFG {

protected static final Logger logger =
LoggerFactory.getLogger(JimpleBasedInterproceduralCFG.class);
private final MethodSignature mainMethodSignature;

protected boolean includeReflectiveCalls;

Expand Down Expand Up @@ -109,60 +107,72 @@ public Collection<Stmt> load(SootMethod method) {

public JimpleBasedInterproceduralCFG(
View view,
MethodSignature mainMethodSignature,
List<MethodSignature> cgEntryPoints,
boolean enableExceptions,
boolean includeReflectiveCalls) {
this(
new ClassHierarchyAnalysisAlgorithm(view).initialize(cgEntryPoints),
view,
enableExceptions,
includeReflectiveCalls);
}

public JimpleBasedInterproceduralCFG(
CallGraph cg, View view, boolean enableExceptions, boolean includeReflectiveCalls) {
super(enableExceptions);
this.includeReflectiveCalls = includeReflectiveCalls;
this.view = view;
this.mainMethodSignature = mainMethodSignature;
cg = initCallGraph();
this.cg = cg;
initializeStmtToOwner();
}

public CallGraph getCg() {
return cg;
}

public String buildICFGGraph(CallGraph callGraph) {
Map<MethodSignature, StmtGraph<?>> signatureToStmtGraph = new LinkedHashMap<>();
computeAllCalls(mainMethodSignature, signatureToStmtGraph, callGraph);
computeAllCalls(callGraph.getEntryMethods(), signatureToStmtGraph, callGraph);
return ICFGDotExporter.buildICFGGraph(signatureToStmtGraph, view, callGraph);
}

public void computeAllCalls(
MethodSignature methodSignature,
List<MethodSignature> entryPoints,
Map<MethodSignature, StmtGraph<?>> signatureToStmtGraph,
CallGraph callGraph) {
ArrayList<MethodSignature> visitedMethods = new ArrayList<>();
computeAllCalls(methodSignature, signatureToStmtGraph, callGraph, visitedMethods);
computeAllCalls(entryPoints, signatureToStmtGraph, callGraph, visitedMethods);
}

private void computeAllCalls(
MethodSignature methodSignature,
List<MethodSignature> entryPoints,
Map<MethodSignature, StmtGraph<?>> signatureToStmtGraph,
CallGraph callGraph,
List<MethodSignature> visitedMethods) {
visitedMethods.add(methodSignature);
final Optional<? extends SootMethod> methodOpt = view.getMethod(methodSignature);
// return if the methodSignature is already added to the hashMap to avoid stackoverflow error.
if (signatureToStmtGraph.containsKey(methodSignature)) {
return;
}
if (methodOpt.isPresent()) {
SootMethod sootMethod = methodOpt.get();
if (sootMethod.hasBody()) {
StmtGraph<?> stmtGraph = sootMethod.getBody().getStmtGraph();
signatureToStmtGraph.put(methodSignature, stmtGraph);
visitedMethods.addAll(entryPoints);
for (MethodSignature methodSignature : entryPoints) {
final Optional<? extends SootMethod> methodOpt = view.getMethod(methodSignature);
// return if the methodSignature is already added to the hashMap to avoid stackoverflow error.
if (signatureToStmtGraph.containsKey(methodSignature)) {
return;
}
if (methodOpt.isPresent()) {
SootMethod sootMethod = methodOpt.get();
if (sootMethod.hasBody()) {
StmtGraph<?> stmtGraph = sootMethod.getBody().getStmtGraph();
signatureToStmtGraph.put(methodSignature, stmtGraph);
}
}
callGraph.callTargetsFrom(methodSignature).stream()
.filter(methodSignature1 -> !visitedMethods.contains(methodSignature1))
.forEach(
nextMethodSignature ->
computeAllCalls(
Collections.singletonList(nextMethodSignature),
signatureToStmtGraph,
callGraph,
visitedMethods));
}
callGraph.callTargetsFrom(methodSignature).stream()
.filter(methodSignature1 -> !visitedMethods.contains(methodSignature1))
.forEach(
nextMethodSignature ->
computeAllCalls(
nextMethodSignature, signatureToStmtGraph, callGraph, visitedMethods));
}

private CallGraph initCallGraph() {
CallGraphAlgorithm cga = new ClassHierarchyAnalysisAlgorithm(view);
return cga.initialize(Collections.singletonList(mainMethodSignature));
}

protected void initializeStmtToOwner() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public static void setup() {
@Test
void methodStartAndEndPointTest() {
JimpleBasedInterproceduralCFG forwardICFG =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);

BackwardsInterproceduralCFG backwardsInterproceduralCFG =
new BackwardsInterproceduralCFG(forwardICFG);
Expand All @@ -58,7 +59,8 @@ void methodStartAndEndPointTest() {
@Test
void methodToCallerStmtTest() {
JimpleBasedInterproceduralCFG forwardICFG =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);

BackwardsInterproceduralCFG backwardsInterproceduralCFG =
new BackwardsInterproceduralCFG(forwardICFG);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public void ICFGDotExportTest() {
entryMethodSignature = entryMethod.getSignature();

JimpleBasedInterproceduralCFG icfg =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);
CallGraph callGraph = loadCallGraph(view);
String expectedCallGraph = icfg.buildICFGGraph(callGraph);
Digraph digraph = parseDigraph(expectedCallGraph);
Expand Down Expand Up @@ -89,7 +90,8 @@ public void ICFGDotExportTest2() {
entryMethodSignature = entryMethod.getSignature();

JimpleBasedInterproceduralCFG icfg =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);
CallGraph callGraph = loadCallGraph(view);
String expectedCallGraph = icfg.buildICFGGraph(callGraph);
Digraph digraph = parseDigraph(expectedCallGraph);
Expand Down Expand Up @@ -124,7 +126,8 @@ public void ICFGArrayListDotExport() {
entryMethodSignature = entryMethod.getSignature();

JimpleBasedInterproceduralCFG icfg =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);
CallGraph callGraph = loadCallGraph(view);
String expectedCallGraph = icfg.buildICFGGraph(callGraph);
Digraph digraph = parseDigraph(expectedCallGraph);
Expand All @@ -151,7 +154,8 @@ public void ICFGInterfaceDotExport() {
entryMethodSignature = entryMethod.getSignature();

JimpleBasedInterproceduralCFG icfg =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);
CallGraph callGraph = loadCallGraph(view);
String expectedCallGraph = icfg.buildICFGGraph(callGraph);
Digraph digraph = parseDigraph(expectedCallGraph);
Expand All @@ -164,7 +168,8 @@ public void ICFGInterfaceDotExport() {
public String edgesFromCallGraph(
MethodSignature methodSignature, JimpleBasedInterproceduralCFG icfg, CallGraph callGraph) {
Map<MethodSignature, StmtGraph<?>> signatureToStmtGraph = new LinkedHashMap<>();
icfg.computeAllCalls(methodSignature, signatureToStmtGraph, callGraph);
icfg.computeAllCalls(
Collections.singletonList(methodSignature), signatureToStmtGraph, callGraph);
Map<Integer, MethodSignature> calls;
calls = ICFGDotExporter.computeCalls(signatureToStmtGraph, view, callGraph);
final Optional<? extends SootMethod> methodOpt = view.getMethod(methodSignature);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ void methodToCallerStmtTest() {
entryMethodSignature = entryMethod.getSignature();

JimpleBasedInterproceduralCFG icfg =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);

MethodSignature sig =
JavaIdentifierFactory.getInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ protected JimpleIFDSSolver<?, InterproceduralCFG<Stmt, SootMethod>> executeStati
private void runAnalysis() {

JimpleBasedInterproceduralCFG icfg =
new JimpleBasedInterproceduralCFG(view, entryMethodSignature, false, false);
new JimpleBasedInterproceduralCFG(
view, Collections.singletonList(entryMethodSignature), false, false);
IFDSTaintAnalysisProblem problem = new IFDSTaintAnalysisProblem(icfg, entryMethod);
JimpleIFDSSolver<?, InterproceduralCFG<Stmt, SootMethod>> solver =
new JimpleIFDSSolver(problem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* #L%
*/

import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
Expand Down

0 comments on commit 4954992

Please sign in to comment.