From 73ae926c66d5b6fed096f3a29d8f0889d2effae3 Mon Sep 17 00:00:00 2001 From: Signior-X Date: Sun, 25 Sep 2022 15:18:25 +0530 Subject: [PATCH 1/7] Make changes in bash file, remove Library methods --- .gitignore | 2 ++ .vscode/settings.json | 6 ++++++ scripts/run.sh | 12 +++++++++--- src/analyser/StaticAnalyser.java | 4 ++++ 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 93fff4ccf..f68a0a678 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ .idea/ stava.iml .DS_Store + +out diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..0b75109cc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "java.project.referencedLibraries": [ + "lib/**/*.jar", + "soot/sootclasses-trunk-jar-with-dependencies.jar" + ] +} \ No newline at end of file diff --git a/scripts/run.sh b/scripts/run.sh index 318dd0e82..32f771271 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -3,8 +3,14 @@ # Sample script to be used to run the project on non-benchmark code. # Set the paths according to your installation. All paths must be full paths. # Instructions: ./run.sh ClassName + +if [ -z "$1" ]; then + echo "No TestCase Number Provided"; + exit +fi + # Installed path of Java 8 JDK -java_install_path="/usr/lib/jvm/java-8-oracle/" +java_install_path="/usr/lib/jvm/java-8-openjdk-amd64/" # The soot jar to be used. soot_path=`realpath ../soot/sootclasses-trunk-jar-with-dependencies.jar` @@ -13,10 +19,10 @@ soot_path=`realpath ../soot/sootclasses-trunk-jar-with-dependencies.jar` stava_path=`realpath ..` # The directory to be analysed. -test_path=`realpath ../tests/test20/` +test_path=`realpath ../tests/test$1/` # The directory inside which stava will output the results. -output_path=`realpath ../out/testcase/` +output_path=`realpath ../out/testcase$1/` java_compiler="${java_install_path}/bin/javac" java_vm="${java_install_path}/bin/java" diff --git a/src/analyser/StaticAnalyser.java b/src/analyser/StaticAnalyser.java index d07487aea..92f60dd6e 100644 --- a/src/analyser/StaticAnalyser.java +++ b/src/analyser/StaticAnalyser.java @@ -93,6 +93,10 @@ protected void internalTransform(Body body, String phasename, Map")){ // System.out.println("Skipping this method"); From cccd66c10d589c44bee87ef72eede310c12d416f Mon Sep 17 00:00:00 2001 From: Signior-X Date: Mon, 26 Sep 2022 20:22:39 +0530 Subject: [PATCH 2/7] Create structure for topoOrder --- src/analyser/StaticAnalyser.java | 1 + src/config/StoreEscape.java | 2 +- src/main/GetSootArgs.java | 1 + src/main/Main.java | 61 ++++++++++++++++++++++++++++---- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/analyser/StaticAnalyser.java b/src/analyser/StaticAnalyser.java index 92f60dd6e..acaf3296e 100644 --- a/src/analyser/StaticAnalyser.java +++ b/src/analyser/StaticAnalyser.java @@ -27,6 +27,7 @@ public class StaticAnalyser extends BodyTransformer { private boolean allNonEscaping; public static Map ptgs; public static Map> summaries; + public static Map> stackOrders; public static LinkedHashMap analysis; public static List noBCIMethods; String[] ignoreFuncs = { diff --git a/src/config/StoreEscape.java b/src/config/StoreEscape.java index b1185bd80..8d595cbd2 100644 --- a/src/config/StoreEscape.java +++ b/src/config/StoreEscape.java @@ -1,7 +1,7 @@ package config; public class StoreEscape { - public static boolean MarkStoreEscaping = true; + public static boolean MarkStoreEscaping = false; public static boolean ReduceParamDependence = true; public static boolean MarkParamReturnEscaping = false; } diff --git a/src/main/GetSootArgs.java b/src/main/GetSootArgs.java index adb992a9b..a1e13877c 100644 --- a/src/main/GetSootArgs.java +++ b/src/main/GetSootArgs.java @@ -213,6 +213,7 @@ private String[] normal(String[] args){ "-p","cg.spark","on", "-p","cg","all-reachable", "-keep-offset", + "-f","J", // "-soot-classpath", cp, //"-prepend-classpath", "-keep-line-number", "-main-class", args[3], diff --git a/src/main/Main.java b/src/main/Main.java index c1f7c7328..4033db9a8 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -113,7 +113,9 @@ public static void main(String[] args) { System.out.println("Static Analysis is done!"); System.out.println("Time Taken:"+(analysis_end-analysis_start)/1000F); - + // Now we are going to find the stack ordering of the non escaping functions + CreateStackOrdering(); + boolean useNewResolver = true; long res_start = System.currentTimeMillis(); // printSummary(staticAnalyser.summaries); @@ -137,9 +139,9 @@ public static void main(String[] args) { HashMap> resolved = (HashMap) kill(sr.solvedSummaries); - printAllInfo(StaticAnalyser.ptgs, resolved, args[4]); + // printAllInfo(StaticAnalyser.ptgs, resolved, args[4]); - saveStats(sr.existingSummaries, resolved, args[4], staticAnalyser.ptgs); + // saveStats(sr.existingSummaries, resolved, args[4], staticAnalyser.ptgs); printResForJVM(sr.solvedSummaries, args[2], args[4]); } @@ -154,13 +156,58 @@ public static void main(String[] args) { HashMap> resolved = (HashMap) kill(sr.solvedSummaries); - printAllInfo(StaticAnalyser.ptgs, staticAnalyser.summaries, args[4]); + // printAllInfo(StaticAnalyser.ptgs, staticAnalyser.summaries, args[4]); - printAllInfo(StaticAnalyser.ptgs, resolved, args[4]); + // printAllInfo(StaticAnalyser.ptgs, resolved, args[4]); - saveStats(sr.existingSummaries, resolved, args[4], staticAnalyser.ptgs); + // saveStats(sr.existingSummaries, resolved, args[4], staticAnalyser.ptgs); - printResForJVM(sr.solvedSummaries, args[2], args[4]); + // printResForJVM(sr.solvedSummaries, args[2], args[4]); + } + } + + /** + * Performs dfs and finds the topological order + * @param node - Starting node of the dfs + * @param ptg - Points to graph + * @param visited - A visited array to have an idea of dfs + * @param topoOrder - The final result of the dfs - Topological Order + */ + static void topologicalSortDfs( + ObjectNode node, + PointsToGraph ptg, + HashSet visited, + ArrayList topoOrder) { + + } + + /** + * Create Stack ordering for each ptg in the Static Analyser + */ + static void CreateStackOrdering() { + // We assumed that the PTGs exist in the StaticAnalyser + + System.out.println("PRIYAM - Starting topological sorting"); + for(SootMethod method : StaticAnalyser.ptgs.keySet()) { + System.out.println("PRIYAM: " + method); + + PointsToGraph ptg = StaticAnalyser.ptgs.get(method); + + // TODO - First check if it is a DAG + // Perform topological sort for the ptg + System.out.println(ptg); + + HashSet visited = new HashSet(); + ArrayList topoOrder = new ArrayList(); + + for(Set objectNodeSet : ptg.vars.values()) { + for (ObjectNode object : objectNodeSet) { + if (!visited.contains(object)) { + // System.out.println("PRIYAM object" + object); + topologicalSortDfs(object, ptg, visited, topoOrder); + } + } + } } } From e7e88a406468cbbda48b4e81c926f130ebb38b31 Mon Sep 17 00:00:00 2001 From: Signior-X Date: Mon, 26 Sep 2022 20:47:45 +0530 Subject: [PATCH 3/7] TopoSort implemented --- src/main/Main.java | 15 +++++++++++++++ tests/test1/Main.java | 5 ++--- tests/test23/Main.java | 13 +++++++++++++ tests/test23/Node.java | 3 +++ 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/test23/Main.java create mode 100644 tests/test23/Node.java diff --git a/src/main/Main.java b/src/main/Main.java index 4033db9a8..7a743e74f 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -178,7 +178,20 @@ static void topologicalSortDfs( PointsToGraph ptg, HashSet visited, ArrayList topoOrder) { + visited.add(node); + + Map> objectNodesMap = ptg.fields.get(node); + if (objectNodesMap != null) { + for (SootField sootField : objectNodesMap.keySet()) { + for (ObjectNode nextObject : objectNodesMap.get(sootField)) { + if (!visited.contains(nextObject)) { + topologicalSortDfs(nextObject, ptg, visited, topoOrder); + } + } + } + } + topoOrder.add(node); } /** @@ -208,6 +221,8 @@ static void CreateStackOrdering() { } } } + + System.out.println("PRIYAM TopoOrder : " + topoOrder); } } diff --git a/tests/test1/Main.java b/tests/test1/Main.java index 64b3938fa..6ca52a26a 100644 --- a/tests/test1/Main.java +++ b/tests/test1/Main.java @@ -5,8 +5,7 @@ public static void main(String[] args) { Node C = new Node(); Node D = new Node(); A.n = B; - B.n = C; - C.n = D; - D.n = B; + B.n = D; + D.n = C; } } diff --git a/tests/test23/Main.java b/tests/test23/Main.java new file mode 100644 index 000000000..efd4fe0fd --- /dev/null +++ b/tests/test23/Main.java @@ -0,0 +1,13 @@ +public class Main { + public static void main(String[] args) { + Node A = new Node(); + Node B = new Node(); + Node C = new Node(); + Node D = new Node(); + Node E = new Node(); + A.n = B; + B.n = D; + B.n = E; + D.n = C; + } +} diff --git a/tests/test23/Node.java b/tests/test23/Node.java new file mode 100644 index 000000000..04f5b0175 --- /dev/null +++ b/tests/test23/Node.java @@ -0,0 +1,3 @@ +public class Node { + public Node n; +} From e92cb08b6182a169b126208c33ca9d9b995685c5 Mon Sep 17 00:00:00 2001 From: Signior-X Date: Tue, 18 Oct 2022 19:40:05 +0530 Subject: [PATCH 4/7] Create interprocedural linking --- .vscode/launch.json | 21 +++ src/analyser/StackOrderAnalyser.java | 184 ++++++++++++++++++++++++ src/analyser/StaticAnalyser.java | 7 +- src/main/Main.java | 104 +++++++------- src/utils/GetListOfNoEscapeObjects.java | 16 ++- tests/test23/Main.java | 2 +- tests/test23/Node.java | 1 + tests/test24/Main.java | 20 +++ tests/test24/Node.java | 4 + tests/test25/Main.java | 26 ++++ tests/test25/Node.java | 4 + tests/test26/Main.java | 33 +++++ tests/test26/Node.java | 4 + 13 files changed, 366 insertions(+), 60 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 src/analyser/StackOrderAnalyser.java create mode 100644 tests/test24/Main.java create mode 100644 tests/test24/Node.java create mode 100644 tests/test25/Main.java create mode 100644 tests/test25/Node.java create mode 100644 tests/test26/Main.java create mode 100644 tests/test26/Node.java diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..dda89494c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Current File", + "request": "launch", + "mainClass": "${file}" + }, + { + "type": "java", + "name": "Launch Main", + "request": "launch", + "mainClass": "Main", + "projectName": "stava_862dc55b" + } + ] +} \ No newline at end of file diff --git a/src/analyser/StackOrderAnalyser.java b/src/analyser/StackOrderAnalyser.java new file mode 100644 index 000000000..a05fa3f7f --- /dev/null +++ b/src/analyser/StackOrderAnalyser.java @@ -0,0 +1,184 @@ +package analyser; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import soot.*; +import es.ConditionalValue; +import es.EscapeStatus; +import main.CHATransform; +import ptg.ObjectNode; +import ptg.ObjectType; +import ptg.PointsToGraph; +import soot.jimple.Constant; +import soot.jimple.InstanceInvokeExpr; +import soot.jimple.InvokeExpr; +import soot.jimple.internal.JInvokeStmt; +import soot.jimple.internal.JStaticInvokeExpr; +import soot.jimple.toolkits.callgraph.CallGraph; +import soot.jimple.toolkits.callgraph.Edge; + +public class StackOrderAnalyser extends BodyTransformer { + public static ConcurrentHashMap > nativeLocals = new ConcurrentHashMap<>(); + + public static ArrayList whitelistedNatives = new ArrayList<> ( + Arrays.asList("") + ); + + public static ArrayList blacklistedNatives = new ArrayList<> ( + Arrays.asList("", + "", + "") + ); + + + private Set methodsProcessed; + private Set methodsProcessing; + + public StackOrderAnalyser() { + methodsProcessed = new HashSet(); + methodsProcessing = new HashSet(); + } + + @Override + protected void internalTransform(Body body, String phasename, Map options) { + SootMethod method = body.getMethod(); + + if (body.getMethod().isJavaLibraryMethod()) { + return; + } + + if (methodsProcessed.contains(method)) { + // Method already computed + // we have the results ready + return; + } + + if (methodsProcessing.contains(method)) { + // Recursive loop + // TODO - See what to do + return; + } + + methodsProcessing.add(method); + processMethod(body); + methodsProcessed.add(method); + } + + private static void processMethod(Body body) { + System.out.println("PRIYAM Method Name: "+ body.getMethod().getBytecodeSignature() + ":"+body.getMethod().getName()); + PatchingChain units = body.getUnits(); + + for (Unit u : units) { + if (u instanceof JInvokeStmt) { + JInvokeStmt stmt = (JInvokeStmt) u; + InvokeExpr expr = stmt.getInvokeExpr(); + handleExpr(body.getMethod(), u, expr); + } + } + } + + public static void handleExpr( + SootMethod m, Unit u, InvokeExpr expr) { + PointsToGraph ptg = StaticAnalyser.ptgs.get(m); + CallGraph cg = Scene.v().getCallGraph(); + + Iterator iedges = cg.edgesOutOf(u); + List args = expr.getArgs(); + + List edges = new ArrayList<>(); + if (!iedges.hasNext()) { + iedges = CHATransform.getCHA().edgesOutOf(u); + } + + while (iedges.hasNext()) { + edges.add(iedges.next()); + } + + if (edges.size() == 0) { + // System.out.println("Empty edges: " + expr + ", function incoming edges: " + cg.edgesInto(m).hasNext() + + // " Method: " + m.getBytecodeSignature()); + edges.add(new Edge(m, u, expr.getMethod(), Kind.SPECIAL)); + } + + if (expr instanceof InstanceInvokeExpr) { + // ASK - No need to handle instance invoke expr? + } else if (expr instanceof JStaticInvokeExpr) { + } else { + System.err.println("Unidentified invoke expr: " + expr.toString()); + throw new IllegalArgumentException(expr.toString()); + } + + for (Edge edge : edges) { + /* 1. + * We traverse and find the caller callie relationship + * between ObjectNodes + */ + SootMethod method = edge.tgt(); + int paramCount = method.getParameterCount(); + + // TODO - Add a recursion to first process the method + // if not already processed + + Map> paramMapping = new HashMap>(); + for (int i = 0; i < paramCount; i++) { + ObjectNode obj = new ObjectNode(i, ObjectType.parameter); + // ConditionalValue cv = new ConditionalValue(method, obj, true); + + if (edge.kind() == Kind.REFL_INVOKE) + paramMapping.put(obj, ptg.vars.get((Local) args.get(1))); + else if (edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) + paramMapping.put(obj, ptg.vars.get((Local) args.get(0))); + else { + Value arg = args.get(i); + if (arg.getType() instanceof RefType || arg.getType() instanceof ArrayType) + if (!(arg instanceof Constant)) { // Notice the not(!) + // ptg.addParametricEdge((Local) args.get(i), cv); + paramMapping.put(obj, ptg.vars.get((Local) args.get(i))); + } + } + } + + // System.out.println("PRIYAM PARAMS MAPPING: " + paramMapping); + + /* 2. + * Now, loop in the callie method's ptg to find if there + * exists any relationship/node between the params + * If exists, add the realtion for corresponding values in + * paramsMapping also + */ + PointsToGraph calliePTG = StaticAnalyser.ptgs.get(method); + // System.out.println("PRIYAM PTGS: " + StaticAnalyser.ptgs); + // System.out.println("PRIYAM calliePTG: " + calliePTG); + // If ptg gives error, ensure StaticAnalysis has been done + + for (int i = 0; i < paramCount; i++) { + ObjectNode obj = new ObjectNode(i, ObjectType.parameter); + Map> pointingTo = calliePTG.fields.get(obj); + + if (pointingTo == null) { + continue; + } + + for (Map.Entry> entry : pointingTo.entrySet()) { + for (ObjectNode fieldObj : entry.getValue()) { + System.out.println("There exists an edge from: " + obj + " to " + fieldObj + " by " + entry.getKey()); + if (fieldObj.type == ObjectType.parameter) { + continue; + } + + // Find paramsMapping for obj + // Find paramsMapping for fieldObj + // Add an edge from objs to fieldObjs + for (ObjectNode objInCaller : paramMapping.get(obj)) { + for (ObjectNode fieldObjInCaller : paramMapping.get(fieldObj)) { + // System.out.println("There should exists an edge from: " + objInCaller + " to " + fieldObjInCaller + " by " + entry.getKey()); + ptg.WEAK_makeField(objInCaller, entry.getKey(), fieldObjInCaller); + } + } + } + } + } + } + } +} diff --git a/src/analyser/StaticAnalyser.java b/src/analyser/StaticAnalyser.java index acaf3296e..2ac53da81 100644 --- a/src/analyser/StaticAnalyser.java +++ b/src/analyser/StaticAnalyser.java @@ -75,6 +75,7 @@ public StaticAnalyser() { analysis = new LinkedHashMap<>(); ptgs = new ConcurrentHashMap<>(); summaries = new ConcurrentHashMap<>(); + stackOrders = new ConcurrentHashMap<>(); noBCIMethods = new ArrayList<>(); allNonEscaping = false; } @@ -98,7 +99,7 @@ protected void internalTransform(Body body, String phasename, Map")){ // System.out.println("Skipping this method"); // return; @@ -337,6 +338,10 @@ private void setParamsAsEscaping(SootMethod m, Map sum public void apply(SootMethod m, Unit u, PointsToGraph ptg, Map summary) { // System.err.println(u+" "+u.getClass().getName()); + + // System.out.println("PRIYAM soot unit " + u); + // System.out.println("PRIYAM soot ptg " + ptg); + if (u instanceof JAssignStmt) { JAssignStmtHandler.handle(m, u, ptg, summary); } else if (u instanceof JIdentityStmt) { diff --git a/src/main/Main.java b/src/main/Main.java index 7a743e74f..e1b656d28 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -1,5 +1,6 @@ package main; +import analyser.StackOrderAnalyser; import analyser.StaticAnalyser; import config.StoreEscape; import es.*; @@ -27,7 +28,6 @@ import java.util.Map; import java.util.*; import java.io.*; -import java.lang.*; import static utils.KillCallerOnly.kill; @@ -50,7 +50,7 @@ static void setStoreEscapeOptions(String[] args) { } } public static void main(String[] args) { - + // Generating soot args GetSootArgs g = new GetSootArgs(); String[] sootArgs = g.get(args); setStoreEscapeOptions(args); @@ -58,22 +58,18 @@ public static void main(String[] args) { System.out.println("Unable to generate args for soot!"); return; } + StaticAnalyser staticAnalyser = new StaticAnalyser(); + StackOrderAnalyser stackOrderAnalyser = new StackOrderAnalyser(); CHATransform prepass = new CHATransform(); PackManager.v().getPack("wjap").add(new Transform("wjap.pre", prepass)); PackManager.v().getPack("jtp").add(new Transform("jtp.sample", staticAnalyser)); + long analysis_start = System.currentTimeMillis(); Options.v().parse(sootArgs); Scene.v().loadNecessaryClasses(); Scene.v().loadDynamicClasses(); List entryPoints = Scene.v().getEntryPoints(); - // SootClass sc = Scene.v().loadClassAndSupport("java.lang.CharacterData"); - // System.out.println(sc.getMethods()); - // Scene.v().forceResolve(sc.getName(), SootClass.BODIES); - // SootMethod tobeAdded = sc.getMethodByName("toUpperCaseEx"); - // System.out.println("Method: "+tobeAdded); - // // SootMethod tobeAdded = Scene.v().getMethod(""); - // entryPoints.add(tobeAdded); Chain appClasses = Scene.v().getClasses(); Iterator appClassItertator = appClasses.iterator(); @@ -92,58 +88,47 @@ public static void main(String[] args) { // System.out.println("SuperClass: "+aclass.getSuperclass()); } } - // aclass = Scene.v().loadClassAndSupport(aclass.getName()); - // aclass = Scene.v().forceResolve(aclass.getName(), SootClass.BODIES); - // // if (aclass.getName().contains("spec.validity.Digests")) { - // // System.out.println("Aclass spec: "+aclass.getName()+" : "+aclass.getMethodByName("crunch_jars")); - // // } - // System.out.println("Aclass: "+aclass.getName()+ " phantom: "+aclass.isPhantomClass()+" app: "+aclass.isApplicationClass()+" Concrete: "+ - // aclass.isConcrete()+" : " + aclass.getMethods()); - // // System.out.println(aclass.getMethods()); - // entryPoints.addAll(aclass.getMethods()); } - // System.out.println(entryPoints); - // if (true) - // return; - Scene.v().setEntryPoints(entryPoints); + Scene.v().setEntryPoints(entryPoints); PackManager.v().runPacks(); - // soot.Main.main(sootArgs); + long analysis_end = System.currentTimeMillis(); System.out.println("Static Analysis is done!"); System.out.println("Time Taken:"+(analysis_end-analysis_start)/1000F); + System.out.println("BEFORE InterProcedural Linking"); + printAllInfo(StaticAnalyser.ptgs, StaticAnalyser.summaries, StaticAnalyser.stackOrders, args[4]); + + // First, we add edges created due to callie function during method call + analysis_start = System.currentTimeMillis(); + PackManager.v().getPack("jtp").add(new Transform("jtp.stackOrder", stackOrderAnalyser)); + PackManager.v().runPacks(); + // Now we are going to find the stack ordering of the non escaping functions CreateStackOrdering(); + analysis_end = System.currentTimeMillis(); + System.out.println("InterProcedural Linking is done!"); + System.out.println("Time Taken:"+(analysis_end-analysis_start)/1000F); boolean useNewResolver = true; long res_start = System.currentTimeMillis(); - // printSummary(staticAnalyser.summaries); - // System.err.println(staticAnalyser.ptgs); - printAllInfo(StaticAnalyser.ptgs, staticAnalyser.summaries, args[4]); - // if (true) - // return; - // printCFG(); + System.out.println("BEFORE Resolver"); + printAllInfo(StaticAnalyser.ptgs, StaticAnalyser.summaries, StaticAnalyser.stackOrders, args[4]); if(useNewResolver) { - ReworkedResolver sr = new ReworkedResolver(staticAnalyser.summaries, - staticAnalyser.ptgs, - staticAnalyser.noBCIMethods); + ReworkedResolver sr = new ReworkedResolver( + StaticAnalyser.summaries, + StaticAnalyser.ptgs, + StaticAnalyser.noBCIMethods); long res_end = System.currentTimeMillis(); System.out.println("Resolution is done"); System.out.println("Time Taken in phase 1:"+(analysis_end-analysis_start)/1000F); System.out.println("Time Taken in phase 2:"+(res_end-res_start)/1000F); - - // System.out.println(staticAnalyser.summaries.size()+ " "+staticAnalyser.ptgs.size()); - - HashMap> resolved = (HashMap) kill(sr.solvedSummaries); - - // printAllInfo(StaticAnalyser.ptgs, resolved, args[4]); - - // saveStats(sr.existingSummaries, resolved, args[4], staticAnalyser.ptgs); - - printResForJVM(sr.solvedSummaries, args[2], args[4]); + System.out.println("AFTER Resolver"); + printAllInfo(StaticAnalyser.ptgs, StaticAnalyser.summaries, StaticAnalyser.stackOrders, args[4]); + printResForJVM(sr.solvedSummaries, StaticAnalyser.stackOrders, args[2], args[4]); } else { SummaryResolver sr = new SummaryResolver(); @@ -202,13 +187,12 @@ static void CreateStackOrdering() { System.out.println("PRIYAM - Starting topological sorting"); for(SootMethod method : StaticAnalyser.ptgs.keySet()) { - System.out.println("PRIYAM: " + method); - PointsToGraph ptg = StaticAnalyser.ptgs.get(method); // TODO - First check if it is a DAG + // TO ASK - Peform a check before or combine with the + // topological dfs // Perform topological sort for the ptg - System.out.println(ptg); HashSet visited = new HashSet(); ArrayList topoOrder = new ArrayList(); @@ -222,7 +206,7 @@ static void CreateStackOrdering() { } } - System.out.println("PRIYAM TopoOrder : " + topoOrder); + StaticAnalyser.stackOrders.put(method, topoOrder); } } @@ -277,8 +261,11 @@ public int compare(EscapeState a, EscapeState b) } } - private static void printAllInfo(Map ptgs, - Map> summaries, String opDir) { + private static void printAllInfo( + Map ptgs, + Map> summaries, + Map> stackOrders, + String opDir) { Path p_opDir = Paths.get(opDir); for (Map.Entry entry : ptgs.entrySet()) { @@ -291,7 +278,15 @@ private static void printAllInfo(Map ptgs, output.append("PTG:\n"); output.append(ptg.toString()); output.append("\nSummary\n"); - output.append(summaries.get(method).toString() + "\n"); + output.append(summaries.get(method).toString()); + + if (stackOrders.containsKey(method)) { + output.append("\nStackOrder\n"); + output.append(stackOrders.get(method).toString() + "\n\n"); + } else { + output.append("\nNo stack Ordering exists for : " + method + "\n\n"); + } + try { Files.write(p_opFile, output.toString().getBytes(StandardCharsets.UTF_8), Files.exists(p_opFile) ? StandardOpenOption.APPEND : StandardOpenOption.CREATE); @@ -302,6 +297,7 @@ private static void printAllInfo(Map ptgs, } } } + static String transformFuncSignature(String inputString) { StringBuilder finalString = new StringBuilder(); for(int i=1;i> summaries, String ipDir, String opDir) { + + static void printResForJVM( + Map> summaries, + Map> stackOrders, + String ipDir, + String opDir) { // Open File Path p_ipDir = Paths.get(ipDir); Path p_opDir = Paths.get(opDir); @@ -328,9 +329,10 @@ static void printResForJVM(Map> su HashMap summary = entry.getValue(); sb.append(transformFuncSignature(method.getBytecodeSignature())); sb.append(" "); - sb.append(GetListOfNoEscapeObjects.get(summary)); + sb.append(GetListOfNoEscapeObjects.get(summary, stackOrders.get(method))); sb.append("\n"); } + try { System.out.println("Trying to write to:" + p_opFile); Files.write(p_opFile, sb.toString().getBytes(StandardCharsets.UTF_8), diff --git a/src/utils/GetListOfNoEscapeObjects.java b/src/utils/GetListOfNoEscapeObjects.java index 021f268d0..46ce44a13 100644 --- a/src/utils/GetListOfNoEscapeObjects.java +++ b/src/utils/GetListOfNoEscapeObjects.java @@ -10,16 +10,18 @@ import java.util.Map; public class GetListOfNoEscapeObjects { - public static String get(HashMap summary) { + public static String get( + HashMap summary, + ArrayList stackOrder) { ArrayList arr = new ArrayList<>(); - for (Map.Entry entry : summary.entrySet()) { - ObjectNode obj = entry.getKey(); - if(obj.type != ObjectType.internal) + for (ObjectNode obj : stackOrder) { + if (obj.type != ObjectType.internal) continue; - EscapeStatus es = entry.getValue(); - if (es.containsNoEscape()) arr.add(obj.ref); + EscapeStatus es = summary.get(obj); + if (es.containsNoEscape()) + arr.add(obj.ref); } - Collections.sort(arr); + String _ret = arr.toString(); return _ret; } diff --git a/tests/test23/Main.java b/tests/test23/Main.java index efd4fe0fd..9cf2b64ff 100644 --- a/tests/test23/Main.java +++ b/tests/test23/Main.java @@ -7,7 +7,7 @@ public static void main(String[] args) { Node E = new Node(); A.n = B; B.n = D; - B.n = E; + B.m = E; D.n = C; } } diff --git a/tests/test23/Node.java b/tests/test23/Node.java index 04f5b0175..391eba7af 100644 --- a/tests/test23/Node.java +++ b/tests/test23/Node.java @@ -1,3 +1,4 @@ public class Node { public Node n; + public Node m; } diff --git a/tests/test24/Main.java b/tests/test24/Main.java new file mode 100644 index 000000000..c60622ac7 --- /dev/null +++ b/tests/test24/Main.java @@ -0,0 +1,20 @@ +public class Main { + public static void main(String[] args) { + } + + static void foo(Node node1, Node node2) { + Node A = new Node(); + Node B = new Node(); + Node C = new Node(); + Node D = new Node(); + Node E = new Node(); + bar(A, B); + bar(A, C); + bar(D, E); + bar(node1, node2); + } + + static void bar(Node n1, Node n2) { + n1.n = n2; + } +} diff --git a/tests/test24/Node.java b/tests/test24/Node.java new file mode 100644 index 000000000..391eba7af --- /dev/null +++ b/tests/test24/Node.java @@ -0,0 +1,4 @@ +public class Node { + public Node n; + public Node m; +} diff --git a/tests/test25/Main.java b/tests/test25/Main.java new file mode 100644 index 000000000..ad5635f25 --- /dev/null +++ b/tests/test25/Main.java @@ -0,0 +1,26 @@ +public class Main { + public static void main(String[] args) { + } + + static void foo(Node node1, Node node2) { + Node A = new Node(); + Node B = new Node(); + Node C = new Node(); + Node D = new Node(); + Node E = new Node(); + bar(A, B); + bar(A, C); + bar(D, E); + bar(node1, node2); + } + + static void bar(Node n1, Node n2) { + Node F = new Node(); + n1.n = F; // we need to heapify F (address check) + F.n = n2; // no heapfication + + + // Theory -- If two objects are directly connected + // Then only we need stack order, else, we will not be needing any stack order + } +} diff --git a/tests/test25/Node.java b/tests/test25/Node.java new file mode 100644 index 000000000..391eba7af --- /dev/null +++ b/tests/test25/Node.java @@ -0,0 +1,4 @@ +public class Node { + public Node n; + public Node m; +} diff --git a/tests/test26/Main.java b/tests/test26/Main.java new file mode 100644 index 000000000..e790590a7 --- /dev/null +++ b/tests/test26/Main.java @@ -0,0 +1,33 @@ +public class Main { + public static void main(String[] args) { + foo(); + } + + static void foo() { + Node A = new Node(); + Node B = new Node(); + bar(A, B); + + Node D = new Node(); + Node E = new Node(); + bar(D, E); + } + + static void bar(Node n1, Node n2) { + n1.n = n2; + + bas(n1); + } + + static void bas(Node x) { + Node x1 = new Node(); + + x.n = x1; + + int i = bat(); + } + + static int bat() { + return 5; + } +} diff --git a/tests/test26/Node.java b/tests/test26/Node.java new file mode 100644 index 000000000..391eba7af --- /dev/null +++ b/tests/test26/Node.java @@ -0,0 +1,4 @@ +public class Node { + public Node n; + public Node m; +} From 6311454b82e6600ad77b1146805d3b9815ddbb92 Mon Sep 17 00:00:00 2001 From: Signior-X Date: Tue, 18 Oct 2022 23:27:01 +0530 Subject: [PATCH 5/7] Complete stack ordering and added tests --- src/analyser/StackOrderAnalyser.java | 41 +++++++++++++++++++--------- src/analyser/StaticAnalyser.java | 2 +- tests/test26/Main.java | 30 ++++++-------------- tests/test27/Main.java | 32 ++++++++++++++++++++++ tests/test27/Node.java | 4 +++ 5 files changed, 73 insertions(+), 36 deletions(-) create mode 100644 tests/test27/Main.java create mode 100644 tests/test27/Node.java diff --git a/src/analyser/StackOrderAnalyser.java b/src/analyser/StackOrderAnalyser.java index a05fa3f7f..521ab426d 100644 --- a/src/analyser/StackOrderAnalyser.java +++ b/src/analyser/StackOrderAnalyser.java @@ -43,8 +43,11 @@ public StackOrderAnalyser() { @Override protected void internalTransform(Body body, String phasename, Map options) { SootMethod method = body.getMethod(); + processMethod(method); + } - if (body.getMethod().isJavaLibraryMethod()) { + private void processMethod(SootMethod method) { + if (method.isJavaLibraryMethod()) { return; } @@ -56,29 +59,30 @@ protected void internalTransform(Body body, String phasename, Map units = body.getUnits(); for (Unit u : units) { + // System.out.println("PRIYAM unit: " + u); if (u instanceof JInvokeStmt) { JInvokeStmt stmt = (JInvokeStmt) u; InvokeExpr expr = stmt.getInvokeExpr(); - handleExpr(body.getMethod(), u, expr); + handleExpr(method, u, expr); } } + + methodsProcessing.remove(method); + methodsProcessed.add(method); } - public static void handleExpr( + public void handleExpr( SootMethod m, Unit u, InvokeExpr expr) { PointsToGraph ptg = StaticAnalyser.ptgs.get(m); CallGraph cg = Scene.v().getCallGraph(); @@ -119,6 +123,9 @@ public static void handleExpr( // TODO - Add a recursion to first process the method // if not already processed + if (!methodsProcessed.contains(method)) { + processMethod(method); + } Map> paramMapping = new HashMap>(); for (int i = 0; i < paramCount; i++) { @@ -148,8 +155,9 @@ else if (edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) * paramsMapping also */ PointsToGraph calliePTG = StaticAnalyser.ptgs.get(method); - // System.out.println("PRIYAM PTGS: " + StaticAnalyser.ptgs); - // System.out.println("PRIYAM calliePTG: " + calliePTG); + System.out.println("PRIYAM METHOD: " + method); + System.out.println("PRIYAM PTGS: " + StaticAnalyser.ptgs); + System.out.println("PRIYAM calliePTG: " + calliePTG); // If ptg gives error, ensure StaticAnalysis has been done for (int i = 0; i < paramCount; i++) { @@ -163,22 +171,29 @@ else if (edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) for (Map.Entry> entry : pointingTo.entrySet()) { for (ObjectNode fieldObj : entry.getValue()) { System.out.println("There exists an edge from: " + obj + " to " + fieldObj + " by " + entry.getKey()); - if (fieldObj.type == ObjectType.parameter) { + if (fieldObj.type != ObjectType.parameter) { continue; } + if (!paramMapping.containsKey(obj) || !paramMapping.containsKey(fieldObj)) { + // If paramsMapping does not have the object, it can happen if null is passed + continue; + } + // Find paramsMapping for obj // Find paramsMapping for fieldObj // Add an edge from objs to fieldObjs for (ObjectNode objInCaller : paramMapping.get(obj)) { for (ObjectNode fieldObjInCaller : paramMapping.get(fieldObj)) { - // System.out.println("There should exists an edge from: " + objInCaller + " to " + fieldObjInCaller + " by " + entry.getKey()); + System.out.println("There should exists an edge from: " + objInCaller + " to " + fieldObjInCaller + " by " + entry.getKey()); ptg.WEAK_makeField(objInCaller, entry.getKey(), fieldObjInCaller); } } } } } + + System.out.println("AFTER PRIYAM PTGS: " + StaticAnalyser.ptgs + "\n"); } } } diff --git a/src/analyser/StaticAnalyser.java b/src/analyser/StaticAnalyser.java index 2ac53da81..541671788 100644 --- a/src/analyser/StaticAnalyser.java +++ b/src/analyser/StaticAnalyser.java @@ -302,7 +302,7 @@ protected void internalTransform(Body body, String phasename, Map nativeList, Map summary, PointsToGraph ptg) { diff --git a/tests/test26/Main.java b/tests/test26/Main.java index e790590a7..39b7ecb7d 100644 --- a/tests/test26/Main.java +++ b/tests/test26/Main.java @@ -1,33 +1,19 @@ public class Main { public static void main(String[] args) { - foo(); + Node x = new Node(); + Node y = new Node(); + foo(x, y); // There should come a linking for x and y from baz } - static void foo() { - Node A = new Node(); - Node B = new Node(); - bar(A, B); - - Node D = new Node(); - Node E = new Node(); - bar(D, E); + static void foo(Node node1, Node node2) { + bar(node1, node2); } static void bar(Node n1, Node n2) { - n1.n = n2; - - bas(n1); - } - - static void bas(Node x) { - Node x1 = new Node(); - - x.n = x1; - - int i = bat(); + baz(n1, n2); } - static int bat() { - return 5; + static void baz(Node p, Node q) { + p.n = q; // Linking the objects here } } diff --git a/tests/test27/Main.java b/tests/test27/Main.java new file mode 100644 index 000000000..60829bb79 --- /dev/null +++ b/tests/test27/Main.java @@ -0,0 +1,32 @@ +public class Main { + public static void main(String[] args) { + // A recursive and multiple params test + } + + static void foo(Node node1, Node node2) { + Node A = new Node(); + Node B = new Node(); + Node C = new Node(); + Node D = new Node(); + Node E = new Node(); + Node F = new Node(); + Node G = new Node(); + + Main obj = new Main(); + obj.bar(A, B, C, D, E, F, G); + } + + void bar(Node n1, Node n2, Node n3, Node n4, Node n5, Node n6, Node n7) { + if (n7 == null) { + return; + } + + n1.n = n3; + n4.n = n5; + n5.n = n6; + n6.n = n2; + n2.n = n3; + + bar(n2, n3, n4, n5, n6, n7, null); + } +} diff --git a/tests/test27/Node.java b/tests/test27/Node.java new file mode 100644 index 000000000..391eba7af --- /dev/null +++ b/tests/test27/Node.java @@ -0,0 +1,4 @@ +public class Node { + public Node n; + public Node m; +} From 1f16acad8b43dc0d7d9ca71432a3aee6c8ccec19 Mon Sep 17 00:00:00 2001 From: Signior-X Date: Thu, 3 Nov 2022 10:27:32 +0530 Subject: [PATCH 6/7] Left in between --- src/analyser/MethodsLinkingAnalyser.java | 211 +++++++++++++++++++++++ src/main/Main.java | 20 ++- src/stackOrdering/StackOrderer.java | 5 + tests/test24/Main.java | 17 +- tests/test25/Main.java | 2 +- 5 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 src/analyser/MethodsLinkingAnalyser.java create mode 100644 src/stackOrdering/StackOrderer.java diff --git a/src/analyser/MethodsLinkingAnalyser.java b/src/analyser/MethodsLinkingAnalyser.java new file mode 100644 index 000000000..4f424e273 --- /dev/null +++ b/src/analyser/MethodsLinkingAnalyser.java @@ -0,0 +1,211 @@ +package analyser; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import soot.*; +import main.CHATransform; +import ptg.ObjectNode; +import ptg.ObjectType; +import ptg.PointsToGraph; +import soot.jimple.Constant; +import soot.jimple.InstanceInvokeExpr; +import soot.jimple.InvokeExpr; +import soot.jimple.internal.JInvokeStmt; +import soot.jimple.internal.JStaticInvokeExpr; +import soot.jimple.toolkits.callgraph.CallGraph; +import soot.jimple.toolkits.callgraph.Edge; + +public class MethodsLinkingAnalyser extends SceneTransformer { + public static ConcurrentHashMap > nativeLocals = new ConcurrentHashMap<>(); + + public static ArrayList whitelistedNatives = new ArrayList<> ( + Arrays.asList("") + ); + + public static ArrayList blacklistedNatives = new ArrayList<> ( + Arrays.asList("", + "", + "") + ); + + + private Set methodsProcessed; + private Set methodsProcessing; + + public MethodsLinkingAnalyser() { + methodsProcessed = new HashSet(); + methodsProcessing = new HashSet(); + } + + @Override + protected void internalTransform(String arg0, Map arg1) { + // Get the call graph, and start processing the methods + CallGraph cg = Scene.v().getCallGraph(); + Iterator callerEdges = cg.sourceMethods(); + + while (callerEdges.hasNext()) { + SootMethod methodCaller = (SootMethod) callerEdges.next(); + // System.out.println("PRIYAM method caller: " + methodCaller); + processMethod(methodCaller); + } + } + + private void processMethod(SootMethod methodCaller) { + if (methodCaller.isJavaLibraryMethod()) { + return; + } + + if (methodsProcessed.contains(methodCaller)) { + // Method already computed + // we have the results ready + return; + } + + if (methodsProcessing.contains(methodCaller)) { + // Recursive loop + // ASK - See what to do + return; + } + + methodsProcessing.add(methodCaller); + + System.out.println("PRIYAM Method Name: "+ methodCaller.getBytecodeSignature() + ":" + methodCaller.getName()); + Body body = methodCaller.getActiveBody(); + PatchingChain units = body.getUnits(); + + for (Unit u : units) { + // System.out.println("PRIYAM unit: " + u); + if (u instanceof JInvokeStmt) { + JInvokeStmt stmt = (JInvokeStmt) u; + InvokeExpr expr = stmt.getInvokeExpr(); + handleExpr(methodCaller, u, expr); + } + } + + methodsProcessing.remove(methodCaller); + methodsProcessed.add(methodCaller); + } + + public void handleExpr( + SootMethod methodCaller, Unit u, InvokeExpr expr) { + PointsToGraph ptg = StaticAnalyser.ptgs.get(methodCaller); + + if (ptg == null) { + // If no points to graph, no need to process further + return; + } + + CallGraph cg = Scene.v().getCallGraph(); + + Iterator iedges = cg.edgesOutOf(u); + List args = expr.getArgs(); + + List edges = new ArrayList<>(); + if (!iedges.hasNext()) { + iedges = CHATransform.getCHA().edgesOutOf(u); + } + + while (iedges.hasNext()) { + edges.add(iedges.next()); + } + + if (edges.size() == 0) { + // System.out.println("Empty edges: " + expr + ", function incoming edges: " + cg.edgesInto(methodCaller).hasNext() + + // " Method: " + methodCaller.getBytecodeSignature()); + edges.add(new Edge(methodCaller, u, expr.getMethod(), Kind.SPECIAL)); + } + + if (expr instanceof InstanceInvokeExpr) { + // ASK - No need to handle instance invoke expr? + } else if (expr instanceof JStaticInvokeExpr) { + } else { + System.err.println("Unidentified invoke expr: " + expr.toString()); + throw new IllegalArgumentException(expr.toString()); + } + + for (Edge edge : edges) { + /* 1. + * We traverse and find the caller callie relationship + * between ObjectNodes + */ + SootMethod method = edge.tgt(); + int paramCount = method.getParameterCount(); + + // Recursion to first process the method + // if not already processed + if (!methodsProcessed.contains(method)) { + processMethod(method); + } + + Map> paramMapping = new HashMap>(); + for (int i = 0; i < paramCount; i++) { + ObjectNode obj = new ObjectNode(i, ObjectType.parameter); + // ConditionalValue cv = new ConditionalValue(method, obj, true); + + if (edge.kind() == Kind.REFL_INVOKE) + paramMapping.put(obj, ptg.vars.get((Local) args.get(1))); + else if (edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) + paramMapping.put(obj, ptg.vars.get((Local) args.get(0))); + else { + Value arg = args.get(i); + if (arg.getType() instanceof RefType || arg.getType() instanceof ArrayType) + if (!(arg instanceof Constant)) { // Notice the not(!) + // ptg.addParametricEdge((Local) args.get(i), cv); + System.out.println("args get i: " + args.get(i)); + paramMapping.put(obj, ptg.vars.get((Local) args.get(i))); + } + } + } + + // System.out.println("PRIYAM PARAMS MAPPING: " + paramMapping); + + /* 2. + * Now, loop in the callie method's ptg to find if there + * exists any relationship/node between the params + * If exists, add the realtion for corresponding values in + * paramsMapping also + */ + PointsToGraph calliePTG = StaticAnalyser.ptgs.get(method); + System.out.println("PRIYAM METHOD: " + method); + System.out.println("PRIYAM PTGS: " + StaticAnalyser.ptgs); + System.out.println("PRIYAM calliePTG: " + calliePTG); + // If ptg gives error, ensure StaticAnalysis has been done + + for (int i = 0; i < paramCount; i++) { + ObjectNode obj = new ObjectNode(i, ObjectType.parameter); + Map> pointingTo = calliePTG.fields.get(obj); + + if (pointingTo == null) { + continue; + } + + for (Map.Entry> entry : pointingTo.entrySet()) { + for (ObjectNode fieldObj : entry.getValue()) { + System.out.println("There exists an edge from: " + obj + " to " + fieldObj + " by " + entry.getKey()); + if (fieldObj.type != ObjectType.parameter) { + continue; + } + + if (!paramMapping.containsKey(obj) || !paramMapping.containsKey(fieldObj)) { + // If paramsMapping does not have the object, it can happen if null is passed + continue; + } + + // Find paramsMapping for obj + // Find paramsMapping for fieldObj + // Add an edge from objs to fieldObjs + for (ObjectNode objInCaller : paramMapping.get(obj)) { + for (ObjectNode fieldObjInCaller : paramMapping.get(fieldObj)) { + System.out.println("There should exists an edge from: " + objInCaller + " to " + fieldObjInCaller + " by " + entry.getKey()); + ptg.WEAK_makeField(objInCaller, entry.getKey(), fieldObjInCaller); + } + } + } + } + } + + System.out.println("AFTER PRIYAM PTGS: " + StaticAnalyser.ptgs + "\n"); + } + } +} diff --git a/src/main/Main.java b/src/main/Main.java index e1b656d28..1032a6e0a 100644 --- a/src/main/Main.java +++ b/src/main/Main.java @@ -1,5 +1,6 @@ package main; +import analyser.MethodsLinkingAnalyser; import analyser.StackOrderAnalyser; import analyser.StaticAnalyser; import config.StoreEscape; @@ -60,7 +61,6 @@ public static void main(String[] args) { } StaticAnalyser staticAnalyser = new StaticAnalyser(); - StackOrderAnalyser stackOrderAnalyser = new StackOrderAnalyser(); CHATransform prepass = new CHATransform(); PackManager.v().getPack("wjap").add(new Transform("wjap.pre", prepass)); PackManager.v().getPack("jtp").add(new Transform("jtp.sample", staticAnalyser)); @@ -98,12 +98,20 @@ public static void main(String[] args) { System.out.println("Time Taken:"+(analysis_end-analysis_start)/1000F); System.out.println("BEFORE InterProcedural Linking"); - printAllInfo(StaticAnalyser.ptgs, StaticAnalyser.summaries, StaticAnalyser.stackOrders, args[4]); + // printAllInfo(StaticAnalyser.ptgs, StaticAnalyser.summaries, StaticAnalyser.stackOrders, args[4]); + + // // Problem - not processing methods + + // // First, we add edges created due to callie function during method call + // analysis_start = System.currentTimeMillis(); + // // How to use spark here? + // // MethodsLinkingAnalyser methodsLinkingAnalyser = new MethodsLinkingAnalyser(); + // // PackManager.v().getPack("wjtp").add(new Transform("wjtp.ada", methodsLinkingAnalyser)); + // StackOrderAnalyser stackOrderAnalyser = new StackOrderAnalyser(); + // PackManager.v().getPack("jtp").add(new Transform("jtp.order", stackOrderAnalyser)); + // Scene.v().setEntryPoints(entryPoints); + // PackManager.v().runPacks(); - // First, we add edges created due to callie function during method call - analysis_start = System.currentTimeMillis(); - PackManager.v().getPack("jtp").add(new Transform("jtp.stackOrder", stackOrderAnalyser)); - PackManager.v().runPacks(); // Now we are going to find the stack ordering of the non escaping functions CreateStackOrdering(); diff --git a/src/stackOrdering/StackOrderer.java b/src/stackOrdering/StackOrderer.java new file mode 100644 index 000000000..15e40829a --- /dev/null +++ b/src/stackOrdering/StackOrderer.java @@ -0,0 +1,5 @@ +package stackOrdering; + +public class StackOrderer { + +} diff --git a/tests/test24/Main.java b/tests/test24/Main.java index c60622ac7..bd8185af7 100644 --- a/tests/test24/Main.java +++ b/tests/test24/Main.java @@ -8,8 +8,21 @@ static void foo(Node node1, Node node2) { Node C = new Node(); Node D = new Node(); Node E = new Node(); - bar(A, B); - bar(A, C); + // bar(A, B); + A.n = B; + + // if I make channges in staticAnalyser? + + Node x = A.n; + + // r10=[, ] + // Assumption 1 + // we do replacement of assignment + // statements after the whole pass + // How to consider for if else branch? + // For different branches? + + bar(x, C); bar(D, E); bar(node1, node2); } diff --git a/tests/test25/Main.java b/tests/test25/Main.java index ad5635f25..e9b503f51 100644 --- a/tests/test25/Main.java +++ b/tests/test25/Main.java @@ -19,7 +19,7 @@ static void bar(Node n1, Node n2) { n1.n = F; // we need to heapify F (address check) F.n = n2; // no heapfication - + // Assumption 2 // Theory -- If two objects are directly connected // Then only we need stack order, else, we will not be needing any stack order } From e173770aa38bfcf018a52c58402144718b30972c Mon Sep 17 00:00:00 2001 From: Signior-X Date: Thu, 3 Nov 2022 11:06:32 +0530 Subject: [PATCH 7/7] Linking in static analyser itself --- src/analyser/MethodsLinkingAnalyser.java | 2 +- src/analyser/StaticAnalyser.java | 42 +++++++++++++-- src/handlers/JInvokeStmtHandler.java | 68 +++++++++++++++++++++++- 3 files changed, 104 insertions(+), 8 deletions(-) diff --git a/src/analyser/MethodsLinkingAnalyser.java b/src/analyser/MethodsLinkingAnalyser.java index 4f424e273..d38f938d1 100644 --- a/src/analyser/MethodsLinkingAnalyser.java +++ b/src/analyser/MethodsLinkingAnalyser.java @@ -152,7 +152,7 @@ else if (edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) if (arg.getType() instanceof RefType || arg.getType() instanceof ArrayType) if (!(arg instanceof Constant)) { // Notice the not(!) // ptg.addParametricEdge((Local) args.get(i), cv); - System.out.println("args get i: " + args.get(i)); + // System.out.println("args get i: " + args.get(i)); paramMapping.put(obj, ptg.vars.get((Local) args.get(i))); } } diff --git a/src/analyser/StaticAnalyser.java b/src/analyser/StaticAnalyser.java index 541671788..ef75a911b 100644 --- a/src/analyser/StaticAnalyser.java +++ b/src/analyser/StaticAnalyser.java @@ -19,17 +19,22 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; +import java.util.Collections; import java.util.regex.*; public class StaticAnalyser extends BodyTransformer { - private boolean allNonEscaping; + private static boolean allNonEscaping; public static Map ptgs; public static Map> summaries; public static Map> stackOrders; public static LinkedHashMap analysis; public static List noBCIMethods; + + public static Set methodsProcessed; + public static Set methodsProcessing; + String[] ignoreFuncs = { // "", // "", @@ -78,6 +83,9 @@ public StaticAnalyser() { stackOrders = new ConcurrentHashMap<>(); noBCIMethods = new ArrayList<>(); allNonEscaping = false; + + methodsProcessed = Collections.synchronizedSet(new HashSet()); + methodsProcessing = Collections.synchronizedSet(new HashSet()); } private int getSummarySize(HashMap summary) @@ -87,6 +95,10 @@ private int getSummarySize(HashMap summary) @Override protected void internalTransform(Body body, String phasename, Map options) { + processMethod(body); + } + + public static void processMethod(Body body) { // if (body.getMethod().getBytecodeSignature().toString() // .compareTo("") != 0) // { @@ -95,10 +107,25 @@ protected void internalTransform(Body body, String phasename, Map")){ // System.out.println("Skipping this method"); @@ -302,10 +329,15 @@ protected void internalTransform(Body body, String phasename, Map nativeList, Map summary, PointsToGraph ptg) { + private static void markAsEscaping(List nativeList, Map summary, PointsToGraph ptg) { if (nativeList == null) return; for (Local obj: nativeList) { @@ -316,14 +348,14 @@ private void markAsEscaping(List nativeList, Map summary) { + private static void markAsNonEscaping(Map summary) { for (ObjectNode obj: summary.keySet()) { EscapeStatus es = new EscapeStatus(NoEscape.getInstance()); summary.put(obj, es); } } - private void setParamsAsEscaping(SootMethod m, Map summary) { + private static void setParamsAsEscaping(SootMethod m, Map summary) { summary.clear(); for (int i=0; i< m.getParameterCount(); i++) { summary.put(new ObjectNode(i, ObjectType.parameter), new EscapeStatus(Escape.getInstance())); @@ -336,7 +368,7 @@ private void setParamsAsEscaping(SootMethod m, Map sum * changes on. */ - public void apply(SootMethod m, Unit u, PointsToGraph ptg, Map summary) { + public static void apply(SootMethod m, Unit u, PointsToGraph ptg, Map summary) { // System.err.println(u+" "+u.getClass().getName()); // System.out.println("PRIYAM soot unit " + u); diff --git a/src/handlers/JInvokeStmtHandler.java b/src/handlers/JInvokeStmtHandler.java index 0a5afce2b..a030cdd90 100644 --- a/src/handlers/JInvokeStmtHandler.java +++ b/src/handlers/JInvokeStmtHandler.java @@ -19,6 +19,9 @@ import java.util.Map; import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; + +import analyser.StaticAnalyser; + import java.util.*; public class JInvokeStmtHandler { @@ -175,6 +178,14 @@ else if (expr instanceof JStaticInvokeExpr) { // Edge edge = edges.next(); SootMethod method = edge.tgt(); SootMethod srcMethod = edge.src(); + + // Recursion to first process the method + // if not already processed + if (!StaticAnalyser.methodsProcessed.contains(method)) { + // PRIYAM - Is correct? + StaticAnalyser.processMethod(method.getActiveBody()); + } + // System.out.println("Method: "+method + "isNative: "+method.isNative()); boolean isNative = method.isNative(); boolean iswhiteListed = !blacklistedNatives.contains(method.getBytecodeSignature()); @@ -183,14 +194,19 @@ else if (expr instanceof JStaticInvokeExpr) { } int paramCount = method.getParameterCount(); + Map> paramMapping = new HashMap>(); for (int i = 0; i < paramCount; i++) { ObjectNode obj = new ObjectNode(i, ObjectType.parameter); ConditionalValue cv = new ConditionalValue(method, obj, true); - if (edge.kind() == Kind.REFL_INVOKE) + if (edge.kind() == Kind.REFL_INVOKE) { ptg.cascadeCV((Local) args.get(1), cv, summary); - else if(edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) + paramMapping.put(obj, ptg.vars.get((Local) args.get(1))); + } + else if(edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) { ptg.cascadeCV((Local) args.get(0), cv, summary); + paramMapping.put(obj, ptg.vars.get((Local) args.get(0))); + } else { Value arg = args.get(i); if (arg.getType() instanceof RefType || arg.getType() instanceof ArrayType) @@ -203,9 +219,57 @@ else if(edge.kind() == Kind.REFL_CONSTR_NEWINSTANCE) } else ptg.cascadeCV((Local) args.get(i), cv, summary); + + paramMapping.put(obj, ptg.vars.get((Local) args.get(i))); } } } + + /* 2. + * Now, loop in the callie method's ptg to find if there + * exists any relationship/node between the params + * If exists, add the realtion for corresponding values in + * paramsMapping also + */ + PointsToGraph calliePTG = StaticAnalyser.ptgs.get(method); + System.out.println("PRIYAM METHOD: " + method); + System.out.println("PRIYAM PTGS: " + StaticAnalyser.ptgs); + System.out.println("PRIYAM calliePTG: " + calliePTG); + // If ptg gives error, ensure StaticAnalysis has been done + + for (int i = 0; i < paramCount; i++) { + ObjectNode obj = new ObjectNode(i, ObjectType.parameter); + Map> pointingTo = calliePTG.fields.get(obj); + + if (pointingTo == null) { + continue; + } + + for (Map.Entry> entry : pointingTo.entrySet()) { + for (ObjectNode fieldObj : entry.getValue()) { + System.out.println("There exists an edge from: " + obj + " to " + fieldObj + " by " + entry.getKey()); + if (fieldObj.type != ObjectType.parameter) { + continue; + } + + if (!paramMapping.containsKey(obj) || !paramMapping.containsKey(fieldObj)) { + // If paramsMapping does not have the object, it can happen if null is passed + continue; + } + + // Find paramsMapping for obj + // Find paramsMapping for fieldObj + // Add an edge from objs to fieldObjs + for (ObjectNode objInCaller : paramMapping.get(obj)) { + for (ObjectNode fieldObjInCaller : paramMapping.get(fieldObj)) { + System.out.println("There should exists an edge from: " + objInCaller + " to " + fieldObjInCaller + " by " + entry.getKey()); + ptg.WEAK_makeField(objInCaller, entry.getKey(), fieldObjInCaller); + } + } + } + } + } + } } } \ No newline at end of file