From 1553caaca2c83f986b426e4d4a4e5058bf2e8cc6 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 14:30:42 +0200 Subject: [PATCH 01/41] introduces Invokable Statements on edges of the call graph to know the target of a specific invokable statement --- .../icfg/JimpleBasedInterproceduralCFG.java | 18 +- .../callgraph/AbstractCallGraphAlgorithm.java | 218 +++++++++--------- .../main/java/sootup/callgraph/CallGraph.java | 91 +++++++- .../ClassHierarchyAnalysisAlgorithm.java | 8 +- .../sootup/callgraph/GraphBasedCallGraph.java | 100 +++++--- .../sootup/callgraph/MutableCallGraph.java | 5 +- .../callgraph/RapidTypeAnalysisAlgorithm.java | 54 ++--- .../sootup/callgraph/CallGraphTestBase.java | 10 + .../core/jimple/common/stmt/AbstractStmt.java | 14 -- .../jimple/common/stmt/InvokableStmt.java | 55 +++++ .../core/jimple/common/stmt/JAssignStmt.java | 22 +- .../core/jimple/common/stmt/JInvokeStmt.java | 14 +- .../sootup/core/jimple/common/stmt/Stmt.java | 4 - .../jimple/common/stmt/JAssignStmtTest.java | 82 +++++++ .../jimple/common/stmt/JInvokeStmtTest.java | 60 +++++ .../test/java/sootup/util/AssignStmtUtil.java | 82 +++++++ .../test/java/sootup/util/ClassTypeUtil.java | 39 ++++ .../test/java/sootup/util/FieldRefUtil.java | 29 +++ .../test/java/sootup/util/InvokeExprUtil.java | 55 +++++ .../src/test/java/sootup/util/LocalUtil.java | 27 +++ .../test/java/sootup/util/SignatureUtil.java | 54 +++++ .../test/java/sootup/util/StmtPosUtil.java | 18 ++ 22 files changed, 842 insertions(+), 217 deletions(-) create mode 100644 sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java create mode 100644 sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java create mode 100644 sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java create mode 100644 sootup.core/src/test/java/sootup/util/AssignStmtUtil.java create mode 100644 sootup.core/src/test/java/sootup/util/ClassTypeUtil.java create mode 100644 sootup.core/src/test/java/sootup/util/FieldRefUtil.java create mode 100644 sootup.core/src/test/java/sootup/util/InvokeExprUtil.java create mode 100644 sootup.core/src/test/java/sootup/util/LocalUtil.java create mode 100644 sootup.core/src/test/java/sootup/util/SignatureUtil.java create mode 100644 sootup.core/src/test/java/sootup/util/StmtPosUtil.java diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java index 3606614af65..47292b856fe 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java @@ -40,6 +40,8 @@ import sootup.callgraph.CallGraphAlgorithm; import sootup.callgraph.ClassHierarchyAnalysisAlgorithm; import sootup.core.graph.StmtGraph; +import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; @@ -71,7 +73,8 @@ public class JimpleBasedInterproceduralCFG extends AbstractJimpleBasedICFG { @Override public Collection load(Stmt stmt) { ArrayList res = new ArrayList<>(); - MethodSignature methodSignature = stmt.getInvokeExpr().getMethodSignature(); + if (!(stmt instanceof InvokableStmt) && !((InvokableStmt)stmt).containsInvokeExpr()) return res; + MethodSignature methodSignature = ((InvokableStmt)stmt).getInvokeExpr().get().getMethodSignature(); Optional smOpt = view.getMethod(methodSignature); if (smOpt.isPresent()) { SootMethod sm = smOpt.get(); @@ -99,7 +102,7 @@ public Collection load(SootMethod method) { ArrayList res = new ArrayList<>(); // only retain callers that are explicit call sites or // Thread.start() - Set callsToMethod = cg.callsTo(method.getSignature()); + Set callsToMethod = cg.callSourcesTo(method.getSignature()); for (MethodSignature methodSignature : callsToMethod) { Stmt stmt = filterEdgeAndGetCallerStmt(methodSignature); if (stmt != null) { @@ -179,7 +182,7 @@ private void computeAllCalls( signatureToStmtGraph.put(methodSignature, stmtGraph); } } - callGraph.callsFrom(methodSignature).stream() + callGraph.callTargetsFrom(methodSignature).stream() .filter(methodSignature1 -> !visitedMethods.contains(methodSignature1)) .forEach( nextMethodSignature -> @@ -219,11 +222,14 @@ public static Set> getCallEdges( final SootMethod method = methodOpt.get(); if (method.hasBody()) { for (Stmt s : method.getBody().getStmtGraph().getNodes()) { - if (s.containsInvokeExpr()) { + //TODO: Consider calls to clinit methods caused by static fields + // Assignment statements without invokeExpressions + if (s instanceof InvokableStmt && ((InvokableStmt)s).containsInvokeExpr()) { + AbstractInvokeExpr expr = ((InvokableStmt)s).getInvokeExpr().get(); CalleeMethodSignature callee = new CalleeMethodSignature( - s.getInvokeExpr().getMethodSignature(), - CGEdgeUtil.findCallGraphEdgeType(s.getInvokeExpr()), + expr.getMethodSignature(), + CGEdgeUtil.findCallGraphEdgeType(expr), s); callEdges.add(new ImmutablePair<>(caller, callee)); } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index 0315caee170..18cea1125d2 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -28,16 +28,15 @@ import javax.annotation.Nonnull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sootup.callgraph.CallGraph.Call; import sootup.core.IdentifierFactory; -import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.ref.JStaticFieldRef; -import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.Method; import sootup.core.model.SootClass; -import sootup.core.model.SootClassMember; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; import sootup.core.signatures.MethodSubSignature; @@ -74,13 +73,14 @@ protected AbstractCallGraphAlgorithm(@Nonnull View view) { */ @Nonnull final CallGraph constructCompleteCallGraph(View view, List entryPoints) { - MutableCallGraph cg = initializeCallGraph(); - Deque workList = new ArrayDeque<>(entryPoints); Set processed = new HashSet<>(); - // implicit edge from entry point to static initializer - addImplicitEdgesOfEntryPoints(entryPoints, cg, workList); + // find additional entry points + List clinits=getClinitFromEntryPoints(entryPoints); + + workList.addAll(clinits); + MutableCallGraph cg = initializeCallGraph(entryPoints,clinits); processWorkList(view, workList, processed, cg); return cg; @@ -92,41 +92,26 @@ final CallGraph constructCompleteCallGraph(View view, List entr * * @return the initialized call graph used in the call graph algorithm */ - protected MutableCallGraph initializeCallGraph() { - return new GraphBasedCallGraph(); + protected MutableCallGraph initializeCallGraph(List entryPoints, List clinits) { + ArrayList rootSignatures=new ArrayList<>(entryPoints); + rootSignatures.addAll(clinits); + return new GraphBasedCallGraph(rootSignatures); } /** - * This method adds implicit edges of the entry points of the call graph algorithm. It will add an - * edge to all static initializer of the entry points. + * This method returns a list of static initializers that should be considered by the given entry points * * @param entryPoints the entry points of the call graph algorithm - * @param cg the call graph which will save the added implicit edges. - * @param workList the implicit targets will be added to the work list to process in the call - * graph algorithm */ - protected void addImplicitEdgesOfEntryPoints( - List entryPoints, MutableCallGraph cg, Deque workList) { - entryPoints.forEach( - methodSignature -> { - SootMethod clintMethod = - view.getMethod(methodSignature.getDeclClassType().getStaticInitializer()) - .orElse(null); - if (clintMethod == null) { - return; - } - MethodSignature staticInitSig = clintMethod.getSignature(); - if (!cg.containsMethod(methodSignature)) { - cg.addMethod(methodSignature); - } - if (!cg.containsMethod(staticInitSig)) { - cg.addMethod(staticInitSig); - } - if (!cg.containsCall(methodSignature, staticInitSig)) { - cg.addCall(methodSignature, staticInitSig); - workList.push(staticInitSig); - } - }); + protected List getClinitFromEntryPoints( + List entryPoints) { + return entryPoints.stream() + .map(methodSignature -> getSignatureOfImplementedStaticInitializer(methodSignature.getDeclClassType())) + .filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); + } + + private Optional getSignatureOfImplementedStaticInitializer(ClassType classType){ + return view.getMethod(classType.getStaticInitializer()).map(sootMethod -> sootMethod.getSignature()); } /** @@ -173,24 +158,10 @@ final void processWorkList( currentClass.getMethod(currentMethodSignature.getSubSignature()).orElse(null); // get all call targets of invocations in the method body - Stream invocationTargets = resolveAllCallsFromSourceMethod(currentMethod); + resolveAllCallsFromSourceMethod(currentMethod,cg,workList); // get all call targets of implicit edges in the method body - Stream implicitTargets = - resolveAllImplicitCallsFromSourceMethod(view, currentMethod); - - // save calls in the call graphs - Stream.concat(invocationTargets, implicitTargets) - .forEach( - t -> { - if (!cg.containsMethod(t)) { - cg.addMethod(t); - } - if (!cg.containsCall(currentMethodSignature, t)) { - cg.addCall(currentMethodSignature, t); - workList.push(t); - } - }); + resolveAllImplicitCallsFromSourceMethod(view, currentMethod,cg,workList); // set method as processed processed.add(currentMethodSignature); @@ -200,24 +171,48 @@ final void processWorkList( } } + /** Adds the defined call to the given call graph. If the source or target method was added as vertex to the call graph, they will be added to the worklist + * + * @param source the method signature of the caller + * @param target the method signature of the callee + * @param invokeStmt the stmt causing the call + * @param cg the call graph that will be updated + * @param workList the worklist in which the method signature of newly added vertexes will be added + */ + protected void addCallToCG(@Nonnull MethodSignature source, @Nonnull MethodSignature target, @Nonnull InvokableStmt invokeStmt, @Nonnull MutableCallGraph cg, @Nonnull Deque workList) { + if (!cg.containsMethod(source)) { + cg.addMethod(source); + workList.push(source); + } + if (!cg.containsMethod(target)) { + cg.addMethod(target); + workList.push(target); + } + if (!cg.containsCall(source, target,invokeStmt)) { + cg.addCall(source, target, invokeStmt); + } + } + /** * This method resolves all calls from a given source method. resolveCall is called for each - * invoke statement in the body of the source method that is implemented in the corresponding call - * graph algorithm. + * invokable statements in the body of the source method that is implemented in the corresponding call + * graph algorithm. If new methods will be added as vertexes in the call graph, the work list will be updated * * @param sourceMethod this signature is used to access the statements contained method body of * the specified method - * @return a stream containing all resolved callable method signatures by the given source method + * @param cg the call graph that will receive the found calls + * @param workList the work list that will be updated of found target methods */ - @Nonnull - Stream resolveAllCallsFromSourceMethod(SootMethod sourceMethod) { + protected void resolveAllCallsFromSourceMethod(SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { - return Stream.empty(); + return; } - return sourceMethod.getBody().getStmts().stream() - .filter(Stmt::containsInvokeExpr) - .flatMap(s -> resolveCall(sourceMethod, s.getInvokeExpr())); + sourceMethod.getBody().getStmts().stream() + .filter(stmt -> stmt instanceof InvokableStmt) + .map(stmt -> (InvokableStmt)stmt) + .forEach(stmt -> resolveCall(sourceMethod, stmt) + .forEach(targetMethod -> addCallToCG(sourceMethod.getSignature(),targetMethod,stmt,cg,workList))); } /** @@ -225,17 +220,17 @@ Stream resolveAllCallsFromSourceMethod(SootMethod sourceMethod) * * @param view it contains the class data * @param sourceMethod the inspected source method - * @return a stream containing all method signatures of targets of implicit calls. + * @param cg new calls will be added to the call graph + * @param workList new target methods will be added to the work list */ - @Nonnull - protected Stream resolveAllImplicitCallsFromSourceMethod( - View view, SootMethod sourceMethod) { + protected void resolveAllImplicitCallsFromSourceMethod( + View view, SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { - return Stream.empty(); + return; } // collect all static initializer calls - return resolveAllStaticInitializerCallsFromSourceMethod(view, sourceMethod); + resolveAllStaticInitializerCallsFromSourceMethod(view, sourceMethod,cg,workList); } /** @@ -243,60 +238,59 @@ protected Stream resolveAllImplicitCallsFromSourceMethod( * * @param view it contains the class data * @param sourceMethod the inspected source method - * @return a stream containing all method signatures of targets of implicit calls. + * @param cg clinit calls will be added to the call graph + * @param workList found clinit methods will be added to the work list */ @Nonnull - protected Stream resolveAllStaticInitializerCallsFromSourceMethod( - View view, SootMethod sourceMethod) { + protected void resolveAllStaticInitializerCallsFromSourceMethod( + View view, SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { - return Stream.empty(); + return; } - - Stream.Builder targetsToStaticInitializer = Stream.builder(); - - InstantiateClassValueVisitor instantiateVisitor = new InstantiateClassValueVisitor(); - sourceMethod .getBody() .getStmts() + .stream().filter(stmt -> stmt instanceof InvokableStmt) + .map(stmt -> (InvokableStmt)stmt) .forEach( - stmt -> { + invokableStmt -> { // static field usage - if (stmt.containsFieldRef() && stmt.getFieldRef() instanceof JStaticFieldRef) { - targetsToStaticInitializer.add( - stmt.getFieldRef().getFieldSignature().getDeclClassType()); + ClassType targetClass = null; + if (invokableStmt.containsFieldRef() && invokableStmt.getFieldRef() instanceof JStaticFieldRef) { + targetClass= invokableStmt.getFieldRef().getFieldSignature().getDeclClassType(); + addStaticInitializerCallsToCallGraph(sourceMethod.getSignature(),targetClass,invokableStmt,cg,workList); } - - // constructor calls - if (stmt instanceof JAssignStmt) { - Value rightOp = ((JAssignStmt) stmt).getRightOp(); - instantiateVisitor.init(); - rightOp.accept(instantiateVisitor); - ClassType classType = instantiateVisitor.getResult(); - if (classType != null) { - targetsToStaticInitializer.add(classType); + // static method calls and constructor calls + if (invokableStmt instanceof InvokableStmt && invokableStmt.containsInvokeExpr()) { + //static method call + Optional exprOptional = invokableStmt.getInvokeExpr(); + if (!exprOptional.isPresent()) + return; + AbstractInvokeExpr expr = exprOptional.get(); + if (expr instanceof JStaticInvokeExpr || (expr instanceof JSpecialInvokeExpr + && view.getIdentifierFactory().isConstructorSignature(expr.getMethodSignature()))) { + ClassType newTargetClass = expr.getMethodSignature().getDeclClassType(); + if (!newTargetClass.equals(targetClass)){ + addStaticInitializerCallsToCallGraph(sourceMethod.getSignature(),newTargetClass,invokableStmt,cg,workList); + } } } - - // static method calls - if (stmt.containsInvokeExpr() && stmt.getInvokeExpr() instanceof JStaticInvokeExpr) { - targetsToStaticInitializer.add( - stmt.getInvokeExpr().getMethodSignature().getDeclClassType()); - } }); + } - return targetsToStaticInitializer - .build() - .flatMap( - classType -> - Stream.concat( - Stream.of(classType), - view.getTypeHierarchy().superClassesOf(classType).stream())) - .filter(Objects::nonNull) - .map(classType -> view.getMethod(classType.getStaticInitializer())) - .filter(Optional::isPresent) - .map(Optional::get) - .map(SootClassMember::getSignature); + /** Adds all static initializer calls of the given targetClass. An edge from the sourceSig to all clinit methods of the targetClass and Superclasses will be added to the call graph. If new target methods will be found, the worklist will be updated. + * + * @param sourceSig the source method causing the static initilzer call + * @param targetClass the class that is statically initialized + * @param invokableStmt the statement causing the call + * @param cg the call graph that will contain the found calls + * @param workList the work list that will be updated with new target methods + */ + private void addStaticInitializerCallsToCallGraph(MethodSignature sourceSig, ClassType targetClass, InvokableStmt invokableStmt, MutableCallGraph cg, Deque workList){ + //static initializer call of class + view.getMethod(targetClass.getStaticInitializer()).ifPresent(targetSig -> addCallToCG(sourceSig,targetSig.getSignature(),invokableStmt, cg, workList)); + //static initializer calls of all superclasses + view.getTypeHierarchy().superClassesOf(targetClass).stream().map(classType -> view.getMethod(classType.getStaticInitializer())).filter(Optional::isPresent).map(Optional::get).forEach(targetSig -> addCallToCG(sourceSig,targetSig.getSignature(),invokableStmt,cg,workList) ); } /** @@ -377,8 +371,8 @@ public CallGraph addClass(@Nonnull CallGraph oldCallGraph, @Nonnull JavaClassTyp clazz.getMethod(overriddenMethodSig.getSubSignature()).get().getSignature(); if (updated.containsMethod(overriddenMethodSig)) { - for (MethodSignature callingMethodSig : updated.callsTo(overriddenMethodSig)) { - updated.addCall(callingMethodSig, overridingMethodSig); + for (Call calls : updated.callsTo(overriddenMethodSig)) { + updated.addCall(calls.getSourceMethodSignature(), overridingMethodSig,calls.getInvokableStmt()); } } }); @@ -440,13 +434,13 @@ public MethodSignature findMainMethod() { * dependable of the applied call graph algorithm. therefore, it is abstract. * * @param method the method object that contains the given invoke expression in the body. - * @param invokeExpr it contains the call which is resolved. + * @param invokableStmt it contains the call which is resolved. * @return a stream of all reachable method signatures defined by the applied call graph * algorithm. */ @Nonnull protected abstract Stream resolveCall( - SootMethod method, AbstractInvokeExpr invokeExpr); + SootMethod method, InvokableStmt invokableStmt); /** * Searches for the signature of the method that is the concrete implementation of m. diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index e90694879bb..de9add7c51c 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -24,11 +24,62 @@ import java.util.Set; import javax.annotation.Nonnull; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.signatures.MethodSignature; /** The interface of all implemented call graph data structures */ public interface CallGraph { + class Call{ + @Nonnull + private MethodSignature sourceMethodSignature; + @Nonnull + private MethodSignature targetMethodSignature; + @Nonnull + private InvokableStmt invokableStmt; + + Call(@Nonnull MethodSignature sourceMethodSignature, @Nonnull MethodSignature targetMethodSignature, @Nonnull InvokableStmt invokableStmt) { + this.sourceMethodSignature = sourceMethodSignature; + this.invokableStmt = invokableStmt; + this.targetMethodSignature = targetMethodSignature; + } + + public MethodSignature getSourceMethodSignature() { + return sourceMethodSignature; + } + + public MethodSignature getTargetMethodSignature() { + return targetMethodSignature; + } + + public InvokableStmt getInvokableStmt() { + return invokableStmt; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Call call = (Call) o; + return sourceMethodSignature.equals(call.sourceMethodSignature) + && targetMethodSignature.equals( + call.targetMethodSignature) && invokableStmt.equals(call.invokableStmt); + } + + @Override + public int hashCode() { + int result = sourceMethodSignature.hashCode(); + result = 31 * result + targetMethodSignature.hashCode(); + result = 31 * result + invokableStmt.hashCode(); + return result; + } + } + /** * This method returns method signatures in the call graph. A method signature is a node in the * call graph. @@ -46,18 +97,42 @@ public interface CallGraph { * @return a set of method signatures that are reached by a direct outgoing edge in the call graph */ @Nonnull - Set callsFrom(@Nonnull MethodSignature sourceMethod); + Set callTargetsFrom(@Nonnull MethodSignature sourceMethod); /** * This method returns all method signatures that call a given method signature. It returns the * sources of incoming edges of the given node (method signature) in the call graph * + * * @param targetMethod the method signature of the requested node in the call graph * @return a set of method signatures that reach the targetMethod by a direct edge in the call * graph */ @Nonnull - Set callsTo(@Nonnull MethodSignature targetMethod); + Set callSourcesTo(@Nonnull MethodSignature targetMethod); + + /** + * This method returns all method signatures that are called by a given method signature. It + * returns the targets of outgoing edges of the given node (method signature) in the call graph + * + * @param sourceMethod the method signature of the requested node in the call graph + * @return a set of method signatures that are reached by a direct outgoing edge in the call graph + */ + @Deprecated + @Nonnull + Set callsFrom(@Nonnull MethodSignature sourceMethod); + + /** + * This method returns all method signatures that call a given method signature. It returns the + * sources of incoming edges of the given node (method signature) in the call graph + * + * @param targetMethod the method signature of the requested node in the call graph + * @return a set of method signatures that reach the targetMethod by a direct edge in the call + * graph + */ + @Deprecated + @Nonnull + Set callsTo(@Nonnull MethodSignature targetMethod); /** * This method checks if a given method signature is a node in the call graph. @@ -74,10 +149,20 @@ public interface CallGraph { * * @param sourceMethod it defines the source node in the call graph * @param targetMethod it defines the target node in the call graph + * @param invokableStmt it defines the invoke stmt of the call * @return true if the edge is contained in the call graph, otherwise it will be false. */ boolean containsCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod); + @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, InvokableStmt invokableStmt); + + /** + * This method checks if an edge is contained in the call graph. The edge is defined by a source + * and target method signature which can be nodes in the call graph + * + * @param call it defines the requested call in the call graph + * @return true if the edge is contained in the call graph, otherwise it will be false. + */ + boolean containsCall(@Nonnull Call call); /** * This method counts every edge in the call graph. diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java index 43ae55c3f5f..0cf1d95356d 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java @@ -30,6 +30,7 @@ import sootup.core.jimple.common.expr.JDynamicInvokeExpr; import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.MethodModifier; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; @@ -77,7 +78,12 @@ public CallGraph initialize(@Nonnull List entryPoints) { */ @Override @Nonnull - protected Stream resolveCall(SootMethod method, AbstractInvokeExpr invokeExpr) { + protected Stream resolveCall(SootMethod method, InvokableStmt invokableStmt) { + Optional optInvokeExpr = invokableStmt.getInvokeExpr(); + if (!optInvokeExpr.isPresent()) { + return Stream.empty(); + } + AbstractInvokeExpr invokeExpr = optInvokeExpr.get(); MethodSignature targetMethodSignature = invokeExpr.getMethodSignature(); if ((invokeExpr instanceof JDynamicInvokeExpr)) { return Stream.empty(); diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java index d6672716bbe..2d58165d77b 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java @@ -23,13 +23,16 @@ */ import com.google.common.base.Preconditions; +import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nonnull; -import org.jgrapht.graph.DefaultDirectedGraph; +import org.jgrapht.graph.DirectedPseudograph; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.signatures.MethodSignature; import sootup.core.signatures.SootClassMemberSignature; @@ -53,23 +56,21 @@ protected MethodSignature getMethodSignature() { } } - /** This internal class is used to describe the edge in the graph. */ - protected static class Edge {} - - @Nonnull private final DefaultDirectedGraph graph; + @Nonnull private final DirectedPseudograph graph; @Nonnull private final Map signatureToVertex; + @Nonnull private final List entryMethods; /** The constructor of the graph based call graph. it initializes the call graph object. */ - public GraphBasedCallGraph() { - graph = new DefaultDirectedGraph<>(null, null, false); - signatureToVertex = new HashMap<>(); + public GraphBasedCallGraph(List entryMethods) { + this(new DirectedPseudograph<>(null, null, false),new HashMap<>(), entryMethods); } public GraphBasedCallGraph( - @Nonnull DefaultDirectedGraph graph, - @Nonnull Map signatureToVertex) { + @Nonnull DirectedPseudograph graph, + @Nonnull Map signatureToVertex, List entryMethods) { this.graph = graph; this.signatureToVertex = signatureToVertex; + this.entryMethods = entryMethods; } @Override @@ -79,19 +80,27 @@ public void addMethod(@Nonnull MethodSignature calledMethod) { } protected void addMethod(@Nonnull MethodSignature calledMethod, Vertex vertex) { + if (containsMethod(calledMethod)){ + return; + } graph.addVertex(vertex); signatureToVertex.put(calledMethod, vertex); } @Override public void addCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod) { - addCall(sourceMethod, targetMethod, new Edge()); + @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, @Nonnull InvokableStmt invokableStmt) { + addCall(sourceMethod, targetMethod, new Call(sourceMethod,targetMethod,invokableStmt)); } protected void addCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, Edge edge) { - graph.addEdge(vertexOf(sourceMethod), vertexOf(targetMethod), edge); + @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, Call call) { + if (!call.getSourceMethodSignature().equals(sourceMethod) || !call.getTargetMethodSignature().equals(targetMethod) || containsCall(call)){ + return; + } + Vertex source=vertexOf(sourceMethod); + Vertex target=vertexOf(targetMethod); + graph.addEdge(source, target, call); } @Nonnull @@ -102,7 +111,7 @@ public Set getMethodSignatures() { @Nonnull @Override - public Set callsFrom(@Nonnull MethodSignature sourceMethod) { + public Set callTargetsFrom(@Nonnull MethodSignature sourceMethod) { return graph.outgoingEdgesOf(vertexOf(sourceMethod)).stream() .map(graph::getEdgeTarget) .map(targetVertex -> targetVertex.methodSignature) @@ -111,13 +120,25 @@ public Set callsFrom(@Nonnull MethodSignature sourceMethod) { @Nonnull @Override - public Set callsTo(@Nonnull MethodSignature targetMethod) { + public Set callSourcesTo(@Nonnull MethodSignature targetMethod) { return graph.incomingEdgesOf(vertexOf(targetMethod)).stream() .map(graph::getEdgeSource) .map(targetVertex -> targetVertex.methodSignature) .collect(Collectors.toSet()); } + @Nonnull + @Override + public Set callsFrom(@Nonnull MethodSignature sourceMethod) { + return graph.outgoingEdgesOf(vertexOf(sourceMethod)); + } + + @Nonnull + @Override + public Set callsTo(@Nonnull MethodSignature targetMethod) { + return graph.incomingEdgesOf(vertexOf(targetMethod)); + } + @Override public boolean containsMethod(@Nonnull MethodSignature method) { return signatureToVertex.containsKey(method); @@ -125,11 +146,16 @@ public boolean containsMethod(@Nonnull MethodSignature method) { @Override public boolean containsCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod) { + @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, @Nonnull InvokableStmt invokableStmt) { if (!containsMethod(sourceMethod) || !containsMethod(targetMethod)) { return false; } - return graph.containsEdge(vertexOf(sourceMethod), vertexOf(targetMethod)); + return containsCall(new Call(sourceMethod,targetMethod,invokableStmt)); + } + + @Override + public boolean containsCall(@Nonnull Call call) { + return graph.containsEdge(call); } @Override @@ -146,33 +172,33 @@ public String exportAsDot() { graph.edgeSet().stream() .sorted( Comparator.comparing( - (Edge edge) -> { - Vertex edgeSource = graph.getEdgeSource(edge); + (Call call) -> { + Vertex edgeSource = graph.getEdgeSource(call); return edgeSource.methodSignature.getDeclClassType().getFullyQualifiedName(); }) .thenComparing( - (Edge edge) -> { - Vertex edgeSource = graph.getEdgeSource(edge); + (Call call) -> { + Vertex edgeSource = graph.getEdgeSource(call); return edgeSource.methodSignature.getName(); }) .thenComparing( - (Edge edge) -> { - Vertex edgeSource = graph.getEdgeSource(edge); + (Call call) -> { + Vertex edgeSource = graph.getEdgeSource(call); return edgeSource.methodSignature.getParameterTypes().toString(); }) .thenComparing( - (Edge edge) -> { - Vertex edgeTarget = graph.getEdgeTarget(edge); + (Call call) -> { + Vertex edgeTarget = graph.getEdgeTarget(call); return edgeTarget.methodSignature.getDeclClassType().getClassName(); }) .thenComparing( - (Edge edge) -> { - Vertex edgeTarget = graph.getEdgeTarget(edge); + (Call call) -> { + Vertex edgeTarget = graph.getEdgeTarget(call); return edgeTarget.methodSignature.getName(); }) .thenComparing( - (Edge edge) -> { - Vertex edgeTarget = graph.getEdgeTarget(edge); + (Call call) -> { + Vertex edgeTarget = graph.getEdgeTarget(call); return edgeTarget.methodSignature.getParameterTypes().toString(); })) .forEach( @@ -195,7 +221,8 @@ public String exportAsDot() { @Override public MutableCallGraph copy() { return new GraphBasedCallGraph( - (DefaultDirectedGraph) graph.clone(), new HashMap<>(signatureToVertex)); + (DirectedPseudograph) graph.clone(), new HashMap<>(signatureToVertex),new ArrayList<>( + entryMethods)); } /** @@ -212,7 +239,7 @@ protected Vertex vertexOf(@Nonnull MethodSignature method) { } @Nonnull - protected DefaultDirectedGraph getGraph() { + protected DirectedPseudograph getGraph() { return graph; } @@ -250,13 +277,13 @@ public String toString() { .forEach( method -> { stringBuilder.append(method).append(":\n"); - callsFrom(method).stream() + callTargetsFrom(method).stream() .sorted( Comparator.comparing((MethodSignature o) -> o.getDeclClassType().toString()) .thenComparing(SootClassMemberSignature::getName) .thenComparing(o -> o.getParameterTypes().toString())) .forEach(m -> stringBuilder.append("\tto ").append(m).append("\n")); - callsTo(method).stream() + callSourcesTo(method).stream() .sorted( Comparator.comparing((MethodSignature o) -> o.getDeclClassType().toString()) .thenComparing(SootClassMemberSignature::getName) @@ -267,4 +294,9 @@ public String toString() { } return stringBuilder.toString(); } + + @Nonnull + public List getEntryMethods() { + return entryMethods; + } } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java index 57028c90107..5c8d3c3429f 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java @@ -23,6 +23,7 @@ */ import javax.annotation.Nonnull; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.signatures.MethodSignature; /** @@ -43,6 +44,8 @@ public interface MutableCallGraph extends CallGraph { * * @param sourceMethod this parameter defines the source node of the edge in the call graph. * @param targetMethod this paramter defines the target node of the edge in the call graph. + * @param invokableStmt this paramter defines the invoke statement of the edge in the call graph. */ - void addCall(@Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod); + void addCall(@Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, @Nonnull + InvokableStmt invokableStmt); } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java index 15079b3b688..936739d2dca 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java @@ -26,9 +26,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nonnull; +import sootup.callgraph.CallGraph.Call; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JNewExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.model.MethodModifier; import sootup.core.model.SootMethod; @@ -46,21 +48,6 @@ */ public class RapidTypeAnalysisAlgorithm extends AbstractCallGraphAlgorithm { - /** - * This private class is used to save reachable calls. Because every method is only processed - * once, ignored calls are saved to include them at a later time if their class is instantiated at - * a later time. - */ - private static class Call { - @Nonnull final MethodSignature source; - @Nonnull final MethodSignature target; - - private Call(@Nonnull MethodSignature source, @Nonnull MethodSignature target) { - this.source = source; - this.target = target; - } - } - @Nonnull private Set instantiatedClasses = Collections.emptySet(); @Nonnull private Map> ignoredCalls = Collections.emptyMap(); @@ -124,14 +111,19 @@ protected List collectInstantiatedClassesInMethod(SootMethod method) * expression. * * @param sourceMethod the method object that contains the given invoke expression in the body. - * @param invokeExpr it contains the call which is resolved. + * @param invokableStmt the statement containing the call which is resolved. * @return a stream containing all reachable method signatures after applying the RTA call graph * algorithm */ @Override @Nonnull protected Stream resolveCall( - SootMethod sourceMethod, AbstractInvokeExpr invokeExpr) { + SootMethod sourceMethod, InvokableStmt invokableStmt) { + Optional optInvokeExpr = invokableStmt.getInvokeExpr(); + if (!optInvokeExpr.isPresent()){ + return Stream.empty(); + } + AbstractInvokeExpr invokeExpr= optInvokeExpr.get(); MethodSignature resolveBaseMethodSignature = invokeExpr.getMethodSignature(); Stream result = Stream.of(resolveBaseMethodSignature); @@ -147,10 +139,10 @@ protected Stream resolveCall( if (instantiatedClasses.contains(resolveBaseMethodSignature.getDeclClassType())) { return Stream.concat( Stream.of(concreteBaseMethod.getSignature()), - resolveAllCallTargets(sourceMethod.getSignature(), resolveBaseMethodSignature)); + resolveAllCallTargets(sourceMethod.getSignature(), resolveBaseMethodSignature,invokableStmt)); } else { - saveIgnoredCall(sourceMethod.getSignature(), resolveBaseMethodSignature); - return resolveAllCallTargets(sourceMethod.getSignature(), resolveBaseMethodSignature); + saveIgnoredCall(sourceMethod.getSignature(), resolveBaseMethodSignature,invokableStmt); + return resolveAllCallTargets(sourceMethod.getSignature(), resolveBaseMethodSignature,invokableStmt); } } } @@ -163,11 +155,12 @@ protected Stream resolveCall( * @param source the method which contains call * @param resolveBaseMethodSignature the base of the resolving. All subtypes of the declaring * class are analyzed as potential targets + * @param invokableStmt the statement causing the call * @return a stream of all method signatures of instantiated classes that can be resolved as * target from the given base method signature. */ private Stream resolveAllCallTargets( - MethodSignature source, MethodSignature resolveBaseMethodSignature) { + MethodSignature source, MethodSignature resolveBaseMethodSignature, InvokableStmt invokableStmt) { return view.getTypeHierarchy().subtypesOf(resolveBaseMethodSignature.getDeclClassType()) .stream() .map( @@ -178,7 +171,7 @@ private Stream resolveAllCallTargets( if (instantiatedClasses.contains(classType)) { return resolveConcreteDispatch(view, method); } else { - saveIgnoredCall(source, method); + saveIgnoredCall(source, method,invokableStmt); return Optional.empty(); } }) @@ -192,11 +185,12 @@ private Stream resolveAllCallTargets( * * @param source the source method of the call * @param target the target method of the call + * @param invokableStmt the statement causing the call */ - private void saveIgnoredCall(MethodSignature source, MethodSignature target) { + private void saveIgnoredCall(MethodSignature source, MethodSignature target, InvokableStmt invokableStmt) { ClassType notInstantiatedClass = target.getDeclClassType(); List calls = ignoredCalls.get(notInstantiatedClass); - Call ignoredCall = new Call(source, target); + Call ignoredCall = new Call(source, target,invokableStmt); if (calls == null) { calls = new ArrayList<>(); ignoredCalls.put(notInstantiatedClass, calls); @@ -238,19 +232,11 @@ protected void preProcessingMethod( newEdges.forEach( call -> { MethodSignature concreteTarget = - resolveConcreteDispatch(view, call.target).orElse(null); + resolveConcreteDispatch(view, call.getTargetMethodSignature()).orElse(null); if (concreteTarget == null) { return; } - if (cg.containsMethod(concreteTarget)) { - // method is already analyzed or is in the work list, simply add the call - cg.addCall(call.source, concreteTarget); - } else { - // new target method found that has to be analyzed - cg.addMethod(concreteTarget); - cg.addCall(call.source, concreteTarget); - workList.push(concreteTarget); - } + addCallToCG(call.getSourceMethodSignature(),concreteTarget,call.getInvokableStmt(),cg,workList); }); // can be removed because the instantiated class will be considered in future resolves ignoredCalls.remove(instantiatedClassType); diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index fd62eead256..b96b0e6dd8a 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -7,6 +7,7 @@ import java.util.List; import org.junit.jupiter.api.Test; import sootup.core.inputlocation.AnalysisInputLocation; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; import sootup.core.model.SourceType; @@ -83,6 +84,15 @@ CallGraph loadCallGraph(String testDirectory, boolean useSourceCodeFrontend, Str return cg; } + protected InvokableStmt getInvokableStmt(MethodSignature sourceMethod, MethodSignature staticTargetMethod){ + return getInvokableStmt(sourceMethod,staticTargetMethod,0); + } + + protected InvokableStmt getInvokableStmt(MethodSignature sourceMethod, MethodSignature staticTargetMethod, int index){ + int currentIndex = 0; + as + } + @Test public void testSingleMethod() { CallGraph cg = loadCallGraph("Misc", "example.SingleMethod"); diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java index 6aa6d246c77..aee13ffbd63 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java @@ -78,20 +78,6 @@ public int getExpectedSuccessorCount() { return 1; } - @Override - public boolean containsInvokeExpr() { - return false; - } - - /** - * This method must only be used for Stmts which contain an InvokeExpr (JInvokeStmt; possible in - * JAssignStmt) check via containsInvokExpr(). - */ - @Override - public AbstractInvokeExpr getInvokeExpr() { - throw new RuntimeException("getInvokeExpr() called with no invokeExpr present!"); - } - @Override public boolean containsArrayRef() { return false; diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java new file mode 100644 index 00000000000..9a16bbde7c4 --- /dev/null +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java @@ -0,0 +1,55 @@ +package sootup.core.jimple.common.stmt; + +/*- + * #%L + * Soot - a J*va Optimization Framework + * %% + * Copyright (C) 2020 Markus Schmidt + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 2.1 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import java.util.List; +import java.util.Optional; +import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.model.Body; + +/** + * Interface for Stmts that could invoke a different method which will be executed before the + * next statement is executed + * + */ +public interface InvokableStmt extends Stmt { + + /** Checks if the invokable statement actually invokes + * + * @return true if the statement invokes something, and false if not. + */ + boolean doesInvoke(); + + /** Checks if the invokable statement contains a invoke expression that defines the invoke. + * + * @return true if the statement contains an invoke expression, false if not + */ + boolean containsInvokeExpr(); + + /** Returns the possible invoke expression in the invokable statement + * + * @return The optional contains the invoke expression of the invokable statement + * or is empty if there is no invoke expression. + */ + Optional getInvokeExpr(); +} diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index 064eb5d359e..a84fee36049 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -44,6 +44,7 @@ * #Value% */ +import java.util.Optional; import javax.annotation.Nonnull; import sootup.core.jimple.basic.*; import sootup.core.jimple.common.expr.AbstractInvokeExpr; @@ -52,11 +53,12 @@ import sootup.core.jimple.common.ref.JArrayRef; import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.common.ref.JInstanceFieldRef; +import sootup.core.jimple.common.ref.JStaticFieldRef; import sootup.core.jimple.visitor.StmtVisitor; import sootup.core.util.printer.StmtPrinter; /** Represents the assignment of one value to another */ -public final class JAssignStmt extends AbstractDefinitionStmt implements FallsThroughStmt { +public final class JAssignStmt extends AbstractDefinitionStmt implements FallsThroughStmt, InvokableStmt { @Nonnull final LValue leftOp; @Nonnull final Value rightOp; @@ -101,17 +103,29 @@ public boolean containsInvokeExpr() { return getRightOp() instanceof AbstractInvokeExpr; } + /** Checks if the assignment statement invokes a method call + * + * @return it is true if the assignment statement contains an invoke expression or if the left or right operand is a static field + */ + @Override + public boolean doesInvoke() { + if (containsInvokeExpr()) + return true; + return getRightOp() instanceof JStaticFieldRef || getLeftOp() instanceof JStaticFieldRef; + } + + /* * (non-Javadoc) * * @see de.upb.sootup.jimple.common.stmt.AbstractStmt#getInvokeExpr() */ @Override - public AbstractInvokeExpr getInvokeExpr() { + public Optional getInvokeExpr() { if (!containsInvokeExpr()) { - throw new RuntimeException("getInvokeExpr() called with no invokeExpr present!"); + return Optional.empty(); } - return (AbstractInvokeExpr) getRightOp(); + return Optional.of((AbstractInvokeExpr) getRightOp()); } /* diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java index fa330bc47d6..27d7404ec2f 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java @@ -21,6 +21,7 @@ * . * #L% */ +import java.util.Optional; import java.util.stream.Stream; import javax.annotation.Nonnull; import sootup.core.jimple.basic.JimpleComparator; @@ -31,7 +32,7 @@ import sootup.core.util.printer.StmtPrinter; /** A method call */ -public final class JInvokeStmt extends AbstractStmt implements FallsThroughStmt { +public final class JInvokeStmt extends AbstractStmt implements FallsThroughStmt,InvokableStmt { @Nonnull private final AbstractInvokeExpr invokeExpr; @@ -46,6 +47,11 @@ public boolean containsInvokeExpr() { return true; } + @Override + public boolean doesInvoke() { + return true; + } + @Override public String toString() { return invokeExpr.toString(); @@ -58,8 +64,8 @@ public void toString(@Nonnull StmtPrinter up) { @Override @Nonnull - public AbstractInvokeExpr getInvokeExpr() { - return invokeExpr; + public Optional getInvokeExpr() { + return Optional.of(invokeExpr); } @Nonnull @@ -100,6 +106,6 @@ public JInvokeStmt withInvokeExpr(AbstractInvokeExpr invokeExpr) { @Nonnull public JInvokeStmt withPositionInfo(@Nonnull StmtPositionInfo positionInfo) { - return new JInvokeStmt(getInvokeExpr(), positionInfo); + return new JInvokeStmt(getInvokeExpr().get(), positionInfo); } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java index 7d8e9d00406..6a0761c78a2 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java @@ -60,10 +60,6 @@ public interface Stmt extends EquivTo, Acceptor { void toString(@Nonnull StmtPrinter up); - boolean containsInvokeExpr(); - - AbstractInvokeExpr getInvokeExpr(); - boolean containsArrayRef(); JArrayRef getArrayRef(); diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java new file mode 100644 index 00000000000..c134581e0b8 --- /dev/null +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java @@ -0,0 +1,82 @@ +package sootup.core.jimple.common.stmt; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.basic.SimpleStmtPositionInfo; +import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; +import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.expr.JVirtualInvokeExpr; +import sootup.core.jimple.common.ref.JInstanceFieldRef; +import sootup.core.jimple.common.ref.JStaticFieldRef; +import sootup.util.AssignStmtUtil; +import sootup.util.FieldRefUtil; +import sootup.util.InvokeExprUtil; +import sootup.util.LocalUtil; + +@Tag("Java8") +public class JAssignStmtTest { + + @Test + public void testDoesInvoke() { + JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); + JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); + Local local = LocalUtil.createDummyLocalForInt(); + + assertTrue(AssignStmtUtil.createDummyAssignStmtWithExpr().doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,local).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(local,staticFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,staticFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,staticFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,instanceFieldRef).doesInvoke()); + + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,local).doesInvoke()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local,instanceFieldRef).doesInvoke()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,instanceFieldRef).doesInvoke()); + assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().doesInvoke()); + } + + @Test + public void testContainsInvokeExpr() { + JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); + JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); + Local local = LocalUtil.createDummyLocalForInt(); + + assertTrue(AssignStmtUtil.createDummyAssignStmtWithExpr().containsInvokeExpr()); + + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,local).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local,staticFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,staticFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,staticFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,instanceFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,local).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local,instanceFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,instanceFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().containsInvokeExpr()); + } + + @Test + public void testGetInvokeExpr() { + JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); + JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); + Local local = LocalUtil.createDummyLocalForInt(); + + assertEquals(InvokeExprUtil.createDummyStaticInvokeExpr(),AssignStmtUtil.createDummyAssignStmtWithExpr().getInvokeExpr()); + + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,local).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local,staticFieldRef).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,staticFieldRef).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,staticFieldRef).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,instanceFieldRef).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,local).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local,instanceFieldRef).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,instanceFieldRef).getInvokeExpr().isPresent()); + assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().getInvokeExpr().isPresent()); + } + +} diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java new file mode 100644 index 00000000000..63ea1b7f28c --- /dev/null +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java @@ -0,0 +1,60 @@ +package sootup.core.jimple.common.stmt; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import sootup.core.jimple.basic.SimpleStmtPositionInfo; +import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; +import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.expr.JVirtualInvokeExpr; +import sootup.util.InvokeExprUtil; + + +@Tag("Java8") +public class JInvokeStmtTest { + + + + @Test + public void testContainsInvokeExpr() { + SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); + + JInvokeStmt invokeStmt = new JInvokeStmt(InvokeExprUtil.createDummyStaticInvokeExpr(),pos); + assertTrue(invokeStmt.containsInvokeExpr()); + + JInvokeStmt invokeStmt1 = new JInvokeStmt(InvokeExprUtil.createDummyInterfaceInvokeExpr(),pos); + assertTrue(invokeStmt1.containsInvokeExpr()); + + JInvokeStmt invokeStmt2 = new JInvokeStmt(InvokeExprUtil.createDummySpecialInvokeExpr(),pos); + assertTrue(invokeStmt2.containsInvokeExpr()); + + JInvokeStmt invokeStmt3 = new JInvokeStmt(InvokeExprUtil.createDummyVirtualInvokeExpr(),pos); + assertTrue(invokeStmt3.containsInvokeExpr()); + } + + @Test + public void testGetInvokeExpr() { + SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); + + JStaticInvokeExpr staticExpr = InvokeExprUtil.createDummyStaticInvokeExpr(); + JInvokeStmt invokeStmt = new JInvokeStmt(staticExpr,pos); + assertEquals(staticExpr,invokeStmt.getInvokeExpr()); + + JVirtualInvokeExpr virtualExpr = InvokeExprUtil.createDummyVirtualInvokeExpr(); + JInvokeStmt invokeStmt1 = new JInvokeStmt(virtualExpr,pos); + assertEquals(virtualExpr,invokeStmt1.getInvokeExpr()); + + JSpecialInvokeExpr specialExpr = InvokeExprUtil.createDummySpecialInvokeExpr(); + JInvokeStmt invokeStmt2 = new JInvokeStmt(specialExpr,pos); + assertEquals(specialExpr,invokeStmt2.getInvokeExpr()); + + JInterfaceInvokeExpr interfaceExpr = InvokeExprUtil.createDummyInterfaceInvokeExpr(); + JInvokeStmt invokeStmt3 = new JInvokeStmt(staticExpr,pos); + assertEquals(interfaceExpr,invokeStmt3.getInvokeExpr()); + } + +} diff --git a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java new file mode 100644 index 00000000000..0963e92edd7 --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java @@ -0,0 +1,82 @@ +package sootup.util; + +import java.util.Collections; +import sootup.core.jimple.basic.LValue; +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.basic.SimpleStmtPositionInfo; +import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; +import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.expr.JVirtualInvokeExpr; +import sootup.core.jimple.common.ref.JFieldRef; +import sootup.core.jimple.common.ref.JStaticFieldRef; +import sootup.core.jimple.common.stmt.JAssignStmt; +import sootup.core.jimple.common.stmt.JAssignStmtTest; +import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.MethodSubSignature; +import sootup.core.signatures.PackageName; +import sootup.core.types.ClassType; +import sootup.core.types.PrimitiveType.IntType; + +public class AssignStmtUtil { + + + + private static Local createDummyLocal(){ + return new Local("a", IntType.getInstance()); + } + + /** will return a dummy assignment statement with an invoke expression + * the left value will be the dummy int local + * the right value will be the dummy static invoke expression + * stmt position is the dummy SimpleStatementPositionInfo + * + * @return a dummy JAssignStmt with a static invoke expression + */ + public static JAssignStmt createDummyAssignStmtWithExpr() { + Local local = LocalUtil.createDummyLocalForInt(); + SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(local,InvokeExprUtil.createDummyStaticInvokeExpr(),pos); + } + + /** will return a dummy assignment statement + * the left value will be the dummy static field ref + * the right value will be the dummy local + * stmt position is the dummy SimpleStatementPositionInfo + * + * @return a dummy JAssignStmt with a static field ref on the left side + */ + public static JAssignStmt createDummyAssignStmtWithStaticFieldRefLeft() { + JFieldRef fieldRef = FieldRefUtil.createDummyStaticFieldRef(); + SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(fieldRef,LocalUtil.createDummyLocalForInt(),pos); + } + + /** will return a dummy assignment statement + * stmt position is the dummy SimpleStatementPositionInfo + * + * @param left defines the left value of the dummy assign statement + * @param right defines the right value of the dummy assign statement + * + * @return a dummy JAssignStmt with an instance field ref on the left side + */ + public static JAssignStmt createDummyAssignStmt(LValue left, Value right) { + SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(left,right,pos); + } + + + /** will return a dummy assignment statement + * the right value will be the dummy local + * the left value will be the dummy local + * stmt position is the dummy SimpleStatementPositionInfo + * + * @return a dummy JAssignStmt with a static field ref on the left side + */ + public static JAssignStmt createDummyAssignStmtWithLocals() { + SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(LocalUtil.createDummyLocalForInt(),LocalUtil.createDummyLocalForInt(),pos); + } + +} diff --git a/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java b/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java new file mode 100644 index 00000000000..f57b1be1de4 --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java @@ -0,0 +1,39 @@ +package sootup.util; + +import sootup.core.signatures.PackageName; +import sootup.core.types.ClassType; + +public class ClassTypeUtil { + + /**creates a dummy Class type + * Classname Test + * Package name test + * Fully Qualified Name test.Test + * + * @return a dummy class type + */ + public static ClassType createDummyClassType(){ + return new ClassType() { + @Override + public boolean isBuiltInClass() { + return false; + } + + @Override + public String getFullyQualifiedName() { + return "Test"; + } + + @Override + public String getClassName() { + return "Test"; + } + + @Override + public PackageName getPackageName() { + return new PackageName("test"); + } + }; + } + +} diff --git a/sootup.core/src/test/java/sootup/util/FieldRefUtil.java b/sootup.core/src/test/java/sootup/util/FieldRefUtil.java new file mode 100644 index 00000000000..35f22ef6231 --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/FieldRefUtil.java @@ -0,0 +1,29 @@ +package sootup.util; + +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.common.ref.JInstanceFieldRef; +import sootup.core.jimple.common.ref.JStaticFieldRef; +import sootup.core.types.PrimitiveType.IntType; + +public class FieldRefUtil { + + /**creates a dummy static field reference + * Signature: dummy Field Signature + * + * @return a dummy JStaticFieldRef + */ + public static JStaticFieldRef createDummyStaticFieldRef(){ + return new JStaticFieldRef( SignatureUtil.createDummyFieldSignature()); + } + + /**creates a dummy instance field reference + * local: dummy local + * Signature: dummy Field Signature + * + * @return a dummy JInstanceFieldRef + */ + public static JInstanceFieldRef createDummyInstanceFieldRef(){ + return new JInstanceFieldRef(LocalUtil.createDummyLocalForInt(), SignatureUtil.createDummyFieldSignature()); + } + +} diff --git a/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java b/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java new file mode 100644 index 00000000000..a22aaf4f399 --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java @@ -0,0 +1,55 @@ +package sootup.util; + +import java.util.Collections; +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; +import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.expr.JVirtualInvokeExpr; +import sootup.core.signatures.MethodSignature; + +public class InvokeExprUtil { + + /** will return a dummy virtual invoke expression + * local is called a and has the class type Test + * method signature is <Test: int test ()> + * arguments is an empty list + */ + public static JVirtualInvokeExpr createDummyVirtualInvokeExpr() { + Local local = LocalUtil.createDummyLocalForObject(); + MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); + return new JVirtualInvokeExpr(local,methodSignature,Collections.emptyList()); + } + + /** will return a dummy special invoke expression + * local is called a and has the class type Test + * method signature is <Test: int test ()> + * arguments is an empty list + */ + public static JSpecialInvokeExpr createDummySpecialInvokeExpr() { + Local local = LocalUtil.createDummyLocalForObject(); + MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); + return new JSpecialInvokeExpr(local,methodSignature,Collections.emptyList()); + } + + /** will return a dummy interface invoke expression + * local is called a and has the class type Test + * method signature is <Test: int test ()> + * arguments is an empty list + */ + public static JInterfaceInvokeExpr createDummyInterfaceInvokeExpr() { + Local local = LocalUtil.createDummyLocalForObject(); + MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); + return new JInterfaceInvokeExpr(local,methodSignature,Collections.emptyList()); + } + + /** will return a dummy static invoke expression + * method signature is <Test: int test ()> + * arguments is an empty list + */ + public static JStaticInvokeExpr createDummyStaticInvokeExpr() { + MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); + return new JStaticInvokeExpr(methodSignature,Collections.emptyList()); + } + +} diff --git a/sootup.core/src/test/java/sootup/util/LocalUtil.java b/sootup.core/src/test/java/sootup/util/LocalUtil.java new file mode 100644 index 00000000000..15cee621c16 --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/LocalUtil.java @@ -0,0 +1,27 @@ +package sootup.util; + +import sootup.core.jimple.basic.Local; +import sootup.core.types.PrimitiveType.IntType; + +public class LocalUtil { + + /**creates a dummy Local for an Object + * Name a + * Type dummy class type + * + * @return a dummy Local for an Object + */ + public static Local createDummyLocalForObject(){ + return new Local("a", ClassTypeUtil.createDummyClassType()); + } + + /**creates a dummy Local for an Int + * Name b + * Type int + * + * @return a dummy Local for a int value + */ + public static Local createDummyLocalForInt(){ + return new Local("b", IntType.getInstance()); + } +} diff --git a/sootup.core/src/test/java/sootup/util/SignatureUtil.java b/sootup.core/src/test/java/sootup/util/SignatureUtil.java new file mode 100644 index 00000000000..89110fd64fa --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/SignatureUtil.java @@ -0,0 +1,54 @@ +package sootup.util; + +import java.util.Collections; +import sootup.core.signatures.FieldSignature; +import sootup.core.signatures.FieldSubSignature; +import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.MethodSubSignature; +import sootup.core.types.PrimitiveType.IntType; + +public class SignatureUtil { + + /**creates a dummy method signature + * Class Type: dummy class type + * SubSignature: dummy method sub signature + * + * @return a dummy method signature + */ + public static MethodSignature createDummyMethodSignature(){ + return new MethodSignature( ClassTypeUtil.createDummyClassType(), createDummyMethodSubSignature()); + } + + /**creates a dummy method sub signature + * name: test + * return type: int + * parameter list: empty + * + * @return a dummy method sub signature + */ + public static MethodSubSignature createDummyMethodSubSignature(){ + return new MethodSubSignature("test", Collections.emptyList(), IntType.getInstance()); + } + + /**creates a dummy field signature + * Class Type: dummy class type + * SubSignature: dummy field sub signature + * + * @return a dummy field signature + */ + public static FieldSignature createDummyFieldSignature(){ + return new FieldSignature( ClassTypeUtil.createDummyClassType(), createDummyFieldSubSignature()); + } + + /**creates a dummy field sub signature + * name: test + * type: int + * + * @return a dummy field sub signature + */ + public static FieldSubSignature createDummyFieldSubSignature(){ + return new FieldSubSignature("test", IntType.getInstance()); + } + + +} diff --git a/sootup.core/src/test/java/sootup/util/StmtPosUtil.java b/sootup.core/src/test/java/sootup/util/StmtPosUtil.java new file mode 100644 index 00000000000..4cdf1a1e66a --- /dev/null +++ b/sootup.core/src/test/java/sootup/util/StmtPosUtil.java @@ -0,0 +1,18 @@ +package sootup.util; + +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.basic.SimpleStmtPositionInfo; +import sootup.core.types.PrimitiveType.IntType; + +public class StmtPosUtil { + + /**creates a dummy SimpleStmtPositionInfo + * lineNumber 1 + * + * @return a dummy SimpleStmtPositionInfo + */ + public static SimpleStmtPositionInfo createDummySimpleStmtPositionInfo(){ + return new SimpleStmtPositionInfo(1); + } + +} From 48150022d25bfefccd2a20d7c6ba1ef4d297c433 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 15:00:14 +0200 Subject: [PATCH 02/41] util function to get a get a specific invoke stmt for testing --- .../java/sootup/callgraph/CallGraphTestBase.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index b96b0e6dd8a..dd0982d1a06 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.jimple.common.stmt.InvokableStmt; +import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; import sootup.core.model.SourceType; @@ -25,6 +26,7 @@ public abstract class CallGraphTestBase { protected JavaIdentifierFactory identifierFactory = JavaIdentifierFactory.getInstance(); protected JavaClassType mainClassSignature; protected MethodSignature mainMethodSignature; + protected JavaView view; protected abstract T createAlgorithm(JavaView view); @@ -63,7 +65,7 @@ CallGraph loadCallGraph(String testDirectory, boolean useSourceCodeFrontend, Str + (useSourceCodeFrontend ? "source" : "binary"); // JavaView view = viewToClassPath.computeIfAbsent(classPath, this::createViewForClassPath); - JavaView view = createViewForClassPath(classPath, useSourceCodeFrontend); + view = createViewForClassPath(classPath, useSourceCodeFrontend); mainClassSignature = identifierFactory.getClassType(className); mainMethodSignature = @@ -90,7 +92,17 @@ protected InvokableStmt getInvokableStmt(MethodSignature sourceMethod, MethodSig protected InvokableStmt getInvokableStmt(MethodSignature sourceMethod, MethodSignature staticTargetMethod, int index){ int currentIndex = 0; - as + SootMethod method = view.getMethod(sourceMethod).orElse(null); + assertNotNull(method); + for(Stmt invokableStmt: method.getBody().getStmts()){ + if(invokableStmt instanceof InvokableStmt && ((InvokableStmt) invokableStmt).containsInvokeExpr() && ((InvokableStmt) invokableStmt).getInvokeExpr().get().getMethodSignature().equals(staticTargetMethod)){ + if(currentIndex == index){ + return (InvokableStmt) invokableStmt; + } + currentIndex++; + } + } + throw new RuntimeException("No invokable stmt found for " + sourceMethod); } @Test From 324ab079d1e85f6f6c5ef889bfc6c82f1f7d30de Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 15:29:17 +0200 Subject: [PATCH 03/41] applied API changes --- .../icfg/AbstractJimpleBasedICFG.java | 3 +- .../interprocedural/icfg/CGEdgeUtil.java | 8 +- .../interprocedural/icfg/ICFGDotExporter.java | 7 +- .../sootup/callgraph/CallGraphTestBase.java | 110 +++++++++--------- .../ClassHierarchyAnalysisAlgorithmTest.java | 22 ++-- .../RapidTypeAnalysisAlgorithmTest.java | 38 +++--- .../core/jimple/basic/JimpleComparator.java | 2 +- .../jimple/visitor/ReplaceUseStmtVisitor.java | 2 +- .../sootup/core/validation/NewValidator.java | 9 +- .../core/interceptors/CopyPropagator.java | 3 +- .../DeadAssignmentEliminator.java | 2 +- .../typeresolving/TypeChecker.java | 2 +- 12 files changed, 107 insertions(+), 101 deletions(-) diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java index 6f692f1a6ff..fa334dcc552 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java @@ -31,6 +31,7 @@ import javax.annotation.Nonnull; import sootup.core.graph.StmtGraph; import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.Body; import sootup.core.model.SootMethod; @@ -185,7 +186,7 @@ public boolean setOwnerStatement(Stmt u, Body b) { @Override public boolean isCallStmt(Stmt stmt) { - return stmt.containsInvokeExpr(); + return stmt instanceof InvokableStmt && ((InvokableStmt)stmt).containsInvokeExpr(); } @Override diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java index 9c938671ebf..55d621a1ab7 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java @@ -28,6 +28,7 @@ import org.apache.commons.lang3.tuple.Pair; import sootup.callgraph.CallGraph; import sootup.core.jimple.common.expr.*; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; @@ -59,11 +60,12 @@ public static Set> getCallEdges( SootMethod method = view.getMethod(caller).orElse(null); if (method != null && method.hasBody()) { for (Stmt s : method.getBody().getStmtGraph().getNodes()) { - if (s.containsInvokeExpr()) { + if (s instanceof InvokableStmt && ((InvokableStmt)s).containsInvokeExpr()) { + AbstractInvokeExpr invokeExpr = ((InvokableStmt)s).getInvokeExpr().get(); CalleeMethodSignature callee = new CalleeMethodSignature( - s.getInvokeExpr().getMethodSignature(), - findCallGraphEdgeType(s.getInvokeExpr()), + invokeExpr.getMethodSignature(), + findCallGraphEdgeType(invokeExpr), s); callEdges.add(new ImmutablePair<>(caller, callee)); } diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java index d7a1f736cb0..98b4c56469d 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java @@ -28,6 +28,7 @@ import sootup.core.graph.BasicBlock; import sootup.core.graph.StmtGraph; import sootup.core.jimple.common.expr.JNewExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; @@ -72,8 +73,8 @@ public static Map computeCalls( for (BasicBlock block : blocks) { List stmts = block.getStmts(); for (Stmt stmt : stmts) { - if (stmt.containsInvokeExpr()) { - MethodSignature target = stmt.getInvokeExpr().getMethodSignature(); + if (stmt instanceof InvokableStmt && ((InvokableStmt)stmt).containsInvokeExpr()) { + MethodSignature target = ((InvokableStmt)stmt).getInvokeExpr().get().getMethodSignature(); int hashCode = stmt.hashCode(); calls.put(hashCode, target); // compute all the classes that are made to the subclasses as well @@ -112,7 +113,7 @@ public static Set getMethodSignatureInSubClass( if (!callGraph.containsMethod(source) || !callGraph.containsMethod(target)) { return Collections.emptySet(); } - return callGraph.callsFrom(source).stream() + return callGraph.callTargetsFrom(source).stream() .filter( methodSignature -> !methodSignature.equals(target) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index dd0982d1a06..ad99225a237 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -153,8 +153,8 @@ public void testRecursiveCall() { // 2 methods + Object::clinit assertEquals(3, cg.getMethodSignatures().size()); - assertTrue(cg.containsCall(mainMethodSignature, mainMethodSignature)); - assertTrue(cg.containsCall(mainMethodSignature, method)); + assertTrue(cg.containsCall(mainMethodSignature, mainMethodSignature,getInvokableStmt(mainMethodSignature,mainMethodSignature))); + assertTrue(cg.containsCall(mainMethodSignature, method,getInvokableStmt(mainMethodSignature,method))); // 2 calls +1 clinit calls assertEquals(3, cg.callsFrom(mainMethodSignature).size()); } @@ -165,7 +165,7 @@ public void testConcreteCall() { MethodSignature targetMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("cvc.Class"), "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod,getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -177,7 +177,7 @@ public void testConcreteCallInSuperClass() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -195,8 +195,8 @@ public void testConcreteCallDifferentDefaultMethodInSubClass() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, interfaceMethod)); - assertTrue(cg.containsCall(mainMethodSignature, subInterfaceMethod)); + assertTrue(cg.containsCall(mainMethodSignature, interfaceMethod, getInvokableStmt(mainMethodSignature,interfaceMethod))); + assertTrue(cg.containsCall(mainMethodSignature, subInterfaceMethod,getInvokableStmt(mainMethodSignature,subInterfaceMethod))); } @Test @@ -208,7 +208,7 @@ public void testConcreteCallInSuperClassWithDefaultInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -220,7 +220,7 @@ public void testConcreteCallInInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -232,7 +232,7 @@ public void testConcreteCallInSubInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -244,7 +244,7 @@ public void testConcreteCallInSuperClassSubInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -256,7 +256,7 @@ public void testClinitCallEntryPoint() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -271,7 +271,7 @@ public void testClinitCallProcessed() { MethodSignature targetMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccp.Class"), "method", "int", Collections.emptyList()); - assertTrue(cg.containsCall(sourceMethod, targetMethod)); + assertTrue(cg.containsCall(sourceMethod, targetMethod, getInvokableStmt(sourceMethod,targetMethod))); } @Test @@ -283,28 +283,28 @@ public void testClinitCallConstructor() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); MethodSignature arrayMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayType"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, arrayMethod)); + assertTrue(cg.containsCall(mainMethodSignature, arrayMethod, getInvokableStmt(mainMethodSignature,arrayMethod))); MethodSignature arrayDimMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayDimType"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, arrayDimMethod)); + assertTrue(cg.containsCall(mainMethodSignature, arrayDimMethod, getInvokableStmt(mainMethodSignature,arrayDimMethod))); MethodSignature arrayInArrayMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayInArrayType"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, arrayInArrayMethod)); + assertTrue(cg.containsCall(mainMethodSignature, arrayInArrayMethod, getInvokableStmt(mainMethodSignature,arrayInArrayMethod))); } @Test @@ -316,14 +316,14 @@ public void testClinitCallSuperConstructor() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); MethodSignature targetMethod2 = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccsc.SuperClinit"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod2)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod2, getInvokableStmt(mainMethodSignature,targetMethod2))); } @Test @@ -335,7 +335,7 @@ public void testClinitStaticMethodCall() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -347,7 +347,7 @@ public void testClinitStaticField() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -356,7 +356,7 @@ public void testNonVirtualCall1() { MethodSignature targetMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -365,7 +365,7 @@ public void testNonVirtualCall2() { MethodSignature targetMethod = identifierFactory.getMethodSignature( mainClassSignature, "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -377,7 +377,7 @@ public void testNonVirtualCall3() { MethodSignature uncalledMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.singletonList("int")); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); assertFalse(cg.containsMethod(uncalledMethod)); } @@ -387,7 +387,7 @@ public void testNonVirtualCall4() { MethodSignature firstMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, firstMethod)); + assertTrue(cg.containsCall(mainMethodSignature, firstMethod, getInvokableStmt(mainMethodSignature,firstMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( @@ -395,7 +395,7 @@ public void testNonVirtualCall4() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(firstMethod, targetMethod)); + assertTrue(cg.containsCall(firstMethod, targetMethod, getInvokableStmt(firstMethod,targetMethod))); } @Test @@ -405,7 +405,7 @@ public void testNonVirtualCall5() { MethodSignature firstMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("nvc5.Sub"), "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, firstMethod)); + assertTrue(cg.containsCall(mainMethodSignature, firstMethod, getInvokableStmt(mainMethodSignature,firstMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( @@ -413,7 +413,7 @@ public void testNonVirtualCall5() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(firstMethod, targetMethod)); + assertTrue(cg.containsCall(firstMethod, targetMethod, getInvokableStmt(firstMethod,targetMethod))); } @Test @@ -423,7 +423,7 @@ public void testVirtualCall1() { MethodSignature targetMethod = identifierFactory.getMethodSignature( mainClassSignature, "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod)); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); } @Test @@ -434,17 +434,17 @@ public void testVirtualCall2() { MethodSignature constructorMethod = identifierFactory.getMethodSignature( subClassSig, "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, constructorMethod)); + assertTrue(cg.containsCall(mainMethodSignature, constructorMethod, getInvokableStmt(mainMethodSignature,constructorMethod))); MethodSignature callMethod = identifierFactory.getMethodSignature( mainClassSignature, "callMethod", "void", Collections.singletonList("vc2.Class")); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( subClassSig, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(callMethod, targetMethod)); + assertTrue(cg.containsCall(callMethod, targetMethod, getInvokableStmt(callMethod,targetMethod))); } @Test @@ -455,7 +455,7 @@ public void testVirtualCall3() { MethodSignature constructorMethod = identifierFactory.getMethodSignature( subClassSig, "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, constructorMethod)); + assertTrue(cg.containsCall(mainMethodSignature, constructorMethod, getInvokableStmt(mainMethodSignature,constructorMethod))); MethodSignature callMethod = identifierFactory.getMethodSignature( @@ -463,12 +463,12 @@ public void testVirtualCall3() { "callOnInterface", "void", Collections.singletonList("vc3.Interface")); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( subClassSig, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(callMethod, targetMethod)); + assertTrue(cg.containsCall(callMethod, targetMethod,getInvokableStmt(callMethod,targetMethod))); } @Test @@ -479,7 +479,7 @@ public void testVirtualCall4() { MethodSignature callMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("vc4.Class"), "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); } @Test @@ -497,8 +497,8 @@ public void testDynamicInterfaceMethod0() { "method", "void", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, interfaceMethod)); - assertTrue(cg.containsCall(mainMethodSignature, classMethod)); + assertFalse(cg.containsCall(mainMethodSignature, interfaceMethod, getInvokableStmt(mainMethodSignature,interfaceMethod))); + assertTrue(cg.containsCall(mainMethodSignature, classMethod, getInvokableStmt(mainMethodSignature,classMethod))); } @Test @@ -510,7 +510,7 @@ public void testDynamicInterfaceMethod1() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); } @Test @@ -523,7 +523,7 @@ public void testDynamicInterfaceMethod2() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); } @Test @@ -533,7 +533,7 @@ public void testDynamicInterfaceMethod3() { MethodSignature callMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); } @Test @@ -546,7 +546,7 @@ public void testDynamicInterfaceMethod4() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod)); + assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); } @Test @@ -559,12 +559,12 @@ public void testDynamicInterfaceMethod5() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method)); + assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,method))); MethodSignature compute = identifierFactory.getMethodSignature( mainClassSignature, "compute", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, compute)); + assertTrue(cg.containsCall(mainMethodSignature, compute, getInvokableStmt(mainMethodSignature,compute))); } @Test @@ -577,7 +577,7 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, combinedInterfaceMethod)); + assertTrue(cg.containsCall(mainMethodSignature, combinedInterfaceMethod, getInvokableStmt(mainMethodSignature,combinedInterfaceMethod))); MethodSignature method = identifierFactory.getMethodSignature( @@ -585,7 +585,7 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(combinedInterfaceMethod, method)); + assertTrue(cg.containsCall(combinedInterfaceMethod, method, getInvokableStmt(combinedInterfaceMethod,method))); MethodSignature anotherMethod = identifierFactory.getMethodSignature( @@ -593,7 +593,7 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(combinedInterfaceMethod, anotherMethod)); + assertTrue(cg.containsCall(combinedInterfaceMethod, anotherMethod, getInvokableStmt(combinedInterfaceMethod,anotherMethod))); } @Test @@ -607,7 +607,7 @@ public void testStaticInterfaceMethod() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method)); + assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,method))); } @Test @@ -625,8 +625,8 @@ public void testAbstractMethod() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method)); - assertFalse(cg.containsCall(mainMethodSignature, abstractMethod)); + assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,abstractMethod))); + assertFalse(cg.containsCall(mainMethodSignature, abstractMethod, getInvokableStmt(mainMethodSignature,abstractMethod))); } @Test @@ -650,14 +650,14 @@ public void testAbstractMethodInSubClass() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method)); - assertFalse(cg.containsCall(mainMethodSignature, abstractMethod)); + assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,abstractMethod))); + assertFalse(cg.containsCall(mainMethodSignature, abstractMethod, getInvokableStmt(mainMethodSignature,superMethod))); if (this instanceof ClassHierarchyAnalysisAlgorithmTest) { - assertTrue(cg.containsCall(mainMethodSignature, superMethod)); + assertTrue(cg.containsCall(mainMethodSignature, superMethod, getInvokableStmt(mainMethodSignature,superMethod))); } if (this instanceof RapidTypeAnalysisAlgorithmTest) { - assertFalse(cg.containsCall(mainMethodSignature, superMethod)); + assertFalse(cg.containsCall(mainMethodSignature, superMethod, getInvokableStmt(mainMethodSignature,superMethod) )); } } @@ -676,8 +676,8 @@ public void testAbstractMethodMissingMethodInSuperclass() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method)); - assertFalse(cg.containsCall(mainMethodSignature, abstractMethod)); + assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,abstractMethod))); + assertFalse(cg.containsCall(mainMethodSignature, abstractMethod, getInvokableStmt(mainMethodSignature,abstractMethod))); } @Test diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java index 7fa2445c802..37dbbd2c105 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java @@ -148,25 +148,25 @@ public void testMiscExample1() { "void", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, constructorA)); - assertTrue(cg.containsCall(mainMethodSignature, constructorB)); - assertTrue(cg.containsCall(mainMethodSignature, constructorC)); - assertFalse(cg.containsCall(mainMethodSignature, constructorD)); - assertTrue(cg.containsCall(mainMethodSignature, constructorE)); + assertFalse(cg.containsCall(mainMethodSignature, constructorA, getInvokableStmt(mainMethodSignature, constructorA))); + assertTrue(cg.containsCall(mainMethodSignature, constructorB, getInvokableStmt(mainMethodSignature, constructorB))); + assertTrue(cg.containsCall(mainMethodSignature, constructorC, getInvokableStmt(mainMethodSignature, constructorC))); + assertFalse(cg.containsCall(mainMethodSignature, constructorD, getInvokableStmt(mainMethodSignature, constructorD))); + assertTrue(cg.containsCall(mainMethodSignature, constructorE, getInvokableStmt(mainMethodSignature, constructorE))); assertFalse(cg.containsMethod(staticMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, staticMethodB)); + assertTrue(cg.containsCall(mainMethodSignature, staticMethodB,getInvokableStmt(mainMethodSignature, staticMethodB))); assertFalse(cg.containsMethod(staticMethodC)); assertFalse(cg.containsMethod(staticMethodD)); assertFalse(cg.containsMethod(staticMethodE)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodB)); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodA, getInvokableStmt(mainMethodSignature, virtualMethodA))); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodB, getInvokableStmt(mainMethodSignature, virtualMethodB))); assertFalse(cg.containsMethod(virtualMethodC)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodD)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodE)); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodD, getInvokableStmt(mainMethodSignature, virtualMethodD))); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodE, getInvokableStmt(mainMethodSignature, virtualMethodE))); - assertTrue(cg.containsCall(mainMethodSignature, clinitObject)); + assertTrue(cg.containsCall(mainMethodSignature, clinitObject, getInvokableStmt(mainMethodSignature, clinitObject))); assertEquals(9, cg.callsFrom(mainMethodSignature).size()); diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java index c5bcff4be5f..2dad97dbd0c 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java @@ -142,25 +142,25 @@ public void testMiscExample1() { "void", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, constructorA)); - assertTrue(cg.containsCall(mainMethodSignature, constructorB)); - assertTrue(cg.containsCall(mainMethodSignature, constructorC)); - assertFalse(cg.containsCall(mainMethodSignature, constructorD)); - assertTrue(cg.containsCall(mainMethodSignature, constructorE)); + assertFalse(cg.containsCall(mainMethodSignature, constructorA,getInvokableStmt(mainMethodSignature,constructorA))); + assertTrue(cg.containsCall(mainMethodSignature, constructorB,getInvokableStmt(mainMethodSignature,constructorB))); + assertTrue(cg.containsCall(mainMethodSignature, constructorC,getInvokableStmt(mainMethodSignature,constructorC))); + assertFalse(cg.containsCall(mainMethodSignature, constructorD,getInvokableStmt(mainMethodSignature,constructorD))); + assertTrue(cg.containsCall(mainMethodSignature, constructorE,getInvokableStmt(mainMethodSignature,constructorE))); assertFalse(cg.containsMethod(staticMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, staticMethodB)); + assertTrue(cg.containsCall(mainMethodSignature, staticMethodB,getInvokableStmt(staticMethodB,staticMethodB))); assertFalse(cg.containsMethod(staticMethodC)); assertFalse(cg.containsMethod(staticMethodD)); assertFalse(cg.containsMethod(staticMethodE)); assertFalse(cg.containsMethod(virtualMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodB)); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodB,getInvokableStmt(virtualMethodB,virtualMethodB))); assertFalse(cg.containsMethod(virtualMethodC)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodD)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodE)); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodD,getInvokableStmt(virtualMethodD,virtualMethodD))); + assertTrue(cg.containsCall(mainMethodSignature, virtualMethodE,getInvokableStmt(virtualMethodE,virtualMethodE))); - assertTrue(cg.containsCall(mainMethodSignature, clinitObject)); + assertTrue(cg.containsCall(mainMethodSignature, clinitObject,getInvokableStmt(clinitObject,clinitObject))); assertEquals(8, cg.callsFrom(mainMethodSignature).size()); @@ -251,9 +251,9 @@ public void testRevisitMethod() { "int", Collections.emptyList()); - assertFalse(cg.containsCall(alreadyVisitedMethod, newTargetA)); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetB)); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetC)); + assertFalse(cg.containsCall(alreadyVisitedMethod, newTargetA,getInvokableStmt(alreadyVisitedMethod, newTargetA))); + assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetB,getInvokableStmt(alreadyVisitedMethod, newTargetB))); + assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetC,getInvokableStmt(alreadyVisitedMethod, newTargetC))); } @Test @@ -287,9 +287,9 @@ public void testRecursiveRevisitMethod() { "int", Collections.emptyList()); - assertFalse(cg.containsCall(alreadyVisitedMethod, newTargetA)); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetB)); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetC)); + assertFalse(cg.containsCall(alreadyVisitedMethod, newTargetA,getInvokableStmt(alreadyVisitedMethod, newTargetA))); + assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetB,getInvokableStmt(alreadyVisitedMethod, newTargetB))); + assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetC,getInvokableStmt(alreadyVisitedMethod, newTargetC))); } @Test @@ -308,8 +308,8 @@ public void testInstantiatedClassInClinit() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, instantiatedClassMethod)); - assertFalse(cg.containsCall(mainMethodSignature, nonInstantiatedClassMethod)); + assertTrue(cg.containsCall(mainMethodSignature, instantiatedClassMethod,getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); + assertFalse(cg.containsCall(mainMethodSignature, nonInstantiatedClassMethod,getInvokableStmt(mainMethodSignature, nonInstantiatedClassMethod))); } @Test @@ -321,6 +321,6 @@ public void testLaterInstantiatedClass() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, instantiatedClassMethod)); + assertTrue(cg.containsCall(mainMethodSignature, instantiatedClassMethod,getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java b/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java index 5da7ae723de..7e743b29c84 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java @@ -143,7 +143,7 @@ public boolean caseBreakpointStmt(JBreakpointStmt stmt, Object o) { public boolean caseInvokeStmt(JInvokeStmt stmt, Object o) { return (o instanceof JInvokeStmt) - && stmt.getInvokeExpr().equivTo(((JInvokeStmt) o).getInvokeExpr(), this); + && stmt.getInvokeExpr().get().equivTo(((JInvokeStmt) o).getInvokeExpr(), this); } public boolean caseAssignStmt(JAssignStmt stmt, Object o) { diff --git a/sootup.core/src/main/java/sootup/core/jimple/visitor/ReplaceUseStmtVisitor.java b/sootup.core/src/main/java/sootup/core/jimple/visitor/ReplaceUseStmtVisitor.java index 35d5bc6b130..0a14e29a0f4 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/visitor/ReplaceUseStmtVisitor.java +++ b/sootup.core/src/main/java/sootup/core/jimple/visitor/ReplaceUseStmtVisitor.java @@ -58,7 +58,7 @@ public void caseBreakpointStmt(@Nonnull JBreakpointStmt stmt) { @Override public void caseInvokeStmt(@Nonnull JInvokeStmt stmt) { - Expr invokeExpr = stmt.getInvokeExpr(); + Expr invokeExpr = stmt.getInvokeExpr().get(); exprVisitor.init(oldUse, newUse); invokeExpr.accept(exprVisitor); diff --git a/sootup.core/src/main/java/sootup/core/validation/NewValidator.java b/sootup.core/src/main/java/sootup/core/validation/NewValidator.java index 693c693524e..896712818eb 100644 --- a/sootup.core/src/main/java/sootup/core/validation/NewValidator.java +++ b/sootup.core/src/main/java/sootup/core/validation/NewValidator.java @@ -29,6 +29,7 @@ import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JNewExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.jimple.common.stmt.Stmt; @@ -96,12 +97,12 @@ private boolean checkForInitializerOnPath( continue; } if (!newStmt.equals(curStmt)) { - if (curStmt.containsInvokeExpr()) { - AbstractInvokeExpr expr = curStmt.getInvokeExpr(); + if (((InvokableStmt)curStmt).containsInvokeExpr()) { + AbstractInvokeExpr expr = ((InvokableStmt)curStmt).getInvokeExpr().get(); if (!(expr instanceof JSpecialInvokeExpr)) { exception.add( new ValidationException( - curStmt.getInvokeExpr(), + expr, " Method calls may only be used with specialinvoke.")); // At least we // found an initializer, so we return true... return true; @@ -109,7 +110,7 @@ private boolean checkForInitializerOnPath( if (!(curStmt instanceof JInvokeStmt)) { exception.add( new ValidationException( - curStmt.getInvokeExpr(), + expr, " methods may only be called with invoke statements.")); // At least we // found an initializer, so we return true... return true; diff --git a/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java b/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java index d9d5808ed22..33b0f30e6bf 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java +++ b/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java @@ -34,6 +34,7 @@ import sootup.core.jimple.common.constant.NullConstant; import sootup.core.jimple.common.expr.JCastExpr; import sootup.core.jimple.common.stmt.AbstractDefinitionStmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.Body; @@ -74,7 +75,7 @@ public void interceptBody(@Nonnull Body.BodyBuilder builder, @Nonnull View view) AbstractDefinitionStmt defStmt = (AbstractDefinitionStmt) defsOfUse.get(0); Value rhs = defStmt.getRightOp(); // if rhs is a constant, then replace use, if it is possible - if (rhs instanceof Constant && !stmt.containsInvokeExpr()) { + if (rhs instanceof Constant && !((stmt instanceof InvokableStmt) && ((InvokableStmt)stmt).containsInvokeExpr())) { replaceUse(stmtGraph, stmt, use, rhs); } diff --git a/sootup.java.core/src/main/java/sootup/java/core/interceptors/DeadAssignmentEliminator.java b/sootup.java.core/src/main/java/sootup/java/core/interceptors/DeadAssignmentEliminator.java index dfebe2cda3b..50d5159ec35 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/interceptors/DeadAssignmentEliminator.java +++ b/sootup.java.core/src/main/java/sootup/java/core/interceptors/DeadAssignmentEliminator.java @@ -240,7 +240,7 @@ public void interceptBody(@Nonnull Body.BodyBuilder builder, @Nonnull View view) for (JAssignStmt assignStmt : postProcess) { // Transform it into a simple invoke Stmt newInvoke = - Jimple.newInvokeStmt(assignStmt.getInvokeExpr(), assignStmt.getPositionInfo()); + Jimple.newInvokeStmt(assignStmt.getInvokeExpr().get(), assignStmt.getPositionInfo()); stmtGraph.replaceNode(assignStmt, newInvoke); builder.removeDefLocalsOf(assignStmt); } diff --git a/sootup.java.core/src/main/java/sootup/java/core/interceptors/typeresolving/TypeChecker.java b/sootup.java.core/src/main/java/sootup/java/core/interceptors/typeresolving/TypeChecker.java index e6186ede693..bde15e23c16 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/interceptors/typeresolving/TypeChecker.java +++ b/sootup.java.core/src/main/java/sootup/java/core/interceptors/typeresolving/TypeChecker.java @@ -74,7 +74,7 @@ public TypeChecker( @Override public void caseInvokeStmt(@Nonnull JInvokeStmt stmt) { - handleInvokeExpr(stmt.getInvokeExpr(), stmt); + handleInvokeExpr(stmt.getInvokeExpr().get(), stmt); } @Override From 951df1408f3e4a7002697a0df44368d9bac4c819 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 15:30:28 +0200 Subject: [PATCH 04/41] fixed Javadoc --- .../java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java index 0cf1d95356d..c0f0b633bd5 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithm.java @@ -72,7 +72,7 @@ public CallGraph initialize(@Nonnull List entryPoints) { * called in the invoke expression. * * @param method the method object that contains the given invoke expression in the body. - * @param invokeExpr it contains the call which is resolved. + * @param invokableStmt it contains the call which is resolved. * @return a stream containing all reachable method signatures after applying the CHA call graph * algorithm */ From 587c0771eb0c5bd0dd8d08883143235f38086531 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 15:30:56 +0200 Subject: [PATCH 05/41] fmt --- .../icfg/AbstractJimpleBasedICFG.java | 2 +- .../interprocedural/icfg/CGEdgeUtil.java | 8 +- .../interprocedural/icfg/ICFGDotExporter.java | 5 +- .../icfg/JimpleBasedInterproceduralCFG.java | 16 +- .../callgraph/AbstractCallGraphAlgorithm.java | 136 +++++--- .../main/java/sootup/callgraph/CallGraph.java | 27 +- .../sootup/callgraph/GraphBasedCallGraph.java | 32 +- .../sootup/callgraph/MutableCallGraph.java | 6 +- .../callgraph/RapidTypeAnalysisAlgorithm.java | 30 +- .../sootup/callgraph/CallGraphTestBase.java | 297 ++++++++++++++---- .../ClassHierarchyAnalysisAlgorithmTest.java | 66 +++- .../RapidTypeAnalysisAlgorithmTest.java | 92 ++++-- .../core/jimple/common/stmt/AbstractStmt.java | 1 - .../jimple/common/stmt/InvokableStmt.java | 20 +- .../core/jimple/common/stmt/JAssignStmt.java | 13 +- .../core/jimple/common/stmt/JInvokeStmt.java | 2 +- .../sootup/core/jimple/common/stmt/Stmt.java | 1 - .../sootup/core/validation/NewValidator.java | 4 +- .../jimple/common/stmt/JAssignStmtTest.java | 84 +++-- .../jimple/common/stmt/JInvokeStmtTest.java | 35 +-- .../test/java/sootup/util/AssignStmtUtil.java | 53 ++-- .../test/java/sootup/util/ClassTypeUtil.java | 9 +- .../test/java/sootup/util/FieldRefUtil.java | 21 +- .../test/java/sootup/util/InvokeExprUtil.java | 34 +- .../src/test/java/sootup/util/LocalUtil.java | 14 +- .../test/java/sootup/util/SignatureUtil.java | 38 +-- .../test/java/sootup/util/StmtPosUtil.java | 9 +- .../core/interceptors/CopyPropagator.java | 3 +- 28 files changed, 687 insertions(+), 371 deletions(-) diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java index fa334dcc552..f79a9a28c26 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java @@ -186,7 +186,7 @@ public boolean setOwnerStatement(Stmt u, Body b) { @Override public boolean isCallStmt(Stmt stmt) { - return stmt instanceof InvokableStmt && ((InvokableStmt)stmt).containsInvokeExpr(); + return stmt instanceof InvokableStmt && ((InvokableStmt) stmt).containsInvokeExpr(); } @Override diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java index 55d621a1ab7..9f415c4d449 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java @@ -60,13 +60,11 @@ public static Set> getCallEdges( SootMethod method = view.getMethod(caller).orElse(null); if (method != null && method.hasBody()) { for (Stmt s : method.getBody().getStmtGraph().getNodes()) { - if (s instanceof InvokableStmt && ((InvokableStmt)s).containsInvokeExpr()) { - AbstractInvokeExpr invokeExpr = ((InvokableStmt)s).getInvokeExpr().get(); + if (s instanceof InvokableStmt && ((InvokableStmt) s).containsInvokeExpr()) { + AbstractInvokeExpr invokeExpr = ((InvokableStmt) s).getInvokeExpr().get(); CalleeMethodSignature callee = new CalleeMethodSignature( - invokeExpr.getMethodSignature(), - findCallGraphEdgeType(invokeExpr), - s); + invokeExpr.getMethodSignature(), findCallGraphEdgeType(invokeExpr), s); callEdges.add(new ImmutablePair<>(caller, callee)); } } diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java index 98b4c56469d..d52bb670668 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java @@ -73,8 +73,9 @@ public static Map computeCalls( for (BasicBlock block : blocks) { List stmts = block.getStmts(); for (Stmt stmt : stmts) { - if (stmt instanceof InvokableStmt && ((InvokableStmt)stmt).containsInvokeExpr()) { - MethodSignature target = ((InvokableStmt)stmt).getInvokeExpr().get().getMethodSignature(); + if (stmt instanceof InvokableStmt && ((InvokableStmt) stmt).containsInvokeExpr()) { + MethodSignature target = + ((InvokableStmt) stmt).getInvokeExpr().get().getMethodSignature(); int hashCode = stmt.hashCode(); calls.put(hashCode, target); // compute all the classes that are made to the subclasses as well diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java index 47292b856fe..ae95adb1552 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java @@ -73,8 +73,10 @@ public class JimpleBasedInterproceduralCFG extends AbstractJimpleBasedICFG { @Override public Collection load(Stmt stmt) { ArrayList res = new ArrayList<>(); - if (!(stmt instanceof InvokableStmt) && !((InvokableStmt)stmt).containsInvokeExpr()) return res; - MethodSignature methodSignature = ((InvokableStmt)stmt).getInvokeExpr().get().getMethodSignature(); + if (!(stmt instanceof InvokableStmt) && !((InvokableStmt) stmt).containsInvokeExpr()) + return res; + MethodSignature methodSignature = + ((InvokableStmt) stmt).getInvokeExpr().get().getMethodSignature(); Optional smOpt = view.getMethod(methodSignature); if (smOpt.isPresent()) { SootMethod sm = smOpt.get(); @@ -222,15 +224,13 @@ public static Set> getCallEdges( final SootMethod method = methodOpt.get(); if (method.hasBody()) { for (Stmt s : method.getBody().getStmtGraph().getNodes()) { - //TODO: Consider calls to clinit methods caused by static fields + // TODO: Consider calls to clinit methods caused by static fields // Assignment statements without invokeExpressions - if (s instanceof InvokableStmt && ((InvokableStmt)s).containsInvokeExpr()) { - AbstractInvokeExpr expr = ((InvokableStmt)s).getInvokeExpr().get(); + if (s instanceof InvokableStmt && ((InvokableStmt) s).containsInvokeExpr()) { + AbstractInvokeExpr expr = ((InvokableStmt) s).getInvokeExpr().get(); CalleeMethodSignature callee = new CalleeMethodSignature( - expr.getMethodSignature(), - CGEdgeUtil.findCallGraphEdgeType(expr), - s); + expr.getMethodSignature(), CGEdgeUtil.findCallGraphEdgeType(expr), s); callEdges.add(new ImmutablePair<>(caller, callee)); } } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index 18cea1125d2..a5ef3a04693 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -77,10 +77,10 @@ final CallGraph constructCompleteCallGraph(View view, List entr Set processed = new HashSet<>(); // find additional entry points - List clinits=getClinitFromEntryPoints(entryPoints); + List clinits = getClinitFromEntryPoints(entryPoints); workList.addAll(clinits); - MutableCallGraph cg = initializeCallGraph(entryPoints,clinits); + MutableCallGraph cg = initializeCallGraph(entryPoints, clinits); processWorkList(view, workList, processed, cg); return cg; @@ -92,26 +92,33 @@ final CallGraph constructCompleteCallGraph(View view, List entr * * @return the initialized call graph used in the call graph algorithm */ - protected MutableCallGraph initializeCallGraph(List entryPoints, List clinits) { - ArrayList rootSignatures=new ArrayList<>(entryPoints); + protected MutableCallGraph initializeCallGraph( + List entryPoints, List clinits) { + ArrayList rootSignatures = new ArrayList<>(entryPoints); rootSignatures.addAll(clinits); return new GraphBasedCallGraph(rootSignatures); } /** - * This method returns a list of static initializers that should be considered by the given entry points + * This method returns a list of static initializers that should be considered by the given entry + * points * * @param entryPoints the entry points of the call graph algorithm */ - protected List getClinitFromEntryPoints( - List entryPoints) { + protected List getClinitFromEntryPoints(List entryPoints) { return entryPoints.stream() - .map(methodSignature -> getSignatureOfImplementedStaticInitializer(methodSignature.getDeclClassType())) - .filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); + .map( + methodSignature -> + getSignatureOfImplementedStaticInitializer(methodSignature.getDeclClassType())) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); } - private Optional getSignatureOfImplementedStaticInitializer(ClassType classType){ - return view.getMethod(classType.getStaticInitializer()).map(sootMethod -> sootMethod.getSignature()); + private Optional getSignatureOfImplementedStaticInitializer( + ClassType classType) { + return view.getMethod(classType.getStaticInitializer()) + .map(sootMethod -> sootMethod.getSignature()); } /** @@ -158,10 +165,10 @@ final void processWorkList( currentClass.getMethod(currentMethodSignature.getSubSignature()).orElse(null); // get all call targets of invocations in the method body - resolveAllCallsFromSourceMethod(currentMethod,cg,workList); + resolveAllCallsFromSourceMethod(currentMethod, cg, workList); // get all call targets of implicit edges in the method body - resolveAllImplicitCallsFromSourceMethod(view, currentMethod,cg,workList); + resolveAllImplicitCallsFromSourceMethod(view, currentMethod, cg, workList); // set method as processed processed.add(currentMethodSignature); @@ -171,15 +178,23 @@ final void processWorkList( } } - /** Adds the defined call to the given call graph. If the source or target method was added as vertex to the call graph, they will be added to the worklist + /** + * Adds the defined call to the given call graph. If the source or target method was added as + * vertex to the call graph, they will be added to the worklist * * @param source the method signature of the caller * @param target the method signature of the callee * @param invokeStmt the stmt causing the call * @param cg the call graph that will be updated - * @param workList the worklist in which the method signature of newly added vertexes will be added + * @param workList the worklist in which the method signature of newly added vertexes will be + * added */ - protected void addCallToCG(@Nonnull MethodSignature source, @Nonnull MethodSignature target, @Nonnull InvokableStmt invokeStmt, @Nonnull MutableCallGraph cg, @Nonnull Deque workList) { + protected void addCallToCG( + @Nonnull MethodSignature source, + @Nonnull MethodSignature target, + @Nonnull InvokableStmt invokeStmt, + @Nonnull MutableCallGraph cg, + @Nonnull Deque workList) { if (!cg.containsMethod(source)) { cg.addMethod(source); workList.push(source); @@ -188,31 +203,38 @@ protected void addCallToCG(@Nonnull MethodSignature source, @Nonnull MethodSigna cg.addMethod(target); workList.push(target); } - if (!cg.containsCall(source, target,invokeStmt)) { + if (!cg.containsCall(source, target, invokeStmt)) { cg.addCall(source, target, invokeStmt); } } /** * This method resolves all calls from a given source method. resolveCall is called for each - * invokable statements in the body of the source method that is implemented in the corresponding call - * graph algorithm. If new methods will be added as vertexes in the call graph, the work list will be updated + * invokable statements in the body of the source method that is implemented in the corresponding + * call graph algorithm. If new methods will be added as vertexes in the call graph, the work list + * will be updated * * @param sourceMethod this signature is used to access the statements contained method body of * the specified method * @param cg the call graph that will receive the found calls * @param workList the work list that will be updated of found target methods */ - protected void resolveAllCallsFromSourceMethod(SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { + protected void resolveAllCallsFromSourceMethod( + SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { return; } sourceMethod.getBody().getStmts().stream() .filter(stmt -> stmt instanceof InvokableStmt) - .map(stmt -> (InvokableStmt)stmt) - .forEach(stmt -> resolveCall(sourceMethod, stmt) - .forEach(targetMethod -> addCallToCG(sourceMethod.getSignature(),targetMethod,stmt,cg,workList))); + .map(stmt -> (InvokableStmt) stmt) + .forEach( + stmt -> + resolveCall(sourceMethod, stmt) + .forEach( + targetMethod -> + addCallToCG( + sourceMethod.getSignature(), targetMethod, stmt, cg, workList))); } /** @@ -230,7 +252,7 @@ protected void resolveAllImplicitCallsFromSourceMethod( } // collect all static initializer calls - resolveAllStaticInitializerCallsFromSourceMethod(view, sourceMethod,cg,workList); + resolveAllStaticInitializerCallsFromSourceMethod(view, sourceMethod, cg, workList); } /** @@ -247,38 +269,43 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( if (sourceMethod == null || !sourceMethod.hasBody()) { return; } - sourceMethod - .getBody() - .getStmts() - .stream().filter(stmt -> stmt instanceof InvokableStmt) - .map(stmt -> (InvokableStmt)stmt) + sourceMethod.getBody().getStmts().stream() + .filter(stmt -> stmt instanceof InvokableStmt) + .map(stmt -> (InvokableStmt) stmt) .forEach( invokableStmt -> { // static field usage ClassType targetClass = null; - if (invokableStmt.containsFieldRef() && invokableStmt.getFieldRef() instanceof JStaticFieldRef) { - targetClass= invokableStmt.getFieldRef().getFieldSignature().getDeclClassType(); - addStaticInitializerCallsToCallGraph(sourceMethod.getSignature(),targetClass,invokableStmt,cg,workList); + if (invokableStmt.containsFieldRef() + && invokableStmt.getFieldRef() instanceof JStaticFieldRef) { + targetClass = invokableStmt.getFieldRef().getFieldSignature().getDeclClassType(); + addStaticInitializerCallsToCallGraph( + sourceMethod.getSignature(), targetClass, invokableStmt, cg, workList); } // static method calls and constructor calls if (invokableStmt instanceof InvokableStmt && invokableStmt.containsInvokeExpr()) { - //static method call + // static method call Optional exprOptional = invokableStmt.getInvokeExpr(); - if (!exprOptional.isPresent()) - return; + if (!exprOptional.isPresent()) return; AbstractInvokeExpr expr = exprOptional.get(); - if (expr instanceof JStaticInvokeExpr || (expr instanceof JSpecialInvokeExpr - && view.getIdentifierFactory().isConstructorSignature(expr.getMethodSignature()))) { + if (expr instanceof JStaticInvokeExpr + || (expr instanceof JSpecialInvokeExpr + && view.getIdentifierFactory() + .isConstructorSignature(expr.getMethodSignature()))) { ClassType newTargetClass = expr.getMethodSignature().getDeclClassType(); - if (!newTargetClass.equals(targetClass)){ - addStaticInitializerCallsToCallGraph(sourceMethod.getSignature(),newTargetClass,invokableStmt,cg,workList); + if (!newTargetClass.equals(targetClass)) { + addStaticInitializerCallsToCallGraph( + sourceMethod.getSignature(), newTargetClass, invokableStmt, cg, workList); } } } }); } - /** Adds all static initializer calls of the given targetClass. An edge from the sourceSig to all clinit methods of the targetClass and Superclasses will be added to the call graph. If new target methods will be found, the worklist will be updated. + /** + * Adds all static initializer calls of the given targetClass. An edge from the sourceSig to all + * clinit methods of the targetClass and Superclasses will be added to the call graph. If new + * target methods will be found, the worklist will be updated. * * @param sourceSig the source method causing the static initilzer call * @param targetClass the class that is statically initialized @@ -286,11 +313,25 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( * @param cg the call graph that will contain the found calls * @param workList the work list that will be updated with new target methods */ - private void addStaticInitializerCallsToCallGraph(MethodSignature sourceSig, ClassType targetClass, InvokableStmt invokableStmt, MutableCallGraph cg, Deque workList){ - //static initializer call of class - view.getMethod(targetClass.getStaticInitializer()).ifPresent(targetSig -> addCallToCG(sourceSig,targetSig.getSignature(),invokableStmt, cg, workList)); - //static initializer calls of all superclasses - view.getTypeHierarchy().superClassesOf(targetClass).stream().map(classType -> view.getMethod(classType.getStaticInitializer())).filter(Optional::isPresent).map(Optional::get).forEach(targetSig -> addCallToCG(sourceSig,targetSig.getSignature(),invokableStmt,cg,workList) ); + private void addStaticInitializerCallsToCallGraph( + MethodSignature sourceSig, + ClassType targetClass, + InvokableStmt invokableStmt, + MutableCallGraph cg, + Deque workList) { + // static initializer call of class + view.getMethod(targetClass.getStaticInitializer()) + .ifPresent( + targetSig -> + addCallToCG(sourceSig, targetSig.getSignature(), invokableStmt, cg, workList)); + // static initializer calls of all superclasses + view.getTypeHierarchy().superClassesOf(targetClass).stream() + .map(classType -> view.getMethod(classType.getStaticInitializer())) + .filter(Optional::isPresent) + .map(Optional::get) + .forEach( + targetSig -> + addCallToCG(sourceSig, targetSig.getSignature(), invokableStmt, cg, workList)); } /** @@ -372,7 +413,10 @@ public CallGraph addClass(@Nonnull CallGraph oldCallGraph, @Nonnull JavaClassTyp if (updated.containsMethod(overriddenMethodSig)) { for (Call calls : updated.callsTo(overriddenMethodSig)) { - updated.addCall(calls.getSourceMethodSignature(), overridingMethodSig,calls.getInvokableStmt()); + updated.addCall( + calls.getSourceMethodSignature(), + overridingMethodSig, + calls.getInvokableStmt()); } } }); diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index de9add7c51c..f62d2054718 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -30,15 +30,15 @@ /** The interface of all implemented call graph data structures */ public interface CallGraph { - class Call{ - @Nonnull - private MethodSignature sourceMethodSignature; - @Nonnull - private MethodSignature targetMethodSignature; - @Nonnull - private InvokableStmt invokableStmt; - - Call(@Nonnull MethodSignature sourceMethodSignature, @Nonnull MethodSignature targetMethodSignature, @Nonnull InvokableStmt invokableStmt) { + class Call { + @Nonnull private MethodSignature sourceMethodSignature; + @Nonnull private MethodSignature targetMethodSignature; + @Nonnull private InvokableStmt invokableStmt; + + Call( + @Nonnull MethodSignature sourceMethodSignature, + @Nonnull MethodSignature targetMethodSignature, + @Nonnull InvokableStmt invokableStmt) { this.sourceMethodSignature = sourceMethodSignature; this.invokableStmt = invokableStmt; this.targetMethodSignature = targetMethodSignature; @@ -67,8 +67,8 @@ public boolean equals(Object o) { Call call = (Call) o; return sourceMethodSignature.equals(call.sourceMethodSignature) - && targetMethodSignature.equals( - call.targetMethodSignature) && invokableStmt.equals(call.invokableStmt); + && targetMethodSignature.equals(call.targetMethodSignature) + && invokableStmt.equals(call.invokableStmt); } @Override @@ -103,7 +103,6 @@ public int hashCode() { * This method returns all method signatures that call a given method signature. It returns the * sources of incoming edges of the given node (method signature) in the call graph * - * * @param targetMethod the method signature of the requested node in the call graph * @return a set of method signatures that reach the targetMethod by a direct edge in the call * graph @@ -153,7 +152,9 @@ public int hashCode() { * @return true if the edge is contained in the call graph, otherwise it will be false. */ boolean containsCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, InvokableStmt invokableStmt); + @Nonnull MethodSignature sourceMethod, + @Nonnull MethodSignature targetMethod, + InvokableStmt invokableStmt); /** * This method checks if an edge is contained in the call graph. The edge is defined by a source diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java index 2d58165d77b..ffed8733590 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java @@ -62,12 +62,13 @@ protected MethodSignature getMethodSignature() { /** The constructor of the graph based call graph. it initializes the call graph object. */ public GraphBasedCallGraph(List entryMethods) { - this(new DirectedPseudograph<>(null, null, false),new HashMap<>(), entryMethods); + this(new DirectedPseudograph<>(null, null, false), new HashMap<>(), entryMethods); } public GraphBasedCallGraph( @Nonnull DirectedPseudograph graph, - @Nonnull Map signatureToVertex, List entryMethods) { + @Nonnull Map signatureToVertex, + List entryMethods) { this.graph = graph; this.signatureToVertex = signatureToVertex; this.entryMethods = entryMethods; @@ -80,7 +81,7 @@ public void addMethod(@Nonnull MethodSignature calledMethod) { } protected void addMethod(@Nonnull MethodSignature calledMethod, Vertex vertex) { - if (containsMethod(calledMethod)){ + if (containsMethod(calledMethod)) { return; } graph.addVertex(vertex); @@ -89,17 +90,21 @@ protected void addMethod(@Nonnull MethodSignature calledMethod, Vertex vertex) { @Override public void addCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, @Nonnull InvokableStmt invokableStmt) { - addCall(sourceMethod, targetMethod, new Call(sourceMethod,targetMethod,invokableStmt)); + @Nonnull MethodSignature sourceMethod, + @Nonnull MethodSignature targetMethod, + @Nonnull InvokableStmt invokableStmt) { + addCall(sourceMethod, targetMethod, new Call(sourceMethod, targetMethod, invokableStmt)); } protected void addCall( @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, Call call) { - if (!call.getSourceMethodSignature().equals(sourceMethod) || !call.getTargetMethodSignature().equals(targetMethod) || containsCall(call)){ + if (!call.getSourceMethodSignature().equals(sourceMethod) + || !call.getTargetMethodSignature().equals(targetMethod) + || containsCall(call)) { return; } - Vertex source=vertexOf(sourceMethod); - Vertex target=vertexOf(targetMethod); + Vertex source = vertexOf(sourceMethod); + Vertex target = vertexOf(targetMethod); graph.addEdge(source, target, call); } @@ -146,11 +151,13 @@ public boolean containsMethod(@Nonnull MethodSignature method) { @Override public boolean containsCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, @Nonnull InvokableStmt invokableStmt) { + @Nonnull MethodSignature sourceMethod, + @Nonnull MethodSignature targetMethod, + @Nonnull InvokableStmt invokableStmt) { if (!containsMethod(sourceMethod) || !containsMethod(targetMethod)) { return false; } - return containsCall(new Call(sourceMethod,targetMethod,invokableStmt)); + return containsCall(new Call(sourceMethod, targetMethod, invokableStmt)); } @Override @@ -221,8 +228,9 @@ public String exportAsDot() { @Override public MutableCallGraph copy() { return new GraphBasedCallGraph( - (DirectedPseudograph) graph.clone(), new HashMap<>(signatureToVertex),new ArrayList<>( - entryMethods)); + (DirectedPseudograph) graph.clone(), + new HashMap<>(signatureToVertex), + new ArrayList<>(entryMethods)); } /** diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java index 5c8d3c3429f..6df01fba4ca 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/MutableCallGraph.java @@ -46,6 +46,8 @@ public interface MutableCallGraph extends CallGraph { * @param targetMethod this paramter defines the target node of the edge in the call graph. * @param invokableStmt this paramter defines the invoke statement of the edge in the call graph. */ - void addCall(@Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod, @Nonnull - InvokableStmt invokableStmt); + void addCall( + @Nonnull MethodSignature sourceMethod, + @Nonnull MethodSignature targetMethod, + @Nonnull InvokableStmt invokableStmt); } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java index 936739d2dca..bc24993d242 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java @@ -120,10 +120,10 @@ protected List collectInstantiatedClassesInMethod(SootMethod method) protected Stream resolveCall( SootMethod sourceMethod, InvokableStmt invokableStmt) { Optional optInvokeExpr = invokableStmt.getInvokeExpr(); - if (!optInvokeExpr.isPresent()){ + if (!optInvokeExpr.isPresent()) { return Stream.empty(); } - AbstractInvokeExpr invokeExpr= optInvokeExpr.get(); + AbstractInvokeExpr invokeExpr = optInvokeExpr.get(); MethodSignature resolveBaseMethodSignature = invokeExpr.getMethodSignature(); Stream result = Stream.of(resolveBaseMethodSignature); @@ -139,10 +139,12 @@ protected Stream resolveCall( if (instantiatedClasses.contains(resolveBaseMethodSignature.getDeclClassType())) { return Stream.concat( Stream.of(concreteBaseMethod.getSignature()), - resolveAllCallTargets(sourceMethod.getSignature(), resolveBaseMethodSignature,invokableStmt)); + resolveAllCallTargets( + sourceMethod.getSignature(), resolveBaseMethodSignature, invokableStmt)); } else { - saveIgnoredCall(sourceMethod.getSignature(), resolveBaseMethodSignature,invokableStmt); - return resolveAllCallTargets(sourceMethod.getSignature(), resolveBaseMethodSignature,invokableStmt); + saveIgnoredCall(sourceMethod.getSignature(), resolveBaseMethodSignature, invokableStmt); + return resolveAllCallTargets( + sourceMethod.getSignature(), resolveBaseMethodSignature, invokableStmt); } } } @@ -160,7 +162,9 @@ protected Stream resolveCall( * target from the given base method signature. */ private Stream resolveAllCallTargets( - MethodSignature source, MethodSignature resolveBaseMethodSignature, InvokableStmt invokableStmt) { + MethodSignature source, + MethodSignature resolveBaseMethodSignature, + InvokableStmt invokableStmt) { return view.getTypeHierarchy().subtypesOf(resolveBaseMethodSignature.getDeclClassType()) .stream() .map( @@ -171,7 +175,7 @@ private Stream resolveAllCallTargets( if (instantiatedClasses.contains(classType)) { return resolveConcreteDispatch(view, method); } else { - saveIgnoredCall(source, method,invokableStmt); + saveIgnoredCall(source, method, invokableStmt); return Optional.empty(); } }) @@ -187,10 +191,11 @@ private Stream resolveAllCallTargets( * @param target the target method of the call * @param invokableStmt the statement causing the call */ - private void saveIgnoredCall(MethodSignature source, MethodSignature target, InvokableStmt invokableStmt) { + private void saveIgnoredCall( + MethodSignature source, MethodSignature target, InvokableStmt invokableStmt) { ClassType notInstantiatedClass = target.getDeclClassType(); List calls = ignoredCalls.get(notInstantiatedClass); - Call ignoredCall = new Call(source, target,invokableStmt); + Call ignoredCall = new Call(source, target, invokableStmt); if (calls == null) { calls = new ArrayList<>(); ignoredCalls.put(notInstantiatedClass, calls); @@ -236,7 +241,12 @@ protected void preProcessingMethod( if (concreteTarget == null) { return; } - addCallToCG(call.getSourceMethodSignature(),concreteTarget,call.getInvokableStmt(),cg,workList); + addCallToCG( + call.getSourceMethodSignature(), + concreteTarget, + call.getInvokableStmt(), + cg, + workList); }); // can be removed because the instantiated class will be considered in future resolves ignoredCalls.remove(instantiatedClassType); diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index ad99225a237..0fd99146aab 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -86,17 +86,25 @@ CallGraph loadCallGraph(String testDirectory, boolean useSourceCodeFrontend, Str return cg; } - protected InvokableStmt getInvokableStmt(MethodSignature sourceMethod, MethodSignature staticTargetMethod){ - return getInvokableStmt(sourceMethod,staticTargetMethod,0); + protected InvokableStmt getInvokableStmt( + MethodSignature sourceMethod, MethodSignature staticTargetMethod) { + return getInvokableStmt(sourceMethod, staticTargetMethod, 0); } - protected InvokableStmt getInvokableStmt(MethodSignature sourceMethod, MethodSignature staticTargetMethod, int index){ + protected InvokableStmt getInvokableStmt( + MethodSignature sourceMethod, MethodSignature staticTargetMethod, int index) { int currentIndex = 0; SootMethod method = view.getMethod(sourceMethod).orElse(null); assertNotNull(method); - for(Stmt invokableStmt: method.getBody().getStmts()){ - if(invokableStmt instanceof InvokableStmt && ((InvokableStmt) invokableStmt).containsInvokeExpr() && ((InvokableStmt) invokableStmt).getInvokeExpr().get().getMethodSignature().equals(staticTargetMethod)){ - if(currentIndex == index){ + for (Stmt invokableStmt : method.getBody().getStmts()) { + if (invokableStmt instanceof InvokableStmt + && ((InvokableStmt) invokableStmt).containsInvokeExpr() + && ((InvokableStmt) invokableStmt) + .getInvokeExpr() + .get() + .getMethodSignature() + .equals(staticTargetMethod)) { + if (currentIndex == index) { return (InvokableStmt) invokableStmt; } currentIndex++; @@ -153,8 +161,14 @@ public void testRecursiveCall() { // 2 methods + Object::clinit assertEquals(3, cg.getMethodSignatures().size()); - assertTrue(cg.containsCall(mainMethodSignature, mainMethodSignature,getInvokableStmt(mainMethodSignature,mainMethodSignature))); - assertTrue(cg.containsCall(mainMethodSignature, method,getInvokableStmt(mainMethodSignature,method))); + assertTrue( + cg.containsCall( + mainMethodSignature, + mainMethodSignature, + getInvokableStmt(mainMethodSignature, mainMethodSignature))); + assertTrue( + cg.containsCall( + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, method))); // 2 calls +1 clinit calls assertEquals(3, cg.callsFrom(mainMethodSignature).size()); } @@ -165,7 +179,11 @@ public void testConcreteCall() { MethodSignature targetMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("cvc.Class"), "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod,getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -177,7 +195,11 @@ public void testConcreteCallInSuperClass() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -195,8 +217,16 @@ public void testConcreteCallDifferentDefaultMethodInSubClass() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, interfaceMethod, getInvokableStmt(mainMethodSignature,interfaceMethod))); - assertTrue(cg.containsCall(mainMethodSignature, subInterfaceMethod,getInvokableStmt(mainMethodSignature,subInterfaceMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + interfaceMethod, + getInvokableStmt(mainMethodSignature, interfaceMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + subInterfaceMethod, + getInvokableStmt(mainMethodSignature, subInterfaceMethod))); } @Test @@ -208,7 +238,11 @@ public void testConcreteCallInSuperClassWithDefaultInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -220,7 +254,11 @@ public void testConcreteCallInInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -232,7 +270,11 @@ public void testConcreteCallInSubInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -244,7 +286,11 @@ public void testConcreteCallInSuperClassSubInterface() { "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -256,7 +302,11 @@ public void testClinitCallEntryPoint() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -271,7 +321,8 @@ public void testClinitCallProcessed() { MethodSignature targetMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccp.Class"), "method", "int", Collections.emptyList()); - assertTrue(cg.containsCall(sourceMethod, targetMethod, getInvokableStmt(sourceMethod,targetMethod))); + assertTrue( + cg.containsCall(sourceMethod, targetMethod, getInvokableStmt(sourceMethod, targetMethod))); } @Test @@ -283,28 +334,42 @@ public void testClinitCallConstructor() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); MethodSignature arrayMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayType"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, arrayMethod, getInvokableStmt(mainMethodSignature,arrayMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, arrayMethod, getInvokableStmt(mainMethodSignature, arrayMethod))); MethodSignature arrayDimMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayDimType"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, arrayDimMethod, getInvokableStmt(mainMethodSignature,arrayDimMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + arrayDimMethod, + getInvokableStmt(mainMethodSignature, arrayDimMethod))); MethodSignature arrayInArrayMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayInArrayType"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, arrayInArrayMethod, getInvokableStmt(mainMethodSignature,arrayInArrayMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + arrayInArrayMethod, + getInvokableStmt(mainMethodSignature, arrayInArrayMethod))); } @Test @@ -316,14 +381,22 @@ public void testClinitCallSuperConstructor() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); MethodSignature targetMethod2 = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccsc.SuperClinit"), "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod2, getInvokableStmt(mainMethodSignature,targetMethod2))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod2, + getInvokableStmt(mainMethodSignature, targetMethod2))); } @Test @@ -335,7 +408,11 @@ public void testClinitStaticMethodCall() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -347,7 +424,11 @@ public void testClinitStaticField() { "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -356,7 +437,11 @@ public void testNonVirtualCall1() { MethodSignature targetMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -365,7 +450,11 @@ public void testNonVirtualCall2() { MethodSignature targetMethod = identifierFactory.getMethodSignature( mainClassSignature, "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -377,7 +466,11 @@ public void testNonVirtualCall3() { MethodSignature uncalledMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.singletonList("int")); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); assertFalse(cg.containsMethod(uncalledMethod)); } @@ -387,7 +480,9 @@ public void testNonVirtualCall4() { MethodSignature firstMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, firstMethod, getInvokableStmt(mainMethodSignature,firstMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, firstMethod, getInvokableStmt(mainMethodSignature, firstMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( @@ -395,7 +490,8 @@ public void testNonVirtualCall4() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(firstMethod, targetMethod, getInvokableStmt(firstMethod,targetMethod))); + assertTrue( + cg.containsCall(firstMethod, targetMethod, getInvokableStmt(firstMethod, targetMethod))); } @Test @@ -405,7 +501,9 @@ public void testNonVirtualCall5() { MethodSignature firstMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("nvc5.Sub"), "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, firstMethod, getInvokableStmt(mainMethodSignature,firstMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, firstMethod, getInvokableStmt(mainMethodSignature, firstMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( @@ -413,7 +511,8 @@ public void testNonVirtualCall5() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(firstMethod, targetMethod, getInvokableStmt(firstMethod,targetMethod))); + assertTrue( + cg.containsCall(firstMethod, targetMethod, getInvokableStmt(firstMethod, targetMethod))); } @Test @@ -423,7 +522,11 @@ public void testVirtualCall1() { MethodSignature targetMethod = identifierFactory.getMethodSignature( mainClassSignature, "target", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, targetMethod, getInvokableStmt(mainMethodSignature,targetMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + targetMethod, + getInvokableStmt(mainMethodSignature, targetMethod))); } @Test @@ -434,17 +537,24 @@ public void testVirtualCall2() { MethodSignature constructorMethod = identifierFactory.getMethodSignature( subClassSig, "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, constructorMethod, getInvokableStmt(mainMethodSignature,constructorMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorMethod, + getInvokableStmt(mainMethodSignature, constructorMethod))); MethodSignature callMethod = identifierFactory.getMethodSignature( mainClassSignature, "callMethod", "void", Collections.singletonList("vc2.Class")); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( subClassSig, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(callMethod, targetMethod, getInvokableStmt(callMethod,targetMethod))); + assertTrue( + cg.containsCall(callMethod, targetMethod, getInvokableStmt(callMethod, targetMethod))); } @Test @@ -455,7 +565,11 @@ public void testVirtualCall3() { MethodSignature constructorMethod = identifierFactory.getMethodSignature( subClassSig, "", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, constructorMethod, getInvokableStmt(mainMethodSignature,constructorMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorMethod, + getInvokableStmt(mainMethodSignature, constructorMethod))); MethodSignature callMethod = identifierFactory.getMethodSignature( @@ -463,12 +577,15 @@ public void testVirtualCall3() { "callOnInterface", "void", Collections.singletonList("vc3.Interface")); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); MethodSignature targetMethod = identifierFactory.getMethodSignature( subClassSig, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(callMethod, targetMethod,getInvokableStmt(callMethod,targetMethod))); + assertTrue( + cg.containsCall(callMethod, targetMethod, getInvokableStmt(callMethod, targetMethod))); } @Test @@ -479,7 +596,9 @@ public void testVirtualCall4() { MethodSignature callMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("vc4.Class"), "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); } @Test @@ -497,8 +616,14 @@ public void testDynamicInterfaceMethod0() { "method", "void", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, interfaceMethod, getInvokableStmt(mainMethodSignature,interfaceMethod))); - assertTrue(cg.containsCall(mainMethodSignature, classMethod, getInvokableStmt(mainMethodSignature,classMethod))); + assertFalse( + cg.containsCall( + mainMethodSignature, + interfaceMethod, + getInvokableStmt(mainMethodSignature, interfaceMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, classMethod, getInvokableStmt(mainMethodSignature, classMethod))); } @Test @@ -510,7 +635,9 @@ public void testDynamicInterfaceMethod1() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); } @Test @@ -523,7 +650,9 @@ public void testDynamicInterfaceMethod2() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); } @Test @@ -533,7 +662,9 @@ public void testDynamicInterfaceMethod3() { MethodSignature callMethod = identifierFactory.getMethodSignature( mainClassSignature, "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); } @Test @@ -546,7 +677,9 @@ public void testDynamicInterfaceMethod4() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature,callMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); } @Test @@ -559,12 +692,16 @@ public void testDynamicInterfaceMethod5() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,method))); + assertTrue( + cg.containsCall( + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, method))); MethodSignature compute = identifierFactory.getMethodSignature( mainClassSignature, "compute", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, compute, getInvokableStmt(mainMethodSignature,compute))); + assertTrue( + cg.containsCall( + mainMethodSignature, compute, getInvokableStmt(mainMethodSignature, compute))); } @Test @@ -577,7 +714,11 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, combinedInterfaceMethod, getInvokableStmt(mainMethodSignature,combinedInterfaceMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + combinedInterfaceMethod, + getInvokableStmt(mainMethodSignature, combinedInterfaceMethod))); MethodSignature method = identifierFactory.getMethodSignature( @@ -585,7 +726,9 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(combinedInterfaceMethod, method, getInvokableStmt(combinedInterfaceMethod,method))); + assertTrue( + cg.containsCall( + combinedInterfaceMethod, method, getInvokableStmt(combinedInterfaceMethod, method))); MethodSignature anotherMethod = identifierFactory.getMethodSignature( @@ -593,7 +736,11 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(combinedInterfaceMethod, anotherMethod, getInvokableStmt(combinedInterfaceMethod,anotherMethod))); + assertTrue( + cg.containsCall( + combinedInterfaceMethod, + anotherMethod, + getInvokableStmt(combinedInterfaceMethod, anotherMethod))); } @Test @@ -607,7 +754,9 @@ public void testStaticInterfaceMethod() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,method))); + assertTrue( + cg.containsCall( + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, method))); } @Test @@ -625,8 +774,14 @@ public void testAbstractMethod() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,abstractMethod))); - assertFalse(cg.containsCall(mainMethodSignature, abstractMethod, getInvokableStmt(mainMethodSignature,abstractMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, abstractMethod))); + assertFalse( + cg.containsCall( + mainMethodSignature, + abstractMethod, + getInvokableStmt(mainMethodSignature, abstractMethod))); } @Test @@ -650,14 +805,28 @@ public void testAbstractMethodInSubClass() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,abstractMethod))); - assertFalse(cg.containsCall(mainMethodSignature, abstractMethod, getInvokableStmt(mainMethodSignature,superMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, abstractMethod))); + assertFalse( + cg.containsCall( + mainMethodSignature, + abstractMethod, + getInvokableStmt(mainMethodSignature, superMethod))); if (this instanceof ClassHierarchyAnalysisAlgorithmTest) { - assertTrue(cg.containsCall(mainMethodSignature, superMethod, getInvokableStmt(mainMethodSignature,superMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + superMethod, + getInvokableStmt(mainMethodSignature, superMethod))); } if (this instanceof RapidTypeAnalysisAlgorithmTest) { - assertFalse(cg.containsCall(mainMethodSignature, superMethod, getInvokableStmt(mainMethodSignature,superMethod) )); + assertFalse( + cg.containsCall( + mainMethodSignature, + superMethod, + getInvokableStmt(mainMethodSignature, superMethod))); } } @@ -676,8 +845,14 @@ public void testAbstractMethodMissingMethodInSuperclass() { "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, method, getInvokableStmt(mainMethodSignature,abstractMethod))); - assertFalse(cg.containsCall(mainMethodSignature, abstractMethod, getInvokableStmt(mainMethodSignature,abstractMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, abstractMethod))); + assertFalse( + cg.containsCall( + mainMethodSignature, + abstractMethod, + getInvokableStmt(mainMethodSignature, abstractMethod))); } @Test diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java index 37dbbd2c105..8c4a3db9ed6 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java @@ -148,25 +148,69 @@ public void testMiscExample1() { "void", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, constructorA, getInvokableStmt(mainMethodSignature, constructorA))); - assertTrue(cg.containsCall(mainMethodSignature, constructorB, getInvokableStmt(mainMethodSignature, constructorB))); - assertTrue(cg.containsCall(mainMethodSignature, constructorC, getInvokableStmt(mainMethodSignature, constructorC))); - assertFalse(cg.containsCall(mainMethodSignature, constructorD, getInvokableStmt(mainMethodSignature, constructorD))); - assertTrue(cg.containsCall(mainMethodSignature, constructorE, getInvokableStmt(mainMethodSignature, constructorE))); + assertFalse( + cg.containsCall( + mainMethodSignature, + constructorA, + getInvokableStmt(mainMethodSignature, constructorA))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorB, + getInvokableStmt(mainMethodSignature, constructorB))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorC, + getInvokableStmt(mainMethodSignature, constructorC))); + assertFalse( + cg.containsCall( + mainMethodSignature, + constructorD, + getInvokableStmt(mainMethodSignature, constructorD))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorE, + getInvokableStmt(mainMethodSignature, constructorE))); assertFalse(cg.containsMethod(staticMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, staticMethodB,getInvokableStmt(mainMethodSignature, staticMethodB))); + assertTrue( + cg.containsCall( + mainMethodSignature, + staticMethodB, + getInvokableStmt(mainMethodSignature, staticMethodB))); assertFalse(cg.containsMethod(staticMethodC)); assertFalse(cg.containsMethod(staticMethodD)); assertFalse(cg.containsMethod(staticMethodE)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodA, getInvokableStmt(mainMethodSignature, virtualMethodA))); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodB, getInvokableStmt(mainMethodSignature, virtualMethodB))); + assertTrue( + cg.containsCall( + mainMethodSignature, + virtualMethodA, + getInvokableStmt(mainMethodSignature, virtualMethodA))); + assertTrue( + cg.containsCall( + mainMethodSignature, + virtualMethodB, + getInvokableStmt(mainMethodSignature, virtualMethodB))); assertFalse(cg.containsMethod(virtualMethodC)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodD, getInvokableStmt(mainMethodSignature, virtualMethodD))); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodE, getInvokableStmt(mainMethodSignature, virtualMethodE))); + assertTrue( + cg.containsCall( + mainMethodSignature, + virtualMethodD, + getInvokableStmt(mainMethodSignature, virtualMethodD))); + assertTrue( + cg.containsCall( + mainMethodSignature, + virtualMethodE, + getInvokableStmt(mainMethodSignature, virtualMethodE))); - assertTrue(cg.containsCall(mainMethodSignature, clinitObject, getInvokableStmt(mainMethodSignature, clinitObject))); + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmt(mainMethodSignature, clinitObject))); assertEquals(9, cg.callsFrom(mainMethodSignature).size()); diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java index 2dad97dbd0c..d4f2fa1223e 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java @@ -142,25 +142,55 @@ public void testMiscExample1() { "void", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, constructorA,getInvokableStmt(mainMethodSignature,constructorA))); - assertTrue(cg.containsCall(mainMethodSignature, constructorB,getInvokableStmt(mainMethodSignature,constructorB))); - assertTrue(cg.containsCall(mainMethodSignature, constructorC,getInvokableStmt(mainMethodSignature,constructorC))); - assertFalse(cg.containsCall(mainMethodSignature, constructorD,getInvokableStmt(mainMethodSignature,constructorD))); - assertTrue(cg.containsCall(mainMethodSignature, constructorE,getInvokableStmt(mainMethodSignature,constructorE))); + assertFalse( + cg.containsCall( + mainMethodSignature, + constructorA, + getInvokableStmt(mainMethodSignature, constructorA))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorB, + getInvokableStmt(mainMethodSignature, constructorB))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorC, + getInvokableStmt(mainMethodSignature, constructorC))); + assertFalse( + cg.containsCall( + mainMethodSignature, + constructorD, + getInvokableStmt(mainMethodSignature, constructorD))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorE, + getInvokableStmt(mainMethodSignature, constructorE))); assertFalse(cg.containsMethod(staticMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, staticMethodB,getInvokableStmt(staticMethodB,staticMethodB))); + assertTrue( + cg.containsCall( + mainMethodSignature, staticMethodB, getInvokableStmt(staticMethodB, staticMethodB))); assertFalse(cg.containsMethod(staticMethodC)); assertFalse(cg.containsMethod(staticMethodD)); assertFalse(cg.containsMethod(staticMethodE)); assertFalse(cg.containsMethod(virtualMethodA)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodB,getInvokableStmt(virtualMethodB,virtualMethodB))); + assertTrue( + cg.containsCall( + mainMethodSignature, virtualMethodB, getInvokableStmt(virtualMethodB, virtualMethodB))); assertFalse(cg.containsMethod(virtualMethodC)); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodD,getInvokableStmt(virtualMethodD,virtualMethodD))); - assertTrue(cg.containsCall(mainMethodSignature, virtualMethodE,getInvokableStmt(virtualMethodE,virtualMethodE))); + assertTrue( + cg.containsCall( + mainMethodSignature, virtualMethodD, getInvokableStmt(virtualMethodD, virtualMethodD))); + assertTrue( + cg.containsCall( + mainMethodSignature, virtualMethodE, getInvokableStmt(virtualMethodE, virtualMethodE))); - assertTrue(cg.containsCall(mainMethodSignature, clinitObject,getInvokableStmt(clinitObject,clinitObject))); + assertTrue( + cg.containsCall( + mainMethodSignature, clinitObject, getInvokableStmt(clinitObject, clinitObject))); assertEquals(8, cg.callsFrom(mainMethodSignature).size()); @@ -251,9 +281,15 @@ public void testRevisitMethod() { "int", Collections.emptyList()); - assertFalse(cg.containsCall(alreadyVisitedMethod, newTargetA,getInvokableStmt(alreadyVisitedMethod, newTargetA))); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetB,getInvokableStmt(alreadyVisitedMethod, newTargetB))); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetC,getInvokableStmt(alreadyVisitedMethod, newTargetC))); + assertFalse( + cg.containsCall( + alreadyVisitedMethod, newTargetA, getInvokableStmt(alreadyVisitedMethod, newTargetA))); + assertTrue( + cg.containsCall( + alreadyVisitedMethod, newTargetB, getInvokableStmt(alreadyVisitedMethod, newTargetB))); + assertTrue( + cg.containsCall( + alreadyVisitedMethod, newTargetC, getInvokableStmt(alreadyVisitedMethod, newTargetC))); } @Test @@ -287,9 +323,15 @@ public void testRecursiveRevisitMethod() { "int", Collections.emptyList()); - assertFalse(cg.containsCall(alreadyVisitedMethod, newTargetA,getInvokableStmt(alreadyVisitedMethod, newTargetA))); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetB,getInvokableStmt(alreadyVisitedMethod, newTargetB))); - assertTrue(cg.containsCall(alreadyVisitedMethod, newTargetC,getInvokableStmt(alreadyVisitedMethod, newTargetC))); + assertFalse( + cg.containsCall( + alreadyVisitedMethod, newTargetA, getInvokableStmt(alreadyVisitedMethod, newTargetA))); + assertTrue( + cg.containsCall( + alreadyVisitedMethod, newTargetB, getInvokableStmt(alreadyVisitedMethod, newTargetB))); + assertTrue( + cg.containsCall( + alreadyVisitedMethod, newTargetC, getInvokableStmt(alreadyVisitedMethod, newTargetC))); } @Test @@ -308,8 +350,16 @@ public void testInstantiatedClassInClinit() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, instantiatedClassMethod,getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); - assertFalse(cg.containsCall(mainMethodSignature, nonInstantiatedClassMethod,getInvokableStmt(mainMethodSignature, nonInstantiatedClassMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + instantiatedClassMethod, + getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); + assertFalse( + cg.containsCall( + mainMethodSignature, + nonInstantiatedClassMethod, + getInvokableStmt(mainMethodSignature, nonInstantiatedClassMethod))); } @Test @@ -321,6 +371,10 @@ public void testLaterInstantiatedClass() { "method", "void", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, instantiatedClassMethod,getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); + assertTrue( + cg.containsCall( + mainMethodSignature, + instantiatedClassMethod, + getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java index aee13ffbd63..f5f4619663a 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java @@ -28,7 +28,6 @@ import sootup.core.jimple.basic.LValue; import sootup.core.jimple.basic.StmtPositionInfo; import sootup.core.jimple.basic.Value; -import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.ref.JArrayRef; import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.visitor.ReplaceUseStmtVisitor; diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java index 9a16bbde7c4..e4b6f68ce3e 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java @@ -22,34 +22,34 @@ * #L% */ -import java.util.List; import java.util.Optional; import sootup.core.jimple.common.expr.AbstractInvokeExpr; -import sootup.core.model.Body; /** - * Interface for Stmts that could invoke a different method which will be executed before the - * next statement is executed - * + * Interface for Stmts that could invoke a different method which will be executed before the next + * statement is executed */ public interface InvokableStmt extends Stmt { - /** Checks if the invokable statement actually invokes + /** + * Checks if the invokable statement actually invokes * * @return true if the statement invokes something, and false if not. */ boolean doesInvoke(); - /** Checks if the invokable statement contains a invoke expression that defines the invoke. + /** + * Checks if the invokable statement contains a invoke expression that defines the invoke. * * @return true if the statement contains an invoke expression, false if not */ boolean containsInvokeExpr(); - /** Returns the possible invoke expression in the invokable statement + /** + * Returns the possible invoke expression in the invokable statement * - * @return The optional contains the invoke expression of the invokable statement - * or is empty if there is no invoke expression. + * @return The optional contains the invoke expression of the invokable statement or is empty if + * there is no invoke expression. */ Optional getInvokeExpr(); } diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index a84fee36049..bd2fe62e1b0 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -58,7 +58,8 @@ import sootup.core.util.printer.StmtPrinter; /** Represents the assignment of one value to another */ -public final class JAssignStmt extends AbstractDefinitionStmt implements FallsThroughStmt, InvokableStmt { +public final class JAssignStmt extends AbstractDefinitionStmt + implements FallsThroughStmt, InvokableStmt { @Nonnull final LValue leftOp; @Nonnull final Value rightOp; @@ -103,18 +104,18 @@ public boolean containsInvokeExpr() { return getRightOp() instanceof AbstractInvokeExpr; } - /** Checks if the assignment statement invokes a method call + /** + * Checks if the assignment statement invokes a method call * - * @return it is true if the assignment statement contains an invoke expression or if the left or right operand is a static field + * @return it is true if the assignment statement contains an invoke expression or if the left or + * right operand is a static field */ @Override public boolean doesInvoke() { - if (containsInvokeExpr()) - return true; + if (containsInvokeExpr()) return true; return getRightOp() instanceof JStaticFieldRef || getLeftOp() instanceof JStaticFieldRef; } - /* * (non-Javadoc) * diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java index 27d7404ec2f..eabbd8cf026 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java @@ -32,7 +32,7 @@ import sootup.core.util.printer.StmtPrinter; /** A method call */ -public final class JInvokeStmt extends AbstractStmt implements FallsThroughStmt,InvokableStmt { +public final class JInvokeStmt extends AbstractStmt implements FallsThroughStmt, InvokableStmt { @Nonnull private final AbstractInvokeExpr invokeExpr; diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java index 6a0761c78a2..597aa4855a3 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java @@ -27,7 +27,6 @@ import sootup.core.jimple.basic.LValue; import sootup.core.jimple.basic.StmtPositionInfo; import sootup.core.jimple.basic.Value; -import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.ref.JArrayRef; import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.visitor.Acceptor; diff --git a/sootup.core/src/main/java/sootup/core/validation/NewValidator.java b/sootup.core/src/main/java/sootup/core/validation/NewValidator.java index 896712818eb..95c3c7024aa 100644 --- a/sootup.core/src/main/java/sootup/core/validation/NewValidator.java +++ b/sootup.core/src/main/java/sootup/core/validation/NewValidator.java @@ -97,8 +97,8 @@ private boolean checkForInitializerOnPath( continue; } if (!newStmt.equals(curStmt)) { - if (((InvokableStmt)curStmt).containsInvokeExpr()) { - AbstractInvokeExpr expr = ((InvokableStmt)curStmt).getInvokeExpr().get(); + if (((InvokableStmt) curStmt).containsInvokeExpr()) { + AbstractInvokeExpr expr = ((InvokableStmt) curStmt).getInvokeExpr().get(); if (!(expr instanceof JSpecialInvokeExpr)) { exception.add( new ValidationException( diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java index c134581e0b8..b2b4d02090f 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java @@ -1,17 +1,12 @@ package sootup.core.jimple.common.stmt; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import sootup.core.jimple.basic.Local; -import sootup.core.jimple.basic.SimpleStmtPositionInfo; -import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; -import sootup.core.jimple.common.expr.JSpecialInvokeExpr; -import sootup.core.jimple.common.expr.JStaticInvokeExpr; -import sootup.core.jimple.common.expr.JVirtualInvokeExpr; import sootup.core.jimple.common.ref.JInstanceFieldRef; import sootup.core.jimple.common.ref.JStaticFieldRef; import sootup.util.AssignStmtUtil; @@ -29,15 +24,16 @@ public void testDoesInvoke() { Local local = LocalUtil.createDummyLocalForInt(); assertTrue(AssignStmtUtil.createDummyAssignStmtWithExpr().doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,local).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(local,staticFieldRef).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,staticFieldRef).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,staticFieldRef).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,instanceFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef).doesInvoke()); + assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef).doesInvoke()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,local).doesInvoke()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local,instanceFieldRef).doesInvoke()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,instanceFieldRef).doesInvoke()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).doesInvoke()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).doesInvoke()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef).doesInvoke()); assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().doesInvoke()); } @@ -49,14 +45,21 @@ public void testContainsInvokeExpr() { assertTrue(AssignStmtUtil.createDummyAssignStmtWithExpr().containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,local).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local,staticFieldRef).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,staticFieldRef).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,staticFieldRef).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,instanceFieldRef).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,local).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local,instanceFieldRef).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,instanceFieldRef).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).containsInvokeExpr()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).containsInvokeExpr()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) + .containsInvokeExpr()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) + .containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).containsInvokeExpr()); + assertFalse(AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).containsInvokeExpr()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) + .containsInvokeExpr()); assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().containsInvokeExpr()); } @@ -66,17 +69,34 @@ public void testGetInvokeExpr() { JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); Local local = LocalUtil.createDummyLocalForInt(); - assertEquals(InvokeExprUtil.createDummyStaticInvokeExpr(),AssignStmtUtil.createDummyAssignStmtWithExpr().getInvokeExpr()); + assertEquals( + InvokeExprUtil.createDummyStaticInvokeExpr(), + AssignStmtUtil.createDummyAssignStmtWithExpr().getInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,local).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local,staticFieldRef).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,staticFieldRef).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,staticFieldRef).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef,instanceFieldRef).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,local).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local,instanceFieldRef).getInvokeExpr().isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef,instanceFieldRef).getInvokeExpr().isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).getInvokeExpr().isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).getInvokeExpr().isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef) + .getInvokeExpr() + .isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) + .getInvokeExpr() + .isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) + .getInvokeExpr() + .isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).getInvokeExpr().isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).getInvokeExpr().isPresent()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) + .getInvokeExpr() + .isPresent()); assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().getInvokeExpr().isPresent()); } - } diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java index 63ea1b7f28c..49c8ef19b3a 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java @@ -1,38 +1,34 @@ package sootup.core.jimple.common.stmt; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import sootup.core.jimple.basic.SimpleStmtPositionInfo; -import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.expr.JVirtualInvokeExpr; import sootup.util.InvokeExprUtil; - @Tag("Java8") public class JInvokeStmtTest { - - @Test public void testContainsInvokeExpr() { - SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); + SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); - JInvokeStmt invokeStmt = new JInvokeStmt(InvokeExprUtil.createDummyStaticInvokeExpr(),pos); - assertTrue(invokeStmt.containsInvokeExpr()); + JInvokeStmt invokeStmt = new JInvokeStmt(InvokeExprUtil.createDummyStaticInvokeExpr(), pos); + assertTrue(invokeStmt.containsInvokeExpr()); - JInvokeStmt invokeStmt1 = new JInvokeStmt(InvokeExprUtil.createDummyInterfaceInvokeExpr(),pos); + JInvokeStmt invokeStmt1 = new JInvokeStmt(InvokeExprUtil.createDummyInterfaceInvokeExpr(), pos); assertTrue(invokeStmt1.containsInvokeExpr()); - JInvokeStmt invokeStmt2 = new JInvokeStmt(InvokeExprUtil.createDummySpecialInvokeExpr(),pos); + JInvokeStmt invokeStmt2 = new JInvokeStmt(InvokeExprUtil.createDummySpecialInvokeExpr(), pos); assertTrue(invokeStmt2.containsInvokeExpr()); - JInvokeStmt invokeStmt3 = new JInvokeStmt(InvokeExprUtil.createDummyVirtualInvokeExpr(),pos); + JInvokeStmt invokeStmt3 = new JInvokeStmt(InvokeExprUtil.createDummyVirtualInvokeExpr(), pos); assertTrue(invokeStmt3.containsInvokeExpr()); } @@ -41,20 +37,19 @@ public void testGetInvokeExpr() { SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); JStaticInvokeExpr staticExpr = InvokeExprUtil.createDummyStaticInvokeExpr(); - JInvokeStmt invokeStmt = new JInvokeStmt(staticExpr,pos); - assertEquals(staticExpr,invokeStmt.getInvokeExpr()); + JInvokeStmt invokeStmt = new JInvokeStmt(staticExpr, pos); + assertEquals(staticExpr, invokeStmt.getInvokeExpr()); JVirtualInvokeExpr virtualExpr = InvokeExprUtil.createDummyVirtualInvokeExpr(); - JInvokeStmt invokeStmt1 = new JInvokeStmt(virtualExpr,pos); - assertEquals(virtualExpr,invokeStmt1.getInvokeExpr()); + JInvokeStmt invokeStmt1 = new JInvokeStmt(virtualExpr, pos); + assertEquals(virtualExpr, invokeStmt1.getInvokeExpr()); JSpecialInvokeExpr specialExpr = InvokeExprUtil.createDummySpecialInvokeExpr(); - JInvokeStmt invokeStmt2 = new JInvokeStmt(specialExpr,pos); - assertEquals(specialExpr,invokeStmt2.getInvokeExpr()); + JInvokeStmt invokeStmt2 = new JInvokeStmt(specialExpr, pos); + assertEquals(specialExpr, invokeStmt2.getInvokeExpr()); JInterfaceInvokeExpr interfaceExpr = InvokeExprUtil.createDummyInterfaceInvokeExpr(); - JInvokeStmt invokeStmt3 = new JInvokeStmt(staticExpr,pos); - assertEquals(interfaceExpr,invokeStmt3.getInvokeExpr()); + JInvokeStmt invokeStmt3 = new JInvokeStmt(staticExpr, pos); + assertEquals(interfaceExpr, invokeStmt3.getInvokeExpr()); } - } diff --git a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java index 0963e92edd7..9de334dd258 100644 --- a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java +++ b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java @@ -1,82 +1,65 @@ package sootup.util; -import java.util.Collections; import sootup.core.jimple.basic.LValue; import sootup.core.jimple.basic.Local; import sootup.core.jimple.basic.SimpleStmtPositionInfo; import sootup.core.jimple.basic.Value; -import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; -import sootup.core.jimple.common.expr.JSpecialInvokeExpr; -import sootup.core.jimple.common.expr.JStaticInvokeExpr; -import sootup.core.jimple.common.expr.JVirtualInvokeExpr; import sootup.core.jimple.common.ref.JFieldRef; -import sootup.core.jimple.common.ref.JStaticFieldRef; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.JAssignStmtTest; -import sootup.core.signatures.MethodSignature; -import sootup.core.signatures.MethodSubSignature; -import sootup.core.signatures.PackageName; -import sootup.core.types.ClassType; import sootup.core.types.PrimitiveType.IntType; public class AssignStmtUtil { - - - private static Local createDummyLocal(){ + private static Local createDummyLocal() { return new Local("a", IntType.getInstance()); } - /** will return a dummy assignment statement with an invoke expression - * the left value will be the dummy int local - * the right value will be the dummy static invoke expression - * stmt position is the dummy SimpleStatementPositionInfo + /** + * will return a dummy assignment statement with an invoke expression the left value will be the + * dummy int local the right value will be the dummy static invoke expression stmt position is the + * dummy SimpleStatementPositionInfo * * @return a dummy JAssignStmt with a static invoke expression */ public static JAssignStmt createDummyAssignStmtWithExpr() { Local local = LocalUtil.createDummyLocalForInt(); SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(local,InvokeExprUtil.createDummyStaticInvokeExpr(),pos); + return new JAssignStmt(local, InvokeExprUtil.createDummyStaticInvokeExpr(), pos); } - /** will return a dummy assignment statement - * the left value will be the dummy static field ref - * the right value will be the dummy local - * stmt position is the dummy SimpleStatementPositionInfo + /** + * will return a dummy assignment statement the left value will be the dummy static field ref the + * right value will be the dummy local stmt position is the dummy SimpleStatementPositionInfo * * @return a dummy JAssignStmt with a static field ref on the left side */ public static JAssignStmt createDummyAssignStmtWithStaticFieldRefLeft() { JFieldRef fieldRef = FieldRefUtil.createDummyStaticFieldRef(); SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(fieldRef,LocalUtil.createDummyLocalForInt(),pos); + return new JAssignStmt(fieldRef, LocalUtil.createDummyLocalForInt(), pos); } - /** will return a dummy assignment statement - * stmt position is the dummy SimpleStatementPositionInfo + /** + * will return a dummy assignment statement stmt position is the dummy SimpleStatementPositionInfo * * @param left defines the left value of the dummy assign statement * @param right defines the right value of the dummy assign statement - * * @return a dummy JAssignStmt with an instance field ref on the left side */ public static JAssignStmt createDummyAssignStmt(LValue left, Value right) { SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(left,right,pos); + return new JAssignStmt(left, right, pos); } - - /** will return a dummy assignment statement - * the right value will be the dummy local - * the left value will be the dummy local - * stmt position is the dummy SimpleStatementPositionInfo + /** + * will return a dummy assignment statement the right value will be the dummy local the left value + * will be the dummy local stmt position is the dummy SimpleStatementPositionInfo * * @return a dummy JAssignStmt with a static field ref on the left side */ public static JAssignStmt createDummyAssignStmtWithLocals() { SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(LocalUtil.createDummyLocalForInt(),LocalUtil.createDummyLocalForInt(),pos); + return new JAssignStmt( + LocalUtil.createDummyLocalForInt(), LocalUtil.createDummyLocalForInt(), pos); } - } diff --git a/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java b/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java index f57b1be1de4..8aa7e3934c5 100644 --- a/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java +++ b/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java @@ -5,14 +5,12 @@ public class ClassTypeUtil { - /**creates a dummy Class type - * Classname Test - * Package name test - * Fully Qualified Name test.Test + /** + * creates a dummy Class type Classname Test Package name test Fully Qualified Name test.Test * * @return a dummy class type */ - public static ClassType createDummyClassType(){ + public static ClassType createDummyClassType() { return new ClassType() { @Override public boolean isBuiltInClass() { @@ -35,5 +33,4 @@ public PackageName getPackageName() { } }; } - } diff --git a/sootup.core/src/test/java/sootup/util/FieldRefUtil.java b/sootup.core/src/test/java/sootup/util/FieldRefUtil.java index 35f22ef6231..ae326337189 100644 --- a/sootup.core/src/test/java/sootup/util/FieldRefUtil.java +++ b/sootup.core/src/test/java/sootup/util/FieldRefUtil.java @@ -1,29 +1,26 @@ package sootup.util; -import sootup.core.jimple.basic.Local; import sootup.core.jimple.common.ref.JInstanceFieldRef; import sootup.core.jimple.common.ref.JStaticFieldRef; -import sootup.core.types.PrimitiveType.IntType; public class FieldRefUtil { - /**creates a dummy static field reference - * Signature: dummy Field Signature + /** + * creates a dummy static field reference Signature: dummy Field Signature * * @return a dummy JStaticFieldRef */ - public static JStaticFieldRef createDummyStaticFieldRef(){ - return new JStaticFieldRef( SignatureUtil.createDummyFieldSignature()); + public static JStaticFieldRef createDummyStaticFieldRef() { + return new JStaticFieldRef(SignatureUtil.createDummyFieldSignature()); } - /**creates a dummy instance field reference - * local: dummy local - * Signature: dummy Field Signature + /** + * creates a dummy instance field reference local: dummy local Signature: dummy Field Signature * * @return a dummy JInstanceFieldRef */ - public static JInstanceFieldRef createDummyInstanceFieldRef(){ - return new JInstanceFieldRef(LocalUtil.createDummyLocalForInt(), SignatureUtil.createDummyFieldSignature()); + public static JInstanceFieldRef createDummyInstanceFieldRef() { + return new JInstanceFieldRef( + LocalUtil.createDummyLocalForInt(), SignatureUtil.createDummyFieldSignature()); } - } diff --git a/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java b/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java index a22aaf4f399..642f5ad4778 100644 --- a/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java +++ b/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java @@ -10,46 +10,42 @@ public class InvokeExprUtil { - /** will return a dummy virtual invoke expression - * local is called a and has the class type Test - * method signature is <Test: int test ()> - * arguments is an empty list + /** + * will return a dummy virtual invoke expression local is called a and has the class type Test + * method signature is <Test: int test ()> arguments is an empty list */ public static JVirtualInvokeExpr createDummyVirtualInvokeExpr() { Local local = LocalUtil.createDummyLocalForObject(); MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JVirtualInvokeExpr(local,methodSignature,Collections.emptyList()); + return new JVirtualInvokeExpr(local, methodSignature, Collections.emptyList()); } - /** will return a dummy special invoke expression - * local is called a and has the class type Test - * method signature is <Test: int test ()> - * arguments is an empty list + /** + * will return a dummy special invoke expression local is called a and has the class type Test + * method signature is <Test: int test ()> arguments is an empty list */ public static JSpecialInvokeExpr createDummySpecialInvokeExpr() { Local local = LocalUtil.createDummyLocalForObject(); MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JSpecialInvokeExpr(local,methodSignature,Collections.emptyList()); + return new JSpecialInvokeExpr(local, methodSignature, Collections.emptyList()); } - /** will return a dummy interface invoke expression - * local is called a and has the class type Test - * method signature is <Test: int test ()> - * arguments is an empty list + /** + * will return a dummy interface invoke expression local is called a and has the class type Test + * method signature is <Test: int test ()> arguments is an empty list */ public static JInterfaceInvokeExpr createDummyInterfaceInvokeExpr() { Local local = LocalUtil.createDummyLocalForObject(); MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JInterfaceInvokeExpr(local,methodSignature,Collections.emptyList()); + return new JInterfaceInvokeExpr(local, methodSignature, Collections.emptyList()); } - /** will return a dummy static invoke expression - * method signature is <Test: int test ()> + /** + * will return a dummy static invoke expression method signature is <Test: int test ()> * arguments is an empty list */ public static JStaticInvokeExpr createDummyStaticInvokeExpr() { MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JStaticInvokeExpr(methodSignature,Collections.emptyList()); + return new JStaticInvokeExpr(methodSignature, Collections.emptyList()); } - } diff --git a/sootup.core/src/test/java/sootup/util/LocalUtil.java b/sootup.core/src/test/java/sootup/util/LocalUtil.java index 15cee621c16..898d9319421 100644 --- a/sootup.core/src/test/java/sootup/util/LocalUtil.java +++ b/sootup.core/src/test/java/sootup/util/LocalUtil.java @@ -5,23 +5,21 @@ public class LocalUtil { - /**creates a dummy Local for an Object - * Name a - * Type dummy class type + /** + * creates a dummy Local for an Object Name a Type dummy class type * * @return a dummy Local for an Object */ - public static Local createDummyLocalForObject(){ + public static Local createDummyLocalForObject() { return new Local("a", ClassTypeUtil.createDummyClassType()); } - /**creates a dummy Local for an Int - * Name b - * Type int + /** + * creates a dummy Local for an Int Name b Type int * * @return a dummy Local for a int value */ - public static Local createDummyLocalForInt(){ + public static Local createDummyLocalForInt() { return new Local("b", IntType.getInstance()); } } diff --git a/sootup.core/src/test/java/sootup/util/SignatureUtil.java b/sootup.core/src/test/java/sootup/util/SignatureUtil.java index 89110fd64fa..70396701f8e 100644 --- a/sootup.core/src/test/java/sootup/util/SignatureUtil.java +++ b/sootup.core/src/test/java/sootup/util/SignatureUtil.java @@ -9,46 +9,42 @@ public class SignatureUtil { - /**creates a dummy method signature - * Class Type: dummy class type - * SubSignature: dummy method sub signature + /** + * creates a dummy method signature Class Type: dummy class type SubSignature: dummy method sub + * signature * * @return a dummy method signature */ - public static MethodSignature createDummyMethodSignature(){ - return new MethodSignature( ClassTypeUtil.createDummyClassType(), createDummyMethodSubSignature()); + public static MethodSignature createDummyMethodSignature() { + return new MethodSignature( + ClassTypeUtil.createDummyClassType(), createDummyMethodSubSignature()); } - /**creates a dummy method sub signature - * name: test - * return type: int - * parameter list: empty + /** + * creates a dummy method sub signature name: test return type: int parameter list: empty * * @return a dummy method sub signature */ - public static MethodSubSignature createDummyMethodSubSignature(){ + public static MethodSubSignature createDummyMethodSubSignature() { return new MethodSubSignature("test", Collections.emptyList(), IntType.getInstance()); } - /**creates a dummy field signature - * Class Type: dummy class type - * SubSignature: dummy field sub signature + /** + * creates a dummy field signature Class Type: dummy class type SubSignature: dummy field sub + * signature * * @return a dummy field signature */ - public static FieldSignature createDummyFieldSignature(){ - return new FieldSignature( ClassTypeUtil.createDummyClassType(), createDummyFieldSubSignature()); + public static FieldSignature createDummyFieldSignature() { + return new FieldSignature(ClassTypeUtil.createDummyClassType(), createDummyFieldSubSignature()); } - /**creates a dummy field sub signature - * name: test - * type: int + /** + * creates a dummy field sub signature name: test type: int * * @return a dummy field sub signature */ - public static FieldSubSignature createDummyFieldSubSignature(){ + public static FieldSubSignature createDummyFieldSubSignature() { return new FieldSubSignature("test", IntType.getInstance()); } - - } diff --git a/sootup.core/src/test/java/sootup/util/StmtPosUtil.java b/sootup.core/src/test/java/sootup/util/StmtPosUtil.java index 4cdf1a1e66a..132d8312c60 100644 --- a/sootup.core/src/test/java/sootup/util/StmtPosUtil.java +++ b/sootup.core/src/test/java/sootup/util/StmtPosUtil.java @@ -1,18 +1,15 @@ package sootup.util; -import sootup.core.jimple.basic.Local; import sootup.core.jimple.basic.SimpleStmtPositionInfo; -import sootup.core.types.PrimitiveType.IntType; public class StmtPosUtil { - /**creates a dummy SimpleStmtPositionInfo - * lineNumber 1 + /** + * creates a dummy SimpleStmtPositionInfo lineNumber 1 * * @return a dummy SimpleStmtPositionInfo */ - public static SimpleStmtPositionInfo createDummySimpleStmtPositionInfo(){ + public static SimpleStmtPositionInfo createDummySimpleStmtPositionInfo() { return new SimpleStmtPositionInfo(1); } - } diff --git a/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java b/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java index 33b0f30e6bf..6f397ef157c 100644 --- a/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java +++ b/sootup.java.core/src/main/java/sootup/java/core/interceptors/CopyPropagator.java @@ -75,7 +75,8 @@ public void interceptBody(@Nonnull Body.BodyBuilder builder, @Nonnull View view) AbstractDefinitionStmt defStmt = (AbstractDefinitionStmt) defsOfUse.get(0); Value rhs = defStmt.getRightOp(); // if rhs is a constant, then replace use, if it is possible - if (rhs instanceof Constant && !((stmt instanceof InvokableStmt) && ((InvokableStmt)stmt).containsInvokeExpr())) { + if (rhs instanceof Constant + && !((stmt instanceof InvokableStmt) && ((InvokableStmt) stmt).containsInvokeExpr())) { replaceUse(stmtGraph, stmt, use, rhs); } From cb74d71f938a6ce94d6d9c5314c54ff692c134c1 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 16:42:22 +0200 Subject: [PATCH 06/41] adapted test to new invokable stmt --- .../bytecode/minimaltestsuite/java14/RecordTest.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java index 675193277c1..93b17696930 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/minimaltestsuite/java14/RecordTest.java @@ -6,13 +6,14 @@ import categories.TestCategories; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import sootup.core.jimple.basic.Immediate; import sootup.core.jimple.common.expr.JDynamicInvokeExpr; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootMethod; import sootup.core.signatures.FieldSignature; import sootup.core.signatures.MethodSignature; @@ -58,8 +59,12 @@ public void test() { assertJimpleStmts(method, expectedBodyStmts()); List dynamicInvokes = method.getBody().getStmts().stream() - .filter(Stmt::containsInvokeExpr) - .map(Stmt::getInvokeExpr) + .filter(stmt -> stmt instanceof InvokableStmt) + .map(stmt -> (InvokableStmt) stmt) + .filter(InvokableStmt::containsInvokeExpr) + .map(InvokableStmt::getInvokeExpr) + .filter(Optional::isPresent) + .map(Optional::get) .filter(abstractInvokeExpr -> abstractInvokeExpr instanceof JDynamicInvokeExpr) .map(abstractInvokeExpr -> (JDynamicInvokeExpr) abstractInvokeExpr) .collect(Collectors.toList()); From ece4097b999f64db3fa8bf4f5fc14977d56d4712 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 16:54:41 +0200 Subject: [PATCH 07/41] fixed compile issues caused by API changes --- .../interprocedural/ifds/CGEdgeUtilTest.java | 10 +- .../ifds/IFDSTaintAnalysisProblem.java | 18 +-- .../examples/basicSetup/BasicSetup.java | 6 +- .../test/java/sootup/tests/CallGraphTest.java | 140 +++++++++++++++--- 4 files changed, 142 insertions(+), 32 deletions(-) diff --git a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java index f2a1a5ff972..9cfc7e09d05 100644 --- a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java +++ b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java @@ -29,6 +29,7 @@ import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.expr.JVirtualInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.jimple.visitor.ExprVisitor; import sootup.core.model.SootClass; @@ -163,7 +164,9 @@ public void testGetCallEdges() { List invokesStmts = m.getBody().getStmts().stream() - .filter(Stmt::containsInvokeExpr) + .filter(stmt -> stmt instanceof InvokableStmt) + .map(stmt -> (InvokableStmt) stmt) + .filter(InvokableStmt::containsInvokeExpr) .collect(Collectors.toList()); assertEquals(invokesStmts.size(), 3); MethodSignature constructorMethodSignature = @@ -222,7 +225,10 @@ private void checkPair( assertNotNull(virtualCall); Stmt virtualStmt = invokesStmts.stream() - .filter(stmt -> stmt.getInvokeExpr().getClass() == invokeClass) + .filter(stmt -> stmt instanceof InvokableStmt) + .map(stmt -> (InvokableStmt) stmt) + .filter(InvokableStmt::containsInvokeExpr) + .filter(stmt -> stmt.getInvokeExpr().get().getClass() == invokeClass) .findAny() .orElse(null); assertNotNull(virtualStmt); diff --git a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java index 4e6ba910147..db42423e082 100644 --- a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java +++ b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java @@ -74,18 +74,18 @@ public FlowFunction getNormalFlowFunction(Stmt curr, Stmt succ) { @Override public FlowFunction getCallFlowFunction(Stmt callStmt, SootMethod destinationMethod) { - return getCallFlow(callStmt, destinationMethod); + return getCallFlow((InvokableStmt) callStmt, destinationMethod); } @Override public FlowFunction getReturnFlowFunction( Stmt callSite, SootMethod calleeMethod, Stmt exitStmt, Stmt returnSite) { - return getReturnFlow(callSite, calleeMethod, exitStmt, returnSite); + return getReturnFlow((InvokableStmt) callSite, calleeMethod, exitStmt, returnSite); } @Override public FlowFunction getCallToReturnFlowFunction(Stmt callSite, Stmt returnSite) { - return getCallToReturnFlow(callSite, returnSite); + return getCallToReturnFlow((InvokableStmt) callSite, returnSite); } }; } @@ -128,12 +128,12 @@ public Set computeTargets(Value source) { return Identity.v(); } - FlowFunction getCallFlow(Stmt callStmt, final SootMethod destinationMethod) { + FlowFunction getCallFlow(InvokableStmt callStmt, final SootMethod destinationMethod) { if ("".equals(destinationMethod.getName())) { return KillAll.v(); } - AbstractInvokeExpr ie = callStmt.getInvokeExpr(); + AbstractInvokeExpr ie = callStmt.getInvokeExpr().get(); final List callArgs = ie.getArgs(); final List paramLocals = new ArrayList(); @@ -173,9 +173,9 @@ public Set computeTargets(Value source) { } FlowFunction getReturnFlow( - final Stmt callSite, final SootMethod calleeMethod, Stmt exitStmt, Stmt returnSite) { + final InvokableStmt callSite, final SootMethod calleeMethod, Stmt exitStmt, Stmt returnSite) { - AbstractInvokeExpr ie = callSite.getInvokeExpr(); + AbstractInvokeExpr ie = callSite.getInvokeExpr().get(); Value base = null; if (ie instanceof JVirtualInvokeExpr) { @@ -239,8 +239,8 @@ public Set computeTargets(Value source) { return KillAll.v(); } - FlowFunction getCallToReturnFlow(final Stmt callSite, Stmt returnSite) { - AbstractInvokeExpr ie = callSite.getInvokeExpr(); + FlowFunction getCallToReturnFlow(final InvokableStmt callSite, Stmt returnSite) { + AbstractInvokeExpr ie = callSite.getInvokeExpr().get(); final List callArgs = ie.getArgs(); Value base = null; diff --git a/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java b/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java index aa1dfb0d215..a05d934e59f 100644 --- a/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java +++ b/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java @@ -64,8 +64,10 @@ public void createByteCodeProject() { .anyMatch( stmt -> stmt instanceof JInvokeStmt - && stmt.getInvokeExpr() instanceof JVirtualInvokeExpr - && stmt.getInvokeExpr() + && ((JInvokeStmt) stmt).getInvokeExpr().get() instanceof JVirtualInvokeExpr + && ((JInvokeStmt) stmt) + .getInvokeExpr() + .get() .getArg(0) .equivTo(JavaJimple.getInstance().newStringConstant("Hello World!")))); } diff --git a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java index 4d401d4be6f..aa928ef0bbd 100644 --- a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java +++ b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java @@ -12,6 +12,8 @@ import sootup.callgraph.ClassHierarchyAnalysisAlgorithm; import sootup.callgraph.RapidTypeAnalysisAlgorithm; import sootup.core.inputlocation.AnalysisInputLocation; +import sootup.core.jimple.common.stmt.InvokableStmt; +import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; @@ -28,6 +30,7 @@ public class CallGraphTest { protected JavaClassType mainClassSignature; protected MethodSignature mainMethodSignature; private String algorithmName; + private JavaView view; protected AbstractCallGraphAlgorithm createAlgorithm(JavaView view) { if (algorithmName.equals("RTA")) { @@ -54,7 +57,7 @@ CallGraph loadCallGraph() { String classPath = "src/test/resources/callgraph/" + "Misc"; // JavaView view = viewToClassPath.computeIfAbsent(classPath, this::createViewForClassPath); - JavaView view = createViewForClassPath(classPath); + view = createViewForClassPath(classPath); mainClassSignature = identifierFactory.getClassType("Main"); mainMethodSignature = @@ -75,6 +78,33 @@ CallGraph loadCallGraph() { return cg; } + protected InvokableStmt getInvokableStmt( + MethodSignature sourceMethod, MethodSignature staticTargetMethod) { + return getInvokableStmt(sourceMethod, staticTargetMethod, 0); + } + + protected InvokableStmt getInvokableStmt( + MethodSignature sourceMethod, MethodSignature staticTargetMethod, int index) { + int currentIndex = 0; + SootMethod method = view.getMethod(sourceMethod).orElse(null); + assertNotNull(method); + for (Stmt invokableStmt : method.getBody().getStmts()) { + if (invokableStmt instanceof InvokableStmt + && ((InvokableStmt) invokableStmt).containsInvokeExpr() + && ((InvokableStmt) invokableStmt) + .getInvokeExpr() + .get() + .getMethodSignature() + .equals(staticTargetMethod)) { + if (currentIndex == index) { + return (InvokableStmt) invokableStmt; + } + currentIndex++; + } + } + throw new RuntimeException("No invokable stmt found for " + sourceMethod); + } + @Test public void testRTA() { algorithmName = "RTA"; @@ -111,11 +141,31 @@ public void testRTA() { "int", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, methodAbstract)); - assertFalse(cg.containsCall(mainMethodSignature, methodMethodImplemented)); - assertTrue(cg.containsCall(mainMethodSignature, methodMethodImplementedInstantiatedInSubClass)); - assertFalse(cg.containsCall(mainMethodSignature, methodSubClassMethodNotImplemented)); - assertTrue(cg.containsCall(mainMethodSignature, methodSubClassMethodImplemented)); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodAbstract, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodMethodImplemented, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodMethodImplementedInstantiatedInSubClass, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodSubClassMethodNotImplemented, + getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodSubClassMethodImplemented, + getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); MethodSignature methodInterface = identifierFactory.getMethodSignature( @@ -142,10 +192,26 @@ public void testRTA() { "int", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, methodInterface)); - assertTrue(cg.containsCall(mainMethodSignature, methodInterfaceImplementation)); - assertFalse(cg.containsCall(mainMethodSignature, methodInterfaceNoImplementation)); - assertFalse(cg.containsCall(mainMethodSignature, methodInterfaceImplementationNotInstatiated)); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodInterface, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodInterfaceImplementation, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodInterfaceNoImplementation, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodInterfaceImplementationNotInstatiated, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); } @Test @@ -184,11 +250,31 @@ public void testCHA() { "int", Collections.emptyList()); - assertFalse(cg.containsCall(mainMethodSignature, methodAbstract)); - assertTrue(cg.containsCall(mainMethodSignature, methodMethodImplemented)); - assertTrue(cg.containsCall(mainMethodSignature, methodMethodImplementedInstantiatedInSubClass)); - assertFalse(cg.containsCall(mainMethodSignature, methodSubClassMethodNotImplemented)); - assertTrue(cg.containsCall(mainMethodSignature, methodSubClassMethodImplemented)); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodAbstract, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodMethodImplemented, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodMethodImplementedInstantiatedInSubClass, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodSubClassMethodNotImplemented, + getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodSubClassMethodImplemented, + getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); MethodSignature methodInterface = identifierFactory.getMethodSignature( @@ -215,10 +301,26 @@ public void testCHA() { "int", Collections.emptyList()); - assertTrue(cg.containsCall(mainMethodSignature, methodInterface)); - assertTrue(cg.containsCall(mainMethodSignature, methodInterfaceImplementation)); - assertFalse(cg.containsCall(mainMethodSignature, methodInterfaceNoImplementation)); - assertTrue(cg.containsCall(mainMethodSignature, methodInterfaceImplementationNotInstatiated)); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodInterface, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodInterfaceImplementation, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertFalse( + cg.containsCall( + mainMethodSignature, + methodInterfaceNoImplementation, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + assertTrue( + cg.containsCall( + mainMethodSignature, + methodInterfaceImplementationNotInstatiated, + getInvokableStmt(mainMethodSignature, methodMethodImplemented))); } @Test From 1f65974a06a06f974600a87c25e0300cac25205e Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 16:56:53 +0200 Subject: [PATCH 08/41] removed wrong deprecated tag on method --- .../src/main/java/sootup/callgraph/CallGraph.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index f62d2054718..89edb03025b 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -117,7 +117,7 @@ public int hashCode() { * @param sourceMethod the method signature of the requested node in the call graph * @return a set of method signatures that are reached by a direct outgoing edge in the call graph */ - @Deprecated + @Nonnull Set callsFrom(@Nonnull MethodSignature sourceMethod); @@ -129,7 +129,7 @@ public int hashCode() { * @return a set of method signatures that reach the targetMethod by a direct edge in the call * graph */ - @Deprecated + @Nonnull Set callsTo(@Nonnull MethodSignature targetMethod); From 0acc12c65b51270f54734206fed2f55ffc8c0e79 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 16:58:46 +0200 Subject: [PATCH 09/41] fixed comparison of Optionals instead of the content in the invoke stmt test --- .../sootup/core/jimple/common/stmt/JInvokeStmtTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java index 49c8ef19b3a..d5b121571a6 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java @@ -38,18 +38,18 @@ public void testGetInvokeExpr() { JStaticInvokeExpr staticExpr = InvokeExprUtil.createDummyStaticInvokeExpr(); JInvokeStmt invokeStmt = new JInvokeStmt(staticExpr, pos); - assertEquals(staticExpr, invokeStmt.getInvokeExpr()); + assertEquals(staticExpr, invokeStmt.getInvokeExpr().get()); JVirtualInvokeExpr virtualExpr = InvokeExprUtil.createDummyVirtualInvokeExpr(); JInvokeStmt invokeStmt1 = new JInvokeStmt(virtualExpr, pos); - assertEquals(virtualExpr, invokeStmt1.getInvokeExpr()); + assertEquals(virtualExpr, invokeStmt1.getInvokeExpr().get()); JSpecialInvokeExpr specialExpr = InvokeExprUtil.createDummySpecialInvokeExpr(); JInvokeStmt invokeStmt2 = new JInvokeStmt(specialExpr, pos); - assertEquals(specialExpr, invokeStmt2.getInvokeExpr()); + assertEquals(specialExpr, invokeStmt2.getInvokeExpr().get()); JInterfaceInvokeExpr interfaceExpr = InvokeExprUtil.createDummyInterfaceInvokeExpr(); JInvokeStmt invokeStmt3 = new JInvokeStmt(staticExpr, pos); - assertEquals(interfaceExpr, invokeStmt3.getInvokeExpr()); + assertEquals(interfaceExpr, invokeStmt3.getInvokeExpr().get()); } } From 5c39930937928eb1d90da35e6e0c6c332c9b38fa Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 17:00:57 +0200 Subject: [PATCH 10/41] fixed warnings --- .../java/sootup/callgraph/AbstractCallGraphAlgorithm.java | 1 - .../src/main/java/sootup/callgraph/CallGraph.java | 2 -- sootup.core/src/test/java/sootup/util/AssignStmtUtil.java | 5 ----- .../src/test/java/sootup/examples/basicSetup/BasicSetup.java | 4 +++- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index a5ef3a04693..fe3caf54390 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -559,7 +559,6 @@ public static Optional findConcreteMethod( hierarchyComparator.compare( m1.getDeclaringClassType(), m2.getDeclaringClassType())) .map(method -> (SootMethod) method); - ; if (defaultMethod.isPresent()) { return defaultMethod; } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index 89edb03025b..0e0da58b1c4 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -117,7 +117,6 @@ public int hashCode() { * @param sourceMethod the method signature of the requested node in the call graph * @return a set of method signatures that are reached by a direct outgoing edge in the call graph */ - @Nonnull Set callsFrom(@Nonnull MethodSignature sourceMethod); @@ -129,7 +128,6 @@ public int hashCode() { * @return a set of method signatures that reach the targetMethod by a direct edge in the call * graph */ - @Nonnull Set callsTo(@Nonnull MethodSignature targetMethod); diff --git a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java index 9de334dd258..d8d392301a4 100644 --- a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java +++ b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java @@ -6,14 +6,9 @@ import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.types.PrimitiveType.IntType; public class AssignStmtUtil { - private static Local createDummyLocal() { - return new Local("a", IntType.getInstance()); - } - /** * will return a dummy assignment statement with an invoke expression the left value will be the * dummy int local the right value will be the dummy static invoke expression stmt position is the diff --git a/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java b/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java index a05d934e59f..a72e8bd9c2a 100644 --- a/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java +++ b/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java @@ -12,6 +12,7 @@ import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; +import sootup.core.model.SourceType; import sootup.core.signatures.MethodSignature; import sootup.core.types.ClassType; import sootup.core.views.View; @@ -28,7 +29,8 @@ public void createByteCodeProject() { // Create a AnalysisInputLocation, which points to a directory. All class files will be loaded // from the directory Path pathToBinary = Paths.get("src/test/resources/BasicSetup/binary"); - AnalysisInputLocation inputLocation = PathBasedAnalysisInputLocation.create(pathToBinary, null); + AnalysisInputLocation inputLocation = + PathBasedAnalysisInputLocation.create(pathToBinary, SourceType.Application); // Create a view for project, which allows us to retrieve classes View view = new JavaView(inputLocation); From 6bbd67438c9262bdba548ca5a7bc01a91dac7f9b Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 17:10:51 +0200 Subject: [PATCH 11/41] fixed core testcases caused by the invoke expression changes --- .../java/sootup/core/jimple/common/stmt/JAssignStmtTest.java | 4 ++-- .../java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java index b2b4d02090f..f0689bd129f 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java @@ -70,8 +70,8 @@ public void testGetInvokeExpr() { Local local = LocalUtil.createDummyLocalForInt(); assertEquals( - InvokeExprUtil.createDummyStaticInvokeExpr(), - AssignStmtUtil.createDummyAssignStmtWithExpr().getInvokeExpr()); + InvokeExprUtil.createDummyStaticInvokeExpr().toString(), + AssignStmtUtil.createDummyAssignStmtWithExpr().getInvokeExpr().get().toString()); assertFalse( AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).getInvokeExpr().isPresent()); diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java index d5b121571a6..ba887d942f0 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java @@ -49,7 +49,7 @@ public void testGetInvokeExpr() { assertEquals(specialExpr, invokeStmt2.getInvokeExpr().get()); JInterfaceInvokeExpr interfaceExpr = InvokeExprUtil.createDummyInterfaceInvokeExpr(); - JInvokeStmt invokeStmt3 = new JInvokeStmt(staticExpr, pos); - assertEquals(interfaceExpr, invokeStmt3.getInvokeExpr().get()); + JInvokeStmt invokeStmt3 = new JInvokeStmt(interfaceExpr, pos); + assertEquals(interfaceExpr.toString(), invokeStmt3.getInvokeExpr().get().toString()); } } From 21e57daf3632427305f378892759b313e65aea40 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 17 May 2024 17:21:48 +0200 Subject: [PATCH 12/41] adapted the jimple comparator to the optional in returned by method getInvokeExpr --- .../main/java/sootup/core/jimple/basic/JimpleComparator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java b/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java index 7e743b29c84..d25e0944d74 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java +++ b/sootup.core/src/main/java/sootup/core/jimple/basic/JimpleComparator.java @@ -143,7 +143,7 @@ public boolean caseBreakpointStmt(JBreakpointStmt stmt, Object o) { public boolean caseInvokeStmt(JInvokeStmt stmt, Object o) { return (o instanceof JInvokeStmt) - && stmt.getInvokeExpr().get().equivTo(((JInvokeStmt) o).getInvokeExpr(), this); + && stmt.getInvokeExpr().get().equivTo(((JInvokeStmt) o).getInvokeExpr().get(), this); } public boolean caseAssignStmt(JAssignStmt stmt, Object o) { From 31da35bcfad40bdf3fc5a2f2b25590f479f1bef3 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 09:22:17 +0200 Subject: [PATCH 13/41] added getEntryMethod to the Callgraph Interface --- .../src/main/java/sootup/callgraph/CallGraph.java | 12 ++++++++++++ .../java/sootup/callgraph/GraphBasedCallGraph.java | 1 + 2 files changed, 13 insertions(+) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index 0e0da58b1c4..63311061a0c 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -22,6 +22,7 @@ * #L% */ +import java.util.List; import java.util.Set; import javax.annotation.Nonnull; import sootup.core.jimple.common.stmt.InvokableStmt; @@ -78,6 +79,11 @@ public int hashCode() { result = 31 * result + invokableStmt.hashCode(); return result; } + + @Override + public String toString() { + return "Call:"+sourceMethodSignature + " -> " + targetMethodSignature +" via " +invokableStmt+";"; + } } /** @@ -180,4 +186,10 @@ boolean containsCall( */ @Nonnull MutableCallGraph copy(); + + /** This method returns all entry methods of the call graph + * + * @return a list of method signatures of entry points of the call graph + */ + List getEntryMethods(); } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java index ffed8733590..c41a3b2cae1 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java @@ -303,6 +303,7 @@ public String toString() { return stringBuilder.toString(); } + @Override @Nonnull public List getEntryMethods() { return entryMethods; From fbd6300e8abd85fdbb6896759c25e27c4992fcd3 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 09:27:52 +0200 Subject: [PATCH 14/41] fixed warnings --- .../main/java/sootup/callgraph/CallGraph.java | 20 ++++++++++---- .../sootup/callgraph/GraphBasedCallGraph.java | 27 ++++++------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index 63311061a0c..17c0396c1fc 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -32,9 +32,9 @@ public interface CallGraph { class Call { - @Nonnull private MethodSignature sourceMethodSignature; - @Nonnull private MethodSignature targetMethodSignature; - @Nonnull private InvokableStmt invokableStmt; + @Nonnull private final MethodSignature sourceMethodSignature; + @Nonnull private final MethodSignature targetMethodSignature; + @Nonnull private final InvokableStmt invokableStmt; Call( @Nonnull MethodSignature sourceMethodSignature, @@ -45,14 +45,17 @@ class Call { this.targetMethodSignature = targetMethodSignature; } + @Nonnull public MethodSignature getSourceMethodSignature() { return sourceMethodSignature; } + @Nonnull public MethodSignature getTargetMethodSignature() { return targetMethodSignature; } + @Nonnull public InvokableStmt getInvokableStmt() { return invokableStmt; } @@ -82,7 +85,13 @@ public int hashCode() { @Override public String toString() { - return "Call:"+sourceMethodSignature + " -> " + targetMethodSignature +" via " +invokableStmt+";"; + return "Call:" + + sourceMethodSignature + + " -> " + + targetMethodSignature + + " via " + + invokableStmt + + ";"; } } @@ -187,7 +196,8 @@ boolean containsCall( @Nonnull MutableCallGraph copy(); - /** This method returns all entry methods of the call graph + /** + * This method returns all entry methods of the call graph * * @return a list of method signatures of entry points of the call graph */ diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java index c41a3b2cae1..4b91c8b4e46 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/GraphBasedCallGraph.java @@ -65,10 +65,10 @@ public GraphBasedCallGraph(List entryMethods) { this(new DirectedPseudograph<>(null, null, false), new HashMap<>(), entryMethods); } - public GraphBasedCallGraph( + protected GraphBasedCallGraph( @Nonnull DirectedPseudograph graph, @Nonnull Map signatureToVertex, - List entryMethods) { + @Nonnull List entryMethods) { this.graph = graph; this.signatureToVertex = signatureToVertex; this.entryMethods = entryMethods; @@ -214,9 +214,13 @@ public String exportAsDot() { Vertex targetVertex = graph.getEdgeTarget(edge); dotFormatBuilder .append("\t") - .append("\"" + sourceVertex.methodSignature + "\"") + .append("\"") + .append(sourceVertex.methodSignature) + .append("\"") .append(" -> ") - .append("\"" + targetVertex.methodSignature + "\"") + .append("\"") + .append(targetVertex.methodSignature) + .append("\"") .append(";\n"); }); @@ -246,21 +250,6 @@ protected Vertex vertexOf(@Nonnull MethodSignature method) { return methodVertex; } - @Nonnull - protected DirectedPseudograph getGraph() { - return graph; - } - - @Nonnull - protected Map getSignatureToVertex() { - return signatureToVertex; - } - - @Nonnull - protected MethodSignature vertex2MethodSignature(@Nonnull Vertex vertex) { - return vertex.getMethodSignature(); - } - /** * This method exports the call graph in a human-readable string. The String lists all nodes in * the call graph. For each node it also lists the outgoing and incoming edges. An outgoing edge From dacacaf5a2d07d5d5e80120d4f5acfebc7666524 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 11:56:43 +0200 Subject: [PATCH 15/41] added new util method to get assignment statements with static fields --- .../sootup/callgraph/CallGraphTestBase.java | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 0fd99146aab..826d42ea6cb 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -7,12 +7,15 @@ import java.util.List; import org.junit.jupiter.api.Test; import sootup.core.inputlocation.AnalysisInputLocation; +import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.stmt.InvokableStmt; +import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; import sootup.core.model.SourceType; import sootup.core.signatures.MethodSignature; +import sootup.core.types.ClassType; import sootup.java.bytecode.inputlocation.DefaultRTJarAnalysisInputLocation; import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation; import sootup.java.core.JavaIdentifierFactory; @@ -110,7 +113,51 @@ protected InvokableStmt getInvokableStmt( currentIndex++; } } - throw new RuntimeException("No invokable stmt found for " + sourceMethod); + throw new RuntimeException("No invokable stmt of method "+staticTargetMethod+" found for " + sourceMethod); + } + + protected InvokableStmt getInvokableStmtNonInvokeExpr( + MethodSignature sourceMethod, ClassType targetClass, boolean leftExpr) { + return getInvokableStmtNonInvokeExpr(sourceMethod, targetClass, leftExpr, 0); + } + + protected InvokableStmt getInvokableStmtNonInvokeExpr( + MethodSignature sourceMethod, ClassType targetClass, boolean leftExpr,int index) { + int currentIndex = 0; + SootMethod method = view.getMethod(sourceMethod).orElse(null); + assertNotNull(method); + for (Stmt invokableStmt : method.getBody().getStmts()) { + //look only at assigments which do Invoke but does not contain a direct invoke expr + // static fields and new array expressions + if (invokableStmt instanceof InvokableStmt + && invokableStmt instanceof JAssignStmt + && !((InvokableStmt) invokableStmt).containsInvokeExpr() + && ((InvokableStmt) invokableStmt).doesInvoke()){ + Value expr; + //look at the left or right side of the assigment + if (leftExpr){ + expr=((JAssignStmt) invokableStmt).getLeftOp(); + } + else { + expr=((JAssignStmt) invokableStmt).getRightOp(); + } + //extract the class type + ClassType classType=null; + if (expr instanceof JFieldRef){ + classType=((JFieldRef)expr).getFieldSignature().getDeclClassType(); + } + assertNotNull(classType); + if (classType.equals(targetClass)){ + //found fitting stmt in given position + if (currentIndex == index) { + return (InvokableStmt) invokableStmt; + } + //search next fitting stmt + currentIndex++; + } + } + } + throw new RuntimeException("No invokable assignment stmt of class "+ targetClass +" found for " + sourceMethod); } @Test From 1d3f9008c625eb58bbb7c7e7dc686befe6efb34e Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 12:09:50 +0200 Subject: [PATCH 16/41] added new util method to get assignment statements with static fields --- .../src/test/java/sootup/callgraph/CallGraphTestBase.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 826d42ea6cb..2ce5b17651e 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.Stmt; From 063f8b9158f6dd0069d4018ce0999acbe6ddea74 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 13:55:24 +0200 Subject: [PATCH 17/41] moved clinit calls of constructor calls to the corresponding new statement to support newarray and newmultiarray --- .../callgraph/AbstractCallGraphAlgorithm.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index fe3caf54390..c0e0c94ad7a 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -30,11 +30,12 @@ import org.slf4j.LoggerFactory; import sootup.callgraph.CallGraph.Call; import sootup.core.IdentifierFactory; +import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.expr.AbstractInvokeExpr; -import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.ref.JStaticFieldRef; import sootup.core.jimple.common.stmt.InvokableStmt; +import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.model.Method; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; @@ -269,6 +270,7 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( if (sourceMethod == null || !sourceMethod.hasBody()) { return; } + InstantiateClassValueVisitor instantiateVisitor = new InstantiateClassValueVisitor(); sourceMethod.getBody().getStmts().stream() .filter(stmt -> stmt instanceof InvokableStmt) .map(stmt -> (InvokableStmt) stmt) @@ -282,22 +284,33 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( addStaticInitializerCallsToCallGraph( sourceMethod.getSignature(), targetClass, invokableStmt, cg, workList); } - // static method calls and constructor calls - if (invokableStmt instanceof InvokableStmt && invokableStmt.containsInvokeExpr()) { + // static method + if (invokableStmt.containsInvokeExpr()) { // static method call Optional exprOptional = invokableStmt.getInvokeExpr(); if (!exprOptional.isPresent()) return; AbstractInvokeExpr expr = exprOptional.get(); - if (expr instanceof JStaticInvokeExpr - || (expr instanceof JSpecialInvokeExpr - && view.getIdentifierFactory() - .isConstructorSignature(expr.getMethodSignature()))) { + if (expr instanceof JStaticInvokeExpr) { ClassType newTargetClass = expr.getMethodSignature().getDeclClassType(); + // checks if the field points to the same clinit if (!newTargetClass.equals(targetClass)) { addStaticInitializerCallsToCallGraph( sourceMethod.getSignature(), newTargetClass, invokableStmt, cg, workList); } } + } else { + if (invokableStmt instanceof JAssignStmt) { + Value rightOp = ((JAssignStmt) invokableStmt).getRightOp(); + // extract class type out of new, new array and new multi array + instantiateVisitor.init(); + rightOp.accept(instantiateVisitor); + ClassType newTargetClass = instantiateVisitor.getResult(); + // check if class type is the same as in the field which could be on the left op + if (newTargetClass != null && !newTargetClass.equals(targetClass)) { + addStaticInitializerCallsToCallGraph( + sourceMethod.getSignature(), newTargetClass, invokableStmt, cg, workList); + } + } } }); } From 7927058d31ef2268557e885487beff207d1632a9 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 13:59:14 +0200 Subject: [PATCH 18/41] assignment statements can invoke a clinit call if it contains a new, newarray or newmultiarray expression --- .../core/jimple/common/stmt/JAssignStmt.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index bd2fe62e1b0..383119a8677 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -49,6 +49,9 @@ import sootup.core.jimple.basic.*; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.Expr; +import sootup.core.jimple.common.expr.JNewArrayExpr; +import sootup.core.jimple.common.expr.JNewExpr; +import sootup.core.jimple.common.expr.JNewMultiArrayExpr; import sootup.core.jimple.common.ref.ConcreteRef; import sootup.core.jimple.common.ref.JArrayRef; import sootup.core.jimple.common.ref.JFieldRef; @@ -112,8 +115,16 @@ public boolean containsInvokeExpr() { */ @Override public boolean doesInvoke() { - if (containsInvokeExpr()) return true; - return getRightOp() instanceof JStaticFieldRef || getLeftOp() instanceof JStaticFieldRef; + if (containsInvokeExpr()) { + return true; + } + Value rightOp = getRightOp(); + if (rightOp instanceof JStaticFieldRef || getLeftOp() instanceof JStaticFieldRef) { + return true; + } + return rightOp instanceof JNewExpr + || rightOp instanceof JNewMultiArrayExpr + || rightOp instanceof JNewArrayExpr; } /* From dec114f7ca865bc3d4882ab250b873542cfeff08 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 14:01:12 +0200 Subject: [PATCH 19/41] fixed warnings --- .../callgraph/AbstractCallGraphAlgorithm.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index c0e0c94ad7a..c6c5c17b501 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -38,6 +38,7 @@ import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.model.Method; import sootup.core.model.SootClass; +import sootup.core.model.SootClassMember; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; import sootup.core.signatures.MethodSubSignature; @@ -119,7 +120,7 @@ protected List getClinitFromEntryPoints(List e private Optional getSignatureOfImplementedStaticInitializer( ClassType classType) { return view.getMethod(classType.getStaticInitializer()) - .map(sootMethod -> sootMethod.getSignature()); + .map(SootClassMember::getSignature); } /** @@ -169,7 +170,7 @@ final void processWorkList( resolveAllCallsFromSourceMethod(currentMethod, cg, workList); // get all call targets of implicit edges in the method body - resolveAllImplicitCallsFromSourceMethod(view, currentMethod, cg, workList); + resolveAllImplicitCallsFromSourceMethod(currentMethod, cg, workList); // set method as processed processed.add(currentMethodSignature); @@ -241,32 +242,29 @@ protected void resolveAllCallsFromSourceMethod( /** * It resolves all implicit calls caused by the given source method * - * @param view it contains the class data * @param sourceMethod the inspected source method * @param cg new calls will be added to the call graph * @param workList new target methods will be added to the work list */ protected void resolveAllImplicitCallsFromSourceMethod( - View view, SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { + SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { return; } // collect all static initializer calls - resolveAllStaticInitializerCallsFromSourceMethod(view, sourceMethod, cg, workList); + resolveAllStaticInitializerCallsFromSourceMethod(sourceMethod, cg, workList); } /** * It resolves all static initializer calls caused by the given source method * - * @param view it contains the class data * @param sourceMethod the inspected source method * @param cg clinit calls will be added to the call graph * @param workList found clinit methods will be added to the work list */ - @Nonnull protected void resolveAllStaticInitializerCallsFromSourceMethod( - View view, SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { + SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { return; } From 0b010d33c148f32de85beaca3d1097ca92dc3b2c Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 14:34:35 +0200 Subject: [PATCH 20/41] added method to check if an array is an array of primitives --- .../core/jimple/common/expr/JNewArrayExpr.java | 11 +++++++++++ .../jimple/common/expr/JNewMultiArrayExpr.java | 4 ++++ .../src/main/java/sootup/core/types/ArrayType.java | 14 ++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java index 0cd4d94b0c8..b3b67120f59 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java @@ -31,6 +31,7 @@ import sootup.core.jimple.basic.Value; import sootup.core.jimple.visitor.ExprVisitor; import sootup.core.types.ArrayType; +import sootup.core.types.PrimitiveType; import sootup.core.types.Type; import sootup.core.util.printer.StmtPrinter; @@ -131,4 +132,14 @@ public JNewArrayExpr withBaseType(@Nonnull Type baseType) { public JNewArrayExpr withSize(@Nonnull Immediate size) { return new JNewArrayExpr(baseType, size, identifierFactory); } + + public boolean isArrayOfPrimitives() { + if (baseType instanceof PrimitiveType) { + return true; + } + if (baseType instanceof ArrayType) { + return ((ArrayType) baseType).isArrayTypeOfPrimitives(); + } + return false; + } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java index ae52793c6ff..b1468d0cb4f 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java @@ -143,4 +143,8 @@ public JNewMultiArrayExpr withBaseType(@Nonnull ArrayType baseType) { public JNewMultiArrayExpr withSizes(@Nonnull List sizes) { return new JNewMultiArrayExpr(baseType, sizes); } + + public boolean isArrayOfPrimitives() { + return ((ArrayType) baseType).isArrayTypeOfPrimitives(); + } } diff --git a/sootup.core/src/main/java/sootup/core/types/ArrayType.java b/sootup.core/src/main/java/sootup/core/types/ArrayType.java index 0fefc0fc8b0..a6d269211ef 100644 --- a/sootup.core/src/main/java/sootup/core/types/ArrayType.java +++ b/sootup.core/src/main/java/sootup/core/types/ArrayType.java @@ -99,4 +99,18 @@ public Type getElementType() { public void accept(@Nonnull TypeVisitor v) { v.caseArrayType(); } + + public boolean isArrayTypeOfPrimitives() { + return isArrayTypeOfPrimitives(baseType); + } + + private boolean isArrayTypeOfPrimitives(Type type) { + if (type instanceof PrimitiveType) { + return true; + } + if (type instanceof ArrayType) { + return isArrayTypeOfPrimitives(((ArrayType) type).getBaseType()); + } + return false; + } } From a2b0c39d093a84dd2cbaae0c2ea3a33bcf0e2191 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 14:36:05 +0200 Subject: [PATCH 21/41] fixed warnings --- .../callgraph/AbstractCallGraphAlgorithm.java | 3 +-- .../core/jimple/common/expr/JNewArrayExpr.java | 2 +- .../core/jimple/common/expr/JNewMultiArrayExpr.java | 6 +++--- .../sootup/core/jimple/common/stmt/JAssignStmt.java | 13 ++++++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index c6c5c17b501..deccccabed1 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -119,8 +119,7 @@ protected List getClinitFromEntryPoints(List e private Optional getSignatureOfImplementedStaticInitializer( ClassType classType) { - return view.getMethod(classType.getStaticInitializer()) - .map(SootClassMember::getSignature); + return view.getMethod(classType.getStaticInitializer()).map(SootClassMember::getSignature); } /** diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java index b3b67120f59..44eef242070 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewArrayExpr.java @@ -74,7 +74,7 @@ public int equivHashCode() { @Override public String toString() { - return (Jimple.NEWARRAY + " (") + baseType.toString() + ")" + "[" + size.toString() + "]"; + return (Jimple.NEWARRAY + " (") + baseType + ")" + "[" + size + "]"; } /** Converts a parameter of type StmtPrinter to a string literal. */ diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java index b1468d0cb4f..f9e9d60e675 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/expr/JNewMultiArrayExpr.java @@ -104,7 +104,7 @@ public ArrayType getBaseType() { return baseType; } - public Value getSize(@Nonnull int index) { + public Value getSize(int index) { return sizes.get(index); } @@ -120,7 +120,7 @@ public List getSizes() { @Override @Nonnull public Stream getUses() { - return Stream.concat(sizes.stream(), sizes.stream().flatMap(size -> size.getUses())); + return Stream.concat(sizes.stream(), sizes.stream().flatMap(Value::getUses)); } @Nonnull @@ -145,6 +145,6 @@ public JNewMultiArrayExpr withSizes(@Nonnull List sizes) { } public boolean isArrayOfPrimitives() { - return ((ArrayType) baseType).isArrayTypeOfPrimitives(); + return baseType.isArrayTypeOfPrimitives(); } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index 383119a8677..0cae086ad0e 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -122,9 +122,16 @@ public boolean doesInvoke() { if (rightOp instanceof JStaticFieldRef || getLeftOp() instanceof JStaticFieldRef) { return true; } - return rightOp instanceof JNewExpr - || rightOp instanceof JNewMultiArrayExpr - || rightOp instanceof JNewArrayExpr; + if (rightOp instanceof JNewExpr) { + return true; + } + if (rightOp instanceof JNewMultiArrayExpr) { + return !((JNewMultiArrayExpr) rightOp).isArrayOfPrimitives(); + } + if (rightOp instanceof JNewArrayExpr) { + return !((JNewArrayExpr) rightOp).isArrayOfPrimitives(); + } + return false; } /* From 4f25d06e0621074dfd6963585d7b3e84c79f8e82 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 15:53:46 +0200 Subject: [PATCH 22/41] adapted all sootup.callgraph tests to the new invoke statements in the call graph. Added a test for multiple calling sides of same methods --- .../sootup/callgraph/CallGraphTestBase.java | 361 +++++++++++++++--- .../ClassHierarchyAnalysisAlgorithmTest.java | 82 ++-- .../RapidTypeAnalysisAlgorithmTest.java | 96 ++--- .../source/MultipleCallsToSameTarget.java | 44 +++ 4 files changed, 416 insertions(+), 167 deletions(-) create mode 100644 sootup.callgraph/src/test/resources/callgraph/Misc/source/MultipleCallsToSameTarget.java diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 2ce5b17651e..32816254496 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -8,6 +8,9 @@ import org.junit.jupiter.api.Test; import sootup.core.inputlocation.AnalysisInputLocation; import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.expr.JNewArrayExpr; +import sootup.core.jimple.common.expr.JNewExpr; +import sootup.core.jimple.common.expr.JNewMultiArrayExpr; import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; @@ -114,7 +117,8 @@ protected InvokableStmt getInvokableStmt( currentIndex++; } } - throw new RuntimeException("No invokable stmt of method "+staticTargetMethod+" found for " + sourceMethod); + throw new RuntimeException( + "No invokable stmt of method " + staticTargetMethod + " found for " + sourceMethod); } protected InvokableStmt getInvokableStmtNonInvokeExpr( @@ -123,42 +127,54 @@ protected InvokableStmt getInvokableStmtNonInvokeExpr( } protected InvokableStmt getInvokableStmtNonInvokeExpr( - MethodSignature sourceMethod, ClassType targetClass, boolean leftExpr,int index) { + MethodSignature sourceMethod, ClassType targetClass, boolean leftExpr, int index) { int currentIndex = 0; SootMethod method = view.getMethod(sourceMethod).orElse(null); assertNotNull(method); + + InstantiateClassValueVisitor instantiateVisitor = new InstantiateClassValueVisitor(); for (Stmt invokableStmt : method.getBody().getStmts()) { - //look only at assigments which do Invoke but does not contain a direct invoke expr + // look only at assigments which do Invoke but does not contain a direct invoke expr // static fields and new array expressions if (invokableStmt instanceof InvokableStmt && invokableStmt instanceof JAssignStmt && !((InvokableStmt) invokableStmt).containsInvokeExpr() - && ((InvokableStmt) invokableStmt).doesInvoke()){ + && ((InvokableStmt) invokableStmt).doesInvoke()) { Value expr; - //look at the left or right side of the assigment - if (leftExpr){ - expr=((JAssignStmt) invokableStmt).getLeftOp(); + // look at the left or right side of the assigment + if (leftExpr) { + expr = ((JAssignStmt) invokableStmt).getLeftOp(); + } else { + expr = ((JAssignStmt) invokableStmt).getRightOp(); } - else { - expr=((JAssignStmt) invokableStmt).getRightOp(); + // extract the class type + ClassType classType = null; + if (expr instanceof JFieldRef) { + classType = ((JFieldRef) expr).getFieldSignature().getDeclClassType(); + } else if (expr instanceof JNewExpr + || expr instanceof JNewArrayExpr + || expr instanceof JNewMultiArrayExpr) { + instantiateVisitor.init(); + expr.accept(instantiateVisitor); + classType = instantiateVisitor.getResult(); } - //extract the class type - ClassType classType=null; - if (expr instanceof JFieldRef){ - classType=((JFieldRef)expr).getFieldSignature().getDeclClassType(); + // probably caused by invoke caused on the other operand side + if (classType == null) { + continue; } - assertNotNull(classType); - if (classType.equals(targetClass)){ - //found fitting stmt in given position + ; + if (classType.equals(targetClass)) { + // found fitting stmt in given position if (currentIndex == index) { return (InvokableStmt) invokableStmt; } - //search next fitting stmt + // search next fitting stmt currentIndex++; } } } - throw new RuntimeException("No invokable assignment stmt of class "+ targetClass +" found for " + sourceMethod); + throw new RuntimeException( + "No invokable assignment stmt of class " + targetClass + " found for " + sourceMethod); } @Test @@ -217,8 +233,8 @@ public void testRecursiveCall() { assertTrue( cg.containsCall( mainMethodSignature, method, getInvokableStmt(mainMethodSignature, method))); - // 2 calls +1 clinit calls - assertEquals(3, cg.callsFrom(mainMethodSignature).size()); + // 2 calls +2 clinit calls + assertEquals(4, cg.callsFrom(mainMethodSignature).size()); } @Test @@ -243,11 +259,17 @@ public void testConcreteCallInSuperClass() { "target", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("cvcsc.Class"), + "target", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmt(mainMethodSignature, targetMethodInvoked))); } @Test @@ -265,16 +287,22 @@ public void testConcreteCallDifferentDefaultMethodInSubClass() { "target", "void", Collections.emptyList()); + MethodSignature invokedMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("cvcscddi.Class"), + "target", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, interfaceMethod, - getInvokableStmt(mainMethodSignature, interfaceMethod))); + getInvokableStmt(mainMethodSignature, invokedMethod))); assertTrue( cg.containsCall( mainMethodSignature, subInterfaceMethod, - getInvokableStmt(mainMethodSignature, subInterfaceMethod))); + getInvokableStmt(mainMethodSignature, invokedMethod))); } @Test @@ -286,11 +314,17 @@ public void testConcreteCallInSuperClassWithDefaultInterface() { "target", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("cvcscwi.Class"), + "target", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmt(mainMethodSignature, targetMethodInvoked))); } @Test @@ -302,11 +336,17 @@ public void testConcreteCallInInterface() { "target", "void", Collections.emptyList()); + MethodSignature invokedMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("cvci.Class"), + "target", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmt(mainMethodSignature, invokedMethod))); } @Test @@ -318,11 +358,17 @@ public void testConcreteCallInSubInterface() { "target", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("cvcsi.Class"), + "target", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmt(mainMethodSignature, targetMethodInvoked))); } @Test @@ -334,11 +380,17 @@ public void testConcreteCallInSuperClassSubInterface() { "target", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("cvcscsi.Class"), + "target", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmt(mainMethodSignature, targetMethodInvoked))); } @Test @@ -350,11 +402,7 @@ public void testClinitCallEntryPoint() { "", "void", Collections.emptyList()); - assertTrue( - cg.containsCall( - mainMethodSignature, - targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + assertTrue(cg.getEntryMethods().contains(targetMethod)); } @Test @@ -382,11 +430,14 @@ public void testClinitCallConstructor() { "", "void", Collections.emptyList()); + assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmtNonInvokeExpr( + mainMethodSignature, identifierFactory.getClassType("ccc.DirectType"), false))); + MethodSignature arrayMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayType"), @@ -395,18 +446,25 @@ public void testClinitCallConstructor() { Collections.emptyList()); assertTrue( cg.containsCall( - mainMethodSignature, arrayMethod, getInvokableStmt(mainMethodSignature, arrayMethod))); + mainMethodSignature, + arrayMethod, + getInvokableStmtNonInvokeExpr( + mainMethodSignature, identifierFactory.getClassType("ccc.ArrayType"), false))); + MethodSignature arrayDimMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayDimType"), "", "void", Collections.emptyList()); + assertTrue( cg.containsCall( mainMethodSignature, arrayDimMethod, - getInvokableStmt(mainMethodSignature, arrayDimMethod))); + getInvokableStmtNonInvokeExpr( + mainMethodSignature, identifierFactory.getClassType("ccc.ArrayDimType"), false))); + MethodSignature arrayInArrayMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccc.ArrayInArrayType"), @@ -417,7 +475,10 @@ public void testClinitCallConstructor() { cg.containsCall( mainMethodSignature, arrayInArrayMethod, - getInvokableStmt(mainMethodSignature, arrayInArrayMethod))); + getInvokableStmtNonInvokeExpr( + mainMethodSignature, + identifierFactory.getClassType("ccc.ArrayInArrayType"), + false))); } @Test @@ -429,22 +490,17 @@ public void testClinitCallSuperConstructor() { "", "void", Collections.emptyList()); - assertTrue( - cg.containsCall( - mainMethodSignature, - targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + InvokableStmt invokedStmt = + getInvokableStmtNonInvokeExpr( + mainMethodSignature, identifierFactory.getClassType("ccsc.Clinit"), false); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod, invokedStmt)); MethodSignature targetMethod2 = identifierFactory.getMethodSignature( identifierFactory.getClassType("ccsc.SuperClinit"), "", "void", Collections.emptyList()); - assertTrue( - cg.containsCall( - mainMethodSignature, - targetMethod2, - getInvokableStmt(mainMethodSignature, targetMethod2))); + assertTrue(cg.containsCall(mainMethodSignature, targetMethod2, invokedStmt)); } @Test @@ -456,11 +512,17 @@ public void testClinitStaticMethodCall() { "", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("ccsmc.Clinit"), + "method", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmt(mainMethodSignature, targetMethodInvoked))); } @Test @@ -476,7 +538,8 @@ public void testClinitStaticField() { cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmt(mainMethodSignature, targetMethod))); + getInvokableStmtNonInvokeExpr( + mainMethodSignature, targetMethod.getDeclClassType(), false))); } @Test @@ -601,8 +664,12 @@ public void testVirtualCall2() { MethodSignature targetMethod = identifierFactory.getMethodSignature( subClassSig, "method", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + mainClassSignature, "method", "void", Collections.emptyList()); assertTrue( - cg.containsCall(callMethod, targetMethod, getInvokableStmt(callMethod, targetMethod))); + cg.containsCall( + callMethod, targetMethod, getInvokableStmt(callMethod, targetMethodInvoked))); } @Test @@ -632,8 +699,15 @@ public void testVirtualCall3() { MethodSignature targetMethod = identifierFactory.getMethodSignature( subClassSig, "method", "void", Collections.emptyList()); + MethodSignature targetMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("vc3.Interface"), + "method", + "void", + Collections.emptyList()); assertTrue( - cg.containsCall(callMethod, targetMethod, getInvokableStmt(callMethod, targetMethod))); + cg.containsCall( + callMethod, targetMethod, getInvokableStmt(callMethod, targetMethodInvoked))); } @Test @@ -644,9 +718,17 @@ public void testVirtualCall4() { MethodSignature callMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("vc4.Class"), "method", "void", Collections.emptyList()); + MethodSignature callMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("vc4.Interface"), + "method", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( - mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); + mainMethodSignature, + callMethod, + getInvokableStmt(mainMethodSignature, callMethodInvoked))); } @Test @@ -671,7 +753,9 @@ public void testDynamicInterfaceMethod0() { getInvokableStmt(mainMethodSignature, interfaceMethod))); assertTrue( cg.containsCall( - mainMethodSignature, classMethod, getInvokableStmt(mainMethodSignature, classMethod))); + mainMethodSignature, + classMethod, + getInvokableStmt(mainMethodSignature, interfaceMethod))); } @Test @@ -698,9 +782,15 @@ public void testDynamicInterfaceMethod2() { "method", "void", Collections.emptyList()); + MethodSignature invokedMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("j8dim2.Interface"), + "method", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( - mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, invokedMethod))); } @Test @@ -725,9 +815,15 @@ public void testDynamicInterfaceMethod4() { "method", "void", Collections.emptyList()); + MethodSignature invokedMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("j8dim4.SubClass"), + "method", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( - mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, callMethod))); + mainMethodSignature, callMethod, getInvokableStmt(mainMethodSignature, invokedMethod))); } @Test @@ -740,16 +836,28 @@ public void testDynamicInterfaceMethod5() { "method", "void", Collections.emptyList()); + MethodSignature invokedMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("j8dim5.Class"), + "method", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( - mainMethodSignature, method, getInvokableStmt(mainMethodSignature, method))); + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, invokedMethod))); MethodSignature compute = identifierFactory.getMethodSignature( mainClassSignature, "compute", "void", Collections.emptyList()); + MethodSignature invokedCompute = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("j8dim5.Class"), + "compute", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( - mainMethodSignature, compute, getInvokableStmt(mainMethodSignature, compute))); + mainMethodSignature, compute, getInvokableStmt(mainMethodSignature, invokedCompute))); } @Test @@ -762,11 +870,17 @@ public void testDynamicInterfaceMethod6() { "method", "void", Collections.emptyList()); + MethodSignature combinedInterfaceMethodInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("j8dim6.Demo$1"), + "method", + "void", + Collections.emptyList()); assertTrue( cg.containsCall( mainMethodSignature, combinedInterfaceMethod, - getInvokableStmt(mainMethodSignature, combinedInterfaceMethod))); + getInvokableStmt(mainMethodSignature, combinedInterfaceMethodInvoked))); MethodSignature method = identifierFactory.getMethodSignature( @@ -855,7 +969,7 @@ public void testAbstractMethodInSubClass() { assertTrue( cg.containsCall( - mainMethodSignature, method, getInvokableStmt(mainMethodSignature, abstractMethod))); + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, superMethod))); assertFalse( cg.containsCall( mainMethodSignature, @@ -886,6 +1000,13 @@ public void testAbstractMethodMissingMethodInSuperclass() { identifierFactory.getMethodSignature( identifierFactory.getClassType("am3.Class"), "method", "void", Collections.emptyList()); + MethodSignature superMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("am3.SuperClass"), + "method", + "void", + Collections.emptyList()); + MethodSignature abstractMethod = identifierFactory.getMethodSignature( identifierFactory.getClassType("am3.AbstractClass"), @@ -895,12 +1016,12 @@ public void testAbstractMethodMissingMethodInSuperclass() { assertTrue( cg.containsCall( - mainMethodSignature, method, getInvokableStmt(mainMethodSignature, abstractMethod))); + mainMethodSignature, method, getInvokableStmt(mainMethodSignature, superMethod))); assertFalse( cg.containsCall( mainMethodSignature, abstractMethod, - getInvokableStmt(mainMethodSignature, abstractMethod))); + getInvokableStmt(mainMethodSignature, superMethod))); } @Test @@ -994,4 +1115,124 @@ public void testStopAtLibraryClass() { } } } + + @Test + public void testMultiCallsToSameTarget() { + CallGraph cg = loadCallGraph("Misc", "multi.MultipleCallsToSameTarget"); + + MethodSignature constructorMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("multi.Instantiated"), + "", + "void", + Collections.emptyList()); + + MethodSignature virtualMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("multi.Instantiated"), + "method", + "void", + Collections.emptyList()); + + MethodSignature staticMethod = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("multi.MultiCalls"), + "method", + "void", + Collections.emptyList()); + + MethodSignature staticMethodField = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("multi.FieldLeft"), + "method", + "void", + Collections.emptyList()); + + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorMethod, + getInvokableStmt(mainMethodSignature, constructorMethod, 0))); + assertTrue( + cg.containsCall( + mainMethodSignature, + constructorMethod, + getInvokableStmt(mainMethodSignature, constructorMethod, 1))); + + assertTrue( + cg.containsCall( + mainMethodSignature, + staticMethod, + getInvokableStmt(mainMethodSignature, staticMethod, 0))); + assertTrue( + cg.containsCall( + mainMethodSignature, + staticMethod, + getInvokableStmt(mainMethodSignature, staticMethod, 1))); + + assertTrue( + cg.containsCall( + mainMethodSignature, + staticMethodField, + getInvokableStmt(mainMethodSignature, staticMethodField, 0))); + + assertTrue( + cg.containsCall( + mainMethodSignature, + virtualMethod, + getInvokableStmt(mainMethodSignature, virtualMethod, 0))); + + assertTrue( + cg.containsCall( + mainMethodSignature, + virtualMethod, + getInvokableStmt(mainMethodSignature, virtualMethod, 1))); + + checkClinit(cg, "multi.Instantiated", 0, false, null); + checkClinit(cg, "multi.Instantiated", 1, false, null); + + checkClinit(cg, "multi.FieldLeft", 0, true, null); + checkClinit(cg, "multi.FieldLeft", 1, true, null); + checkClinit(cg, "multi.FieldLeft", 2, true, null); + + checkClinit(cg, "multi.FieldRight", 0, false, null); + checkClinit(cg, "multi.FieldRight", 1, false, null); + + checkClinit(cg, "multi.MultiCalls", 0, false, staticMethod); + checkClinit(cg, "multi.MultiCalls", 1, false, staticMethod); + + assertEquals(27, cg.callsFrom(mainMethodSignature).size()); + + assertEquals(2, cg.callsTo(staticMethod).size()); + assertEquals(1, cg.callsTo(staticMethodField).size()); + assertEquals(2, cg.callsTo(constructorMethod).size()); + assertEquals(2, cg.callsTo(virtualMethod).size()); + + assertEquals(0, cg.callsFrom(staticMethod).size()); + assertEquals(0, cg.callsFrom(staticMethodField).size()); + assertEquals(1, cg.callsFrom(constructorMethod).size()); + assertEquals(0, cg.callsFrom(virtualMethod).size()); + } + + private void checkClinit( + CallGraph cg, String clinitClassName, int index, boolean left, MethodSignature ms) { + ClassType clinitClass = identifierFactory.getClassType(clinitClassName); + MethodSignature clinitMethod = + identifierFactory.getMethodSignature( + clinitClass, "", "void", Collections.emptyList()); + MethodSignature clinitObject = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("java.lang.Object"), + "", + "void", + Collections.emptyList()); + InvokableStmt invokeStmt; + if (ms == null) { + invokeStmt = getInvokableStmtNonInvokeExpr(mainMethodSignature, clinitClass, left, index); + } else { + invokeStmt = getInvokableStmt(mainMethodSignature, ms, index); + } + assertTrue(cg.containsCall(mainMethodSignature, clinitObject, invokeStmt)); + assertTrue(cg.containsCall(mainMethodSignature, clinitMethod, invokeStmt)); + } } diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java index 8c4a3db9ed6..0c11d04e5e7 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java @@ -152,7 +152,7 @@ public void testMiscExample1() { cg.containsCall( mainMethodSignature, constructorA, - getInvokableStmt(mainMethodSignature, constructorA))); + getInvokableStmt(mainMethodSignature, constructorB))); assertTrue( cg.containsCall( mainMethodSignature, @@ -163,11 +163,13 @@ public void testMiscExample1() { mainMethodSignature, constructorC, getInvokableStmt(mainMethodSignature, constructorC))); + assertFalse( cg.containsCall( mainMethodSignature, constructorD, - getInvokableStmt(mainMethodSignature, constructorD))); + getInvokableStmt(mainMethodSignature, constructorC))); + assertTrue( cg.containsCall( mainMethodSignature, @@ -193,26 +195,47 @@ public void testMiscExample1() { cg.containsCall( mainMethodSignature, virtualMethodB, - getInvokableStmt(mainMethodSignature, virtualMethodB))); + getInvokableStmt(mainMethodSignature, virtualMethodA))); assertFalse(cg.containsMethod(virtualMethodC)); assertTrue( cg.containsCall( mainMethodSignature, virtualMethodD, - getInvokableStmt(mainMethodSignature, virtualMethodD))); + getInvokableStmt(mainMethodSignature, virtualMethodA))); assertTrue( cg.containsCall( mainMethodSignature, virtualMethodE, - getInvokableStmt(mainMethodSignature, virtualMethodE))); + getInvokableStmt(mainMethodSignature, virtualMethodA))); + + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmtNonInvokeExpr( + mainMethodSignature, constructorB.getDeclClassType(), false))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmt(mainMethodSignature, clinitObject))); + getInvokableStmtNonInvokeExpr( + mainMethodSignature, constructorC.getDeclClassType(), false))); - assertEquals(9, cg.callsFrom(mainMethodSignature).size()); + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmtNonInvokeExpr( + mainMethodSignature, constructorE.getDeclClassType(), false))); + + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmt(mainMethodSignature, staticMethodB))); + + assertEquals(12, cg.callsFrom(mainMethodSignature).size()); assertEquals(1, cg.callsTo(constructorB).size()); assertEquals(1, cg.callsTo(constructorC).size()); @@ -228,50 +251,5 @@ public void testMiscExample1() { assertEquals(0, cg.callsFrom(virtualMethodB).size()); assertEquals(0, cg.callsFrom(virtualMethodD).size()); assertEquals(0, cg.callsFrom(virtualMethodE).size()); - - assertEquals( - cg.toString().replace("\n", "").replace("\t", ""), - "GraphBasedCallGraph(14):" - + "()>:" - + "to ()>" - + "from ()>" - + "from ()>" - + "from ()>" - + ":" - + "from " - + "()>:" - + "to ()>" - + "from " - + ":" - + "from " - + ":" - + "from " - + "()>:" - + "to ()>" - + "from " - + "()>:" - + "to ()>" - + "from ()>" - + ":" - + "from " - + "()>:" - + "to ()>" - + "from " - + ":" - + "from " - + ":" - + "to " - + "to ()>" - + "to " - + "to " - + "to ()>" - + "to " - + "to ()>" - + "to " - + "to ()>" - + "()>:" - + "from " - + "()>:" - + "from ()>"); } } diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java index d4f2fa1223e..0b4d5012a1f 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java @@ -146,7 +146,7 @@ public void testMiscExample1() { cg.containsCall( mainMethodSignature, constructorA, - getInvokableStmt(mainMethodSignature, constructorA))); + getInvokableStmt(mainMethodSignature, constructorB))); assertTrue( cg.containsCall( mainMethodSignature, @@ -161,7 +161,7 @@ public void testMiscExample1() { cg.containsCall( mainMethodSignature, constructorD, - getInvokableStmt(mainMethodSignature, constructorD))); + getInvokableStmt(mainMethodSignature, constructorC))); assertTrue( cg.containsCall( mainMethodSignature, @@ -171,7 +171,9 @@ public void testMiscExample1() { assertFalse(cg.containsMethod(staticMethodA)); assertTrue( cg.containsCall( - mainMethodSignature, staticMethodB, getInvokableStmt(staticMethodB, staticMethodB))); + mainMethodSignature, + staticMethodB, + getInvokableStmt(mainMethodSignature, staticMethodB))); assertFalse(cg.containsMethod(staticMethodC)); assertFalse(cg.containsMethod(staticMethodD)); assertFalse(cg.containsMethod(staticMethodE)); @@ -179,20 +181,46 @@ public void testMiscExample1() { assertFalse(cg.containsMethod(virtualMethodA)); assertTrue( cg.containsCall( - mainMethodSignature, virtualMethodB, getInvokableStmt(virtualMethodB, virtualMethodB))); + mainMethodSignature, + virtualMethodB, + getInvokableStmt(mainMethodSignature, virtualMethodA))); assertFalse(cg.containsMethod(virtualMethodC)); assertTrue( cg.containsCall( - mainMethodSignature, virtualMethodD, getInvokableStmt(virtualMethodD, virtualMethodD))); + mainMethodSignature, + virtualMethodD, + getInvokableStmt(mainMethodSignature, virtualMethodA))); assertTrue( cg.containsCall( - mainMethodSignature, virtualMethodE, getInvokableStmt(virtualMethodE, virtualMethodE))); + mainMethodSignature, + virtualMethodE, + getInvokableStmt(mainMethodSignature, virtualMethodA))); assertTrue( cg.containsCall( - mainMethodSignature, clinitObject, getInvokableStmt(clinitObject, clinitObject))); + mainMethodSignature, + clinitObject, + getInvokableStmtNonInvokeExpr( + mainMethodSignature, constructorB.getDeclClassType(), false))); + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmtNonInvokeExpr( + mainMethodSignature, constructorC.getDeclClassType(), false))); + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmtNonInvokeExpr( + mainMethodSignature, constructorE.getDeclClassType(), false))); + assertTrue( + cg.containsCall( + mainMethodSignature, + clinitObject, + getInvokableStmt(mainMethodSignature, staticMethodB))); - assertEquals(8, cg.callsFrom(mainMethodSignature).size()); + assertEquals(11, cg.callsFrom(mainMethodSignature).size()); assertEquals(1, cg.callsTo(constructorB).size()); assertEquals(1, cg.callsTo(constructorC).size()); @@ -206,48 +234,6 @@ public void testMiscExample1() { assertEquals(0, cg.callsFrom(virtualMethodB).size()); assertEquals(0, cg.callsFrom(virtualMethodD).size()); assertEquals(0, cg.callsFrom(virtualMethodE).size()); - - assertEquals( - cg.toString().replace("\n", "").replace("\t", ""), - "GraphBasedCallGraph(13):" - + "()>:" - + "to ()>" - + "from ()>" - + "from ()>" - + "from ()>" - + "()>:" - + "to ()>" - + "from " - + ":" - + "from " - + ":" - + "from " - + "()>:" - + "to ()>" - + "from " - + "()>:" - + "to ()>" - + "from ()>" - + ":" - + "from " - + "()>:" - + "to ()>" - + "from " - + ":" - + "from " - + ":" - + "to ()>" - + "to " - + "to " - + "to ()>" - + "to " - + "to ()>" - + "to " - + "to ()>" - + "()>:" - + "from " - + "()>:" - + "from ()>"); } @Test @@ -286,10 +272,10 @@ public void testRevisitMethod() { alreadyVisitedMethod, newTargetA, getInvokableStmt(alreadyVisitedMethod, newTargetA))); assertTrue( cg.containsCall( - alreadyVisitedMethod, newTargetB, getInvokableStmt(alreadyVisitedMethod, newTargetB))); + alreadyVisitedMethod, newTargetB, getInvokableStmt(alreadyVisitedMethod, newTargetA))); assertTrue( cg.containsCall( - alreadyVisitedMethod, newTargetC, getInvokableStmt(alreadyVisitedMethod, newTargetC))); + alreadyVisitedMethod, newTargetC, getInvokableStmt(alreadyVisitedMethod, newTargetA))); } @Test @@ -328,10 +314,10 @@ public void testRecursiveRevisitMethod() { alreadyVisitedMethod, newTargetA, getInvokableStmt(alreadyVisitedMethod, newTargetA))); assertTrue( cg.containsCall( - alreadyVisitedMethod, newTargetB, getInvokableStmt(alreadyVisitedMethod, newTargetB))); + alreadyVisitedMethod, newTargetB, getInvokableStmt(alreadyVisitedMethod, newTargetA))); assertTrue( cg.containsCall( - alreadyVisitedMethod, newTargetC, getInvokableStmt(alreadyVisitedMethod, newTargetC))); + alreadyVisitedMethod, newTargetC, getInvokableStmt(alreadyVisitedMethod, newTargetA))); } @Test @@ -354,7 +340,7 @@ public void testInstantiatedClassInClinit() { cg.containsCall( mainMethodSignature, instantiatedClassMethod, - getInvokableStmt(mainMethodSignature, instantiatedClassMethod))); + getInvokableStmt(mainMethodSignature, nonInstantiatedClassMethod))); assertFalse( cg.containsCall( mainMethodSignature, diff --git a/sootup.callgraph/src/test/resources/callgraph/Misc/source/MultipleCallsToSameTarget.java b/sootup.callgraph/src/test/resources/callgraph/Misc/source/MultipleCallsToSameTarget.java new file mode 100644 index 00000000000..dc4288c87d8 --- /dev/null +++ b/sootup.callgraph/src/test/resources/callgraph/Misc/source/MultipleCallsToSameTarget.java @@ -0,0 +1,44 @@ +package multi; + +class MultipleCallsToSameTarget { + + public static void main(String[] args){ + MultiCalls.method(); + MultiCalls.method(); + + FieldLeft.field = 5; + FieldLeft.field = FieldLeft.method(); + + int f = FieldRight.field; + FieldLeft.field = FieldRight.field; + + Instantiated in1 = new Instantiated(); + Instantiated in2 = new Instantiated(); + + in1.method(); + in2.method(); + } +} + +class MultiCalls{ + static int field=3; + + static void method(){ + + } +} + +class FieldLeft{ + static int field=3; + static void method(){} +} + +class FieldRight{ + static int field=3; +} + +class Instantiated{ + static int field=3; + + void method(){} +} \ No newline at end of file From 11885980f6d899b937fefc1f7b24d2175b4087fd Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 15:54:51 +0200 Subject: [PATCH 23/41] improved call graphs tests --- .../src/test/java/sootup/callgraph/CallGraphTestBase.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 32816254496..47c8f7b5d6e 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -136,8 +136,7 @@ protected InvokableStmt getInvokableStmtNonInvokeExpr( for (Stmt invokableStmt : method.getBody().getStmts()) { // look only at assigments which do Invoke but does not contain a direct invoke expr // static fields and new array expressions - if (invokableStmt instanceof InvokableStmt - && invokableStmt instanceof JAssignStmt + if (invokableStmt instanceof JAssignStmt && !((InvokableStmt) invokableStmt).containsInvokeExpr() && ((InvokableStmt) invokableStmt).doesInvoke()) { Value expr; @@ -162,7 +161,6 @@ protected InvokableStmt getInvokableStmtNonInvokeExpr( if (classType == null) { continue; } - ; if (classType.equals(targetClass)) { // found fitting stmt in given position if (currentIndex == index) { From f0fedce3ce915b9f54c5c53dbb4b3129158f6072 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 16:03:20 +0200 Subject: [PATCH 24/41] adapted sootup.tests to the changes in the call graph algorithm --- .../test/java/sootup/tests/CallGraphTest.java | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java index aa928ef0bbd..0ee7e3692a3 100644 --- a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java +++ b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java @@ -145,27 +145,27 @@ public void testRTA() { cg.containsCall( mainMethodSignature, methodAbstract, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertFalse( cg.containsCall( mainMethodSignature, methodMethodImplemented, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertTrue( cg.containsCall( mainMethodSignature, methodMethodImplementedInstantiatedInSubClass, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertFalse( cg.containsCall( mainMethodSignature, methodSubClassMethodNotImplemented, - getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertTrue( cg.containsCall( mainMethodSignature, methodSubClassMethodImplemented, - getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); MethodSignature methodInterface = identifierFactory.getMethodSignature( @@ -196,22 +196,22 @@ public void testRTA() { cg.containsCall( mainMethodSignature, methodInterface, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); assertTrue( cg.containsCall( mainMethodSignature, methodInterfaceImplementation, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); assertFalse( cg.containsCall( mainMethodSignature, methodInterfaceNoImplementation, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); assertFalse( cg.containsCall( mainMethodSignature, methodInterfaceImplementationNotInstatiated, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); } @Test @@ -254,27 +254,27 @@ public void testCHA() { cg.containsCall( mainMethodSignature, methodAbstract, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertTrue( cg.containsCall( mainMethodSignature, methodMethodImplemented, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertTrue( cg.containsCall( mainMethodSignature, methodMethodImplementedInstantiatedInSubClass, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertFalse( cg.containsCall( mainMethodSignature, methodSubClassMethodNotImplemented, - getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); assertTrue( cg.containsCall( mainMethodSignature, methodSubClassMethodImplemented, - getInvokableStmt(mainMethodSignature, methodSubClassMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodAbstract))); MethodSignature methodInterface = identifierFactory.getMethodSignature( @@ -305,22 +305,22 @@ public void testCHA() { cg.containsCall( mainMethodSignature, methodInterface, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); assertTrue( cg.containsCall( mainMethodSignature, methodInterfaceImplementation, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); assertFalse( cg.containsCall( mainMethodSignature, methodInterfaceNoImplementation, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); assertTrue( cg.containsCall( mainMethodSignature, methodInterfaceImplementationNotInstatiated, - getInvokableStmt(mainMethodSignature, methodMethodImplemented))); + getInvokableStmt(mainMethodSignature, methodInterface))); } @Test @@ -339,6 +339,9 @@ public void checkCallGraphDotExporter() { + "\t\"\" -> \"()>\";\n" + "\t\"\" -> \"\";\n" + "\t\"\" -> \"()>\";\n" + + "\t\"\" -> \"()>\";\n" + + "\t\"\" -> \"()>\";\n" + + "\t\"\" -> \"()>\";\n" + "\t\"\" -> \"()>\";\n" + "\t\"\" -> \"\";\n" + "\t\"\" -> \"()>\";\n" From fdc5f58cb34a3982da9ba1835a3ce7fcbe2144a0 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 16:08:21 +0200 Subject: [PATCH 25/41] simplified util method in CallGraphTest --- .../src/test/java/sootup/tests/CallGraphTest.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java index 0ee7e3692a3..e0ffd04f06b 100644 --- a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java +++ b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java @@ -80,12 +80,6 @@ CallGraph loadCallGraph() { protected InvokableStmt getInvokableStmt( MethodSignature sourceMethod, MethodSignature staticTargetMethod) { - return getInvokableStmt(sourceMethod, staticTargetMethod, 0); - } - - protected InvokableStmt getInvokableStmt( - MethodSignature sourceMethod, MethodSignature staticTargetMethod, int index) { - int currentIndex = 0; SootMethod method = view.getMethod(sourceMethod).orElse(null); assertNotNull(method); for (Stmt invokableStmt : method.getBody().getStmts()) { @@ -96,10 +90,7 @@ protected InvokableStmt getInvokableStmt( .get() .getMethodSignature() .equals(staticTargetMethod)) { - if (currentIndex == index) { - return (InvokableStmt) invokableStmt; - } - currentIndex++; + return (InvokableStmt) invokableStmt; } } throw new RuntimeException("No invokable stmt found for " + sourceMethod); From 2ed9606a9476b328c5f3149ed29ac0b077804d10 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 16:11:24 +0200 Subject: [PATCH 26/41] removed left op flag from the method that will grab the first fitting stmt --- .../sootup/callgraph/CallGraphTestBase.java | 18 +++++++++--------- .../ClassHierarchyAnalysisAlgorithmTest.java | 6 +++--- .../RapidTypeAnalysisAlgorithmTest.java | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 47c8f7b5d6e..10d77a9d478 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -122,8 +122,8 @@ protected InvokableStmt getInvokableStmt( } protected InvokableStmt getInvokableStmtNonInvokeExpr( - MethodSignature sourceMethod, ClassType targetClass, boolean leftExpr) { - return getInvokableStmtNonInvokeExpr(sourceMethod, targetClass, leftExpr, 0); + MethodSignature sourceMethod, ClassType targetClass) { + return getInvokableStmtNonInvokeExpr(sourceMethod, targetClass, false, 0); } protected InvokableStmt getInvokableStmtNonInvokeExpr( @@ -434,7 +434,7 @@ public void testClinitCallConstructor() { mainMethodSignature, targetMethod, getInvokableStmtNonInvokeExpr( - mainMethodSignature, identifierFactory.getClassType("ccc.DirectType"), false))); + mainMethodSignature, identifierFactory.getClassType("ccc.DirectType")))); MethodSignature arrayMethod = identifierFactory.getMethodSignature( @@ -447,7 +447,7 @@ public void testClinitCallConstructor() { mainMethodSignature, arrayMethod, getInvokableStmtNonInvokeExpr( - mainMethodSignature, identifierFactory.getClassType("ccc.ArrayType"), false))); + mainMethodSignature, identifierFactory.getClassType("ccc.ArrayType")))); MethodSignature arrayDimMethod = identifierFactory.getMethodSignature( @@ -461,7 +461,7 @@ public void testClinitCallConstructor() { mainMethodSignature, arrayDimMethod, getInvokableStmtNonInvokeExpr( - mainMethodSignature, identifierFactory.getClassType("ccc.ArrayDimType"), false))); + mainMethodSignature, identifierFactory.getClassType("ccc.ArrayDimType")))); MethodSignature arrayInArrayMethod = identifierFactory.getMethodSignature( @@ -475,8 +475,8 @@ public void testClinitCallConstructor() { arrayInArrayMethod, getInvokableStmtNonInvokeExpr( mainMethodSignature, - identifierFactory.getClassType("ccc.ArrayInArrayType"), - false))); + identifierFactory.getClassType("ccc.ArrayInArrayType") + ))); } @Test @@ -490,7 +490,7 @@ public void testClinitCallSuperConstructor() { Collections.emptyList()); InvokableStmt invokedStmt = getInvokableStmtNonInvokeExpr( - mainMethodSignature, identifierFactory.getClassType("ccsc.Clinit"), false); + mainMethodSignature, identifierFactory.getClassType("ccsc.Clinit")); assertTrue(cg.containsCall(mainMethodSignature, targetMethod, invokedStmt)); MethodSignature targetMethod2 = identifierFactory.getMethodSignature( @@ -537,7 +537,7 @@ public void testClinitStaticField() { mainMethodSignature, targetMethod, getInvokableStmtNonInvokeExpr( - mainMethodSignature, targetMethod.getDeclClassType(), false))); + mainMethodSignature, targetMethod.getDeclClassType()))); } @Test diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java index 0c11d04e5e7..c51e94f4bb7 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java @@ -213,21 +213,21 @@ public void testMiscExample1() { mainMethodSignature, clinitObject, getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorB.getDeclClassType(), false))); + mainMethodSignature, constructorB.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorC.getDeclClassType(), false))); + mainMethodSignature, constructorC.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorE.getDeclClassType(), false))); + mainMethodSignature, constructorE.getDeclClassType()))); assertTrue( cg.containsCall( diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java index 0b4d5012a1f..4b7a6e496b4 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java @@ -201,19 +201,19 @@ public void testMiscExample1() { mainMethodSignature, clinitObject, getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorB.getDeclClassType(), false))); + mainMethodSignature, constructorB.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorC.getDeclClassType(), false))); + mainMethodSignature, constructorC.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorE.getDeclClassType(), false))); + mainMethodSignature, constructorE.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, From 66706fb22e6e3faf9cc96b648260cc0c88a45a25 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Fri, 24 May 2024 16:11:55 +0200 Subject: [PATCH 27/41] fmt --- .../test/java/sootup/callgraph/CallGraphTestBase.java | 7 ++----- .../callgraph/ClassHierarchyAnalysisAlgorithmTest.java | 9 +++------ .../sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java | 9 +++------ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 10d77a9d478..328ae0a6e93 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -474,9 +474,7 @@ public void testClinitCallConstructor() { mainMethodSignature, arrayInArrayMethod, getInvokableStmtNonInvokeExpr( - mainMethodSignature, - identifierFactory.getClassType("ccc.ArrayInArrayType") - ))); + mainMethodSignature, identifierFactory.getClassType("ccc.ArrayInArrayType")))); } @Test @@ -536,8 +534,7 @@ public void testClinitStaticField() { cg.containsCall( mainMethodSignature, targetMethod, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, targetMethod.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, targetMethod.getDeclClassType()))); } @Test diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java index c51e94f4bb7..27216c45851 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/ClassHierarchyAnalysisAlgorithmTest.java @@ -212,22 +212,19 @@ public void testMiscExample1() { cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorB.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, constructorB.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorC.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, constructorC.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorE.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, constructorE.getDeclClassType()))); assertTrue( cg.containsCall( diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java index 4b7a6e496b4..afb804127cb 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/RapidTypeAnalysisAlgorithmTest.java @@ -200,20 +200,17 @@ public void testMiscExample1() { cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorB.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, constructorB.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorC.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, constructorC.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, clinitObject, - getInvokableStmtNonInvokeExpr( - mainMethodSignature, constructorE.getDeclClassType()))); + getInvokableStmtNonInvokeExpr(mainMethodSignature, constructorE.getDeclClassType()))); assertTrue( cg.containsCall( mainMethodSignature, From 6e871e74078657fc8d39f7cfb0e82cd6e1c89221 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 27 May 2024 12:27:32 +0200 Subject: [PATCH 28/41] shorter method names --- .../sootup/callgraph/AbstractCallGraphAlgorithm.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index deccccabed1..faf0342e0fa 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -252,7 +252,7 @@ protected void resolveAllImplicitCallsFromSourceMethod( } // collect all static initializer calls - resolveAllStaticInitializerCallsFromSourceMethod(sourceMethod, cg, workList); + resolveAllStaticInitializerCalls(sourceMethod, cg, workList); } /** @@ -262,7 +262,7 @@ protected void resolveAllImplicitCallsFromSourceMethod( * @param cg clinit calls will be added to the call graph * @param workList found clinit methods will be added to the work list */ - protected void resolveAllStaticInitializerCallsFromSourceMethod( + protected void resolveAllStaticInitializerCalls( SootMethod sourceMethod, MutableCallGraph cg, Deque workList) { if (sourceMethod == null || !sourceMethod.hasBody()) { return; @@ -278,7 +278,7 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( if (invokableStmt.containsFieldRef() && invokableStmt.getFieldRef() instanceof JStaticFieldRef) { targetClass = invokableStmt.getFieldRef().getFieldSignature().getDeclClassType(); - addStaticInitializerCallsToCallGraph( + addStaticInitializerCalls( sourceMethod.getSignature(), targetClass, invokableStmt, cg, workList); } // static method @@ -291,7 +291,7 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( ClassType newTargetClass = expr.getMethodSignature().getDeclClassType(); // checks if the field points to the same clinit if (!newTargetClass.equals(targetClass)) { - addStaticInitializerCallsToCallGraph( + addStaticInitializerCalls( sourceMethod.getSignature(), newTargetClass, invokableStmt, cg, workList); } } @@ -304,7 +304,7 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( ClassType newTargetClass = instantiateVisitor.getResult(); // check if class type is the same as in the field which could be on the left op if (newTargetClass != null && !newTargetClass.equals(targetClass)) { - addStaticInitializerCallsToCallGraph( + addStaticInitializerCalls( sourceMethod.getSignature(), newTargetClass, invokableStmt, cg, workList); } } @@ -323,7 +323,7 @@ protected void resolveAllStaticInitializerCallsFromSourceMethod( * @param cg the call graph that will contain the found calls * @param workList the work list that will be updated with new target methods */ - private void addStaticInitializerCallsToCallGraph( + private void addStaticInitializerCalls( MethodSignature sourceSig, ClassType targetClass, InvokableStmt invokableStmt, From c5c28bba22af91be25693fe5cc512ce0e8d54934 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 27 May 2024 12:38:25 +0200 Subject: [PATCH 29/41] made isArrayTypeOfPrimitives public static --- sootup.core/src/main/java/sootup/core/types/ArrayType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sootup.core/src/main/java/sootup/core/types/ArrayType.java b/sootup.core/src/main/java/sootup/core/types/ArrayType.java index a6d269211ef..df57ef7ed62 100644 --- a/sootup.core/src/main/java/sootup/core/types/ArrayType.java +++ b/sootup.core/src/main/java/sootup/core/types/ArrayType.java @@ -104,7 +104,7 @@ public boolean isArrayTypeOfPrimitives() { return isArrayTypeOfPrimitives(baseType); } - private boolean isArrayTypeOfPrimitives(Type type) { + public static boolean isArrayTypeOfPrimitives(Type type) { if (type instanceof PrimitiveType) { return true; } From 189962bec0626d3ba1bcd7b6303992b57fd27777 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 27 May 2024 15:09:01 +0200 Subject: [PATCH 30/41] removed duplicate dependency --- sootup.tests/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sootup.tests/pom.xml b/sootup.tests/pom.xml index beb729fe6ae..4e6e88ce2f7 100644 --- a/sootup.tests/pom.xml +++ b/sootup.tests/pom.xml @@ -44,12 +44,6 @@ sootup.callgraph ${project.version} - - org.soot-oss - sootup.jimple.parser - 1.2.1-SNAPSHOT - test - From bb1baa3d3483a13b790da188d6049d2aae9d3072 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 27 May 2024 15:09:54 +0200 Subject: [PATCH 31/41] introduced invokesStaticInitializer by adapting doesInvokes to only check for static initializer calls --- .../sootup/callgraph/CallGraphTestBase.java | 2 +- .../jimple/common/stmt/InvokableStmt.java | 8 ++- .../core/jimple/common/stmt/JAssignStmt.java | 11 +--- .../core/jimple/common/stmt/JInvokeStmt.java | 5 +- .../jimple/common/stmt/JAssignStmtTest.java | 55 ++++++++++++++----- .../jimple/common/stmt/JInvokeStmtTest.java | 18 ++++++ .../test/java/sootup/util/AssignStmtUtil.java | 10 ++-- 7 files changed, 78 insertions(+), 31 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 328ae0a6e93..84f15c7db7d 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -138,7 +138,7 @@ protected InvokableStmt getInvokableStmtNonInvokeExpr( // static fields and new array expressions if (invokableStmt instanceof JAssignStmt && !((InvokableStmt) invokableStmt).containsInvokeExpr() - && ((InvokableStmt) invokableStmt).doesInvoke()) { + && ((InvokableStmt) invokableStmt).invokesStaticInitializer()) { Value expr; // look at the left or right side of the assigment if (leftExpr) { diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java index e4b6f68ce3e..11008b35fe3 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/InvokableStmt.java @@ -32,11 +32,13 @@ public interface InvokableStmt extends Stmt { /** - * Checks if the invokable statement actually invokes + * Checks if the invokable statement can potentially invoke a static initializer To cause a static + * initializer call, the statement contains a static method call, a new expression, or a static + * field reference. * - * @return true if the statement invokes something, and false if not. + * @return true if the statement can cause a static initializer call, and false if not. */ - boolean doesInvoke(); + boolean invokesStaticInitializer(); /** * Checks if the invokable statement contains a invoke expression that defines the invoke. diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java index 0cae086ad0e..fb9f54c19ab 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JAssignStmt.java @@ -52,6 +52,7 @@ import sootup.core.jimple.common.expr.JNewArrayExpr; import sootup.core.jimple.common.expr.JNewExpr; import sootup.core.jimple.common.expr.JNewMultiArrayExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.ref.ConcreteRef; import sootup.core.jimple.common.ref.JArrayRef; import sootup.core.jimple.common.ref.JFieldRef; @@ -107,15 +108,9 @@ public boolean containsInvokeExpr() { return getRightOp() instanceof AbstractInvokeExpr; } - /** - * Checks if the assignment statement invokes a method call - * - * @return it is true if the assignment statement contains an invoke expression or if the left or - * right operand is a static field - */ @Override - public boolean doesInvoke() { - if (containsInvokeExpr()) { + public boolean invokesStaticInitializer() { + if (getInvokeExpr().isPresent() && getInvokeExpr().get() instanceof JStaticInvokeExpr) { return true; } Value rightOp = getRightOp(); diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java index eabbd8cf026..2d5316701e3 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/JInvokeStmt.java @@ -28,6 +28,7 @@ import sootup.core.jimple.basic.StmtPositionInfo; import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.visitor.StmtVisitor; import sootup.core.util.printer.StmtPrinter; @@ -48,8 +49,8 @@ public boolean containsInvokeExpr() { } @Override - public boolean doesInvoke() { - return true; + public boolean invokesStaticInitializer() { + return invokeExpr instanceof JStaticInvokeExpr; } @Override diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java index f0689bd129f..e47b23ee7ef 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java @@ -18,23 +18,47 @@ public class JAssignStmtTest { @Test - public void testDoesInvoke() { + public void testInvokesStaticInitializer() { JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); Local local = LocalUtil.createDummyLocalForInt(); - assertTrue(AssignStmtUtil.createDummyAssignStmtWithExpr().doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef).doesInvoke()); - assertTrue(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef).doesInvoke()); + assertTrue( + AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyStaticInvokeExpr()) + .invokesStaticInitializer()); + assertFalse( + AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyVirtualInvokeExpr()) + .invokesStaticInitializer()); + assertFalse( + AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummySpecialInvokeExpr()) + .invokesStaticInitializer()); + assertFalse( + AssignStmtUtil.createDummyAssignStmtWithExpr( + InvokeExprUtil.createDummyInterfaceInvokeExpr()) + .invokesStaticInitializer()); + + assertTrue( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).invokesStaticInitializer()); + assertTrue( + AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).invokesStaticInitializer()); + assertTrue( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef) + .invokesStaticInitializer()); + assertTrue( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) + .invokesStaticInitializer()); + assertTrue( + AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) + .invokesStaticInitializer()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).doesInvoke()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).doesInvoke()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef).doesInvoke()); - assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().doesInvoke()); + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).invokesStaticInitializer()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).invokesStaticInitializer()); + assertFalse( + AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) + .invokesStaticInitializer()); + assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().invokesStaticInitializer()); } @Test @@ -43,7 +67,9 @@ public void testContainsInvokeExpr() { JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); Local local = LocalUtil.createDummyLocalForInt(); - assertTrue(AssignStmtUtil.createDummyAssignStmtWithExpr().containsInvokeExpr()); + assertTrue( + AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyStaticInvokeExpr()) + .containsInvokeExpr()); assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).containsInvokeExpr()); assertFalse(AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).containsInvokeExpr()); @@ -71,7 +97,10 @@ public void testGetInvokeExpr() { assertEquals( InvokeExprUtil.createDummyStaticInvokeExpr().toString(), - AssignStmtUtil.createDummyAssignStmtWithExpr().getInvokeExpr().get().toString()); + AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyStaticInvokeExpr()) + .getInvokeExpr() + .get() + .toString()); assertFalse( AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).getInvokeExpr().isPresent()); diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java index ba887d942f0..d29a2fd0126 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java @@ -1,6 +1,7 @@ package sootup.core.jimple.common.stmt; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Tag; @@ -32,6 +33,23 @@ public void testContainsInvokeExpr() { assertTrue(invokeStmt3.containsInvokeExpr()); } + @Test + public void testInvokesStaticInitializer() { + SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); + + JInvokeStmt invokeStmt = new JInvokeStmt(InvokeExprUtil.createDummyStaticInvokeExpr(), pos); + assertTrue(invokeStmt.invokesStaticInitializer()); + + JInvokeStmt invokeStmt1 = new JInvokeStmt(InvokeExprUtil.createDummyInterfaceInvokeExpr(), pos); + assertFalse(invokeStmt1.invokesStaticInitializer()); + + JInvokeStmt invokeStmt2 = new JInvokeStmt(InvokeExprUtil.createDummySpecialInvokeExpr(), pos); + assertFalse(invokeStmt2.invokesStaticInitializer()); + + JInvokeStmt invokeStmt3 = new JInvokeStmt(InvokeExprUtil.createDummyVirtualInvokeExpr(), pos); + assertFalse(invokeStmt3.invokesStaticInitializer()); + } + @Test public void testGetInvokeExpr() { SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); diff --git a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java index d8d392301a4..aa81e1fe3c0 100644 --- a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java +++ b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java @@ -4,6 +4,7 @@ import sootup.core.jimple.basic.Local; import sootup.core.jimple.basic.SimpleStmtPositionInfo; import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.ref.JFieldRef; import sootup.core.jimple.common.stmt.JAssignStmt; @@ -11,15 +12,16 @@ public class AssignStmtUtil { /** * will return a dummy assignment statement with an invoke expression the left value will be the - * dummy int local the right value will be the dummy static invoke expression stmt position is the - * dummy SimpleStatementPositionInfo + * dummy int local the right value will be the given invoke expression stmt position is the dummy + * SimpleStatementPositionInfo * + * @param invokeExpr the invokeExpr in the dummy assignment statement * @return a dummy JAssignStmt with a static invoke expression */ - public static JAssignStmt createDummyAssignStmtWithExpr() { + public static JAssignStmt createDummyAssignStmtWithExpr(AbstractInvokeExpr invokeExpr) { Local local = LocalUtil.createDummyLocalForInt(); SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(local, InvokeExprUtil.createDummyStaticInvokeExpr(), pos); + return new JAssignStmt(local, invokeExpr, pos); } /** From c42a253c8a9f5e480696448b11e0ed07b8fa6b53 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 27 May 2024 16:00:39 +0200 Subject: [PATCH 32/41] added testcase for bug report 903 --- .../sootup/callgraph/CallGraphTestBase.java | 33 ++++++++++++++++++ .../callgraph/Bugfixes/binary/Issue903.java | 16 +++++++++ .../Bugfixes/binary/issue903/A.class | Bin 0 -> 222 bytes .../Bugfixes/binary/issue903/B.class | Bin 0 -> 514 bytes 4 files changed, 49 insertions(+) create mode 100644 sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/Issue903.java create mode 100644 sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/issue903/A.class create mode 100644 sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/issue903/B.class diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 84f15c7db7d..2e6163bffe3 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -1230,4 +1230,37 @@ private void checkClinit( assertTrue(cg.containsCall(mainMethodSignature, clinitObject, invokeStmt)); assertTrue(cg.containsCall(mainMethodSignature, clinitMethod, invokeStmt)); } + + @Test + public void testIssue903() { + CallGraph cg = loadCallGraph("Bugfixes", false,"issue903.B"); + + MethodSignature closingCall = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("issue903.A"), + "close", + "void", + Collections.emptyList()); + MethodSignature closingCallInvoked = + identifierFactory.getMethodSignature( + identifierFactory.getClassType("issue903.B"), + "close", + "void", + Collections.emptyList()); + + assertTrue( + cg.containsCall( + mainMethodSignature, + closingCall, + getInvokableStmt(mainMethodSignature, closingCallInvoked, 0))); + + assertTrue( + cg.containsCall( + closingCall, + closingCall, + getInvokableStmt(closingCall, closingCall, 0))); + + } + } + diff --git a/sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/Issue903.java b/sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/Issue903.java new file mode 100644 index 00000000000..17787ab98c8 --- /dev/null +++ b/sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/Issue903.java @@ -0,0 +1,16 @@ +package issue903; +import java.io.Closeable; + +interface A extends Closeable { + @Override + default void close(){ + close(); + } +} + +class B implements A { + public static void main(String[] args) { + try (B b = new B()) { + } + } +} \ No newline at end of file diff --git a/sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/issue903/A.class b/sootup.callgraph/src/test/resources/callgraph/Bugfixes/binary/issue903/A.class new file mode 100644 index 0000000000000000000000000000000000000000..22eb620165567fc717b6a9b8bb39bbc0d3e90801 GIT binary patch literal 222 zcmXX=y9&ZU5S&X)F6LqM8*J3V6ST3EfFOt#ihU9fNr*W}jQ?e+g&*KYiF-j7hMn2j z-T8c9ZvYE~9t?OKK1aaOW3bXf)sn#+jZX}nNS%p<+pLtk=9a7(v&0Aov)P&1+4ttn?0$T`z5_T$K?X;PBP~NhN|-f{jEoSn9P1o8hVYqXTi!WC zptyU-5WMOeCPTbx*=F7EwM?g}wYroE_B6|8NEaWf9qn1GbTzwOX?Tuhw@(F8ZFrjg zRMQ4CJjVv9k`{y9==+XtUR$DydgHpjd2)DkAc`nhf=meOH(9wo`nm;KT2nBj94u%Ll zq(qxKrBjrmJb6Ywv^N18QNW;(4bPHM0;-5nETA?~gXDMKAl*+8sIppVid=b$WND1x z5Q%zue~j=DT%1QlTR|FG`XFgmG=>1tRnm@O8*y5o+rYOl90`tPP7FpS@<~t{p8yh8 Fe*oRdVkZCq literal 0 HcmV?d00001 From 531b25ad95d577a18f25bf37af37270165a1275b Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 27 May 2024 16:02:26 +0200 Subject: [PATCH 33/41] fmt --- .../sootup/callgraph/CallGraphTestBase.java | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index 2e6163bffe3..e88faabf1d6 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -1233,20 +1233,14 @@ private void checkClinit( @Test public void testIssue903() { - CallGraph cg = loadCallGraph("Bugfixes", false,"issue903.B"); + CallGraph cg = loadCallGraph("Bugfixes", false, "issue903.B"); MethodSignature closingCall = identifierFactory.getMethodSignature( - identifierFactory.getClassType("issue903.A"), - "close", - "void", - Collections.emptyList()); + identifierFactory.getClassType("issue903.A"), "close", "void", Collections.emptyList()); MethodSignature closingCallInvoked = identifierFactory.getMethodSignature( - identifierFactory.getClassType("issue903.B"), - "close", - "void", - Collections.emptyList()); + identifierFactory.getClassType("issue903.B"), "close", "void", Collections.emptyList()); assertTrue( cg.containsCall( @@ -1255,12 +1249,6 @@ public void testIssue903() { getInvokableStmt(mainMethodSignature, closingCallInvoked, 0))); assertTrue( - cg.containsCall( - closingCall, - closingCall, - getInvokableStmt(closingCall, closingCall, 0))); - + cg.containsCall(closingCall, closingCall, getInvokableStmt(closingCall, closingCall, 0))); } - } - From 45292192587d6e5e87e12b14a5cb63efca3d8170 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Wed, 5 Jun 2024 11:58:16 +0200 Subject: [PATCH 34/41] fmt --- .../main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java | 3 ++- .../main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java | 3 ++- sootup.tests/src/test/java/sootup/tests/CallGraphTest.java | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index b4b926ed5b4..3d654e856ff 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -335,7 +335,8 @@ private void addStaticInitializerCalls( targetSig -> addCallToCG(sourceSig, targetSig.getSignature(), invokableStmt, cg, workList)); // static initializer calls of all superclasses - view.getTypeHierarchy().superClassesOf(targetClass) + view.getTypeHierarchy() + .superClassesOf(targetClass) .map(classType -> view.getMethod(classType.getStaticInitializer())) .filter(Optional::isPresent) .map(Optional::get) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java index 438e51d4a27..5dce36986ec 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/RapidTypeAnalysisAlgorithm.java @@ -165,7 +165,8 @@ private Stream resolveAllCallTargets( MethodSignature source, MethodSignature resolveBaseMethodSignature, InvokableStmt invokableStmt) { - return view.getTypeHierarchy().subtypesOf(resolveBaseMethodSignature.getDeclClassType()) + return view.getTypeHierarchy() + .subtypesOf(resolveBaseMethodSignature.getDeclClassType()) .map( classType -> { MethodSignature method = diff --git a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java index 671c793c04b..f2fd07c5ef6 100644 --- a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java +++ b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java @@ -57,7 +57,7 @@ CallGraph loadCallGraph() { String classPath = "src/test/resources/callgraph/" + "Misc"; // JavaView view = viewToClassPath.computeIfAbsent(classPath, this::createViewForClassPath); - view =createViewForClassPath(classPath); + view = createViewForClassPath(classPath); identifierFactory = view.getIdentifierFactory(); mainClassSignature = identifierFactory.getClassType("Main"); From 796dc7db2a18a6dfdcf0d50acfc1bad8f364442f Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 15 Jul 2024 14:12:52 +0200 Subject: [PATCH 35/41] added isInvokableStmt and asInvokableStmt to the Stmt API --- .../icfg/AbstractJimpleBasedICFG.java | 3 +-- .../interprocedural/icfg/CGEdgeUtil.java | 5 ++-- .../interprocedural/icfg/ICFGDotExporter.java | 5 ++-- .../icfg/JimpleBasedInterproceduralCFG.java | 5 ++-- .../interprocedural/ifds/CGEdgeUtilTest.java | 8 +++---- .../ifds/IFDSTaintAnalysisProblem.java | 6 ++--- .../callgraph/AbstractCallGraphAlgorithm.java | 9 ++++---- .../core/jimple/common/stmt/AbstractStmt.java | 23 +++++++++++++++++++ .../sootup/core/jimple/common/stmt/Stmt.java | 4 ++++ .../sootup/core/validation/NewValidator.java | 5 ++-- .../test/java/sootup/tests/CallGraphTest.java | 10 ++++---- 11 files changed, 53 insertions(+), 30 deletions(-) diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java index f79a9a28c26..93543f5b7c2 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java @@ -31,7 +31,6 @@ import javax.annotation.Nonnull; import sootup.core.graph.StmtGraph; import sootup.core.jimple.basic.Value; -import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.Body; import sootup.core.model.SootMethod; @@ -186,7 +185,7 @@ public boolean setOwnerStatement(Stmt u, Body b) { @Override public boolean isCallStmt(Stmt stmt) { - return stmt instanceof InvokableStmt && ((InvokableStmt) stmt).containsInvokeExpr(); + return stmt.isInvokableStmt() && stmt.asInvokableStmt().containsInvokeExpr(); } @Override diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java index 9f415c4d449..01b2e0b38f6 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java @@ -28,7 +28,6 @@ import org.apache.commons.lang3.tuple.Pair; import sootup.callgraph.CallGraph; import sootup.core.jimple.common.expr.*; -import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; @@ -60,8 +59,8 @@ public static Set> getCallEdges( SootMethod method = view.getMethod(caller).orElse(null); if (method != null && method.hasBody()) { for (Stmt s : method.getBody().getStmtGraph().getNodes()) { - if (s instanceof InvokableStmt && ((InvokableStmt) s).containsInvokeExpr()) { - AbstractInvokeExpr invokeExpr = ((InvokableStmt) s).getInvokeExpr().get(); + if (s.isInvokableStmt() && s.asInvokableStmt().containsInvokeExpr()) { + AbstractInvokeExpr invokeExpr = s.asInvokableStmt().getInvokeExpr().get(); CalleeMethodSignature callee = new CalleeMethodSignature( invokeExpr.getMethodSignature(), findCallGraphEdgeType(invokeExpr), s); diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java index d52bb670668..b7d6a285a2b 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/ICFGDotExporter.java @@ -28,7 +28,6 @@ import sootup.core.graph.BasicBlock; import sootup.core.graph.StmtGraph; import sootup.core.jimple.common.expr.JNewExpr; -import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; @@ -73,9 +72,9 @@ public static Map computeCalls( for (BasicBlock block : blocks) { List stmts = block.getStmts(); for (Stmt stmt : stmts) { - if (stmt instanceof InvokableStmt && ((InvokableStmt) stmt).containsInvokeExpr()) { + if (stmt.isInvokableStmt() && stmt.asInvokableStmt().containsInvokeExpr()) { MethodSignature target = - ((InvokableStmt) stmt).getInvokeExpr().get().getMethodSignature(); + stmt.asInvokableStmt().getInvokeExpr().get().getMethodSignature(); int hashCode = stmt.hashCode(); calls.put(hashCode, target); // compute all the classes that are made to the subclasses as well diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java index ae95adb1552..141a4101e4a 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/JimpleBasedInterproceduralCFG.java @@ -73,10 +73,9 @@ public class JimpleBasedInterproceduralCFG extends AbstractJimpleBasedICFG { @Override public Collection load(Stmt stmt) { ArrayList res = new ArrayList<>(); - if (!(stmt instanceof InvokableStmt) && !((InvokableStmt) stmt).containsInvokeExpr()) - return res; + if (!stmt.isInvokableStmt() && !stmt.asInvokableStmt().containsInvokeExpr()) return res; MethodSignature methodSignature = - ((InvokableStmt) stmt).getInvokeExpr().get().getMethodSignature(); + stmt.asInvokableStmt().getInvokeExpr().get().getMethodSignature(); Optional smOpt = view.getMethod(methodSignature); if (smOpt.isPresent()) { SootMethod sm = smOpt.get(); diff --git a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java index 9cfc7e09d05..df115508df5 100644 --- a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java +++ b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/CGEdgeUtilTest.java @@ -164,8 +164,8 @@ public void testGetCallEdges() { List invokesStmts = m.getBody().getStmts().stream() - .filter(stmt -> stmt instanceof InvokableStmt) - .map(stmt -> (InvokableStmt) stmt) + .filter(Stmt::isInvokableStmt) + .map(Stmt::asInvokableStmt) .filter(InvokableStmt::containsInvokeExpr) .collect(Collectors.toList()); assertEquals(invokesStmts.size(), 3); @@ -225,8 +225,8 @@ private void checkPair( assertNotNull(virtualCall); Stmt virtualStmt = invokesStmts.stream() - .filter(stmt -> stmt instanceof InvokableStmt) - .map(stmt -> (InvokableStmt) stmt) + .filter(Stmt::isInvokableStmt) + .map(Stmt::asInvokableStmt) .filter(InvokableStmt::containsInvokeExpr) .filter(stmt -> stmt.getInvokeExpr().get().getClass() == invokeClass) .findAny() diff --git a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java index db42423e082..51441a701c5 100644 --- a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java +++ b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java @@ -74,18 +74,18 @@ public FlowFunction getNormalFlowFunction(Stmt curr, Stmt succ) { @Override public FlowFunction getCallFlowFunction(Stmt callStmt, SootMethod destinationMethod) { - return getCallFlow((InvokableStmt) callStmt, destinationMethod); + return getCallFlow(callStmt.asInvokableStmt(), destinationMethod); } @Override public FlowFunction getReturnFlowFunction( Stmt callSite, SootMethod calleeMethod, Stmt exitStmt, Stmt returnSite) { - return getReturnFlow((InvokableStmt) callSite, calleeMethod, exitStmt, returnSite); + return getReturnFlow(callSite.asInvokableStmt(), calleeMethod, exitStmt, returnSite); } @Override public FlowFunction getCallToReturnFlowFunction(Stmt callSite, Stmt returnSite) { - return getCallToReturnFlow((InvokableStmt) callSite, returnSite); + return getCallToReturnFlow(callSite.asInvokableStmt(), returnSite); } }; } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java index 3d654e856ff..be599ea6adc 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/AbstractCallGraphAlgorithm.java @@ -36,6 +36,7 @@ import sootup.core.jimple.common.ref.JStaticFieldRef; import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; +import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.Method; import sootup.core.model.SootClass; import sootup.core.model.SootClassMember; @@ -227,8 +228,8 @@ protected void resolveAllCallsFromSourceMethod( } sourceMethod.getBody().getStmts().stream() - .filter(stmt -> stmt instanceof InvokableStmt) - .map(stmt -> (InvokableStmt) stmt) + .filter(Stmt::isInvokableStmt) + .map(Stmt::asInvokableStmt) .forEach( stmt -> resolveCall(sourceMethod, stmt) @@ -269,8 +270,8 @@ protected void resolveAllStaticInitializerCalls( } InstantiateClassValueVisitor instantiateVisitor = new InstantiateClassValueVisitor(); sourceMethod.getBody().getStmts().stream() - .filter(stmt -> stmt instanceof InvokableStmt) - .map(stmt -> (InvokableStmt) stmt) + .filter(Stmt::isInvokableStmt) + .map(Stmt::asInvokableStmt) .forEach( invokableStmt -> { // static field usage diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java index f5f4619663a..6d57e9ede2b 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java @@ -129,4 +129,27 @@ public Stmt withNewUse(@Nonnull Value oldUse, @Nonnull Value newUse) { } return visitor.getResult(); } + + /** + * Checks if the statement is an invokable statement, this means it either contains an invoke + * expression or causes a static initializer call + * + * @return true if the Object is an instance of {@link{ #InvokableStmt}}, otherwise false + */ + @Override + public boolean isInvokableStmt() { + return this instanceof InvokableStmt; + } + + /** + * Transforms the statement to an {@link{ #InvokableStmt}} if it is possible. if not it will throw + * an Exception. Before this method is used {@link{ #isInvokableStmt}} should be called to prevent + * exceptions + * + * @return the typecast of this to InvokableStmt + */ + @Override + public InvokableStmt asInvokableStmt() { + return (InvokableStmt) this; + } } diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java index 597aa4855a3..c2d188fa150 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/Stmt.java @@ -70,4 +70,8 @@ public interface Stmt extends EquivTo, Acceptor { StmtPositionInfo getPositionInfo(); Stmt withNewUse(@Nonnull Value oldUse, @Nonnull Value newUse); + + boolean isInvokableStmt(); + + InvokableStmt asInvokableStmt(); } diff --git a/sootup.core/src/main/java/sootup/core/validation/NewValidator.java b/sootup.core/src/main/java/sootup/core/validation/NewValidator.java index 95c3c7024aa..214dd1c1b49 100644 --- a/sootup.core/src/main/java/sootup/core/validation/NewValidator.java +++ b/sootup.core/src/main/java/sootup/core/validation/NewValidator.java @@ -29,7 +29,6 @@ import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JNewExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; -import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.jimple.common.stmt.Stmt; @@ -97,8 +96,8 @@ private boolean checkForInitializerOnPath( continue; } if (!newStmt.equals(curStmt)) { - if (((InvokableStmt) curStmt).containsInvokeExpr()) { - AbstractInvokeExpr expr = ((InvokableStmt) curStmt).getInvokeExpr().get(); + if (curStmt.isInvokableStmt() && curStmt.asInvokableStmt().containsInvokeExpr()) { + AbstractInvokeExpr expr = curStmt.asInvokableStmt().getInvokeExpr().get(); if (!(expr instanceof JSpecialInvokeExpr)) { exception.add( new ValidationException( diff --git a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java index f2fd07c5ef6..63f02d032ce 100644 --- a/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java +++ b/sootup.tests/src/test/java/sootup/tests/CallGraphTest.java @@ -83,15 +83,15 @@ protected InvokableStmt getInvokableStmt( MethodSignature sourceMethod, MethodSignature staticTargetMethod) { SootMethod method = view.getMethod(sourceMethod).orElse(null); assertNotNull(method); - for (Stmt invokableStmt : method.getBody().getStmts()) { - if (invokableStmt instanceof InvokableStmt - && ((InvokableStmt) invokableStmt).containsInvokeExpr() - && ((InvokableStmt) invokableStmt) + for (Stmt stmt : method.getBody().getStmts()) { + if (stmt.isInvokableStmt() + && stmt.asInvokableStmt().containsInvokeExpr() + && stmt.asInvokableStmt() .getInvokeExpr() .get() .getMethodSignature() .equals(staticTargetMethod)) { - return (InvokableStmt) invokableStmt; + return stmt.asInvokableStmt(); } } throw new RuntimeException("No invokable stmt found for " + sourceMethod); From 02907b008b15aed535c38c79d5d3e6a262995a62 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 15 Jul 2024 14:19:28 +0200 Subject: [PATCH 36/41] fixed warnings --- .../icfg/AbstractJimpleBasedICFG.java | 3 + .../interprocedural/icfg/CGEdgeUtil.java | 2 +- .../ifds/IFDSTaintAnalysisProblem.java | 133 ++++++++---------- .../core/jimple/common/stmt/AbstractStmt.java | 11 +- 4 files changed, 67 insertions(+), 82 deletions(-) diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java index 93543f5b7c2..753140915f7 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/AbstractJimpleBasedICFG.java @@ -49,6 +49,7 @@ public abstract class AbstractJimpleBasedICFG implements BiDiInterproceduralCFG< protected LoadingCache> bodyToStmtGraph = IDESolver.DEFAULT_CACHE_BUILDER.build( new CacheLoader>() { + @Nonnull @Override public StmtGraph load(@Nonnull Body body) { return makeGraph(body); @@ -59,6 +60,7 @@ public StmtGraph load(@Nonnull Body body) { protected LoadingCache> methodToParameterRefs = IDESolver.DEFAULT_CACHE_BUILDER.build( new CacheLoader>() { + @Nonnull @Override public List load(@Nonnull SootMethod m) { return new ArrayList<>(m.getBody().getParameterLocals()); @@ -69,6 +71,7 @@ public List load(@Nonnull SootMethod m) { protected LoadingCache> methodToCallsFromWithin = IDESolver.DEFAULT_CACHE_BUILDER.build( new CacheLoader>() { + @Nonnull @Override public Set load(@Nonnull SootMethod m) { return getCallsFromWithinMethod(m); diff --git a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java index 01b2e0b38f6..50194965d8e 100644 --- a/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java +++ b/sootup.analysis/src/main/java/sootup/analysis/interprocedural/icfg/CGEdgeUtil.java @@ -115,7 +115,7 @@ public enum CallGraphEdgeType { /** Due to call to Class.newInstance(..) when reflection log is enabled. */ REFL_CLASS_NEWINSTANCE("REFL_CLASS_NEWINSTANCE"); - private String name; + private final String name; CallGraphEdgeType(String name) { this.name = name; diff --git a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java index 51441a701c5..f3392c84fc6 100644 --- a/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java +++ b/sootup.analysis/src/test/java/sootup/analysis/interprocedural/ifds/IFDSTaintAnalysisProblem.java @@ -46,7 +46,7 @@ public class IFDSTaintAnalysisProblem extends DefaultJimpleIFDSTabulationProblem> { - private SootMethod entryMethod; + private final SootMethod entryMethod; protected InterproceduralCFG icfg; @@ -107,22 +107,19 @@ FlowFunction getNormalFlow(Stmt curr, Stmt succ) { return new Gen<>(leftOp, zeroValue()); } } - return new FlowFunction() { - @Override - public Set computeTargets(Value source) { - // source = {v.f*} some local and all its fields - // Kill T = ... - if (source == leftOp) { - return Collections.emptySet(); - } - Set res = new HashSet(); - res.add(source); - // x = T - if (source == rightOp) { - res.add(leftOp); - } - return res; + return source -> { + // source = {v.f*} some local and all its fields + // Kill T = ... + if (source == leftOp) { + return Collections.emptySet(); + } + Set res = new HashSet<>(); + res.add(source); + // x = T + if (source == rightOp) { + res.add(leftOp); } + return res; }; } return Identity.v(); @@ -136,7 +133,7 @@ FlowFunction getCallFlow(InvokableStmt callStmt, final SootMethod destina AbstractInvokeExpr ie = callStmt.getInvokeExpr().get(); final List callArgs = ie.getArgs(); - final List paramLocals = new ArrayList(); + final List paramLocals = new ArrayList<>(); for (int i = 0; i < destinationMethod.getParameterCount(); i++) { paramLocals.add(destinationMethod.getBody().getParameterLocal(i)); } @@ -154,21 +151,18 @@ FlowFunction getCallFlow(InvokableStmt callStmt, final SootMethod destina } final Value baseF = base; - return new FlowFunction() { - @Override - public Set computeTargets(Value source) { - Set ret = new HashSet<>(); - if (source instanceof JStaticFieldRef) { - ret.add(source); - } - // Tainted func parameters - for (int i = 0; i < callArgs.size(); i++) { - if (callArgs.get(i).equivTo(source) && i < paramLocals.size()) { - ret.add(paramLocals.get(i)); - } + return source -> { + Set ret = new HashSet<>(); + if (source instanceof JStaticFieldRef) { + ret.add(source); + } + // Tainted func parameters + for (int i = 0; i < callArgs.size(); i++) { + if (callArgs.get(i).equivTo(source) && i < paramLocals.size()) { + ret.add(paramLocals.get(i)); } - return ret; } + return ret; }; } @@ -203,37 +197,31 @@ FlowFunction getReturnFlow( } } } - return new FlowFunction() { - @Override - public Set computeTargets(Value source) { - Set ret = new HashSet<>(); - if (source instanceof JStaticFieldRef) { - ret.add(source); - } - if (callSite instanceof AbstractDefinitionStmt && source == retOp) { - AbstractDefinitionStmt defnStmt = (AbstractDefinitionStmt) callSite; - ret.add(defnStmt.getLeftOp()); - } - if (baseF != null && source.equals(calleeMethod.getBody().getThisLocal())) { - ret.add(baseF); - } - return ret; + return source -> { + Set ret = new HashSet<>(); + if (source instanceof JStaticFieldRef) { + ret.add(source); + } + if (callSite instanceof AbstractDefinitionStmt && source == retOp) { + AbstractDefinitionStmt defnStmt = (AbstractDefinitionStmt) callSite; + ret.add(defnStmt.getLeftOp()); } + if (baseF != null && source.equals(calleeMethod.getBody().getThisLocal())) { + ret.add(baseF); + } + return ret; }; } if (exitStmt instanceof JReturnVoidStmt) { - return new FlowFunction() { - @Override - public Set computeTargets(Value source) { - Set ret = new HashSet(); - if (source instanceof JStaticFieldRef) { - ret.add(source); - } - if (baseF != null && source.equals(calleeMethod.getBody().getThisLocal())) { - ret.add(baseF); - } - return ret; + return source -> { + Set ret = new HashSet<>(); + if (source instanceof JStaticFieldRef) { + ret.add(source); } + if (baseF != null && source.equals(calleeMethod.getBody().getThisLocal())) { + ret.add(baseF); + } + return ret; }; } return KillAll.v(); @@ -267,25 +255,22 @@ FlowFunction getCallToReturnFlow(final InvokableStmt callSite, Stmt retur // use assumption if no callees to analyze if (icfg.getCalleesOfCallAt(callSite).isEmpty()) { - return new FlowFunction() { - @Override - public Set computeTargets(Value source) { - Set ret = new HashSet(); - ret.add(source); - // taint leftOp if base is tainted - if (baseF != null && leftOpF != null && source == baseF) { - ret.add(leftOpF); - } - // taint leftOp if one of the args is tainted - if (leftOpF != null && callArgs.contains(source)) { - ret.add(leftOpF); - } - // taint base if one of the args is tainted and has no callee in known methods - if (baseF != null && callArgs.contains(source)) { - ret.add(baseF); - } - return ret; + return source -> { + Set ret = new HashSet<>(); + ret.add(source); + // taint leftOp if base is tainted + if (baseF != null && leftOpF != null && source == baseF) { + ret.add(leftOpF); + } + // taint leftOp if one of the args is tainted + if (leftOpF != null && callArgs.contains(source)) { + ret.add(leftOpF); } + // taint base if one of the args is tainted and has no callee in known methods + if (baseF != null && callArgs.contains(source)) { + ret.add(baseF); + } + return ret; }; } return Identity.v(); diff --git a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java index 6d57e9ede2b..8251b0fee15 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/common/stmt/AbstractStmt.java @@ -65,10 +65,7 @@ public Optional getDef() { @Nonnull public Stream getUsesAndDefs() { Optional def = getDef(); - if (def.isPresent()) { - return Stream.concat(getUses(), Stream.of(def.get())); - } - return getUses(); + return def.map(lValue -> Stream.concat(getUses(), Stream.of(lValue))).orElseGet(this::getUses); } /** Returns the amount of unexceptional successors the Stmt needs to have in the StmtGraph. */ @@ -134,7 +131,7 @@ public Stmt withNewUse(@Nonnull Value oldUse, @Nonnull Value newUse) { * Checks if the statement is an invokable statement, this means it either contains an invoke * expression or causes a static initializer call * - * @return true if the Object is an instance of {@link{ #InvokableStmt}}, otherwise false + * @return true if the Object is an instance of {@link InvokableStmt}, otherwise false */ @Override public boolean isInvokableStmt() { @@ -142,8 +139,8 @@ public boolean isInvokableStmt() { } /** - * Transforms the statement to an {@link{ #InvokableStmt}} if it is possible. if not it will throw - * an Exception. Before this method is used {@link{ #isInvokableStmt}} should be called to prevent + * Transforms the statement to an {@link InvokableStmt} if it is possible. if not it will throw an + * Exception. Before this method is used {@link #isInvokableStmt} should be called to prevent * exceptions * * @return the typecast of this to InvokableStmt From 38bd53ead25796e8949631b971050ba1f0821977 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 15 Jul 2024 14:32:30 +0200 Subject: [PATCH 37/41] moved all Util methods into one class --- .../src/test/java/sootup/core/TestUtil.java | 230 ++++++++++++++++++ .../jimple/common/stmt/JAssignStmtTest.java | 104 ++++---- .../jimple/common/stmt/JInvokeStmtTest.java | 26 +- .../test/java/sootup/util/AssignStmtUtil.java | 62 ----- .../test/java/sootup/util/ClassTypeUtil.java | 36 --- .../test/java/sootup/util/FieldRefUtil.java | 26 -- .../test/java/sootup/util/InvokeExprUtil.java | 51 ---- .../src/test/java/sootup/util/LocalUtil.java | 25 -- .../test/java/sootup/util/SignatureUtil.java | 50 ---- .../test/java/sootup/util/StmtPosUtil.java | 15 -- 10 files changed, 287 insertions(+), 338 deletions(-) create mode 100644 sootup.core/src/test/java/sootup/core/TestUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/AssignStmtUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/ClassTypeUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/FieldRefUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/InvokeExprUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/LocalUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/SignatureUtil.java delete mode 100644 sootup.core/src/test/java/sootup/util/StmtPosUtil.java diff --git a/sootup.core/src/test/java/sootup/core/TestUtil.java b/sootup.core/src/test/java/sootup/core/TestUtil.java new file mode 100644 index 00000000000..6ebd19ae2d6 --- /dev/null +++ b/sootup.core/src/test/java/sootup/core/TestUtil.java @@ -0,0 +1,230 @@ +package sootup.core; + +import java.util.Collections; +import sootup.core.jimple.basic.LValue; +import sootup.core.jimple.basic.Local; +import sootup.core.jimple.basic.SimpleStmtPositionInfo; +import sootup.core.jimple.basic.Value; +import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; +import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.expr.JVirtualInvokeExpr; +import sootup.core.jimple.common.ref.JFieldRef; +import sootup.core.jimple.common.ref.JInstanceFieldRef; +import sootup.core.jimple.common.ref.JStaticFieldRef; +import sootup.core.jimple.common.stmt.JAssignStmt; +import sootup.core.signatures.FieldSignature; +import sootup.core.signatures.FieldSubSignature; +import sootup.core.signatures.MethodSignature; +import sootup.core.signatures.MethodSubSignature; +import sootup.core.signatures.PackageName; +import sootup.core.types.ClassType; +import sootup.core.types.PrimitiveType.IntType; + +public class TestUtil { + + /** + * creates a dummy SimpleStmtPositionInfo lineNumber 1 + * + * @return a dummy SimpleStmtPositionInfo + */ + public static SimpleStmtPositionInfo createDummySimpleStmtPositionInfo() { + return new SimpleStmtPositionInfo(1); + } + + /** + * creates a dummy method signature Class Type: dummy class type SubSignature: dummy method sub + * signature + * + * @return a dummy method signature + */ + public static MethodSignature createDummyMethodSignature() { + return new MethodSignature( + TestUtil.createDummyClassType(), TestUtil.createDummyMethodSubSignature()); + } + + /** + * creates a dummy method sub signature name: test return type: int parameter list: empty + * + * @return a dummy method sub signature + */ + public static MethodSubSignature createDummyMethodSubSignature() { + return new MethodSubSignature("test", Collections.emptyList(), IntType.getInstance()); + } + + /** + * creates a dummy field signature Class Type: dummy class type SubSignature: dummy field sub + * signature + * + * @return a dummy field signature + */ + public static FieldSignature createDummyFieldSignature() { + return new FieldSignature( + TestUtil.createDummyClassType(), TestUtil.createDummyFieldSubSignature()); + } + + /** + * creates a dummy field sub signature name: test type: int + * + * @return a dummy field sub signature + */ + public static FieldSubSignature createDummyFieldSubSignature() { + return new FieldSubSignature("test", IntType.getInstance()); + } + + /** + * creates a dummy Local for an Object Name a Type dummy class type + * + * @return a dummy Local for an Object + */ + public static Local createDummyLocalForObject() { + return new Local("a", TestUtil.createDummyClassType()); + } + + /** + * creates a dummy Local for an Int Name b Type int + * + * @return a dummy Local for a int value + */ + public static Local createDummyLocalForInt() { + return new Local("b", IntType.getInstance()); + } + + /** + * will return a dummy virtual invoke expression local is called a and has the class type Test + * method signature is <Test: int test ()> arguments is an empty list + */ + public static JVirtualInvokeExpr createDummyVirtualInvokeExpr() { + Local local = TestUtil.createDummyLocalForObject(); + MethodSignature methodSignature = TestUtil.createDummyMethodSignature(); + return new JVirtualInvokeExpr(local, methodSignature, Collections.emptyList()); + } + + /** + * will return a dummy special invoke expression local is called a and has the class type Test + * method signature is <Test: int test ()> arguments is an empty list + */ + public static JSpecialInvokeExpr createDummySpecialInvokeExpr() { + Local local = TestUtil.createDummyLocalForObject(); + MethodSignature methodSignature = TestUtil.createDummyMethodSignature(); + return new JSpecialInvokeExpr(local, methodSignature, Collections.emptyList()); + } + + /** + * will return a dummy interface invoke expression local is called a and has the class type Test + * method signature is <Test: int test ()> arguments is an empty list + */ + public static JInterfaceInvokeExpr createDummyInterfaceInvokeExpr() { + Local local = TestUtil.createDummyLocalForObject(); + MethodSignature methodSignature = TestUtil.createDummyMethodSignature(); + return new JInterfaceInvokeExpr(local, methodSignature, Collections.emptyList()); + } + + /** + * will return a dummy static invoke expression method signature is <Test: int test ()> + * arguments is an empty list + */ + public static JStaticInvokeExpr createDummyStaticInvokeExpr() { + MethodSignature methodSignature = TestUtil.createDummyMethodSignature(); + return new JStaticInvokeExpr(methodSignature, Collections.emptyList()); + } + + /** + * creates a dummy static field reference Signature: dummy Field Signature + * + * @return a dummy JStaticFieldRef + */ + public static JStaticFieldRef createDummyStaticFieldRef() { + return new JStaticFieldRef(TestUtil.createDummyFieldSignature()); + } + + /** + * creates a dummy instance field reference local: dummy local Signature: dummy Field Signature + * + * @return a dummy JInstanceFieldRef + */ + public static JInstanceFieldRef createDummyInstanceFieldRef() { + return new JInstanceFieldRef( + TestUtil.createDummyLocalForInt(), TestUtil.createDummyFieldSignature()); + } + + /** + * creates a dummy Class type Classname Test Package name test Fully Qualified Name test.Test + * + * @return a dummy class type + */ + public static ClassType createDummyClassType() { + return new ClassType() { + @Override + public boolean isBuiltInClass() { + return false; + } + + @Override + public String getFullyQualifiedName() { + return "Test"; + } + + @Override + public String getClassName() { + return "Test"; + } + + @Override + public PackageName getPackageName() { + return new PackageName("test"); + } + }; + } + + /** + * will return a dummy assignment statement with an invoke expression the left value will be the + * dummy int local the right value will be the given invoke expression stmt position is the dummy + * SimpleStatementPositionInfo + * + * @param invokeExpr the invokeExpr in the dummy assignment statement + * @return a dummy JAssignStmt with a static invoke expression + */ + public static JAssignStmt createDummyAssignStmtWithExpr(AbstractInvokeExpr invokeExpr) { + Local local = TestUtil.createDummyLocalForInt(); + SimpleStmtPositionInfo pos = TestUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(local, invokeExpr, pos); + } + + /** + * will return a dummy assignment statement the left value will be the dummy static field ref the + * right value will be the dummy local stmt position is the dummy SimpleStatementPositionInfo + * + * @return a dummy JAssignStmt with a static field ref on the left side + */ + public static JAssignStmt createDummyAssignStmtWithStaticFieldRefLeft() { + JFieldRef fieldRef = TestUtil.createDummyStaticFieldRef(); + SimpleStmtPositionInfo pos = TestUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(fieldRef, TestUtil.createDummyLocalForInt(), pos); + } + + /** + * will return a dummy assignment statement stmt position is the dummy SimpleStatementPositionInfo + * + * @param left defines the left value of the dummy assign statement + * @param right defines the right value of the dummy assign statement + * @return a dummy JAssignStmt with an instance field ref on the left side + */ + public static JAssignStmt createDummyAssignStmt(LValue left, Value right) { + SimpleStmtPositionInfo pos = TestUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt(left, right, pos); + } + + /** + * will return a dummy assignment statement the right value will be the dummy local the left value + * will be the dummy local stmt position is the dummy SimpleStatementPositionInfo + * + * @return a dummy JAssignStmt with a static field ref on the left side + */ + public static JAssignStmt createDummyAssignStmtWithLocals() { + SimpleStmtPositionInfo pos = TestUtil.createDummySimpleStmtPositionInfo(); + return new JAssignStmt( + TestUtil.createDummyLocalForInt(), TestUtil.createDummyLocalForInt(), pos); + } +} diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java index e47b23ee7ef..f582954ea59 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JAssignStmtTest.java @@ -6,126 +6,110 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import sootup.core.TestUtil; import sootup.core.jimple.basic.Local; import sootup.core.jimple.common.ref.JInstanceFieldRef; import sootup.core.jimple.common.ref.JStaticFieldRef; -import sootup.util.AssignStmtUtil; -import sootup.util.FieldRefUtil; -import sootup.util.InvokeExprUtil; -import sootup.util.LocalUtil; @Tag("Java8") public class JAssignStmtTest { @Test public void testInvokesStaticInitializer() { - JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); - JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); - Local local = LocalUtil.createDummyLocalForInt(); + JStaticFieldRef staticFieldRef = TestUtil.createDummyStaticFieldRef(); + JInstanceFieldRef instanceFieldRef = TestUtil.createDummyInstanceFieldRef(); + Local local = TestUtil.createDummyLocalForInt(); assertTrue( - AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyStaticInvokeExpr()) + TestUtil.createDummyAssignStmtWithExpr(TestUtil.createDummyStaticInvokeExpr()) .invokesStaticInitializer()); assertFalse( - AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyVirtualInvokeExpr()) + TestUtil.createDummyAssignStmtWithExpr(TestUtil.createDummyVirtualInvokeExpr()) .invokesStaticInitializer()); assertFalse( - AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummySpecialInvokeExpr()) + TestUtil.createDummyAssignStmtWithExpr(TestUtil.createDummySpecialInvokeExpr()) .invokesStaticInitializer()); assertFalse( - AssignStmtUtil.createDummyAssignStmtWithExpr( - InvokeExprUtil.createDummyInterfaceInvokeExpr()) + TestUtil.createDummyAssignStmtWithExpr(TestUtil.createDummyInterfaceInvokeExpr()) .invokesStaticInitializer()); + assertTrue(TestUtil.createDummyAssignStmt(staticFieldRef, local).invokesStaticInitializer()); + assertTrue(TestUtil.createDummyAssignStmt(local, staticFieldRef).invokesStaticInitializer()); assertTrue( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).invokesStaticInitializer()); + TestUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).invokesStaticInitializer()); assertTrue( - AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).invokesStaticInitializer()); - assertTrue( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef) - .invokesStaticInitializer()); - assertTrue( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) + TestUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) .invokesStaticInitializer()); assertTrue( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) + TestUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) .invokesStaticInitializer()); + assertFalse(TestUtil.createDummyAssignStmt(instanceFieldRef, local).invokesStaticInitializer()); + assertFalse(TestUtil.createDummyAssignStmt(local, instanceFieldRef).invokesStaticInitializer()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).invokesStaticInitializer()); - assertFalse( - AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).invokesStaticInitializer()); - assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) + TestUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) .invokesStaticInitializer()); - assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().invokesStaticInitializer()); + assertFalse(TestUtil.createDummyAssignStmtWithLocals().invokesStaticInitializer()); } @Test public void testContainsInvokeExpr() { - JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); - JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); - Local local = LocalUtil.createDummyLocalForInt(); + JStaticFieldRef staticFieldRef = TestUtil.createDummyStaticFieldRef(); + JInstanceFieldRef instanceFieldRef = TestUtil.createDummyInstanceFieldRef(); + Local local = TestUtil.createDummyLocalForInt(); assertTrue( - AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyStaticInvokeExpr()) + TestUtil.createDummyAssignStmtWithExpr(TestUtil.createDummyStaticInvokeExpr()) .containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).containsInvokeExpr()); + assertFalse(TestUtil.createDummyAssignStmt(staticFieldRef, local).containsInvokeExpr()); + assertFalse(TestUtil.createDummyAssignStmt(local, staticFieldRef).containsInvokeExpr()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).containsInvokeExpr()); + TestUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).containsInvokeExpr()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) - .containsInvokeExpr()); + TestUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef).containsInvokeExpr()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) - .containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).containsInvokeExpr()); + TestUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef).containsInvokeExpr()); + assertFalse(TestUtil.createDummyAssignStmt(instanceFieldRef, local).containsInvokeExpr()); + assertFalse(TestUtil.createDummyAssignStmt(local, instanceFieldRef).containsInvokeExpr()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) - .containsInvokeExpr()); - assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().containsInvokeExpr()); + TestUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef).containsInvokeExpr()); + assertFalse(TestUtil.createDummyAssignStmtWithLocals().containsInvokeExpr()); } @Test public void testGetInvokeExpr() { - JStaticFieldRef staticFieldRef = FieldRefUtil.createDummyStaticFieldRef(); - JInstanceFieldRef instanceFieldRef = FieldRefUtil.createDummyInstanceFieldRef(); - Local local = LocalUtil.createDummyLocalForInt(); + JStaticFieldRef staticFieldRef = TestUtil.createDummyStaticFieldRef(); + JInstanceFieldRef instanceFieldRef = TestUtil.createDummyInstanceFieldRef(); + Local local = TestUtil.createDummyLocalForInt(); assertEquals( - InvokeExprUtil.createDummyStaticInvokeExpr().toString(), - AssignStmtUtil.createDummyAssignStmtWithExpr(InvokeExprUtil.createDummyStaticInvokeExpr()) + TestUtil.createDummyStaticInvokeExpr().toString(), + TestUtil.createDummyAssignStmtWithExpr(TestUtil.createDummyStaticInvokeExpr()) .getInvokeExpr() .get() .toString()); + assertFalse(TestUtil.createDummyAssignStmt(staticFieldRef, local).getInvokeExpr().isPresent()); + assertFalse(TestUtil.createDummyAssignStmt(local, staticFieldRef).getInvokeExpr().isPresent()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, local).getInvokeExpr().isPresent()); - assertFalse( - AssignStmtUtil.createDummyAssignStmt(local, staticFieldRef).getInvokeExpr().isPresent()); - assertFalse( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef) - .getInvokeExpr() - .isPresent()); + TestUtil.createDummyAssignStmt(staticFieldRef, staticFieldRef).getInvokeExpr().isPresent()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) + TestUtil.createDummyAssignStmt(instanceFieldRef, staticFieldRef) .getInvokeExpr() .isPresent()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) + TestUtil.createDummyAssignStmt(staticFieldRef, instanceFieldRef) .getInvokeExpr() .isPresent()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, local).getInvokeExpr().isPresent()); + TestUtil.createDummyAssignStmt(instanceFieldRef, local).getInvokeExpr().isPresent()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(local, instanceFieldRef).getInvokeExpr().isPresent()); + TestUtil.createDummyAssignStmt(local, instanceFieldRef).getInvokeExpr().isPresent()); assertFalse( - AssignStmtUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) + TestUtil.createDummyAssignStmt(instanceFieldRef, instanceFieldRef) .getInvokeExpr() .isPresent()); - assertFalse(AssignStmtUtil.createDummyAssignStmtWithLocals().getInvokeExpr().isPresent()); + assertFalse(TestUtil.createDummyAssignStmtWithLocals().getInvokeExpr().isPresent()); } } diff --git a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java index d29a2fd0126..4e2f6914ddb 100644 --- a/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java +++ b/sootup.core/src/test/java/sootup/core/jimple/common/stmt/JInvokeStmtTest.java @@ -6,12 +6,12 @@ import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import sootup.core.TestUtil; import sootup.core.jimple.basic.SimpleStmtPositionInfo; import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.expr.JVirtualInvokeExpr; -import sootup.util.InvokeExprUtil; @Tag("Java8") public class JInvokeStmtTest { @@ -20,16 +20,16 @@ public class JInvokeStmtTest { public void testContainsInvokeExpr() { SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); - JInvokeStmt invokeStmt = new JInvokeStmt(InvokeExprUtil.createDummyStaticInvokeExpr(), pos); + JInvokeStmt invokeStmt = new JInvokeStmt(TestUtil.createDummyStaticInvokeExpr(), pos); assertTrue(invokeStmt.containsInvokeExpr()); - JInvokeStmt invokeStmt1 = new JInvokeStmt(InvokeExprUtil.createDummyInterfaceInvokeExpr(), pos); + JInvokeStmt invokeStmt1 = new JInvokeStmt(TestUtil.createDummyInterfaceInvokeExpr(), pos); assertTrue(invokeStmt1.containsInvokeExpr()); - JInvokeStmt invokeStmt2 = new JInvokeStmt(InvokeExprUtil.createDummySpecialInvokeExpr(), pos); + JInvokeStmt invokeStmt2 = new JInvokeStmt(TestUtil.createDummySpecialInvokeExpr(), pos); assertTrue(invokeStmt2.containsInvokeExpr()); - JInvokeStmt invokeStmt3 = new JInvokeStmt(InvokeExprUtil.createDummyVirtualInvokeExpr(), pos); + JInvokeStmt invokeStmt3 = new JInvokeStmt(TestUtil.createDummyVirtualInvokeExpr(), pos); assertTrue(invokeStmt3.containsInvokeExpr()); } @@ -37,16 +37,16 @@ public void testContainsInvokeExpr() { public void testInvokesStaticInitializer() { SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); - JInvokeStmt invokeStmt = new JInvokeStmt(InvokeExprUtil.createDummyStaticInvokeExpr(), pos); + JInvokeStmt invokeStmt = new JInvokeStmt(TestUtil.createDummyStaticInvokeExpr(), pos); assertTrue(invokeStmt.invokesStaticInitializer()); - JInvokeStmt invokeStmt1 = new JInvokeStmt(InvokeExprUtil.createDummyInterfaceInvokeExpr(), pos); + JInvokeStmt invokeStmt1 = new JInvokeStmt(TestUtil.createDummyInterfaceInvokeExpr(), pos); assertFalse(invokeStmt1.invokesStaticInitializer()); - JInvokeStmt invokeStmt2 = new JInvokeStmt(InvokeExprUtil.createDummySpecialInvokeExpr(), pos); + JInvokeStmt invokeStmt2 = new JInvokeStmt(TestUtil.createDummySpecialInvokeExpr(), pos); assertFalse(invokeStmt2.invokesStaticInitializer()); - JInvokeStmt invokeStmt3 = new JInvokeStmt(InvokeExprUtil.createDummyVirtualInvokeExpr(), pos); + JInvokeStmt invokeStmt3 = new JInvokeStmt(TestUtil.createDummyVirtualInvokeExpr(), pos); assertFalse(invokeStmt3.invokesStaticInitializer()); } @@ -54,19 +54,19 @@ public void testInvokesStaticInitializer() { public void testGetInvokeExpr() { SimpleStmtPositionInfo pos = new SimpleStmtPositionInfo(1); - JStaticInvokeExpr staticExpr = InvokeExprUtil.createDummyStaticInvokeExpr(); + JStaticInvokeExpr staticExpr = TestUtil.createDummyStaticInvokeExpr(); JInvokeStmt invokeStmt = new JInvokeStmt(staticExpr, pos); assertEquals(staticExpr, invokeStmt.getInvokeExpr().get()); - JVirtualInvokeExpr virtualExpr = InvokeExprUtil.createDummyVirtualInvokeExpr(); + JVirtualInvokeExpr virtualExpr = TestUtil.createDummyVirtualInvokeExpr(); JInvokeStmt invokeStmt1 = new JInvokeStmt(virtualExpr, pos); assertEquals(virtualExpr, invokeStmt1.getInvokeExpr().get()); - JSpecialInvokeExpr specialExpr = InvokeExprUtil.createDummySpecialInvokeExpr(); + JSpecialInvokeExpr specialExpr = TestUtil.createDummySpecialInvokeExpr(); JInvokeStmt invokeStmt2 = new JInvokeStmt(specialExpr, pos); assertEquals(specialExpr, invokeStmt2.getInvokeExpr().get()); - JInterfaceInvokeExpr interfaceExpr = InvokeExprUtil.createDummyInterfaceInvokeExpr(); + JInterfaceInvokeExpr interfaceExpr = TestUtil.createDummyInterfaceInvokeExpr(); JInvokeStmt invokeStmt3 = new JInvokeStmt(interfaceExpr, pos); assertEquals(interfaceExpr.toString(), invokeStmt3.getInvokeExpr().get().toString()); } diff --git a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java b/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java deleted file mode 100644 index aa81e1fe3c0..00000000000 --- a/sootup.core/src/test/java/sootup/util/AssignStmtUtil.java +++ /dev/null @@ -1,62 +0,0 @@ -package sootup.util; - -import sootup.core.jimple.basic.LValue; -import sootup.core.jimple.basic.Local; -import sootup.core.jimple.basic.SimpleStmtPositionInfo; -import sootup.core.jimple.basic.Value; -import sootup.core.jimple.common.expr.AbstractInvokeExpr; -import sootup.core.jimple.common.ref.JFieldRef; -import sootup.core.jimple.common.stmt.JAssignStmt; - -public class AssignStmtUtil { - - /** - * will return a dummy assignment statement with an invoke expression the left value will be the - * dummy int local the right value will be the given invoke expression stmt position is the dummy - * SimpleStatementPositionInfo - * - * @param invokeExpr the invokeExpr in the dummy assignment statement - * @return a dummy JAssignStmt with a static invoke expression - */ - public static JAssignStmt createDummyAssignStmtWithExpr(AbstractInvokeExpr invokeExpr) { - Local local = LocalUtil.createDummyLocalForInt(); - SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(local, invokeExpr, pos); - } - - /** - * will return a dummy assignment statement the left value will be the dummy static field ref the - * right value will be the dummy local stmt position is the dummy SimpleStatementPositionInfo - * - * @return a dummy JAssignStmt with a static field ref on the left side - */ - public static JAssignStmt createDummyAssignStmtWithStaticFieldRefLeft() { - JFieldRef fieldRef = FieldRefUtil.createDummyStaticFieldRef(); - SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(fieldRef, LocalUtil.createDummyLocalForInt(), pos); - } - - /** - * will return a dummy assignment statement stmt position is the dummy SimpleStatementPositionInfo - * - * @param left defines the left value of the dummy assign statement - * @param right defines the right value of the dummy assign statement - * @return a dummy JAssignStmt with an instance field ref on the left side - */ - public static JAssignStmt createDummyAssignStmt(LValue left, Value right) { - SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt(left, right, pos); - } - - /** - * will return a dummy assignment statement the right value will be the dummy local the left value - * will be the dummy local stmt position is the dummy SimpleStatementPositionInfo - * - * @return a dummy JAssignStmt with a static field ref on the left side - */ - public static JAssignStmt createDummyAssignStmtWithLocals() { - SimpleStmtPositionInfo pos = StmtPosUtil.createDummySimpleStmtPositionInfo(); - return new JAssignStmt( - LocalUtil.createDummyLocalForInt(), LocalUtil.createDummyLocalForInt(), pos); - } -} diff --git a/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java b/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java deleted file mode 100644 index 8aa7e3934c5..00000000000 --- a/sootup.core/src/test/java/sootup/util/ClassTypeUtil.java +++ /dev/null @@ -1,36 +0,0 @@ -package sootup.util; - -import sootup.core.signatures.PackageName; -import sootup.core.types.ClassType; - -public class ClassTypeUtil { - - /** - * creates a dummy Class type Classname Test Package name test Fully Qualified Name test.Test - * - * @return a dummy class type - */ - public static ClassType createDummyClassType() { - return new ClassType() { - @Override - public boolean isBuiltInClass() { - return false; - } - - @Override - public String getFullyQualifiedName() { - return "Test"; - } - - @Override - public String getClassName() { - return "Test"; - } - - @Override - public PackageName getPackageName() { - return new PackageName("test"); - } - }; - } -} diff --git a/sootup.core/src/test/java/sootup/util/FieldRefUtil.java b/sootup.core/src/test/java/sootup/util/FieldRefUtil.java deleted file mode 100644 index ae326337189..00000000000 --- a/sootup.core/src/test/java/sootup/util/FieldRefUtil.java +++ /dev/null @@ -1,26 +0,0 @@ -package sootup.util; - -import sootup.core.jimple.common.ref.JInstanceFieldRef; -import sootup.core.jimple.common.ref.JStaticFieldRef; - -public class FieldRefUtil { - - /** - * creates a dummy static field reference Signature: dummy Field Signature - * - * @return a dummy JStaticFieldRef - */ - public static JStaticFieldRef createDummyStaticFieldRef() { - return new JStaticFieldRef(SignatureUtil.createDummyFieldSignature()); - } - - /** - * creates a dummy instance field reference local: dummy local Signature: dummy Field Signature - * - * @return a dummy JInstanceFieldRef - */ - public static JInstanceFieldRef createDummyInstanceFieldRef() { - return new JInstanceFieldRef( - LocalUtil.createDummyLocalForInt(), SignatureUtil.createDummyFieldSignature()); - } -} diff --git a/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java b/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java deleted file mode 100644 index 642f5ad4778..00000000000 --- a/sootup.core/src/test/java/sootup/util/InvokeExprUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package sootup.util; - -import java.util.Collections; -import sootup.core.jimple.basic.Local; -import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; -import sootup.core.jimple.common.expr.JSpecialInvokeExpr; -import sootup.core.jimple.common.expr.JStaticInvokeExpr; -import sootup.core.jimple.common.expr.JVirtualInvokeExpr; -import sootup.core.signatures.MethodSignature; - -public class InvokeExprUtil { - - /** - * will return a dummy virtual invoke expression local is called a and has the class type Test - * method signature is <Test: int test ()> arguments is an empty list - */ - public static JVirtualInvokeExpr createDummyVirtualInvokeExpr() { - Local local = LocalUtil.createDummyLocalForObject(); - MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JVirtualInvokeExpr(local, methodSignature, Collections.emptyList()); - } - - /** - * will return a dummy special invoke expression local is called a and has the class type Test - * method signature is <Test: int test ()> arguments is an empty list - */ - public static JSpecialInvokeExpr createDummySpecialInvokeExpr() { - Local local = LocalUtil.createDummyLocalForObject(); - MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JSpecialInvokeExpr(local, methodSignature, Collections.emptyList()); - } - - /** - * will return a dummy interface invoke expression local is called a and has the class type Test - * method signature is <Test: int test ()> arguments is an empty list - */ - public static JInterfaceInvokeExpr createDummyInterfaceInvokeExpr() { - Local local = LocalUtil.createDummyLocalForObject(); - MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JInterfaceInvokeExpr(local, methodSignature, Collections.emptyList()); - } - - /** - * will return a dummy static invoke expression method signature is <Test: int test ()> - * arguments is an empty list - */ - public static JStaticInvokeExpr createDummyStaticInvokeExpr() { - MethodSignature methodSignature = SignatureUtil.createDummyMethodSignature(); - return new JStaticInvokeExpr(methodSignature, Collections.emptyList()); - } -} diff --git a/sootup.core/src/test/java/sootup/util/LocalUtil.java b/sootup.core/src/test/java/sootup/util/LocalUtil.java deleted file mode 100644 index 898d9319421..00000000000 --- a/sootup.core/src/test/java/sootup/util/LocalUtil.java +++ /dev/null @@ -1,25 +0,0 @@ -package sootup.util; - -import sootup.core.jimple.basic.Local; -import sootup.core.types.PrimitiveType.IntType; - -public class LocalUtil { - - /** - * creates a dummy Local for an Object Name a Type dummy class type - * - * @return a dummy Local for an Object - */ - public static Local createDummyLocalForObject() { - return new Local("a", ClassTypeUtil.createDummyClassType()); - } - - /** - * creates a dummy Local for an Int Name b Type int - * - * @return a dummy Local for a int value - */ - public static Local createDummyLocalForInt() { - return new Local("b", IntType.getInstance()); - } -} diff --git a/sootup.core/src/test/java/sootup/util/SignatureUtil.java b/sootup.core/src/test/java/sootup/util/SignatureUtil.java deleted file mode 100644 index 70396701f8e..00000000000 --- a/sootup.core/src/test/java/sootup/util/SignatureUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -package sootup.util; - -import java.util.Collections; -import sootup.core.signatures.FieldSignature; -import sootup.core.signatures.FieldSubSignature; -import sootup.core.signatures.MethodSignature; -import sootup.core.signatures.MethodSubSignature; -import sootup.core.types.PrimitiveType.IntType; - -public class SignatureUtil { - - /** - * creates a dummy method signature Class Type: dummy class type SubSignature: dummy method sub - * signature - * - * @return a dummy method signature - */ - public static MethodSignature createDummyMethodSignature() { - return new MethodSignature( - ClassTypeUtil.createDummyClassType(), createDummyMethodSubSignature()); - } - - /** - * creates a dummy method sub signature name: test return type: int parameter list: empty - * - * @return a dummy method sub signature - */ - public static MethodSubSignature createDummyMethodSubSignature() { - return new MethodSubSignature("test", Collections.emptyList(), IntType.getInstance()); - } - - /** - * creates a dummy field signature Class Type: dummy class type SubSignature: dummy field sub - * signature - * - * @return a dummy field signature - */ - public static FieldSignature createDummyFieldSignature() { - return new FieldSignature(ClassTypeUtil.createDummyClassType(), createDummyFieldSubSignature()); - } - - /** - * creates a dummy field sub signature name: test type: int - * - * @return a dummy field sub signature - */ - public static FieldSubSignature createDummyFieldSubSignature() { - return new FieldSubSignature("test", IntType.getInstance()); - } -} diff --git a/sootup.core/src/test/java/sootup/util/StmtPosUtil.java b/sootup.core/src/test/java/sootup/util/StmtPosUtil.java deleted file mode 100644 index 132d8312c60..00000000000 --- a/sootup.core/src/test/java/sootup/util/StmtPosUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package sootup.util; - -import sootup.core.jimple.basic.SimpleStmtPositionInfo; - -public class StmtPosUtil { - - /** - * creates a dummy SimpleStmtPositionInfo lineNumber 1 - * - * @return a dummy SimpleStmtPositionInfo - */ - public static SimpleStmtPositionInfo createDummySimpleStmtPositionInfo() { - return new SimpleStmtPositionInfo(1); - } -} From c7fcbe9fa60b3a1bfc8d1631599143acd9caed04 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 15 Jul 2024 18:29:45 +0200 Subject: [PATCH 38/41] adapted qilin to the Callgraph API --- .../main/java/sootup/callgraph/CallGraph.java | 2 +- .../qilin/core/builder/CallGraphBuilder.java | 16 +++-- .../qilin/core/builder/MethodNodeFactory.java | 11 ++-- .../qilin/core/builder/callgraph/Edge.java | 41 ++++++------- .../builder/callgraph/OnFlyCallGraph.java | 59 +++++++++++++++---- .../main/java/qilin/core/pag/CallSite.java | 8 +-- .../main/java/qilin/core/pag/MethodPAG.java | 7 ++- .../src/main/java/qilin/core/pag/PAG.java | 4 +- .../java/qilin/core/pag/VirtualCallSite.java | 4 +- .../core/reflection/NopReflectionModel.java | 19 +++--- .../core/reflection/ReflectionModel.java | 29 ++++----- .../qilin/core/reflection/TamiflexModel.java | 36 +++++------ .../main/java/qilin/core/solver/Solver.java | 9 +-- .../java/qilin/pta/toolkits/conch/Conch.java | 11 ++-- .../toolkits/conch/DepOnParamAnalysis.java | 4 +- .../pta/toolkits/conch/LeakAnalysis.java | 8 +-- .../dd/CtxTunnelingFeaturesTrueTable.java | 2 +- .../debloaterx/IntraFlowAnalysis.java | 6 +- .../qilin/pta/toolkits/debloaterx/XPAG.java | 10 ++-- .../pta/toolkits/debloaterx/XUtility.java | 6 +- .../java/qilin/pta/toolkits/eagle/Eagle.java | 6 +- .../qilin/pta/toolkits/selectx/Selectx.java | 6 +- .../pta/toolkits/turner/AbstractMVFG.java | 2 +- .../zipper/flowgraph/FlowAnalysis.java | 2 +- .../zipper/flowgraph/ObjectFlowGraph.java | 6 +- .../pta/tools/PartialCallSiteSensPTA.java | 6 +- .../qilin/pta/tools/PartialObjSensPTA.java | 2 +- .../main/java/qilin/pta/tools/ZipperPTA.java | 6 +- .../java/qilin/stat/SimplifiedEvaluator.java | 4 +- .../main/java/qilin/stat/TypeClientStat.java | 4 +- .../src/main/java/qilin/util/PTAUtils.java | 15 ++--- .../java/qilin/test/context/CFATests.java | 1 + .../qilin/test/util/AssertionsParser.java | 4 +- 33 files changed, 201 insertions(+), 155 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index 17c0396c1fc..11074f9fde1 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -36,7 +36,7 @@ class Call { @Nonnull private final MethodSignature targetMethodSignature; @Nonnull private final InvokableStmt invokableStmt; - Call( + public Call( @Nonnull MethodSignature sourceMethodSignature, @Nonnull MethodSignature targetMethodSignature, @Nonnull InvokableStmt invokableStmt) { diff --git a/sootup.qilin/src/main/java/qilin/core/builder/CallGraphBuilder.java b/sootup.qilin/src/main/java/qilin/core/builder/CallGraphBuilder.java index b914b53e1af..e388732bb69 100644 --- a/sootup.qilin/src/main/java/qilin/core/builder/CallGraphBuilder.java +++ b/sootup.qilin/src/main/java/qilin/core/builder/CallGraphBuilder.java @@ -41,6 +41,7 @@ import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.jimple.common.stmt.Stmt; @@ -54,7 +55,7 @@ public class CallGraphBuilder { private static final ClassType clRunnable = PTAUtils.getClassType("java.lang.Runnable"); protected final Map> receiverToSites; - protected final Map> methodToInvokeStmt; + protected final Map> methodToInvokeStmt; protected final Set reachMethods; private ChunkedQueue rmQueue; @@ -177,7 +178,11 @@ protected void dispatch(AllocNode receiverNode, VirtualCallSite site) { } private void addVirtualEdge( - ContextMethod caller, Stmt callStmt, SootMethod callee, Kind kind, AllocNode receiverNode) { + ContextMethod caller, + InvokableStmt callStmt, + SootMethod callee, + Kind kind, + AllocNode receiverNode) { Context tgtContext = pta.createCalleeCtx(caller, receiverNode, new CallSite(callStmt), callee); ContextMethod cstarget = pta.parameterize(callee, tgtContext); handleCallEdge(new Edge(caller, callStmt, cstarget, kind)); @@ -187,7 +192,7 @@ private void addVirtualEdge( } public void injectCallEdge(Object heapOrType, ContextMethod callee, Kind kind) { - Map stmtMap = + Map stmtMap = methodToInvokeStmt.computeIfAbsent(callee.method(), k -> DataFactory.createMap()); if (!stmtMap.containsKey(heapOrType)) { AbstractInvokeExpr ie = @@ -203,7 +208,8 @@ public void injectCallEdge(Object heapOrType, ContextMethod callee, Kind kind) { } } - public void addStaticEdge(ContextMethod caller, Stmt callStmt, SootMethod calleem, Kind kind) { + public void addStaticEdge( + ContextMethod caller, InvokableStmt callStmt, SootMethod calleem, Kind kind) { Context typeContext = pta.createCalleeCtx(caller, null, new CallSite(callStmt), calleem); ContextMethod callee = pta.parameterize(calleem, typeContext); handleCallEdge(new Edge(caller, callStmt, callee, kind)); @@ -247,7 +253,7 @@ private void processCallAssign(Edge e) { MethodNodeFactory srcnf = srcmpag.nodeFactory(); MethodNodeFactory tgtnf = tgtmpag.nodeFactory(); SootMethod tgtmtd = tgtmpag.getMethod(); - AbstractInvokeExpr ie = s.getInvokeExpr(); + AbstractInvokeExpr ie = s.asInvokableStmt().getInvokeExpr().get(); // add arg --> param edges. int numArgs = ie.getArgCount(); for (int i = 0; i < numArgs; i++) { diff --git a/sootup.qilin/src/main/java/qilin/core/builder/MethodNodeFactory.java b/sootup.qilin/src/main/java/qilin/core/builder/MethodNodeFactory.java index 42acdc1918c..2f4fd470d55 100644 --- a/sootup.qilin/src/main/java/qilin/core/builder/MethodNodeFactory.java +++ b/sootup.qilin/src/main/java/qilin/core/builder/MethodNodeFactory.java @@ -51,6 +51,7 @@ import sootup.core.jimple.common.ref.JParameterRef; import sootup.core.jimple.common.ref.JStaticFieldRef; import sootup.core.jimple.common.ref.JThisRef; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.JIdentityStmt; import sootup.core.jimple.common.stmt.JReturnStmt; @@ -131,9 +132,9 @@ public Node getNode(Value v) { /** Adds the edges required for this statement to the graph. */ public final void handleStmt(Stmt s) { - if (s.containsInvokeExpr()) { - mpag.addCallStmt(s); - handleInvokeStmt(s); + if (s.isInvokableStmt() && s.asInvokableStmt().containsInvokeExpr()) { + mpag.addCallStmt(s.asInvokableStmt()); + handleInvokeStmt(s.asInvokableStmt()); } else { handleIntraStmt(s); } @@ -143,8 +144,8 @@ public final void handleStmt(Stmt s) { * Adds the edges required for this statement to the graph. Add throw stmt if the invoke method * throws an Exception. */ - protected void handleInvokeStmt(Stmt s) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + protected void handleInvokeStmt(InvokableStmt s) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); int numArgs = ie.getArgCount(); for (int i = 0; i < numArgs; i++) { Value arg = ie.getArg(i); diff --git a/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java b/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java index 063527bfdcf..54e0dc4f382 100644 --- a/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java +++ b/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java @@ -3,12 +3,13 @@ import qilin.core.context.Context; import qilin.core.pag.ContextMethod; import qilin.util.Invalidable; +import sootup.callgraph.CallGraph; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; import sootup.core.jimple.common.expr.JVirtualInvokeExpr; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootMethod; /** @@ -16,7 +17,7 @@ * * @author Ondrej Lhotak */ -public final class Edge implements Invalidable { +public final class Edge extends CallGraph.Call implements Invalidable { /** * The method in which the call occurs; may be null for calls not occurring in a specific method @@ -27,12 +28,6 @@ public final class Edge implements Invalidable { /** The target method of the call edge. */ private ContextMethod tgt; - /** - * The unit at which the call occurs; may be null for calls not occurring at a specific statement - * (eg. calls in native code) - */ - private Stmt srcUnit; - /** * The kind of edge. Note: kind should not be tested by other classes; instead, accessors such as * isExplicit() should be added. @@ -41,17 +36,17 @@ public final class Edge implements Invalidable { private boolean invalid = false; - public Edge(ContextMethod src, Stmt srcUnit, ContextMethod tgt, Kind kind) { + public Edge(ContextMethod src, InvokableStmt srcUnit, ContextMethod tgt, Kind kind) { + super(src.method().getSignature(), tgt.method().getSignature(), srcUnit); this.src = src; - this.srcUnit = srcUnit; this.tgt = tgt; this.kind = kind; } - public Edge(ContextMethod src, Stmt srcUnit, ContextMethod tgt) { - this.kind = ieToKind(srcUnit.getInvokeExpr()); + public Edge(ContextMethod src, InvokableStmt srcUnit, ContextMethod tgt) { + super(src.method().getSignature(), tgt.method().getSignature(), srcUnit); + this.kind = ieToKind(srcUnit.getInvokeExpr().get()); this.src = src; - this.srcUnit = srcUnit; this.tgt = tgt; } @@ -67,12 +62,12 @@ public ContextMethod getSrc() { return src; } - public Stmt srcUnit() { - return srcUnit; + public InvokableStmt srcUnit() { + return getInvokableStmt(); } - public Stmt srcStmt() { - return srcUnit; + public InvokableStmt srcStmt() { + return getInvokableStmt(); } public SootMethod tgt() { @@ -150,7 +145,6 @@ public boolean isInvalid() { public void invalidate() { // Since the edge remains in the QueueReaders for a while, the GC could not claim old units. src = null; - srcUnit = null; tgt = null; invalid = true; } @@ -164,8 +158,8 @@ public int hashCode() { if (src != null) { ret = ret * 32 + src.hashCode(); } - if (srcUnit != null) { - ret = ret * 32 + srcUnit.hashCode(); + if (getInvokableStmt() != null) { + ret = ret * 32 + getInvokableStmt().hashCode(); } return ret; } @@ -176,12 +170,15 @@ public boolean equals(Object other) { return false; } Edge o = (Edge) other; - return (o.src == this.src) && (o.srcUnit == srcUnit) && (o.tgt == tgt) && (o.kind == kind); + return (o.src == this.src) + && (o.srcStmt() == this.srcStmt()) + && (o.tgt == tgt) + && (o.kind == kind); } @Override public String toString() { - return this.kind + " edge: " + srcUnit + " in " + src + " ==> " + tgt; + return this.kind + " edge: " + srcStmt() + " in " + src + " ==> " + tgt; } private Edge nextByUnit = this; diff --git a/sootup.qilin/src/main/java/qilin/core/builder/callgraph/OnFlyCallGraph.java b/sootup.qilin/src/main/java/qilin/core/builder/callgraph/OnFlyCallGraph.java index d7b8caa1fb3..3692fc1f863 100644 --- a/sootup.qilin/src/main/java/qilin/core/builder/callgraph/OnFlyCallGraph.java +++ b/sootup.qilin/src/main/java/qilin/core/builder/callgraph/OnFlyCallGraph.java @@ -28,14 +28,17 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import qilin.core.pag.ContextMethod; import qilin.util.DataFactory; import qilin.util.queue.ChunkedQueue; import qilin.util.queue.QueueReader; import sootup.callgraph.MutableCallGraph; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSignature; @@ -49,7 +52,7 @@ */ public class OnFlyCallGraph implements MutableCallGraph, Iterable { protected Set methods = DataFactory.createSet(); - protected Map> calls = DataFactory.createMap(); + protected Map> calls = DataFactory.createMap(); protected int callCnt = 0; protected Set edges = new LinkedHashSet<>(); @@ -69,7 +72,7 @@ public boolean addEdge(Edge e) { MethodSignature tgtSig = e.getTgt().method().getSignature(); addMethod(srcSig); addMethod(tgtSig); - addCall(srcSig, tgtSig); + addCall(srcSig, tgtSig, e.srcStmt()); stream.add(e); Edge position = srcUnitToEdge.get(e.srcUnit()); @@ -129,7 +132,7 @@ public boolean removeAllEdgesOutOf(Stmt u) { * @param in The new statement * @return True if at least one edge was affected by this operation */ - public boolean swapEdgesOutOf(Stmt out, Stmt in) { + public boolean swapEdgesOutOf(InvokableStmt out, InvokableStmt in) { boolean hasSwapped = false; for (Iterator edgeRdr = edgesOutOf(out); edgeRdr.hasNext(); ) { Edge e = edgeRdr.next(); @@ -166,7 +169,7 @@ public boolean removeEdge(Edge e, boolean removeInEdgeList) { } MethodSignature srcSig = e.getSrc().method().getSignature(); MethodSignature tgtSig = e.getTgt().method().getSignature(); - Set tgtSigs = calls.getOrDefault(srcSig, Collections.emptySet()); + Set tgtSigs = calls.getOrDefault(srcSig, Collections.emptySet()); assert (!tgtSigs.isEmpty()); tgtSigs.remove(tgtSig); // !FIXME only edge is removed. I do not remove the added nodes. @@ -430,10 +433,11 @@ public void addMethod(@Nonnull MethodSignature calledMethod) { @Override public void addCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod) { - Set targets = - this.calls.computeIfAbsent(sourceMethod, k -> DataFactory.createSet()); - if (targets.add(targetMethod)) { + @Nonnull MethodSignature sourceMethod, + @Nonnull MethodSignature targetMethod, + @Nonnull InvokableStmt stmt) { + Set targets = this.calls.computeIfAbsent(sourceMethod, k -> DataFactory.createSet()); + if (targets.add(new Call(sourceMethod, targetMethod, stmt))) { ++callCnt; } } @@ -457,9 +461,16 @@ public boolean containsMethod(@Nonnull MethodSignature method) { @Override public boolean containsCall( - @Nonnull MethodSignature sourceMethod, @Nonnull MethodSignature targetMethod) { - if (this.calls.containsKey(sourceMethod)) { - if (this.calls.get(sourceMethod).contains(targetMethod)) { + @Nonnull MethodSignature sourceMethod, + @Nonnull MethodSignature targetMethod, + InvokableStmt stmt) { + return containsCall(new Call(sourceMethod, targetMethod, stmt)); + } + + @Override + public boolean containsCall(@Nonnull Call call) { + if (this.calls.containsKey(call.getSourceMethodSignature())) { + if (this.calls.get(call.getSourceMethodSignature()).contains(call)) { return true; } } @@ -478,13 +489,35 @@ public String exportAsDot() { @Nonnull @Override - public Set callsFrom(@Nonnull MethodSignature sourceMethod) { + public Set callsFrom(@Nonnull MethodSignature sourceMethod) { return this.calls.getOrDefault(sourceMethod, Collections.emptySet()); } @Nonnull @Override - public Set callsTo(@Nonnull MethodSignature targetMethod) { + public Set callsTo(@Nonnull MethodSignature targetMethod) { throw new UnsupportedOperationException(); } + + @Nonnull + @Override + public Set callTargetsFrom(@Nonnull MethodSignature sourceMethod) { + return callsFrom(sourceMethod).stream() + .map(call -> call.getTargetMethodSignature()) + .collect(Collectors.toSet()); + } + + @Nonnull + @Override + public Set callSourcesTo(@Nonnull MethodSignature targetMethod) { + return callsTo(targetMethod).stream() + .map(call -> call.getSourceMethodSignature()) + .collect(Collectors.toSet()); + } + + // TODO: implement me + @Override + public List getEntryMethods() { + return Collections.emptyList(); + } } diff --git a/sootup.qilin/src/main/java/qilin/core/pag/CallSite.java b/sootup.qilin/src/main/java/qilin/core/pag/CallSite.java index c2c7e742b9c..f776279e0a5 100644 --- a/sootup.qilin/src/main/java/qilin/core/pag/CallSite.java +++ b/sootup.qilin/src/main/java/qilin/core/pag/CallSite.java @@ -19,18 +19,18 @@ package qilin.core.pag; import qilin.core.context.ContextElement; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; /** callsite based context element in the points to analysis. */ public class CallSite implements ContextElement { - private final Stmt unit; + private final InvokableStmt unit; - public CallSite(Stmt unit) { + public CallSite(InvokableStmt unit) { this.unit = unit; } - public Stmt getUnit() { + public InvokableStmt getUnit() { return unit; } diff --git a/sootup.qilin/src/main/java/qilin/core/pag/MethodPAG.java b/sootup.qilin/src/main/java/qilin/core/pag/MethodPAG.java index 6c770f31ce4..f0da201b02e 100644 --- a/sootup.qilin/src/main/java/qilin/core/pag/MethodPAG.java +++ b/sootup.qilin/src/main/java/qilin/core/pag/MethodPAG.java @@ -29,6 +29,7 @@ import sootup.core.jimple.Jimple; import sootup.core.jimple.basic.Trap; import sootup.core.jimple.common.ref.JStaticFieldRef; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.Body; import sootup.core.model.SootClass; @@ -44,7 +45,7 @@ public class MethodPAG { private final ChunkedQueue internalEdges = new ChunkedQueue<>(); private final QueueReader internalReader = internalEdges.reader(); private final Set clinits = DataFactory.createSet(); - private final Collection invokeStmts = DataFactory.createSet(); + private final Collection invokeStmts = DataFactory.createSet(); public Body body; /** @@ -81,11 +82,11 @@ public MethodNodeFactory nodeFactory() { return nodeFactory; } - public Collection getInvokeStmts() { + public Collection getInvokeStmts() { return invokeStmts; } - public boolean addCallStmt(Stmt unit) { + public boolean addCallStmt(InvokableStmt unit) { return this.invokeStmts.add(unit); } diff --git a/sootup.qilin/src/main/java/qilin/core/pag/PAG.java b/sootup.qilin/src/main/java/qilin/core/pag/PAG.java index a3e6503a789..7d8274c8ee7 100644 --- a/sootup.qilin/src/main/java/qilin/core/pag/PAG.java +++ b/sootup.qilin/src/main/java/qilin/core/pag/PAG.java @@ -570,8 +570,8 @@ private void handleArrayCopy(SootMethod method) { Body.BodyBuilder builder = Body.builder(body, Collections.emptySet()); int localCount = body.getLocalCount(); for (Stmt s : body.getStmts()) { - if (s.containsInvokeExpr()) { - AbstractInvokeExpr invokeExpr = s.getInvokeExpr(); + if (s.isInvokableStmt() && s.asInvokableStmt().containsInvokeExpr()) { + AbstractInvokeExpr invokeExpr = s.asInvokableStmt().getInvokeExpr().get(); if (invokeExpr instanceof JStaticInvokeExpr) { JStaticInvokeExpr sie = (JStaticInvokeExpr) invokeExpr; String sig = sie.getMethodSignature().toString(); diff --git a/sootup.qilin/src/main/java/qilin/core/pag/VirtualCallSite.java b/sootup.qilin/src/main/java/qilin/core/pag/VirtualCallSite.java index 42696812805..b985cdc1df7 100644 --- a/sootup.qilin/src/main/java/qilin/core/pag/VirtualCallSite.java +++ b/sootup.qilin/src/main/java/qilin/core/pag/VirtualCallSite.java @@ -21,7 +21,7 @@ import java.util.Objects; import qilin.core.builder.callgraph.Kind; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.signatures.MethodSubSignature; /** @@ -38,7 +38,7 @@ public class VirtualCallSite extends CallSite { public VirtualCallSite( VarNode recNode, - Stmt stmt, + InvokableStmt stmt, ContextMethod container, AbstractInstanceInvokeExpr iie, MethodSubSignature subSig, diff --git a/sootup.qilin/src/main/java/qilin/core/reflection/NopReflectionModel.java b/sootup.qilin/src/main/java/qilin/core/reflection/NopReflectionModel.java index 59be216aba2..0659b77c5a6 100644 --- a/sootup.qilin/src/main/java/qilin/core/reflection/NopReflectionModel.java +++ b/sootup.qilin/src/main/java/qilin/core/reflection/NopReflectionModel.java @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.Collections; import qilin.core.PTAScene; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.Stmt; /* @@ -34,47 +35,47 @@ public NopReflectionModel(PTAScene scene) { } @Override - Collection transformClassForName(Stmt s) { + Collection transformClassForName(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformClassNewInstance(Stmt s) { + Collection transformClassNewInstance(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformContructorNewInstance(Stmt s) { + Collection transformConstructorNewInstance(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformMethodInvoke(Stmt s) { + Collection transformMethodInvoke(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformFieldSet(Stmt s) { + Collection transformFieldSet(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformFieldGet(Stmt s) { + Collection transformFieldGet(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformArrayNewInstance(Stmt s) { + Collection transformArrayNewInstance(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformArrayGet(Stmt s) { + Collection transformArrayGet(InvokableStmt s) { return Collections.emptySet(); } @Override - Collection transformArraySet(Stmt s) { + Collection transformArraySet(InvokableStmt s) { return Collections.emptySet(); } } diff --git a/sootup.qilin/src/main/java/qilin/core/reflection/ReflectionModel.java b/sootup.qilin/src/main/java/qilin/core/reflection/ReflectionModel.java index a4f2faa108a..bfffa990954 100644 --- a/sootup.qilin/src/main/java/qilin/core/reflection/ReflectionModel.java +++ b/sootup.qilin/src/main/java/qilin/core/reflection/ReflectionModel.java @@ -28,6 +28,7 @@ import sootup.core.graph.MutableStmtGraph; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.stmt.FallsThroughStmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.jimple.common.stmt.Stmt; @@ -76,8 +77,8 @@ protected ReflectionModel(PTAScene ptaScene) { this.ptaScene = ptaScene; } - private Collection transform(Stmt s) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + private Collection transform(InvokableStmt s) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); switch (ie.getMethodSignature().toString()) { case sigForName: case sigForName2: @@ -85,7 +86,7 @@ private Collection transform(Stmt s) { case sigClassNewInstance: return transformClassNewInstance(s); case sigConstructorNewInstance: - return transformContructorNewInstance(s); + return transformConstructorNewInstance(s); case sigMethodInvoke: return transformMethodInvoke(s); case sigFieldSet: @@ -112,8 +113,8 @@ public void buildReflection(SootMethod m) { Body body = PTAUtils.getMethodBody(m); List units = body.getStmts(); for (final Stmt u : units) { - if (u.containsInvokeExpr()) { - newUnits.put(u, transform(u)); + if (u.isInvokableStmt() && u.asInvokableStmt().containsInvokeExpr()) { + newUnits.put(u, transform(u.asInvokableStmt())); } } Body.BodyBuilder builder = Body.builder(body, Collections.emptySet()); @@ -136,21 +137,21 @@ public void buildReflection(SootMethod m) { PTAUtils.updateMethodBody(m, builder.build()); } - abstract Collection transformClassForName(Stmt s); + abstract Collection transformClassForName(InvokableStmt s); - abstract Collection transformClassNewInstance(Stmt s); + abstract Collection transformClassNewInstance(InvokableStmt s); - abstract Collection transformContructorNewInstance(Stmt s); + abstract Collection transformConstructorNewInstance(InvokableStmt s); - abstract Collection transformMethodInvoke(Stmt s); + abstract Collection transformMethodInvoke(InvokableStmt s); - abstract Collection transformFieldSet(Stmt s); + abstract Collection transformFieldSet(InvokableStmt s); - abstract Collection transformFieldGet(Stmt s); + abstract Collection transformFieldGet(InvokableStmt s); - abstract Collection transformArrayNewInstance(Stmt s); + abstract Collection transformArrayNewInstance(InvokableStmt s); - abstract Collection transformArrayGet(Stmt s); + abstract Collection transformArrayGet(InvokableStmt s); - abstract Collection transformArraySet(Stmt s); + abstract Collection transformArraySet(InvokableStmt s); } diff --git a/sootup.qilin/src/main/java/qilin/core/reflection/TamiflexModel.java b/sootup.qilin/src/main/java/qilin/core/reflection/TamiflexModel.java index 917a338531a..99b7f2af88d 100644 --- a/sootup.qilin/src/main/java/qilin/core/reflection/TamiflexModel.java +++ b/sootup.qilin/src/main/java/qilin/core/reflection/TamiflexModel.java @@ -40,6 +40,7 @@ import sootup.core.jimple.common.expr.JVirtualInvokeExpr; import sootup.core.jimple.common.ref.JArrayRef; import sootup.core.jimple.common.ref.JFieldRef; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.jimple.common.stmt.Stmt; @@ -68,7 +69,7 @@ public TamiflexModel(PTAScene ptaScene) { } @Override - Collection transformClassForName(Stmt s) { + Collection transformClassForName(InvokableStmt s) { // // Collection ret = DataFactory.createSet(); @@ -94,7 +95,7 @@ public static String dot2slashStyle(String clazz) { } @Override - protected Collection transformClassNewInstance(Stmt s) { + protected Collection transformClassNewInstance(InvokableStmt s) { // if (!(s instanceof JAssignStmt)) { return Collections.emptySet(); @@ -126,7 +127,7 @@ protected Collection transformClassNewInstance(Stmt s) { } @Override - protected Collection transformContructorNewInstance(Stmt s) { + protected Collection transformConstructorNewInstance(InvokableStmt s) { // if (!(s instanceof JAssignStmt)) { return Collections.emptySet(); @@ -137,7 +138,7 @@ protected Collection transformContructorNewInstance(Stmt s) { reflectionMap.getOrDefault(ReflectionKind.ConstructorNewInstance, Collections.emptyMap()); if (constructorNewInstances.containsKey(s)) { Collection constructorSignatures = constructorNewInstances.get(s); - AbstractInvokeExpr iie = s.getInvokeExpr(); + AbstractInvokeExpr iie = s.asInvokableStmt().getInvokeExpr().get(); Value args = iie.getArg(0); JArrayRef arrayRef = JavaJimple.getInstance().newArrayRef((Local) args, IntConstant.getInstance(0)); @@ -163,14 +164,14 @@ protected Collection transformContructorNewInstance(Stmt s) { } @Override - protected Collection transformMethodInvoke(Stmt s) { + protected Collection transformMethodInvoke(InvokableStmt s) { // Collection ret = DataFactory.createSet(); Map> methodInvokes = reflectionMap.getOrDefault(ReflectionKind.MethodInvoke, Collections.emptyMap()); if (methodInvokes.containsKey(s)) { Collection methodSignatures = methodInvokes.get(s); - AbstractInvokeExpr iie = s.getInvokeExpr(); + AbstractInvokeExpr iie = s.getInvokeExpr().get(); Value base = iie.getArg(0); Value args = iie.getArg(1); Local arg = null; @@ -213,14 +214,14 @@ protected Collection transformMethodInvoke(Stmt s) { } @Override - protected Collection transformFieldSet(Stmt s) { + protected Collection transformFieldSet(InvokableStmt s) { // Collection ret = DataFactory.createSet(); Map> fieldSets = reflectionMap.getOrDefault(ReflectionKind.FieldSet, Collections.emptyMap()); if (fieldSets.containsKey(s)) { Collection fieldSignatures = fieldSets.get(s); - AbstractInvokeExpr iie = s.getInvokeExpr(); + AbstractInvokeExpr iie = s.getInvokeExpr().get(); Value base = iie.getArg(0); Value rValue = iie.getArg(1); for (String fieldSignature : fieldSignatures) { @@ -243,7 +244,7 @@ protected Collection transformFieldSet(Stmt s) { } @Override - protected Collection transformFieldGet(Stmt s) { + protected Collection transformFieldGet(InvokableStmt s) { // Collection ret = DataFactory.createSet(); Map> fieldGets = @@ -251,7 +252,7 @@ protected Collection transformFieldGet(Stmt s) { if (fieldGets.containsKey(s) && s instanceof JAssignStmt) { Collection fieldSignatures = fieldGets.get(s); LValue lvalue = ((JAssignStmt) s).getLeftOp(); - AbstractInvokeExpr iie = s.getInvokeExpr(); + AbstractInvokeExpr iie = s.getInvokeExpr().get(); Value base = iie.getArg(0); for (String fieldSignature : fieldSignatures) { FieldSignature fieldSig = @@ -275,7 +276,7 @@ protected Collection transformFieldGet(Stmt s) { } @Override - protected Collection transformArrayNewInstance(Stmt s) { + protected Collection transformArrayNewInstance(InvokableStmt s) { // Collection ret = DataFactory.createSet(); Map> mappedToArrayTypes = @@ -294,9 +295,9 @@ protected Collection transformArrayNewInstance(Stmt s) { } @Override - Collection transformArrayGet(Stmt s) { + Collection transformArrayGet(InvokableStmt s) { Collection ret = DataFactory.createSet(); - AbstractInvokeExpr iie = s.getInvokeExpr(); + AbstractInvokeExpr iie = s.getInvokeExpr().get(); Value base = iie.getArg(0); if (s instanceof JAssignStmt) { LValue lvalue = ((JAssignStmt) s).getLeftOp(); @@ -319,9 +320,9 @@ Collection transformArrayGet(Stmt s) { } @Override - Collection transformArraySet(Stmt s) { + Collection transformArraySet(InvokableStmt s) { Collection ret = DataFactory.createSet(); - AbstractInvokeExpr iie = s.getInvokeExpr(); + AbstractInvokeExpr iie = s.getInvokeExpr().get(); Value base = iie.getArg(0); if (base.getType() instanceof ArrayType) { Value from = iie.getArg(2); @@ -436,8 +437,9 @@ private Collection inferSourceStmt( for (SootMethod sm : sourceMethods) { Body body = PTAUtils.getMethodBody(sm); for (Stmt stmt : body.getStmts()) { - if (stmt.containsInvokeExpr()) { - String methodSig = stmt.getInvokeExpr().getMethodSignature().toString(); + if (stmt.isInvokableStmt() && stmt.asInvokableStmt().containsInvokeExpr()) { + String methodSig = + stmt.asInvokableStmt().getInvokeExpr().get().getMethodSignature().toString(); if (matchReflectionKind(kind, methodSig)) { potential.add(stmt); } diff --git a/sootup.qilin/src/main/java/qilin/core/solver/Solver.java b/sootup.qilin/src/main/java/qilin/core/solver/Solver.java index d2008d28c09..59c10a84afe 100644 --- a/sootup.qilin/src/main/java/qilin/core/solver/Solver.java +++ b/sootup.qilin/src/main/java/qilin/core/solver/Solver.java @@ -38,6 +38,7 @@ import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JDynamicInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JThrowStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; @@ -132,10 +133,10 @@ public void processStmts(Iterator newRMs) { } } - private void recordCallStmts(ContextMethod m, Collection units) { - for (final Stmt s : units) { + private void recordCallStmts(ContextMethod m, Collection units) { + for (final InvokableStmt s : units) { if (s.containsInvokeExpr()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + AbstractInvokeExpr ie = s.getInvokeExpr().get(); if (ie instanceof AbstractInstanceInvokeExpr) { AbstractInstanceInvokeExpr iie = (AbstractInstanceInvokeExpr) ie; Local receiver = iie.getBase(); @@ -173,7 +174,7 @@ private void recordThrowStmts(ContextMethod m, Collection stmts) { MethodPAG mpag = pag.getMethodPAG(sm); MethodNodeFactory nodeFactory = mpag.nodeFactory(); Node src; - if (stmt.containsInvokeExpr()) { + if (stmt.isInvokableStmt() && stmt.asInvokableStmt().containsInvokeExpr()) { src = nodeFactory.makeInvokeStmtThrowVarNode(stmt, sm); } else { assert stmt instanceof JThrowStmt; diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/Conch.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/Conch.java index 43e4694746c..83b270ecafa 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/Conch.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/Conch.java @@ -29,6 +29,7 @@ import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JInvokeStmt; import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; @@ -70,7 +71,7 @@ private SootMethod findInvokedConstructorOf(AllocNode heap) { for (Stmt unit : cmpag.getInvokeStmts()) { if (unit instanceof JInvokeStmt) { JInvokeStmt invokeStmt = (JInvokeStmt) unit; - AbstractInvokeExpr expr = invokeStmt.getInvokeExpr(); + AbstractInvokeExpr expr = invokeStmt.getInvokeExpr().get(); if (expr instanceof JSpecialInvokeExpr) { JSpecialInvokeExpr iie = (JSpecialInvokeExpr) expr; Value base = iie.getBase(); @@ -95,7 +96,7 @@ private SootMethod findInvokedConstructorOf(SootMethod outerInit) { for (Stmt unit : cmpag.getInvokeStmts()) { if (unit instanceof JInvokeStmt) { JInvokeStmt invokeStmt = (JInvokeStmt) unit; - AbstractInvokeExpr expr = invokeStmt.getInvokeExpr(); + AbstractInvokeExpr expr = invokeStmt.getInvokeExpr().get(); if (expr instanceof JSpecialInvokeExpr) { JSpecialInvokeExpr iie = (JSpecialInvokeExpr) expr; Value base = iie.getBase(); @@ -131,11 +132,11 @@ private Set mappingtoCallerCommingParamsOrHeaps( Set params, SootMethod curr, SootMethod caller) { MethodPAG cmpag = pag.getMethodPAG(caller); Set ret = new HashSet<>(); - for (Stmt stmt : cmpag.getInvokeStmts()) { - if (!(stmt.getInvokeExpr() instanceof JSpecialInvokeExpr)) { + for (InvokableStmt stmt : cmpag.getInvokeStmts()) { + if (!(stmt.getInvokeExpr().get() instanceof JSpecialInvokeExpr)) { continue; } - MethodSignature methodSig = stmt.getInvokeExpr().getMethodSignature(); + MethodSignature methodSig = stmt.getInvokeExpr().get().getMethodSignature(); Optional otarget = pta.getView().getMethod(methodSig); if (otarget.isPresent() && otarget.get().equals(curr)) { for (Node n : params) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/DepOnParamAnalysis.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/DepOnParamAnalysis.java index a391de9be6d..c4c4ebb9f47 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/DepOnParamAnalysis.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/DepOnParamAnalysis.java @@ -28,8 +28,8 @@ import qilin.core.builder.callgraph.Edge; import qilin.core.pag.*; import qilin.util.PTAUtils; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; /* @@ -119,7 +119,7 @@ public void run() { SootMethod srcMethod = edge.src(); MethodPAG srcmpag = prePAG.getMethodPAG(srcMethod); MethodNodeFactory srcnf = srcmpag.nodeFactory(); - Stmt invokeStmt = edge.srcUnit(); + InvokableStmt invokeStmt = edge.srcUnit(); if (invokeStmt instanceof JAssignStmt) { JAssignStmt assignStmt = (JAssignStmt) invokeStmt; diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/LeakAnalysis.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/LeakAnalysis.java index b621ac9dcc8..29c58e507e7 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/LeakAnalysis.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/conch/LeakAnalysis.java @@ -27,7 +27,7 @@ import qilin.core.builder.callgraph.Edge; import qilin.core.pag.*; import qilin.util.PTAUtils; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootMethod; /* @@ -133,7 +133,7 @@ public void run() { Edge edge = it.next(); SootMethod srcMethod = edge.src(); MethodPAG srcmpag = prePAG.getMethodPAG(srcMethod); - Stmt invokeStmt = edge.srcUnit(); + InvokableStmt invokeStmt = edge.srcUnit(); if (targetState == DFA.State.F) { // ret.f* = heap // add S -new-> r summary edge for symbolic heaps. VarNode ret = (VarNode) targetNode; @@ -154,7 +154,7 @@ public void run() { Edge edge = it.next(); SootMethod srcMethod = edge.src(); MethodPAG srcmpag = prePAG.getMethodPAG(srcMethod); - Stmt invokeStmt = edge.srcUnit(); + InvokableStmt invokeStmt = edge.srcUnit(); VarNode aj = PTAUtils.paramToArg(prePAG, invokeStmt, srcmpag, pj); // a param reach end state. if (targetState == DFA.State.B && sourceNode != targetNode) { // pi.f* = pj, pi != pj. @@ -185,7 +185,7 @@ public void run() { Edge edge = it.next(); SootMethod srcMethod = edge.src(); MethodPAG srcmpag = prePAG.getMethodPAG(srcMethod); - Stmt invokeStmt = edge.srcUnit(); + InvokableStmt invokeStmt = edge.srcUnit(); VarNode ai = PTAUtils.paramToArg(prePAG, invokeStmt, srcmpag, pi); VarNode r = PTAUtils.paramToArg(prePAG, invokeStmt, srcmpag, retOrThrow); if (r != null && ai != null) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/dd/CtxTunnelingFeaturesTrueTable.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/dd/CtxTunnelingFeaturesTrueTable.java index 61f15ebeb30..1f380c63f7c 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/dd/CtxTunnelingFeaturesTrueTable.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/dd/CtxTunnelingFeaturesTrueTable.java @@ -94,7 +94,7 @@ public CtxTunnelingFeaturesTrueTable(View view, SootMethod sm) { } } else if (unit instanceof JInvokeStmt) { JInvokeStmt invokeStmt = (JInvokeStmt) unit; - AbstractInvokeExpr expr = invokeStmt.getInvokeExpr(); + AbstractInvokeExpr expr = invokeStmt.asInvokableStmt().getInvokeExpr().get(); if (expr instanceof JStaticInvokeExpr) { this.f[17] = true; } else if (expr instanceof JVirtualInvokeExpr || expr instanceof JInterfaceInvokeExpr) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/IntraFlowAnalysis.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/IntraFlowAnalysis.java index e6fa96f8c29..ec5f37e3d90 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/IntraFlowAnalysis.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/IntraFlowAnalysis.java @@ -14,7 +14,7 @@ import sootup.core.jimple.common.constant.NullConstant; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootMethod; import sootup.core.signatures.MethodSubSignature; import sootup.core.types.ArrayType; @@ -142,8 +142,8 @@ private Set collectParamInArguments(AllocNode heap) { HeapContainerQuery hcq = this.utility.getHCQ(heap); Set inParams = hcq.getInParamsToCSFields(); MethodPAG srcmpag = pag.getMethodPAG(method); - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); if (!(ie instanceof AbstractInstanceInvokeExpr)) { continue; } diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XPAG.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XPAG.java index 5969fa91ec6..d63b7166b7c 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XPAG.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XPAG.java @@ -14,8 +14,8 @@ import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.types.ReferenceType; @@ -75,8 +75,8 @@ protected void buildInternalWithInline(SootMethod method) { } // global-local } // handle call statements. - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); int numArgs = ie.getArgCount(); Value[] args = new Value[numArgs]; for (int i = 0; i < numArgs; i++) { @@ -158,8 +158,8 @@ private void modelVirtualCall( addCStoreEdge(receiver, receiver); } - private void inline(SootMethod srcMethod, Stmt invokeStmt, SootMethod tgtMethod) { - AbstractInvokeExpr ie = invokeStmt.getInvokeExpr(); + private void inline(SootMethod srcMethod, InvokableStmt invokeStmt, SootMethod tgtMethod) { + AbstractInvokeExpr ie = invokeStmt.getInvokeExpr().get(); int numArgs = ie.getArgCount(); Value[] args = new Value[numArgs]; for (int i = 0; i < numArgs; i++) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XUtility.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XUtility.java index e1f9bdf5170..328fc10d10b 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XUtility.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/debloaterx/XUtility.java @@ -14,7 +14,7 @@ import sootup.core.jimple.basic.Local; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootClass; import sootup.core.model.SootField; import sootup.core.model.SootMethod; @@ -224,8 +224,8 @@ private void buildHeapMethodsMapping() { if (tgtM.isStatic() || !PTAUtils.hasBody(tgtM)) { continue; } - final Stmt s = edge.srcStmt(); - AbstractInvokeExpr ie = s.getInvokeExpr(); + final InvokableStmt s = edge.srcStmt(); + AbstractInvokeExpr ie = s.getInvokeExpr().get(); if (ie instanceof AbstractInstanceInvokeExpr) { AbstractInstanceInvokeExpr iie = (AbstractInstanceInvokeExpr) ie; Local base = iie.getBase(); diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/eagle/Eagle.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/eagle/Eagle.java index 8fb78dbbd30..50f51846249 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/eagle/Eagle.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/eagle/Eagle.java @@ -36,8 +36,8 @@ import sootup.core.jimple.common.constant.NullConstant; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.types.ReferenceType; @@ -344,8 +344,8 @@ else if (to instanceof FieldRefNode) { } // add invoke edges - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); int numArgs = ie.getArgCount(); Value[] args = new Value[numArgs]; for (int i = 0; i < numArgs; i++) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/selectx/Selectx.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/selectx/Selectx.java index 4ca2eb37ff2..d1ae487089e 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/selectx/Selectx.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/selectx/Selectx.java @@ -33,8 +33,8 @@ import sootup.core.jimple.common.constant.NullConstant; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.types.ReferenceType; @@ -295,9 +295,9 @@ private void buildGraph() { // add invoke edges MethodNodeFactory srcnf = srcmpag.nodeFactory(); - for (final Stmt s : srcmpag.getInvokeStmts()) { + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { CallSite callSite = new CallSite(s); - AbstractInvokeExpr ie = s.getInvokeExpr(); + AbstractInvokeExpr ie = s.getInvokeExpr().get(); int numArgs = ie.getArgCount(); Value[] args = new Value[numArgs]; for (int i = 0; i < numArgs; i++) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/turner/AbstractMVFG.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/turner/AbstractMVFG.java index 1612242b541..4a2f1e0f41d 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/turner/AbstractMVFG.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/turner/AbstractMVFG.java @@ -158,7 +158,7 @@ else if (to instanceof FieldRefNode) { // add invoke edges for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + AbstractInvokeExpr ie = s.asInvokableStmt().getInvokeExpr().get(); int numArgs = ie.getArgCount(); Value[] args = new Value[numArgs]; for (int i = 0; i < numArgs; i++) { diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/FlowAnalysis.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/FlowAnalysis.java index e952716e526..e4466e833be 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/FlowAnalysis.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/FlowAnalysis.java @@ -148,7 +148,7 @@ private void dfs(Node node) { .forEach( vcs -> { Stmt callsiteStmt = vcs.getUnit(); - AbstractInvokeExpr invo = callsiteStmt.getInvokeExpr(); + AbstractInvokeExpr invo = callsiteStmt.asInvokableStmt().getInvokeExpr().get(); if (!(invo instanceof AbstractInstanceInvokeExpr)) { return; } diff --git a/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/ObjectFlowGraph.java b/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/ObjectFlowGraph.java index f18e390a444..2ad061d02ae 100644 --- a/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/ObjectFlowGraph.java +++ b/sootup.qilin/src/main/java/qilin/pta/toolkits/zipper/flowgraph/ObjectFlowGraph.java @@ -8,7 +8,7 @@ import sootup.core.jimple.basic.Value; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; -import sootup.core.jimple.common.stmt.Stmt; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.model.SootMethod; public class ObjectFlowGraph implements IObjectFlowGraph { @@ -112,14 +112,14 @@ private void init() { pta.getCallGraph() .forEach( e -> { - Stmt callsite = e.srcStmt(); + InvokableStmt callsite = e.srcStmt(); SootMethod caller = e.src(); if (caller != null) { SootMethod callee = e.tgt(); if (!callee.isStatic()) { MethodNodeFactory calleeNF = pta.getPag().getMethodPAG(callee).nodeFactory(); LocalVarNode thisVar = (LocalVarNode) calleeNF.caseThis(); - AbstractInvokeExpr ie = callsite.getInvokeExpr(); + AbstractInvokeExpr ie = callsite.getInvokeExpr().get(); Value base = null; if (ie instanceof AbstractInstanceInvokeExpr) { AbstractInstanceInvokeExpr iie = (AbstractInstanceInvokeExpr) ie; diff --git a/sootup.qilin/src/main/java/qilin/pta/tools/PartialCallSiteSensPTA.java b/sootup.qilin/src/main/java/qilin/pta/tools/PartialCallSiteSensPTA.java index 8e23047f4bf..91891403b69 100644 --- a/sootup.qilin/src/main/java/qilin/pta/tools/PartialCallSiteSensPTA.java +++ b/sootup.qilin/src/main/java/qilin/pta/tools/PartialCallSiteSensPTA.java @@ -36,8 +36,8 @@ import sootup.core.jimple.common.constant.NullConstant; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.types.ReferenceType; @@ -148,8 +148,8 @@ protected void extraStats() { } } } - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); int numArgs = ie.getArgCount(); for (int i = 0; i < numArgs; i++) { Value arg = ie.getArg(i); diff --git a/sootup.qilin/src/main/java/qilin/pta/tools/PartialObjSensPTA.java b/sootup.qilin/src/main/java/qilin/pta/tools/PartialObjSensPTA.java index 20029388eb6..0b89aba749f 100644 --- a/sootup.qilin/src/main/java/qilin/pta/tools/PartialObjSensPTA.java +++ b/sootup.qilin/src/main/java/qilin/pta/tools/PartialObjSensPTA.java @@ -153,7 +153,7 @@ protected void extraStats() { } } for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + AbstractInvokeExpr ie = s.asInvokableStmt().getInvokeExpr().get(); int numArgs = ie.getArgCount(); for (int i = 0; i < numArgs; i++) { Value arg = ie.getArg(i); diff --git a/sootup.qilin/src/main/java/qilin/pta/tools/ZipperPTA.java b/sootup.qilin/src/main/java/qilin/pta/tools/ZipperPTA.java index a239b1ed997..0c75c03bb21 100644 --- a/sootup.qilin/src/main/java/qilin/pta/tools/ZipperPTA.java +++ b/sootup.qilin/src/main/java/qilin/pta/tools/ZipperPTA.java @@ -39,8 +39,8 @@ import sootup.core.jimple.common.constant.NullConstant; import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr; import sootup.core.jimple.common.expr.AbstractInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.SootMethod; import sootup.core.types.ReferenceType; @@ -121,8 +121,8 @@ protected void extraStats() { } } } - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); int numArgs = ie.getArgCount(); for (int i = 0; i < numArgs; i++) { Value arg = ie.getArg(i); diff --git a/sootup.qilin/src/main/java/qilin/stat/SimplifiedEvaluator.java b/sootup.qilin/src/main/java/qilin/stat/SimplifiedEvaluator.java index 1b76a5ca652..69e06dc565f 100644 --- a/sootup.qilin/src/main/java/qilin/stat/SimplifiedEvaluator.java +++ b/sootup.qilin/src/main/java/qilin/stat/SimplifiedEvaluator.java @@ -81,8 +81,8 @@ public void end() { // All the statements in the method for (Stmt st : PTAUtils.getMethodBody(sm).getStmts()) { // virtual calls - if (st.containsInvokeExpr()) { - AbstractInvokeExpr ie = st.getInvokeExpr(); + if (st.isInvokableStmt() && st.asInvokableStmt().containsInvokeExpr()) { + AbstractInvokeExpr ie = st.asInvokableStmt().getInvokeExpr().get(); if (!(ie instanceof JStaticInvokeExpr)) { // Virtual, Special or Instance // have to check target soot method, cannot just diff --git a/sootup.qilin/src/main/java/qilin/stat/TypeClientStat.java b/sootup.qilin/src/main/java/qilin/stat/TypeClientStat.java index ae51e63f874..bfaba5c754b 100644 --- a/sootup.qilin/src/main/java/qilin/stat/TypeClientStat.java +++ b/sootup.qilin/src/main/java/qilin/stat/TypeClientStat.java @@ -85,8 +85,8 @@ private void init() { // All the statements in the method for (Stmt st : PTAUtils.getMethodBody(sm).getStmts()) { // virtual calls - if (st.containsInvokeExpr()) { - AbstractInvokeExpr ie = st.getInvokeExpr(); + if (st.isInvokableStmt() && st.asInvokableStmt().containsInvokeExpr()) { + AbstractInvokeExpr ie = st.asInvokableStmt().getInvokeExpr().get(); if (ie instanceof JStaticInvokeExpr) { totalStaticCalls++; } else { // Virtual, Special or Instance diff --git a/sootup.qilin/src/main/java/qilin/util/PTAUtils.java b/sootup.qilin/src/main/java/qilin/util/PTAUtils.java index d5392c5775c..bdfe0a1a79a 100644 --- a/sootup.qilin/src/main/java/qilin/util/PTAUtils.java +++ b/sootup.qilin/src/main/java/qilin/util/PTAUtils.java @@ -45,8 +45,8 @@ import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JNewArrayExpr; import sootup.core.jimple.common.expr.JStaticInvokeExpr; +import sootup.core.jimple.common.stmt.InvokableStmt; import sootup.core.jimple.common.stmt.JAssignStmt; -import sootup.core.jimple.common.stmt.Stmt; import sootup.core.model.Body; import sootup.core.model.SootClass; import sootup.core.model.SootMethod; @@ -89,8 +89,8 @@ public static Map> calcStaticThisPTS(PTA pta) { LocalVarNode thisRef = (LocalVarNode) srcmpag.nodeFactory().caseThis(); final PointsToSet other = pta.reachingObjects(thisRef).toCIPointsToSet(); - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); if (ie instanceof JStaticInvokeExpr) { for (Iterator it = pta.getCallGraph().edgesOutOf(s); it.hasNext(); ) { Edge e = it.next(); @@ -122,8 +122,8 @@ public static Map> calcStaticThisPTS(PTA pta) { LocalVarNode thisRef = (LocalVarNode) srcmpag.nodeFactory().caseThis(); final Set other = pts.computeIfAbsent(thisRef, k -> new HashSet<>()); - for (final Stmt s : srcmpag.getInvokeStmts()) { - AbstractInvokeExpr ie = s.getInvokeExpr(); + for (final InvokableStmt s : srcmpag.getInvokeStmts()) { + AbstractInvokeExpr ie = s.getInvokeExpr().get(); if (ie instanceof JStaticInvokeExpr) { for (Iterator it = pta.getCallGraph().edgesOutOf(s); it.hasNext(); ) { Edge e = it.next(); @@ -364,9 +364,10 @@ public static boolean isEmptyArray(AllocNode heap) { return false; } - public static LocalVarNode paramToArg(PAG pag, Stmt invokeStmt, MethodPAG srcmpag, VarNode pi) { + public static LocalVarNode paramToArg( + PAG pag, InvokableStmt invokeStmt, MethodPAG srcmpag, VarNode pi) { MethodNodeFactory srcnf = srcmpag.nodeFactory(); - AbstractInvokeExpr ie = invokeStmt.getInvokeExpr(); + AbstractInvokeExpr ie = invokeStmt.getInvokeExpr().get(); Parm mPi = (Parm) pi.getVariable(); LocalVarNode thisRef = (LocalVarNode) srcnf.caseThis(); LocalVarNode receiver; diff --git a/sootup.qilin/src/test/java/qilin/test/context/CFATests.java b/sootup.qilin/src/test/java/qilin/test/context/CFATests.java index 043a155c280..697041c52e9 100644 --- a/sootup.qilin/src/test/java/qilin/test/context/CFATests.java +++ b/sootup.qilin/src/test/java/qilin/test/context/CFATests.java @@ -19,6 +19,7 @@ package qilin.test.context; import org.junit.Test; +import org.junit.jupiter.api.Tag; import qilin.test.util.JunitTests; public class CFATests extends JunitTests { diff --git a/sootup.qilin/src/test/java/qilin/test/util/AssertionsParser.java b/sootup.qilin/src/test/java/qilin/test/util/AssertionsParser.java index 1bddbff2f90..dbbf668c7cd 100644 --- a/sootup.qilin/src/test/java/qilin/test/util/AssertionsParser.java +++ b/sootup.qilin/src/test/java/qilin/test/util/AssertionsParser.java @@ -50,8 +50,8 @@ public static Set retrieveQueryInfo(PTA pta) { // System.out.println("================================================================="); // } for (final Stmt stmt : PTAUtils.getMethodBody(sm).getStmts()) { - if (stmt.containsInvokeExpr()) { - AbstractInvokeExpr ie = stmt.getInvokeExpr(); + if (stmt.isInvokableStmt() && stmt.asInvokableStmt().containsInvokeExpr()) { + AbstractInvokeExpr ie = stmt.asInvokableStmt().getInvokeExpr().get(); if (ie instanceof JStaticInvokeExpr) { final MethodSignature calleeSig = ie.getMethodSignature(); if (calleeSig.toString().equals(mayAliasSig)) { From 856a31853d2b8c5805751e872b785d6058a743e7 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Mon, 15 Jul 2024 21:35:16 +0200 Subject: [PATCH 39/41] removed unnecessary import --- sootup.qilin/src/test/java/qilin/test/context/CFATests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sootup.qilin/src/test/java/qilin/test/context/CFATests.java b/sootup.qilin/src/test/java/qilin/test/context/CFATests.java index 697041c52e9..043a155c280 100644 --- a/sootup.qilin/src/test/java/qilin/test/context/CFATests.java +++ b/sootup.qilin/src/test/java/qilin/test/context/CFATests.java @@ -19,7 +19,6 @@ package qilin.test.context; import org.junit.Test; -import org.junit.jupiter.api.Tag; import qilin.test.util.JunitTests; public class CFATests extends JunitTests { From a8e125d143cf4b241129facb951a0c0a5d91ed4e Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Tue, 16 Jul 2024 16:18:48 +0200 Subject: [PATCH 40/41] roll back edge class --- .../qilin/core/builder/callgraph/Edge.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java b/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java index 54e0dc4f382..c1ac72ba839 100644 --- a/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java +++ b/sootup.qilin/src/main/java/qilin/core/builder/callgraph/Edge.java @@ -3,7 +3,6 @@ import qilin.core.context.Context; import qilin.core.pag.ContextMethod; import qilin.util.Invalidable; -import sootup.callgraph.CallGraph; import sootup.core.jimple.common.expr.AbstractInvokeExpr; import sootup.core.jimple.common.expr.JInterfaceInvokeExpr; import sootup.core.jimple.common.expr.JSpecialInvokeExpr; @@ -17,7 +16,7 @@ * * @author Ondrej Lhotak */ -public final class Edge extends CallGraph.Call implements Invalidable { +public final class Edge implements Invalidable { /** * The method in which the call occurs; may be null for calls not occurring in a specific method @@ -28,6 +27,12 @@ public final class Edge extends CallGraph.Call implements Invalidable { /** The target method of the call edge. */ private ContextMethod tgt; + /** + * The unit at which the call occurs; may be null for calls not occurring at a specific statement + * (eg. calls in native code) + */ + private InvokableStmt srcUnit; + /** * The kind of edge. Note: kind should not be tested by other classes; instead, accessors such as * isExplicit() should be added. @@ -37,16 +42,18 @@ public final class Edge extends CallGraph.Call implements Invalidable { private boolean invalid = false; public Edge(ContextMethod src, InvokableStmt srcUnit, ContextMethod tgt, Kind kind) { - super(src.method().getSignature(), tgt.method().getSignature(), srcUnit); + this.src = src; + this.srcUnit = srcUnit; this.tgt = tgt; this.kind = kind; } public Edge(ContextMethod src, InvokableStmt srcUnit, ContextMethod tgt) { - super(src.method().getSignature(), tgt.method().getSignature(), srcUnit); + this.kind = ieToKind(srcUnit.getInvokeExpr().get()); this.src = src; + this.srcUnit = srcUnit; this.tgt = tgt; } @@ -63,11 +70,11 @@ public ContextMethod getSrc() { } public InvokableStmt srcUnit() { - return getInvokableStmt(); + return srcUnit; } public InvokableStmt srcStmt() { - return getInvokableStmt(); + return srcUnit; } public SootMethod tgt() { @@ -145,6 +152,7 @@ public boolean isInvalid() { public void invalidate() { // Since the edge remains in the QueueReaders for a while, the GC could not claim old units. src = null; + srcUnit = null; tgt = null; invalid = true; } @@ -158,8 +166,8 @@ public int hashCode() { if (src != null) { ret = ret * 32 + src.hashCode(); } - if (getInvokableStmt() != null) { - ret = ret * 32 + getInvokableStmt().hashCode(); + if (srcUnit != null) { + ret = ret * 32 + srcUnit.hashCode(); } return ret; } @@ -170,15 +178,12 @@ public boolean equals(Object other) { return false; } Edge o = (Edge) other; - return (o.src == this.src) - && (o.srcStmt() == this.srcStmt()) - && (o.tgt == tgt) - && (o.kind == kind); + return (o.src == this.src) && (o.srcUnit == srcUnit) && (o.tgt == tgt) && (o.kind == kind); } @Override public String toString() { - return this.kind + " edge: " + srcStmt() + " in " + src + " ==> " + tgt; + return this.kind + " edge: " + srcUnit + " in " + src + " ==> " + tgt; } private Edge nextByUnit = this; From 8028c0ec595093fb69a80b4cff0e98b646e607a4 Mon Sep 17 00:00:00 2001 From: Jonas Klauke Date: Thu, 25 Jul 2024 14:35:43 +0200 Subject: [PATCH 41/41] clean up after merge --- .../src/main/java/sootup/callgraph/CallGraph.java | 2 -- .../src/main/java/sootup/callgraph/CallGraphDifference.java | 2 +- .../src/test/java/sootup/callgraph/CallGraphTestBase.java | 1 - sootup.core/src/main/java/sootup/core/util/Utils.java | 4 ---- .../java/sootup/java/bytecode/RuntimeJarConversionTests.java | 3 +-- 5 files changed, 2 insertions(+), 10 deletions(-) diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java index 54037160abe..0e222948acc 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraph.java @@ -209,6 +209,4 @@ boolean containsCall( */ @Nonnull CallGraphDifference diff(@Nonnull CallGraph callGraph); - - } diff --git a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraphDifference.java b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraphDifference.java index 3aaf15a5fc9..01a605ae633 100644 --- a/sootup.callgraph/src/main/java/sootup/callgraph/CallGraphDifference.java +++ b/sootup.callgraph/src/main/java/sootup/callgraph/CallGraphDifference.java @@ -46,7 +46,7 @@ public CallGraphDifference(CallGraph baseCallGraph, CallGraph otherCallGraph) { private List> constructEdges(CallGraph cg) { List> cgEdges = new ArrayList<>(); for (MethodSignature srcNode : cg.getMethodSignatures()) { - Set outNodes = cg.callsFrom(srcNode); + Set outNodes = cg.callTargetsFrom(srcNode); for (MethodSignature targetNode : outNodes) { cgEdges.add(new MutablePair<>(srcNode, targetNode)); } diff --git a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java index e88faabf1d6..f7fbfafbbdf 100644 --- a/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java +++ b/sootup.callgraph/src/test/java/sootup/callgraph/CallGraphTestBase.java @@ -1067,7 +1067,6 @@ public void testNoMainMethod() { algorithm.initialize(); fail("Runtime Exception not thrown, when no main methods are defined."); } catch (RuntimeException e) { - System.out.println(e.getMessage()); assertEquals( e.getMessage(), "No main method is present in the input programs. initialize() method can be used if only one main method exists in the input program and that should be used as entry point for call graph. \n Please specify entry point as a parameter to initialize method."); diff --git a/sootup.core/src/main/java/sootup/core/util/Utils.java b/sootup.core/src/main/java/sootup/core/util/Utils.java index d9d51cb70e1..3a7c75ce1c8 100644 --- a/sootup.core/src/main/java/sootup/core/util/Utils.java +++ b/sootup.core/src/main/java/sootup/core/util/Utils.java @@ -217,10 +217,6 @@ public static ArrayList filterJimple(Stream stream) { .collect(Collectors.toCollection(ArrayList::new)); } - public static void generateJimpleForTest(@Nonnull SootMethod m) { - System.out.println(generateJimpleForTest(m.getBody())); - } - /** Helper for writing tests . */ public static String generateJimpleForTest(@Nonnull Body b) { ArrayList arr = filterJimple(Utils.bodyStmtsAsStrings(b).stream()); diff --git a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/RuntimeJarConversionTests.java b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/RuntimeJarConversionTests.java index ff256e051d8..18110fc5ef3 100644 --- a/sootup.java.bytecode/src/test/java/sootup/java/bytecode/RuntimeJarConversionTests.java +++ b/sootup.java.bytecode/src/test/java/sootup/java/bytecode/RuntimeJarConversionTests.java @@ -24,7 +24,7 @@ @Tag("Java8") public class RuntimeJarConversionTests { - private static boolean debug = true; + private static boolean debug = false; @Test public void testJarWithDefaultInterceptors() { @@ -61,7 +61,6 @@ private static void convertInputLocation(AnalysisInputLocation inputLocation) { .peek( javaSootMethod -> { try { - System.out.println(javaSootMethod.getSignature()); javaSootMethod.getBody(); } catch (Exception e) { e.printStackTrace();