diff --git a/src/main/java/br/unb/cic/analysis/Main.java b/src/main/java/br/unb/cic/analysis/Main.java index 47e7556f..a6aa40d2 100644 --- a/src/main/java/br/unb/cic/analysis/Main.java +++ b/src/main/java/br/unb/cic/analysis/Main.java @@ -28,24 +28,23 @@ public class Main { + private static CommandLine cmd; private Options options; private AbstractMergeConflictDefinition definition; private Set targetClasses; private List conflicts = new ArrayList<>(); private ReachDefinitionAnalysis analysis; - - public static void main(String args[]) { Main m = new Main(); try { m.createOptions(); CommandLineParser parser = new DefaultParser(); - CommandLine cmd = parser.parse(m.options, args); - - String mode = "dataflow"; - + cmd = parser.parse(m.options, args); + + String mode = "dataflow"; + if (cmd.hasOption("mode")) { mode = cmd.getOptionValue("mode"); } @@ -58,16 +57,14 @@ public static void main(String args[]) { m.loadDefinition(cmd.getOptionValue("csv")); } m.runAnalysis(mode, m.parseClassPath(cmd.getOptionValue("cp"))); - + m.exportResults(); - - } - catch(ParseException e) { + + } catch (ParseException e) { System.out.println("Error: " + e.getMessage()); HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp( "java Main", m.options ); - } - catch(Exception e) { + formatter.printHelp("java Main", m.options); + } catch (Exception e) { e.printStackTrace(); } } @@ -75,9 +72,9 @@ public static void main(String args[]) { private String parseClassPath(String cp) { File f = new File(cp); String res = cp; - if(f.exists() && f.isDirectory()) { - for(File file : f.listFiles()) { - if(file.getName().endsWith(".jar")) { + if (f.exists() && f.isDirectory()) { + for (File file : f.listFiles()) { + if (file.getName().endsWith(".jar")) { res += ":"; res += file.getAbsolutePath(); } @@ -87,31 +84,30 @@ private String parseClassPath(String cp) { } private void exportResults() throws Exception { - System.out.println(" Analysis results"); + System.out.println(" Analysis results"); System.out.println("----------------------------"); - - if(conflicts.size() == 0) { - System.out.println(" No conflicts detected"); - System.out.println("----------------------------"); - return; + + if (conflicts.size() == 0) { + System.out.println(" No conflicts detected"); + System.out.println("----------------------------"); + return; } - + System.out.println(" Number of conflicts: " + conflicts.size()); - final String out = "out.txt"; + final String out = "out.txt"; final FileWriter fw = new FileWriter(out); conflicts.forEach(c -> { - try { + try { fw.write(c + "\n\n"); + } catch (Exception e) { + System.out.println("error exporting the results " + e.getMessage()); } - catch(Exception e) { - System.out.println("error exporting the results " + e.getMessage()); - } - }); + }); fw.close(); System.out.println(" Results exported to " + out); System.out.println("----------------------------"); } - + private void createOptions() { options = new Options(); Option classPathOption = Option.builder("cp").argName("class-path") @@ -136,23 +132,29 @@ private void createOptions() { .hasArg().desc("the commit merge to analysis") .build(); - Option verbose = Option.builder("verbose").argName("verbose").desc("run in the verbose mode").build(); - Option recursive = Option.builder("recursive").argName("recursive") + Option verboseOption = Option.builder("verbose").argName("verbose").hasArg().desc("run in the verbose mode").build(); + + Option recursiveOption = Option.builder("recursive").argName("recursive").hasArg() .desc("run using the recursive strategy for mapping sources and sinks") .build(); + Option oaDepthLimitOption = Option.builder("oaDepthLimit").argName("oaDepthLimit").hasArg() + .desc("sets the depth limit on accessing methods when performing Overriding Assignment " + + "Interprocedural analysis") + .build(); + options.addOption(classPathOption); options.addOption(inputFileOption); options.addOption(analysisOption); options.addOption(repoOption); options.addOption(commitOption); - options.addOption(verbose); - options.addOption(recursive); + options.addOption(verboseOption); + options.addOption(recursiveOption); + options.addOption(oaDepthLimitOption); } - private void runAnalysis(String mode, String classpath) { - switch(mode) { + switch (mode) { case "svfa-interprocedural": runSparseValueFlowAnalysis(classpath, true); break; @@ -178,7 +180,7 @@ private void runAnalysis(String mode, String classpath) { runDataFlowAnalysis(classpath, mode); } } - + private void runPessimisticDataFlowAnalysis(String classpath) { PackManager.v().getPack("jtp").add( new Transform("jtp.analysis", new BodyTransformer() { @@ -202,17 +204,21 @@ protected void internalTransform(Body body, String s, Map map) { .execute(); } - private void runDataFlowAnalysis(String classpath, String mode) { PackManager.v().getPack("jtp").add( new Transform("jtp.analysis", new BodyTransformer() { @Override protected void internalTransform(Body body, String phaseName, Map options) { - switch(mode) { - case "dataflow" : analysis = new ReachDefinitionAnalysis(body, definition); break; - case "tainted" : analysis = new TaintedAnalysis(body, definition); - case "confluence" : analysis = new ConfluentAnalysis(body, definition); break; + switch (mode) { + case "dataflow": + analysis = new ReachDefinitionAnalysis(body, definition); + break; + case "tainted": + analysis = new TaintedAnalysis(body, definition); + case "confluence": + analysis = new ConfluentAnalysis(body, definition); + break; case "confluence-tainted": analysis = new ConfluentTaintedAnalysis(body, definition); break; @@ -237,8 +243,10 @@ protected void internalTransform(Body body, String phaseName, Map classes = Collections.singletonList(classpath); SootWrapper.configureSootOptionsToRunInterproceduralOverrideAssignmentAnalysis(classes); @@ -289,8 +297,8 @@ private void runSparseValueFlowAnalysis(String classpath, boolean interprocedura private void runSparseValueFlowConfluenceAnalysis(String classpath, boolean interprocedural) { definition.setRecursiveMode(options.hasOption("recursive")); - SVFAConfluenceAnalysis analysis = new SVFAConfluenceAnalysis(classpath, this.definition, interprocedural); - + SVFAConfluenceAnalysis analysis = new SVFAConfluenceAnalysis(classpath, this.definition, interprocedural); + analysis.execute(); conflicts.addAll(analysis.getConfluentConflicts() .stream() @@ -304,11 +312,10 @@ private void loadDefinition(String filePath) throws Exception { Map> sourceDefs = new HashMap<>(); Map> sinkDefs = new HashMap<>(); targetClasses = new HashSet<>(); - for(ClassChangeDefinition change : changes) { - if(change.getType().equals(Statement.Type.SOURCE)) { + for (ClassChangeDefinition change : changes) { + if (change.getType().equals(Statement.Type.SOURCE)) { addChange(sourceDefs, change); - } - else { + } else { addChange(sinkDefs, change); } targetClasses.add(change.getClassName()); @@ -327,10 +334,9 @@ protected Map> sinkDefinitions() { } private void addChange(Map> map, ClassChangeDefinition change) { - if(map.containsKey(change.getClassName())) { + if (map.containsKey(change.getClassName())) { map.get(change.getClassName()).add(change.getLineNumber()); - } - else { + } else { List lines = new ArrayList<>(); lines.add(change.getLineNumber()); map.put(change.getClassName(), lines); @@ -366,17 +372,13 @@ protected Map> sinkDefinitions() { } private void addChangeFromDiffAnalysis(Map> map, Entry change) { - if(map.containsKey(change.getKey())) { + if (map.containsKey(change.getKey())) { map.get(change.getKey()).add(change.getValue()); - } - else { + } else { List lines = new ArrayList<>(); lines.add(change.getValue()); map.put(change.getKey(), lines); } } - - - } diff --git a/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java b/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java index 87120cc9..1dae3471 100644 --- a/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java +++ b/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java @@ -26,6 +26,7 @@ // TODO Do not add anything when assignments are equal. public class InterproceduralOverrideAssignment extends SceneTransformer implements AbstractAnalysis { + private int depthLimit; private Set conflicts; private PointsToAnalysis pointsToAnalysis; private List traversedMethods; @@ -34,11 +35,23 @@ public class InterproceduralOverrideAssignment extends SceneTransformer implemen private FlowSet right; private List stacktraceList; - private final Logger logger; + private Logger logger; public InterproceduralOverrideAssignment(AbstractMergeConflictDefinition definition) { this.definition = definition; + this.depthLimit = 10; + initDefaultFields(); + } + + public InterproceduralOverrideAssignment(AbstractMergeConflictDefinition definition, int depthLimit) { + this.definition = definition; + this.depthLimit = depthLimit; + + initDefaultFields(); + } + + private void initDefaultFields() { this.conflicts = new HashSet<>(); this.left = new ArraySparseSet<>(); this.right = new ArraySparseSet<>(); @@ -136,7 +149,7 @@ private Set filterConflicts(Set conflictsResults) { private FlowSet traverse(FlowSet in, SootMethod sootMethod, Statement.Type flowChangeTag) { - if (this.traversedMethods.contains(sootMethod) || this.traversedMethods.size() > 2 || sootMethod.isPhantom()) { + if (this.traversedMethods.contains(sootMethod) || this.traversedMethods.size() > depthLimit || sootMethod.isPhantom()) { return in; }