Initial commit.
This commit is contained in:
parent
228120c6c9
commit
73d1bd37e6
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow;
|
||||
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends AbstractUIPlugin {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "com.sap.research.analysis.wala.sourcecode"; //$NON-NLS-1$
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared instance
|
||||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.actions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.ui.IWorkbenchWindow;
|
||||
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.AnalysisUtil;
|
||||
import eu.aniketos.dasca.dataflow.util.PlugInUtil;
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
import com.ibm.wala.cast.java.client.JDTJavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.dataflow.IFDS.ICFGSupergraph;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
|
||||
/**
|
||||
* Our sample action implements workbench action delegate.
|
||||
* The action proxy will be created by the workbench and
|
||||
* shown in the UI. When the user tries to use the action,
|
||||
* this delegate will be created and execution will be
|
||||
* delegated to it.
|
||||
* @see IWorkbenchWindowActionDelegate
|
||||
*/
|
||||
public class AnalyzeSourceCode implements IWorkbenchWindowActionDelegate {
|
||||
Logger log = AnalysisUtil.getLogger(AnalyzeSourceCode.class);
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public AnalyzeSourceCode() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The action has been activated. The argument of the
|
||||
* method represents the 'real' action sitting
|
||||
* in the workbench UI.
|
||||
* @see IWorkbenchWindowActionDelegate#run
|
||||
*/
|
||||
public void run(IAction action) {
|
||||
|
||||
List<IJavaProject> javaProjects = new ArrayList<IJavaProject>();
|
||||
|
||||
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
|
||||
for(IProject project: projects) {
|
||||
try {
|
||||
project.open(null /* IProgressMonitor */);
|
||||
} catch (CoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
IJavaProject javaProject = JavaCore.create(project);
|
||||
javaProjects.add(javaProject);
|
||||
}
|
||||
|
||||
IJavaProject javaProject = null;
|
||||
String testProject = AnalysisUtil.getPropertyString(AnalysisUtil.CONFIG_ENTRY_CLASS);
|
||||
|
||||
for (IJavaProject iJavaProject : javaProjects) {
|
||||
boolean bool = iJavaProject.exists();
|
||||
if(bool && iJavaProject.getElementName().startsWith(testProject)) {
|
||||
javaProject = iJavaProject;
|
||||
}
|
||||
}
|
||||
|
||||
if(javaProject == null) {
|
||||
javaProject = PlugInUtil.getSelectedIJavaProject();
|
||||
}
|
||||
|
||||
if (javaProject != null) {
|
||||
|
||||
try {
|
||||
JDTJavaSourceAnalysisEngine engine = PlugInUtil.createEngine(javaProject);
|
||||
|
||||
CallGraph cg = engine.buildDefaultCallGraph();
|
||||
|
||||
log.debug("callgraph generated (size:" + cg.getNumberOfNodes() + ")");
|
||||
|
||||
AnalysisCache ac = new AnalysisCache();
|
||||
ICFGSupergraph sg = ICFGSupergraph.make(cg, ac);
|
||||
log.debug("supergraph generated (size:" + sg.getNumberOfNodes() + ")");
|
||||
|
||||
String entryClass = AnalysisUtil.getPropertyString(AnalysisUtil.CONFIG_ENTRY_CLASS);
|
||||
String entryMethods = AnalysisUtil.getPropertyString(AnalysisUtil.CONFIG_ENTRY_METHOD);
|
||||
|
||||
String[] methods = entryMethods.split(",");
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
String entryMethod = methods[i].trim();
|
||||
SuperGraphUtil.analyzeAndSaveSuperGraph(sg, entryClass, entryMethod);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CoreException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CancelException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
log.error("Warning: You did not select a project or something failed while getting the project");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selection in the workbench has been changed. We
|
||||
* can change the state of the 'real' action here
|
||||
* if we want, but this can only happen after
|
||||
* the delegate has been created.
|
||||
* @see IWorkbenchWindowActionDelegate#selectionChanged
|
||||
*/
|
||||
public void selectionChanged(IAction action, ISelection selection) {
|
||||
}
|
||||
|
||||
/**
|
||||
* We can use this method to dispose of any system
|
||||
* resources we previously allocated.
|
||||
* @see IWorkbenchWindowActionDelegate#dispose
|
||||
*/
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
/**
|
||||
* We will cache window object in order to
|
||||
* be able to provide parent shell for the message dialog.
|
||||
* @see IWorkbenchWindowActionDelegate#init
|
||||
*/
|
||||
public void init(IWorkbenchWindow window) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.chainsaw.Main;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.AnalysisUtil;
|
||||
import eu.aniketos.dasca.dataflow.util.PlugInUtil;
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
import com.ibm.wala.cast.java.client.JDTJavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.dataflow.IFDS.ICFGSupergraph;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
/* Test01.class, Test02.class, Test03.class, Test04.class,
|
||||
Test05.class, */ Test06.class /*, Test07.class, Test08.class,
|
||||
Test09.class, Test10.class, Test11.class, Test12.class,
|
||||
Test13.class, Test14.class, Test15.class, Test16.class,
|
||||
Test17.class, Test18.class, Test19.class
|
||||
*/
|
||||
})
|
||||
|
||||
public class AllTests {
|
||||
private static final Logger log = AnalysisUtil.getLogger(SuperGraphUtil.class);
|
||||
protected static ICFGSupergraph superGraph = null;
|
||||
protected static ICFGSupergraph superGraph2 = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
//
|
||||
// IJavaProject javaProject = null;
|
||||
// IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
|
||||
// for (IProject project : projects) {
|
||||
// try {
|
||||
// project.open(null /* IProgressMonitor */);
|
||||
// } catch (CoreException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// IJavaProject javaProjectintern = JavaCore.create(project);
|
||||
// if(javaProjectintern.getElementName().equals("TestCases")){
|
||||
// log.warn("Found project with name 'TestCases' ("+javaProjectintern+")");
|
||||
// javaProject = javaProjectintern;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
try {
|
||||
/* log.warn("javaProject = "+javaProject);
|
||||
JDTJavaSourceAnalysisEngine engine = PlugInUtil.createEngine(javaProject);
|
||||
log.warn("Engine = "+engine);
|
||||
CallGraph cg = engine.buildDefaultCallGraph();
|
||||
log.warn("CallGraph = "+cg);
|
||||
*/ String [] classes= {
|
||||
/* "Ltests/Test01"
|
||||
,"Ltests/Test02"
|
||||
,"Ltests/Test03"
|
||||
,"Ltests/Test04"
|
||||
,"Ltests/Test05"
|
||||
,*/
|
||||
"Ltests/Test06"
|
||||
/* ,"Ltests/Test07"
|
||||
,"Ltests/Test08"
|
||||
,"Ltests/Test09"
|
||||
,"Ltests/Test10"
|
||||
,"Ltests/Test11"
|
||||
,"Ltests/Test12"
|
||||
,"Ltests/Test13"
|
||||
,"Ltests/Test14"
|
||||
,"Ltests/Test15"
|
||||
,"Ltests/Test16"
|
||||
,"Ltests/Test17"
|
||||
,"Ltests/Test18"
|
||||
,"Ltests/Test19"
|
||||
*/
|
||||
};
|
||||
CallGraph cg = com.sap.research.wala.cross.javajs.SingleLanguageBuilders.makeJavaCG("test.jar", classes).fst;
|
||||
AnalysisCache ac = new AnalysisCache();
|
||||
log.warn("AnalsyisCache = "+ac);
|
||||
// CallGraph cg = Main.makeJavaCG();
|
||||
superGraph = ICFGSupergraph.make(cg, ac);
|
||||
superGraph2 = superGraph;
|
||||
log.warn("SuperGraph = "+superGraph);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (CancelException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassHierarchyException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test01 {
|
||||
|
||||
String entryClass = "Test01";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test02 {
|
||||
|
||||
String entryClass = "Test02";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test03 {
|
||||
|
||||
String entryClass = "Test03";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test04 {
|
||||
|
||||
String entryClass = "Test04";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test05 {
|
||||
|
||||
String entryClass = "Test05";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test06 {
|
||||
|
||||
String entryClass = "Test06";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test07 {
|
||||
|
||||
String entryClass = "Test07";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test08 {
|
||||
|
||||
String entryClass = "Test08";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood03() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good03");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test09 {
|
||||
|
||||
String entryClass = "Test09";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood03() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good03");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test10 {
|
||||
|
||||
String entryClass = "Test10";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood03() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good03");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test11 {
|
||||
|
||||
String entryClass = "Test11";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood03() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good03");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood04() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good04");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood05() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good05");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test12 {
|
||||
|
||||
String entryClass = "Test12";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test13 {
|
||||
|
||||
String entryClass = "Test13";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test14 {
|
||||
|
||||
String entryClass = "Test14";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test15 {
|
||||
|
||||
String entryClass = "Test15";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood01() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good01");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood02() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good02");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGood03() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "good03");
|
||||
assertEquals(0, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test16 {
|
||||
|
||||
String entryClass = "Test16";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test17 {
|
||||
|
||||
String entryClass = "Test17";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(2, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test18 {
|
||||
|
||||
String entryClass = "Test18";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(1, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.tests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.util.SuperGraphUtil;
|
||||
|
||||
public class Test19 {
|
||||
|
||||
String entryClass = "Test19";
|
||||
|
||||
@Test
|
||||
public void testBad() {
|
||||
AllTests.init();
|
||||
int result = SuperGraphUtil.analyzeAndSaveSuperGraph(AllTests.superGraph, entryClass, "bad");
|
||||
assertEquals(2, result);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.PropertyConfigurator;
|
||||
import org.eclipse.core.runtime.FileLocator;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
import eu.aniketos.dasca.dataflow.Activator;
|
||||
|
||||
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.ConcreteJavaMethod;
|
||||
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisCache;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder;
|
||||
import com.ibm.wala.ipa.cfg.BasicBlockInContext;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.SSABinaryOpInstruction;
|
||||
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.analysis.IExplodedBasicBlock;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||
|
||||
/**
|
||||
* static class for graph independent helper methods and constants
|
||||
*
|
||||
*/
|
||||
public class AnalysisUtil {
|
||||
|
||||
private static final Logger log = AnalysisUtil.getLogger(AnalysisUtil.class);
|
||||
|
||||
/**
|
||||
* Relative path to the main configuration file
|
||||
*/
|
||||
public static final String PLUGIN_MAIN_CONFIG = "config/main.config";
|
||||
|
||||
/**
|
||||
* Relative path to the logging configuration file
|
||||
*/
|
||||
public static final String LOGGING_FILE = "logging_properties_file";
|
||||
|
||||
/**
|
||||
* Boolean value of configuration file, if subgraphs should be included into the DOT file
|
||||
*/
|
||||
public static final String CONFIG_BOOLEAN_PRINT_SUBGRAPHS = "bool_print_subgraphs";
|
||||
|
||||
/**
|
||||
* DOT files will be generated into the specified sub directory of the working directory
|
||||
*/
|
||||
public static final String CONFIG_DOT_PATH = "dot_path";
|
||||
|
||||
/**
|
||||
* DOT files will be generated into the specified sub directory of the working directory
|
||||
*/
|
||||
public static final String CONFIG_DOT_REMOVE_EMPTY_NODES = "dot_remove_empty_nodes";
|
||||
|
||||
/**
|
||||
* Specifies which project contains the entry class
|
||||
*/
|
||||
public static final String CONFIG_ANALYSIS_PROJECT = "analysis_project";
|
||||
|
||||
/**
|
||||
* Specifies which class contains the entry method
|
||||
*/
|
||||
public static final String CONFIG_ENTRY_CLASS = "analysis_entry_class";
|
||||
|
||||
/**
|
||||
* Specifies the entry methods of the analysis
|
||||
*/
|
||||
public static final String CONFIG_ENTRY_METHOD = "analysis_entry_method";
|
||||
|
||||
/**
|
||||
* Specifies sanitizing methods of the analysis
|
||||
*/
|
||||
public static final String CONFIG_SANITIZER = "analysis_sanitizer";
|
||||
|
||||
/**
|
||||
* Specifies bad source methods of the analysis
|
||||
*/
|
||||
public static final String CONFIG_BAD_SRC = "analysis_bad_src";
|
||||
|
||||
/**
|
||||
* Specifies the depth (precision) of the analysis
|
||||
*/
|
||||
public static final String CONFIG_ANALYSIS_DEPTH = "analysis_depth";
|
||||
public static final int ANALYSIS_DEPTH_DETECTION = 0;
|
||||
public static final int ANALYSIS_DEPTH_EXCLUSIVE = 1;
|
||||
public static final int ANALYSIS_DEPTH_SANITIZING = 2;
|
||||
|
||||
/**
|
||||
* Specifies where to find the exclusion file
|
||||
*/
|
||||
public static final String CONFIG_EXCLUSION_FILE = "analysis_exclusion_file";
|
||||
|
||||
/**
|
||||
* Gets callgraph for given parameters (binary analysis only)
|
||||
* @param exclusionFilePath
|
||||
* @param classPath
|
||||
* @param entryClass
|
||||
* @param entryMethod
|
||||
* @return
|
||||
*/
|
||||
public static CallGraph getCallGraph(String exclusionFilePath, String classPath, String entryClass, String entryMethod) {
|
||||
AnalysisScope scope = null;
|
||||
ClassHierarchy cha = null;
|
||||
HashSet<Entrypoint> entryPoints = null;
|
||||
try {
|
||||
File exclusionFile = new File(exclusionFilePath);
|
||||
scope = AnalysisScopeReader.makeJavaBinaryAnalysisScope(classPath, exclusionFile); // works with class and jar files
|
||||
cha = ClassHierarchy.make(scope);
|
||||
|
||||
ClassLoaderReference clr = scope.getApplicationLoader();
|
||||
entryPoints = HashSetFactory.make();
|
||||
for(IClass class1 : cha) {
|
||||
if(class1.getClassLoader().getReference().equals(clr)) {
|
||||
Collection<IMethod> allMethods = class1.getDeclaredMethods();
|
||||
for(IMethod m : allMethods) {
|
||||
if(m.isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
TypeName tn = m.getDeclaringClass().getName();//MainApplication
|
||||
if(tn.toString().contains("/" + entryClass) && m.getName().toString().contains(entryMethod)) { // TODO: too weak
|
||||
entryPoints.add(new DefaultEntrypoint(m, cha));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Iterable<Entrypoint> result1 = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha); // uses the static main methods as entry methods
|
||||
if(entryPoints.size() == 0) {
|
||||
log.error("Could not find specified entry point for analysis.\n" +
|
||||
" path: " + classPath + "\n" +
|
||||
" class: " + entryClass + "\n" +
|
||||
" method: " + entryMethod);
|
||||
System.exit(1);
|
||||
}
|
||||
AnalysisOptions options = new AnalysisOptions(scope, entryPoints);
|
||||
|
||||
// CallGraphBuilder builder = com.ibm.wala.ipa.callgraph.impl.Util.makeRTABuilder(options, new AnalysisCache(), cha, scope); // Rapid Type Analysis
|
||||
SSAPropagationCallGraphBuilder builder = com.ibm.wala.ipa.callgraph.impl.Util.makeZeroCFABuilder(options, new AnalysisCache(), cha, scope); // 0-CFA = context-insensitive, class-based heap
|
||||
// CallGraphBuilder builder = com.ibm.wala.ipa.callgraph.impl.Util.makeZeroOneCFABuilder(options, new AnalysisCache(), cha, scope); // 0-1-CFA = context-insensitive, allocation-site-based heap
|
||||
// CallGraphBuilder builder = com.ibm.wala.ipa.callgraph.impl.Util.makeZeroOneContainerCFABuilder(options, new AnalysisCache(), cha, scope); // 0-1-Container-CFA = object-sensitive container
|
||||
|
||||
return builder.makeCallGraph(options);
|
||||
} catch (Exception e) {
|
||||
log.error("Error while building the call graph");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the corresponding integer value of the given property name, or 0 if no integer value was found
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static int getPropertyInteger(String name) {
|
||||
String value = getPropertyString(name);
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the corresponding boolean value of the given property name, or false if no value was found
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static boolean getPropertyBoolean(String name) {
|
||||
String value = getPropertyString(name);
|
||||
return value.equalsIgnoreCase("yes") | value.equalsIgnoreCase("true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the corresponding value of the given property name, or an empty String if no value was found
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static String getPropertyString(String name) {
|
||||
Properties properties = new Properties();
|
||||
BufferedInputStream stream;
|
||||
try {
|
||||
Bundle bundle = Platform.getBundle(Activator.PLUGIN_ID);
|
||||
Path path = new Path(PLUGIN_MAIN_CONFIG);
|
||||
InputStream in;
|
||||
if(bundle!=null) { // Util is called from eclipse PlugIn
|
||||
URL fileURL = FileLocator.find(bundle, path, null);
|
||||
in = fileURL.openStream();
|
||||
} else { // Util is called from java Application
|
||||
File f = new File("config/main.config");
|
||||
in = new FileInputStream(f);
|
||||
}
|
||||
stream = new BufferedInputStream(in);
|
||||
properties.load(stream);
|
||||
stream.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("no config file found");
|
||||
return "";
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
String value = properties.getProperty(name);
|
||||
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all chars from the string which confuse dotty <br />
|
||||
* Currently '<' and '>' <br />
|
||||
* Expand this if you run into trouble with other chars
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
public static String sanitize(String input) {
|
||||
String output = "";
|
||||
|
||||
for (char c : input.toCharArray()) {
|
||||
if (!(c == '<' || c == '>')) {
|
||||
output += c;
|
||||
} else {
|
||||
output += ' ';
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get root logger
|
||||
* @param class
|
||||
* @return
|
||||
*/
|
||||
public static org.apache.log4j.Logger getLogger(Class<?> class1) {
|
||||
Logger log = Logger.getLogger(class1);
|
||||
PropertyConfigurator.configure(getPropertyString(LOGGING_FILE));
|
||||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get source code line number for each instruction
|
||||
* @param sgNodes
|
||||
* @param print
|
||||
* @return
|
||||
*/
|
||||
public static HashMap<SSAInstruction, Integer> getLineNumbers(HashMap<Integer,BasicBlockInContext<IExplodedBasicBlock>> sgNodes) {
|
||||
log.debug("** get source code line number for each instruction");
|
||||
HashMap<SSAInstruction, Integer> map = new HashMap<SSAInstruction, Integer>();
|
||||
for(BasicBlockInContext<IExplodedBasicBlock> bbic : sgNodes.values()) {
|
||||
SSAInstruction inst = bbic.getLastInstruction();
|
||||
if(inst == null) {
|
||||
continue;
|
||||
}
|
||||
IMethod method = bbic.getMethod();
|
||||
int lineNumber = method.getLineNumber(bbic.getLastInstructionIndex());
|
||||
map.put(inst, lineNumber);
|
||||
log.debug(lineNumber + ". " + inst);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get corresponding instruction for the definition of each SSA value
|
||||
* @param sgNodes
|
||||
* @return
|
||||
*/
|
||||
public static HashMap<Integer, SSAInstruction> getDefs(HashMap<Integer,BasicBlockInContext<IExplodedBasicBlock>> sgNodes) {
|
||||
log.debug("** get definition instruction for each SSA value");
|
||||
HashMap<Integer, SSAInstruction> map = new HashMap<Integer, SSAInstruction>();
|
||||
for(BasicBlockInContext<IExplodedBasicBlock> bbic : sgNodes.values()) {
|
||||
SymbolTable symbolTable = bbic.getNode().getIR().getSymbolTable();
|
||||
DefUse du = bbic.getNode().getDU();
|
||||
|
||||
for (int i = 0; i <= symbolTable.getMaxValueNumber(); i++) {
|
||||
log.debug(i + " [" + symbolTable.getValueString(i) + "] " + du.getDef(i));
|
||||
map.put(i, du.getDef(i));
|
||||
}
|
||||
break; // there are the same definitions in each basic block, iff there is only one method FIXME: read different scopes, if multiple methods are required
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the corresponding instruction for each SQL execution (java.sql)
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<SSAInstruction> getSQLExecutes(HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes) {
|
||||
log.debug("** get SQL execution instructions");
|
||||
ArrayList<SSAInstruction> list = new ArrayList<SSAInstruction>();
|
||||
for(BasicBlockInContext<IExplodedBasicBlock> bbic : sgNodes.values()) {
|
||||
SSAInstruction inst = bbic.getLastInstruction();
|
||||
if(inst != null && inst instanceof AstJavaInvokeInstruction && inst.toString().contains("java/sql") && inst.toString().contains("execute")) {
|
||||
log.debug("SQL execution instruction: " + inst.toString());
|
||||
list.add(inst);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the corresponding instruction for each conditional branch
|
||||
* @return
|
||||
*/
|
||||
public static ArrayList<SSAInstruction> getConditions(HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes) {
|
||||
log.debug("** get conditional branch instructions");
|
||||
ArrayList<SSAInstruction> list = new ArrayList<SSAInstruction>();
|
||||
for(BasicBlockInContext<IExplodedBasicBlock> bbic : sgNodes.values()) {
|
||||
SSAInstruction inst = bbic.getLastInstruction();
|
||||
if(inst != null && inst instanceof SSAConditionalBranchInstruction) {
|
||||
log.debug("conditional branch instruction: " + inst.toString());
|
||||
list.add(inst);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints adjacency list to log using debug level
|
||||
* @param adjList
|
||||
*/
|
||||
public static void printAdjList(HashMap<Integer, ArrayList<Integer>> adjList, Logger log) {
|
||||
ArrayList<Integer> keySet1 = new ArrayList<Integer>(adjList.keySet());
|
||||
Collections.sort(keySet1);
|
||||
for (Integer src: keySet1) {
|
||||
log.debug(" " + src + ":");
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for(Integer dest : adjList.get(src)) {
|
||||
sb.append(", " + dest);
|
||||
}
|
||||
sb.append(" ");
|
||||
log.debug(" " + sb.substring(1));
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<SSAInstruction> analyzeStatementExecute(
|
||||
SSAInstruction ssaInstruction,
|
||||
HashMap<Integer, SSAInstruction> definitions,
|
||||
boolean prepared,
|
||||
HashSet<String> badMethods) {
|
||||
|
||||
if(prepared) {
|
||||
ssaInstruction = definitions.get(ssaInstruction.getUse(0));
|
||||
}
|
||||
|
||||
ArrayList<SSAInstruction> sources = new ArrayList<SSAInstruction>();
|
||||
int use = ssaInstruction.getUse(1); // use 0 is the createStatement, use 1 is the SQL String
|
||||
SSAInstruction inst = definitions.get(use);
|
||||
if(inst != null) {
|
||||
String instString = inst.toString();
|
||||
if(isBadSource(instString, badMethods)) {
|
||||
if(!sources.contains(inst)) {
|
||||
log.debug("SINK [bad]: " + ssaInstruction);
|
||||
sources.add(inst);
|
||||
}
|
||||
}
|
||||
if(inst instanceof SSABinaryOpInstruction) {
|
||||
if(isBadBinaryOpSource(use, definitions, sources, badMethods)) {
|
||||
log.debug("SINK [bad]: " + ssaInstruction);
|
||||
return sources;
|
||||
} else {
|
||||
log.debug("SINK [good]: " + ssaInstruction);
|
||||
}
|
||||
} else if(inst instanceof SSAPhiInstruction) {
|
||||
if(isBadPhiInstruction(use, definitions, sources, badMethods)) {
|
||||
log.debug("SINK [bad]: " + ssaInstruction);
|
||||
return sources;
|
||||
} else {
|
||||
log.debug("SINK [good]: " + ssaInstruction);
|
||||
}
|
||||
} else { //FIXME: rewrite to according procedure
|
||||
log.debug("unidentified instruction [" + instString + "], handled like phi function");
|
||||
if(isBadPhiInstruction(use, definitions, sources, badMethods)) {
|
||||
log.debug("SINK [bad]: " + ssaInstruction);
|
||||
return sources;
|
||||
} else {
|
||||
log.debug("SINK [good]: " + ssaInstruction);
|
||||
}
|
||||
}
|
||||
|
||||
} else { // is constant String
|
||||
log.debug("SINK [good]: " + ssaInstruction.toString());
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
public static boolean isBadSource(String instString, HashSet<String> badMethods) {
|
||||
if(instString != null) {
|
||||
for (String src : badMethods) {
|
||||
if(instString.contains(src)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isBadBinaryOpSource(int use, HashMap<Integer,SSAInstruction> definitions, ArrayList<SSAInstruction> badSources, HashSet<String> badMethods) {
|
||||
SSAInstruction inst = definitions.get(use);
|
||||
int part1 = inst.getUse(0);
|
||||
SSAInstruction inst1 = definitions.get(part1);
|
||||
String inst1String = "";
|
||||
if(inst1 != null) {
|
||||
inst1String = inst1.toString();
|
||||
}
|
||||
|
||||
int part2 = inst.getUse(1);
|
||||
SSAInstruction inst2 = definitions.get(part2);
|
||||
String inst2String = "";
|
||||
if(inst2 != null) {
|
||||
inst2String = inst2.toString();
|
||||
}
|
||||
|
||||
boolean isBad = false;
|
||||
if(inst1 == null) {
|
||||
isBad = isBad | false;
|
||||
} else if(inst1 instanceof SSABinaryOpInstruction) {
|
||||
isBad = isBad | isBadBinaryOpSource(part1, definitions, badSources, badMethods);
|
||||
} else if(inst1 instanceof SSAPhiInstruction) {
|
||||
isBad = isBad | isBadPhiInstruction(part1, definitions, badSources, badMethods);
|
||||
} else if(isBadSource(inst1String, badMethods)) {
|
||||
if(!badSources.contains(inst1)) {
|
||||
log.debug("SOURCE [bad]: " + inst1String);
|
||||
badSources.add(inst1);
|
||||
}
|
||||
isBad = true;
|
||||
}
|
||||
if(inst2 == null) {
|
||||
isBad = isBad | false;
|
||||
} else if(inst2 instanceof SSABinaryOpInstruction) {
|
||||
isBad = isBad | isBadBinaryOpSource(part2, definitions, badSources, badMethods);
|
||||
} else if(inst2 instanceof SSAPhiInstruction) {
|
||||
isBad = isBad | isBadPhiInstruction(part2, definitions, badSources, badMethods);
|
||||
} else if(isBadSource(inst2String, badMethods)) {
|
||||
if(!badSources.contains(inst2)) {
|
||||
log.debug("SOURCE [bad]: " + inst2String);
|
||||
badSources.add(inst2);
|
||||
}
|
||||
isBad = true;
|
||||
}
|
||||
return isBad;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isBadPhiInstruction(int use,
|
||||
HashMap<Integer, SSAInstruction> definitions,
|
||||
ArrayList<SSAInstruction> badSources, HashSet<String> badMethods) {
|
||||
SSAInstruction inst = definitions.get(use);
|
||||
boolean isBad = false;
|
||||
SSAPhiInstruction phiInst = (SSAPhiInstruction) inst;
|
||||
for(int i=0; i<phiInst.getNumberOfUses(); i++) {
|
||||
int part = phiInst.getUse(i);
|
||||
SSAInstruction useInst = definitions.get(part);
|
||||
String useInstString = "";
|
||||
if(useInst != null) {
|
||||
useInstString = useInst.toString();
|
||||
}
|
||||
if(useInst == null) {
|
||||
isBad = isBad | false;
|
||||
} else if(useInst instanceof SSABinaryOpInstruction) {
|
||||
isBad = isBad | isBadBinaryOpSource(part, definitions, badSources, badMethods);
|
||||
} else if(useInst instanceof SSAPhiInstruction) {
|
||||
isBad = isBad | isBadPhiInstruction(part, definitions, badSources, badMethods);
|
||||
} else if(isBadSource(useInstString, badMethods)) {
|
||||
if(!badSources.contains(useInst)) {
|
||||
log.debug("SOURCE [bad]: " + useInstString);
|
||||
badSources.add(useInst);
|
||||
}
|
||||
isBad = true;
|
||||
}
|
||||
}
|
||||
return isBad;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.TreeSelection;
|
||||
import org.eclipse.ui.IWorkbenchWindow;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
|
||||
import com.ibm.wala.cast.java.client.JDTJavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.cast.java.client.JavaSourceAnalysisEngine;
|
||||
import com.ibm.wala.cast.java.ipa.callgraph.JavaSourceAnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.Entrypoint;
|
||||
import com.ibm.wala.ipa.callgraph.impl.Util;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
|
||||
public class PlugInUtil {
|
||||
|
||||
public static String REGRESSION_EXCLUSIONS;
|
||||
|
||||
/**
|
||||
* Private constructor to ensure no object will be created
|
||||
*/
|
||||
private PlugInUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected project. Can return null if no project is selected
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static IJavaProject getSelectedIJavaProject() {
|
||||
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||
IJavaProject javaProject = null;
|
||||
|
||||
assert window == null : "Eclipse failed to load the active workbench window in BuildCallgraph.run()";
|
||||
if (window != null) {
|
||||
ISelection selection = window.getSelectionService().getSelection();
|
||||
if (selection instanceof TreeSelection) {
|
||||
TreeSelection tselection = (TreeSelection) selection;
|
||||
Object firstElement = tselection.getFirstElement();
|
||||
if (firstElement instanceof IAdaptable) {
|
||||
IProject project = (IProject) ((IAdaptable) firstElement).getAdapter(IProject.class);
|
||||
javaProject = JavaCore.create(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
return javaProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Created the {@link JavaSourceAnalysisEngine} for a given {@link IJavaProject}
|
||||
* @param project
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws CoreException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws CancelException
|
||||
*/
|
||||
public static JDTJavaSourceAnalysisEngine /* JavaSourceAnalysisEngine */
|
||||
createEngine(IJavaProject project) throws IOException, CoreException, IllegalArgumentException, CancelException {
|
||||
assert project == null : "You must provide a valid IJavaProject";
|
||||
project.open(null);
|
||||
|
||||
JDTJavaSourceAnalysisEngine engine;
|
||||
// engine = new JDTJavaSourceAnalysisEngine(project.getElementName());
|
||||
|
||||
|
||||
engine = new JDTJavaSourceAnalysisEngine(project.getElementName()) {
|
||||
@Override
|
||||
protected Iterable<Entrypoint> makeDefaultEntrypoints(AnalysisScope scope, IClassHierarchy cha) {
|
||||
String [] classes= {
|
||||
"Ltests/Test01"
|
||||
,"Ltests/Test02"
|
||||
,"Ltests/Test03"
|
||||
,"Ltests/Test04"
|
||||
,"Ltests/Test05"
|
||||
,"Ltests/Test06"
|
||||
,"Ltests/Test07"
|
||||
,"Ltests/Test08"
|
||||
,"Ltests/Test09"
|
||||
,"Ltests/Test10"
|
||||
,"Ltests/Test11"
|
||||
,"Ltests/Test12"
|
||||
,"Ltests/Test13"
|
||||
,"Ltests/Test14"
|
||||
,"Ltests/Test15"
|
||||
,"Ltests/Test16"
|
||||
,"Ltests/Test17"
|
||||
,"Ltests/Test18"
|
||||
,"Ltests/Test19"
|
||||
};
|
||||
|
||||
|
||||
return Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE,cha, classes);
|
||||
|
||||
}
|
||||
};
|
||||
engine.setExclusionsFile(REGRESSION_EXCLUSIONS);
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.ibm.wala.cast.ir.ssa.AstConstants;
|
||||
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
|
||||
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
|
||||
import com.ibm.wala.shrikeBT.IBinaryOpInstruction.IOperator;
|
||||
import com.ibm.wala.ssa.ConstantValue;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSABinaryOpInstruction;
|
||||
import com.ibm.wala.ssa.SSACFG.BasicBlock;
|
||||
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
|
||||
import com.ibm.wala.ssa.SSAConversionInstruction;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||
import com.ibm.wala.ssa.SSAUnaryOpInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
import cvc3.Expr;
|
||||
import cvc3.ValidityChecker;
|
||||
|
||||
public class SMTChecker {
|
||||
|
||||
private static Logger log = AnalysisUtil.getLogger(SMTChecker.class);
|
||||
|
||||
public static Expr getExprForCondition(ValidityChecker vc, BasicBlock basicBlock, IR entryIR) {
|
||||
// According to WALA documentation these blocks contain exactly one instruction
|
||||
SSAConditionalBranchInstruction inst = (SSAConditionalBranchInstruction) basicBlock.getLastInstruction();
|
||||
int var = inst.getUse(0); // This Instruction contains exactly two uses (0, 1) and use 1 is always 0.
|
||||
Expr expr = getExprForInstruction(vc, var, entryIR, null);
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns simple expression for loop-condition. Expects for-loop with simple comparison with constant on the right hand side
|
||||
*
|
||||
* <br />TODO: implement correct for all kinds of loops
|
||||
* @param vc
|
||||
* @param inst
|
||||
* @param entryIR
|
||||
* @return
|
||||
*/
|
||||
public static Expr getExprForLoop(ValidityChecker vc, SSAInstruction inst, IR entryIR) {
|
||||
// According to WALA documentation these blocks contain exactly one instruction
|
||||
SSAConditionalBranchInstruction condInst = (SSAConditionalBranchInstruction) inst;
|
||||
int var = condInst.getUse(0); // This Instruction contains exactly the two uses 0 and 1. Use 1 has always the value 0, since it stands for TRUE.
|
||||
SymbolTable symTab = entryIR.getSymbolTable();
|
||||
DefUse du = new DefUse(entryIR);
|
||||
|
||||
SSAInstruction useInst = du.getDef(var);
|
||||
SSABinaryOpInstruction binOpInstruction = (SSABinaryOpInstruction) useInst;
|
||||
|
||||
int varNo0 = useInst.getUse(0); // value at the left hand side
|
||||
|
||||
Expr exprLhs = null;
|
||||
SSAInstruction leftInstruction = du.getDef(varNo0);
|
||||
SSAPhiInstruction phiInstruction = (SSAPhiInstruction) leftInstruction;
|
||||
for(int i = 0; i< phiInstruction.getNumberOfUses(); i++) { // TODO: use bit array to identify overflows
|
||||
int varNo = phiInstruction.getUse(i);
|
||||
if(symTab.isIntegerConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Integer integer = (Integer) value.getValue();
|
||||
exprLhs = vc.exprFromString("" + integer.intValue());
|
||||
break;
|
||||
} else if(symTab.isLongConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Long longValue = (Long) value.getValue();
|
||||
exprLhs = vc.exprFromString("" + longValue.longValue());
|
||||
break;
|
||||
} else if(symTab.isDoubleConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Double doubleValue = (Double) value.getValue();
|
||||
exprLhs = vc.exprFromString("" + doubleValue.doubleValue());
|
||||
break;
|
||||
} else if(symTab.isFloatConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Float floatValue = (Float) value.getValue();
|
||||
exprLhs = vc.exprFromString("" + floatValue.floatValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int varNo1 = useInst.getUse(1); // value at the right hand side
|
||||
|
||||
Expr exprRhs;
|
||||
if(symTab.isIntegerConstant(varNo1)) { // TODO: use bit array to identify overflows
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo1);
|
||||
Integer integer = (Integer) value.getValue();
|
||||
exprRhs = vc.exprFromString("" + integer.intValue());
|
||||
} else if(symTab.isLongConstant(varNo1)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo1);
|
||||
Long longValue = (Long) value.getValue();
|
||||
exprRhs = vc.exprFromString("" + longValue.longValue());
|
||||
} else if(symTab.isDoubleConstant(varNo1)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo1);
|
||||
Double doubleValue = (Double) value.getValue();
|
||||
exprRhs = vc.exprFromString("" + doubleValue.doubleValue());
|
||||
} else if(symTab.isFloatConstant(varNo1)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo1);
|
||||
Float floatValue = (Float) value.getValue();
|
||||
exprRhs = vc.exprFromString("" + floatValue.floatValue());
|
||||
} else {
|
||||
exprRhs = vc.varExpr(String.format("v%d",varNo1), vc.realType());
|
||||
}
|
||||
|
||||
IOperator op = binOpInstruction.getOperator();
|
||||
|
||||
if(op == BinaryOpInstruction.Operator.OR) {
|
||||
return vc.orExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.AND) {
|
||||
return vc.andExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.SUB) {
|
||||
return vc.minusExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.ADD) {
|
||||
return vc.plusExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.DIV) {
|
||||
return vc.divideExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.MUL) {
|
||||
return vc.multExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.LT) {
|
||||
return vc.ltExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.LE) {
|
||||
return vc.leExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.EQ) {
|
||||
return vc.eqExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.GE) {
|
||||
return vc.geExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.GT) {
|
||||
return vc.gtExpr(exprLhs, exprRhs);
|
||||
} else {
|
||||
return vc.notExpr(vc.eqExpr(exprLhs, exprRhs));
|
||||
}
|
||||
}
|
||||
|
||||
public static Expr getExprForConditionalBranchInstruction(ValidityChecker vc, SSAInstruction inst, IR entryIR) {
|
||||
// According to WALA documentation these blocks contain exactly one instruction
|
||||
SSAConditionalBranchInstruction condInst = (SSAConditionalBranchInstruction) inst;
|
||||
int var = condInst.getUse(0); // This Instruction contains exactly two uses (0, 1) and use 1 is always 0.
|
||||
Expr expr = getExprForInstruction(vc, var, entryIR, BinaryOpInstruction.Operator.AND); // The AND operator identifies the expression as a boolean type
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
private static Expr getExprForInstruction(ValidityChecker vc, int varNo, IR ir, IOperator op2) {
|
||||
SymbolTable symTab = ir.getSymbolTable();
|
||||
if(symTab.isConstant(varNo)) {
|
||||
if(symTab.isBooleanConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
boolean isTrueConstant = value.isTrueConstant();
|
||||
if(symTab.isTrue(varNo)) {
|
||||
return vc.trueExpr();
|
||||
} else if(symTab.isFalse(varNo)) {
|
||||
return vc.falseExpr();
|
||||
}
|
||||
return vc.varExpr(String.format("v%d",varNo), vc.boolType(), (isTrueConstant) ? vc.trueExpr() : vc.falseExpr());
|
||||
} else if(symTab.isNumberConstant(varNo)) { // TODO: use bit array to identify overflows
|
||||
if(symTab.isIntegerConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Integer integer = (Integer) value.getValue();
|
||||
return vc.exprFromString("" + integer.intValue());
|
||||
} else if(symTab.isLongConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Long longValue = (Long) value.getValue();
|
||||
return vc.exprFromString("" + longValue.longValue());
|
||||
} else if(symTab.isDoubleConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Double doubleValue = (Double) value.getValue();
|
||||
return vc.exprFromString("" + doubleValue.doubleValue());
|
||||
} else if(symTab.isFloatConstant(varNo)) {
|
||||
ConstantValue value = (ConstantValue) symTab.getValue(varNo);
|
||||
Float floatValue = (Float) value.getValue();
|
||||
return vc.exprFromString("" + floatValue.floatValue());
|
||||
}
|
||||
} else if(symTab.isTrue(varNo)) {
|
||||
return vc.trueExpr();
|
||||
} else if(symTab.isFalse(varNo)) {
|
||||
return vc.falseExpr();
|
||||
} else if(symTab.isNullConstant(varNo)) {
|
||||
return vc.nullExpr();
|
||||
}
|
||||
} else {
|
||||
DefUse du = new DefUse(ir);
|
||||
SSAInstruction defInst = du.getDef(varNo);
|
||||
if(defInst == null) {
|
||||
if(op2 == BinaryOpInstruction.Operator.OR || op2 == BinaryOpInstruction.Operator.AND) {
|
||||
return vc.varExpr(String.format("v%d",varNo), vc.boolType());
|
||||
} else {
|
||||
return vc.varExpr(String.format("v%d",varNo), vc.realType());
|
||||
}
|
||||
} else if(defInst instanceof SSAGetInstruction) { // def refers to static value
|
||||
SSAGetInstruction inst = (SSAGetInstruction) defInst;
|
||||
FieldReference fr = inst.getDeclaredField();
|
||||
TypeReference tr = fr.getFieldType();
|
||||
if(tr.equals(TypeReference.Boolean)) {
|
||||
return vc.varExpr(String.format("v%d",varNo), vc.boolType());
|
||||
}
|
||||
}
|
||||
if(defInst instanceof SSABinaryOpInstruction) {
|
||||
SSABinaryOpInstruction binaryInst = (SSABinaryOpInstruction) defInst;
|
||||
|
||||
IOperator op = binaryInst.getOperator();
|
||||
|
||||
// BinaryInstructions always contain exactly two uses
|
||||
|
||||
// left hand side
|
||||
int var1 = binaryInst.getUse(0);
|
||||
Expr exprLhs = getExprForInstruction(vc, var1, ir, op);
|
||||
|
||||
// right hand side
|
||||
int var2 = binaryInst.getUse(1);
|
||||
Expr exprRhs = getExprForInstruction(vc, var2, ir, op);
|
||||
|
||||
if(op == BinaryOpInstruction.Operator.OR) {
|
||||
return vc.orExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.AND) {
|
||||
return vc.andExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.SUB) {
|
||||
return vc.minusExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.ADD) {
|
||||
return vc.plusExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.DIV) {
|
||||
return vc.divideExpr(exprLhs, exprRhs);
|
||||
} else if(op == BinaryOpInstruction.Operator.MUL) {
|
||||
return vc.multExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.LT) {
|
||||
return vc.ltExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.LE) {
|
||||
return vc.leExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.EQ) {
|
||||
return vc.eqExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.GE) {
|
||||
return vc.geExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.GT) {
|
||||
return vc.gtExpr(exprLhs, exprRhs);
|
||||
} else if(op == AstConstants.BinaryOp.NE) {
|
||||
return vc.notExpr(vc.eqExpr(exprLhs, exprRhs));
|
||||
}
|
||||
} else if(defInst instanceof SSAUnaryOpInstruction) { // WALA uses unary operation ONLY for negation
|
||||
SSAUnaryOpInstruction unaryInst = (SSAUnaryOpInstruction) defInst;
|
||||
|
||||
int var = unaryInst.getUse(0);
|
||||
Expr expr = getExprForInstruction(vc, var, ir, BinaryOpInstruction.Operator.AND);
|
||||
return vc.notExpr(expr);
|
||||
} else if(defInst instanceof SSAConversionInstruction) {
|
||||
SSAConversionInstruction conversionInst = (SSAConversionInstruction) defInst;
|
||||
|
||||
// ConversionInstructions always contain exactly one use
|
||||
int var = conversionInst.getUse(0);
|
||||
return getExprForInstruction(vc, var, ir, op2);
|
||||
} else if(defInst instanceof SSAPhiInstruction) {
|
||||
SSAPhiInstruction phiInst = (SSAPhiInstruction) defInst;
|
||||
List<Expr> expr = new ArrayList<Expr>();
|
||||
for(int i = 0; i<phiInst.getNumberOfUses(); i++) {
|
||||
expr.add(getExprForInstruction(vc, phiInst.getUse(i), ir, null));
|
||||
}
|
||||
return vc.orExpr(expr);
|
||||
} else if(defInst instanceof AstJavaInvokeInstruction) {
|
||||
//TODO: handle invoke for accepted methods
|
||||
if(op2 == BinaryOpInstruction.Operator.OR || op2 == BinaryOpInstruction.Operator.AND) {
|
||||
return vc.varExpr(String.format("v%d_invoke",varNo), vc.boolType());
|
||||
} else {
|
||||
return vc.varExpr(String.format("v%d_invoke",varNo), vc.realType());
|
||||
}
|
||||
}
|
||||
log.error(defInst.getClass() + " is not handled yet");
|
||||
}
|
||||
log.error("unhandled type of instruction");
|
||||
System.exit(1);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,872 @@
|
|||
/*
|
||||
* (C) Copyright 2010-2015 SAP SE.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
*/
|
||||
|
||||
package eu.aniketos.dasca.dataflow.util;
|
||||
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.ibm.wala.dataflow.IFDS.ICFGSupergraph;
|
||||
import com.ibm.wala.ipa.cfg.BasicBlockInContext;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.SSABinaryOpInstruction;
|
||||
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
|
||||
import com.ibm.wala.ssa.SSAGotoInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.analysis.IExplodedBasicBlock;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
|
||||
import cvc3.Expr;
|
||||
import cvc3.SatResult;
|
||||
import cvc3.ValidityChecker;
|
||||
|
||||
|
||||
/**
|
||||
* static class for SG helper methods
|
||||
*
|
||||
*/
|
||||
public class SuperGraphUtil {
|
||||
|
||||
private static final Logger log = AnalysisUtil.getLogger(SuperGraphUtil.class);
|
||||
|
||||
/**
|
||||
* Adds every nodes ID to iDs, iff it is on a path between the entry and exit point. Uses recursive DFS
|
||||
* @param iDs
|
||||
* @param sg
|
||||
* @param sgNodes
|
||||
* @param sgNodesReverse
|
||||
* @param currentId
|
||||
* @param endId
|
||||
*/
|
||||
private static void relevantPathSearch(
|
||||
HashSet<Integer> iDs,
|
||||
ICFGSupergraph sg,
|
||||
HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes,
|
||||
HashMap<BasicBlockInContext<IExplodedBasicBlock>, Integer> sgNodesReverse,
|
||||
ArrayList<MethodReference> acceptedMethods,
|
||||
int currentId,
|
||||
int endId) {
|
||||
if(iDs.contains(currentId)) {
|
||||
return;
|
||||
}
|
||||
iDs.add(currentId);
|
||||
if(currentId == endId) {
|
||||
return;
|
||||
}
|
||||
BasicBlockInContext<IExplodedBasicBlock> bbic = sgNodes.get(currentId);
|
||||
boolean isInvoke = bbic.getLastInstruction() instanceof SSAInvokeInstruction;
|
||||
boolean isStringConcat = isInvoke && bbic.getLastInstruction().toString().contains("StringBuilder") && (bbic.getLastInstruction().toString().contains("append") | bbic.getLastInstruction().toString().contains("toString"));
|
||||
|
||||
Iterator<BasicBlockInContext<IExplodedBasicBlock>> sucIt = sg.getSuccNodes(bbic);
|
||||
while(sucIt.hasNext()) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> nextChild = sucIt.next();
|
||||
|
||||
if(isStringConcat) {
|
||||
if(!sucIt.hasNext()) { // last association of a String concatenation is java intern
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
MethodReference method = nextChild.getMethod().getReference();
|
||||
if(isInvoke) {
|
||||
if(!acceptedMethods.contains(method)) {
|
||||
acceptedMethods.add(method);
|
||||
}
|
||||
} else {
|
||||
if(!acceptedMethods.contains(method)) {
|
||||
log.debug("supergraph cut at '" + bbic.getNumber() + " -> " + nextChild.getNumber() + " (" + nextChild.toString() + ")'");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
IExplodedBasicBlock del = nextChild.getDelegate();
|
||||
if(del.isEntryBlock() && del.toString().contains("init")) {
|
||||
log.debug("supergraph cut at '" + bbic.getNumber() + " -> " + nextChild.getNumber() + " (" + nextChild.toString() + ")'");
|
||||
continue;
|
||||
}
|
||||
relevantPathSearch(iDs, sg, sgNodes, sgNodesReverse, acceptedMethods, sgNodesReverse.get(nextChild), endId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the supergraph and saves the relevant part as a dot file to the location <graphs folder>/<entryClass/
|
||||
* @return
|
||||
*/
|
||||
public static int analyzeAndSaveSuperGraph(ICFGSupergraph sg, String entryClass, String entryMethod) {
|
||||
int weaknessCount = 0;
|
||||
|
||||
if (sg == null) {
|
||||
throw new IllegalArgumentException("sg was null for entry Class \""+entryClass+"\" and entry method \""+entryMethod+"\"");
|
||||
}
|
||||
|
||||
log.info("--- start analyzing " + entryMethod + " ---");
|
||||
ValidityChecker vc = ValidityChecker.create();
|
||||
vc.push();
|
||||
|
||||
Iterator<BasicBlockInContext<IExplodedBasicBlock>> completeIterator = sg.iterator();
|
||||
int analysisLevel = AnalysisUtil.getPropertyInteger(AnalysisUtil.CONFIG_ANALYSIS_DEPTH);
|
||||
|
||||
HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes = new HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>>();
|
||||
HashMap<BasicBlockInContext<IExplodedBasicBlock>, Integer> sgNodesReversed = new HashMap<BasicBlockInContext<IExplodedBasicBlock>, Integer>();
|
||||
HashMap<SSAInstruction, Integer> sgNodesInstId = new HashMap<SSAInstruction, Integer>();
|
||||
ArrayList<MethodReference> acceptedMethods = new ArrayList<MethodReference>();
|
||||
|
||||
// Add all blocks into a Map with a unique identifier in both directions and find entry/exit node
|
||||
int i = 0;
|
||||
int mainEntryId = 0;
|
||||
int mainExitId = 0;
|
||||
while (completeIterator.hasNext()) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> current = completeIterator.next();
|
||||
sgNodes.put(i, current);
|
||||
sgNodesReversed.put(current, i);
|
||||
Iterator<SSAInstruction> instIt = current.iterator();
|
||||
while (instIt.hasNext()) {
|
||||
SSAInstruction inst = instIt.next();
|
||||
sgNodesInstId.put(inst, i);
|
||||
/* add to include other required methods into CFG
|
||||
if(inst instanceof AstJavaInvokeInstruction){
|
||||
AstJavaInvokeInstruction in = (AstJavaInvokeInstruction) inst;
|
||||
MethodReference meth = in.getDeclaredTarget();
|
||||
if(meth.toString().contains("calledMethod")){ // check for required method
|
||||
acceptedMethods.add(meth);
|
||||
}
|
||||
}
|
||||
//*/
|
||||
|
||||
}
|
||||
String signature = current.getMethod().getSignature();
|
||||
// find entry and exit nodes
|
||||
if(signature.contains(entryClass) && signature.contains(entryMethod) && current.isEntryBlock()) { // FIXME: entry/exit nodes definition via name is too weak
|
||||
mainEntryId = i;
|
||||
} else if(signature.contains(entryClass) && signature.contains(entryMethod) && current.isExitBlock()) {
|
||||
mainExitId = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(mainEntryId == 0 && mainExitId == 0) {
|
||||
log.error("empty entry method, ensure invocation in main method");
|
||||
return 0;
|
||||
}
|
||||
HashSet<Integer> relevantIDs = new HashSet<Integer>();
|
||||
BasicBlockInContext<IExplodedBasicBlock> bbic = sgNodes.get(mainEntryId);
|
||||
acceptedMethods.add(bbic.getMethod().getReference());
|
||||
log.debug("start recursive graph building");
|
||||
relevantPathSearch(relevantIDs, sg, sgNodes, sgNodesReversed, acceptedMethods, mainEntryId, mainExitId);
|
||||
|
||||
// remove irrelevant nodes (not on at least one path between entry and exit node)
|
||||
log.debug("remove irrelevant nodes");
|
||||
for (int j = 0; j < i; j++) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> tmp = sgNodes.get(j);
|
||||
if(!relevantIDs.contains(j)) {
|
||||
sgNodesReversed.remove(tmp);
|
||||
sgNodes.remove(j);
|
||||
}
|
||||
}
|
||||
|
||||
// build separate adjacency list
|
||||
log.debug("build seperate adjacency list");
|
||||
HashMap<Integer, ArrayList<Integer>> adjList = new HashMap<Integer, ArrayList<Integer>>();
|
||||
HashMap<Integer, ArrayList<Integer>> adjListReverse = new HashMap<Integer, ArrayList<Integer>>();
|
||||
|
||||
boolean removeEmptyNodes = AnalysisUtil.getPropertyBoolean(AnalysisUtil.CONFIG_DOT_REMOVE_EMPTY_NODES);
|
||||
ArrayList<Integer> emptyNodes = new ArrayList<Integer>();
|
||||
|
||||
buildAdjacencyLists(sg, sgNodes, sgNodesReversed, adjList, adjListReverse, emptyNodes, relevantIDs);
|
||||
|
||||
/* <<< print original adjacency list to log
|
||||
log.debug("adjacency list before removing empty nodes:");
|
||||
AnalysisUtil.printAdjList(adjList, log);
|
||||
//*/
|
||||
if(removeEmptyNodes) {
|
||||
removeEmptyNodes(emptyNodes, adjList, adjListReverse, sgNodes, sgNodesReversed);
|
||||
}
|
||||
|
||||
log.debug("add conditions to graph nodes");
|
||||
ArrayList<Integer> visited = new ArrayList<Integer>();
|
||||
ArrayList<Integer> currentConditions = new ArrayList<Integer>();
|
||||
HashMap<Integer, Integer> currentConditionsEndId = new HashMap<Integer, Integer>();
|
||||
HashMap<Integer, ArrayList<Integer>> finalConditions = new HashMap<Integer, ArrayList<Integer>>();
|
||||
HashMap<Integer, Integer> loops = new HashMap<Integer, Integer>();
|
||||
addConditionsToGraph(sgNodes, adjList, mainEntryId, visited, mainExitId, currentConditions, currentConditionsEndId, finalConditions, loops);
|
||||
|
||||
// remove goto statements for later analysis steps
|
||||
for (int loopId : loops.keySet()) {
|
||||
int gotoId = loops.get(loopId);
|
||||
int gotoTargetId = adjList.get(gotoId).get(0); // goto has exact one child
|
||||
int afterLoopId = 0;
|
||||
for(int id : adjList.get(loopId)) {
|
||||
afterLoopId = Math.max(afterLoopId, id);
|
||||
}
|
||||
ArrayList<Integer> newList = new ArrayList<Integer>();
|
||||
newList.add(afterLoopId);
|
||||
adjList.put(gotoId, newList);
|
||||
adjListReverse.get(afterLoopId).add(gotoId);
|
||||
ArrayList<Integer> gotoTargetReverseList = adjListReverse.get(gotoTargetId);
|
||||
ArrayList<Integer> newGotoTargetReverseList = new ArrayList<Integer>();
|
||||
for (int child : gotoTargetReverseList) {
|
||||
if(child != gotoId) {
|
||||
newGotoTargetReverseList.add(child);
|
||||
}
|
||||
}
|
||||
adjListReverse.put(gotoTargetId, newGotoTargetReverseList);
|
||||
}
|
||||
|
||||
/* <<< print required conditions for each node
|
||||
for (Integer key : finalConditions.keySet()) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for(int condition : finalConditions.get(key)){
|
||||
sb.append(", " + condition);
|
||||
}sb.append(" ");
|
||||
log.debug(key + ": " + sb.substring(2));
|
||||
}
|
||||
//*/
|
||||
|
||||
/* <<< print changed adjacency list to log
|
||||
log.debug("adjacency list after removing empty nodes:");
|
||||
AnalysisUtil.printAdjList(adjList, log);
|
||||
//*/
|
||||
|
||||
//* <<< get definition instruction for each SSA value
|
||||
HashMap<Integer, SSAInstruction> definitions = AnalysisUtil.getDefs(sgNodes);
|
||||
//*/
|
||||
|
||||
//* <<< get source code line number for each instruction
|
||||
HashMap<SSAInstruction, Integer> lineNumbers = AnalysisUtil.getLineNumbers(sgNodes);
|
||||
//*/
|
||||
|
||||
//* <<< get the corresponding instruction for each condition inside the callgraph
|
||||
ArrayList<SSAInstruction> conditionsList = AnalysisUtil.getConditions(sgNodes);
|
||||
ArrayList<Integer> conditionsIdList = new ArrayList<Integer>();
|
||||
for (SSAInstruction cond : conditionsList) {
|
||||
conditionsIdList.add(sgNodesInstId.get(cond));
|
||||
}
|
||||
//*/
|
||||
//* <<< get the corresponding source code line number for each condition (node id) inside the callgraph
|
||||
HashMap<Integer, Integer> conditionLineNumber = new HashMap<Integer, Integer>();
|
||||
for (SSAInstruction instCondition : conditionsList) {
|
||||
int nodeId = sgNodesInstId.get(instCondition);
|
||||
int lineNumber = lineNumbers.get(instCondition);
|
||||
conditionLineNumber.put(nodeId, lineNumber);
|
||||
}
|
||||
|
||||
//*/
|
||||
|
||||
//* <<< build CVC3 expressions from conditional instruction
|
||||
|
||||
log.debug("** get CVC3 expressions for each conditional branch instruction");
|
||||
HashMap<Integer, Expr> expressions = new HashMap<Integer, Expr>();
|
||||
IR entryIR = sgNodes.values().iterator().next().getNode().getIR();
|
||||
vc.pop();
|
||||
vc.push();
|
||||
for (SSAInstruction instCondition : conditionsList) {
|
||||
int condId = sgNodesInstId.get(instCondition);
|
||||
if(loops.keySet().contains(condId)) {
|
||||
Expr expr = SMTChecker.getExprForLoop(vc , instCondition, entryIR);
|
||||
expressions.put(sgNodesInstId.get(instCondition), expr);
|
||||
} else {
|
||||
Expr expr = SMTChecker.getExprForConditionalBranchInstruction(vc , instCondition, entryIR);
|
||||
expressions.put(sgNodesInstId.get(instCondition), expr);
|
||||
}
|
||||
vc.pop();
|
||||
vc.push();
|
||||
}
|
||||
vc.pop();
|
||||
vc.push();
|
||||
//*/
|
||||
|
||||
ArrayList<SSAInstruction> sqlExecutes = AnalysisUtil.getSQLExecutes(sgNodes);
|
||||
|
||||
log.debug("** get source/sink pairs for each SQL instruction");
|
||||
|
||||
String sanitizerMethods = AnalysisUtil.getPropertyString(AnalysisUtil.CONFIG_SANITIZER); // good sources are specified as sanitizer
|
||||
|
||||
String[] methods = sanitizerMethods.split(",");
|
||||
HashSet<String> sanitizer = new HashSet<String>();
|
||||
for (int k = 0; k < methods.length; k++) {
|
||||
String sanitizerMethod = methods[k].trim();
|
||||
sanitizer.add(sanitizerMethod);
|
||||
}
|
||||
|
||||
String badSourceMethods = AnalysisUtil.getPropertyString(AnalysisUtil.CONFIG_BAD_SRC);
|
||||
|
||||
methods = badSourceMethods.split(",");
|
||||
HashSet<String> badMethods = new HashSet<String>();
|
||||
for (int k = 0; k < methods.length; k++) {
|
||||
String badMethod = methods[k].trim() + "()";
|
||||
badMethods.add(badMethod);
|
||||
}
|
||||
|
||||
//* <<< get possible vulnerabilities for each SQL execute
|
||||
|
||||
HashMap<SSAInstruction, ArrayList<SSAInstruction>> sinkSources = new HashMap<SSAInstruction, ArrayList<SSAInstruction>>();
|
||||
for (SSAInstruction ssaInstruction : sqlExecutes) {
|
||||
boolean isPreparedStmt = ssaInstruction.toString().contains("Prepared");
|
||||
sinkSources.put(ssaInstruction, AnalysisUtil.analyzeStatementExecute(ssaInstruction, definitions, isPreparedStmt, badMethods));
|
||||
}
|
||||
boolean containsVulnerability = false;
|
||||
for (SSAInstruction sink : sqlExecutes) {
|
||||
if(!sinkSources.containsKey(sink)) { // no vulnerability possible
|
||||
continue;
|
||||
}
|
||||
ArrayList<SSAInstruction> badSources = sinkSources.get(sink);
|
||||
if(badSources != null) {
|
||||
for (SSAInstruction source : badSources) {
|
||||
boolean isNotMutuallyExclusive = true;
|
||||
if(analysisLevel >= AnalysisUtil.ANALYSIS_DEPTH_EXCLUSIVE) {
|
||||
isNotMutuallyExclusive = isNotMutuallyExclusive(sink, source, sgNodesInstId, finalConditions, expressions, vc);
|
||||
}
|
||||
if(isNotMutuallyExclusive) {
|
||||
boolean isNotSanitized = true;
|
||||
if(analysisLevel >= AnalysisUtil.ANALYSIS_DEPTH_SANITIZING) {
|
||||
isNotSanitized = isNotSanitized(sgNodesInstId.get(source), sgNodesInstId.get(sink), adjList, finalConditions, expressions, vc, conditionsIdList, sanitizer, sgNodes);
|
||||
}
|
||||
if(isNotSanitized) {
|
||||
weaknessCount++;
|
||||
containsVulnerability = true;
|
||||
log.warn("SQL execute [" + lineNumbers.get(sink) + "] with bad source readLine [" + lineNumbers.get(source) + "] (" + entryClass + "." + entryMethod + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!containsVulnerability) {
|
||||
log.info("(" + entryClass + "." + entryMethod + ") is save");
|
||||
}
|
||||
//*/
|
||||
|
||||
|
||||
String filePath = String.format("%s_SG.dot", entryMethod);
|
||||
generateDotFile(sgNodes, adjList, entryClass, filePath, finalConditions);
|
||||
return weaknessCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes all possible control flows between source and sink and checks, if every single path is sanitized.
|
||||
* @return true, iff there exists at least one direct unsanitized path between source and sink
|
||||
*/
|
||||
private static boolean isNotSanitized(int sourceId,
|
||||
int sinkId, HashMap<Integer, ArrayList<Integer>> adjList,
|
||||
HashMap<Integer, ArrayList<Integer>> finalConditions,
|
||||
HashMap<Integer, Expr> expressions,
|
||||
ValidityChecker vc,
|
||||
ArrayList<Integer> conditionsIdList,
|
||||
HashSet<String> sanitizer,
|
||||
HashMap<Integer,BasicBlockInContext<IExplodedBasicBlock>> sgNodes) {
|
||||
|
||||
log.debug("** get possible control flows from source to sink");
|
||||
HashMap<Integer, HashSet<ArrayList<Integer>>> paths = new HashMap<Integer, HashSet<ArrayList<Integer>>>();
|
||||
|
||||
calculatePaths(sourceId, sinkId, adjList, paths);
|
||||
HashSet<ArrayList<Integer>> pathList = paths.get(sourceId);
|
||||
HashSet<ArrayList<Integer>> possibleFlowPaths = new HashSet<ArrayList<Integer>>();
|
||||
|
||||
for (ArrayList<Integer> path : pathList) {
|
||||
boolean isPossibleFlow = isPossibleFlow(path, finalConditions, expressions, vc, conditionsIdList);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
sb.append(" -> " + path.get(i));
|
||||
}
|
||||
sb.append(" ");
|
||||
if(isPossibleFlow) {
|
||||
log.debug("FLOW [possible]: " + sb.substring(3)); // cut off the last arrow
|
||||
possibleFlowPaths.add(path);
|
||||
} else {
|
||||
log.debug("FLOW [impossible]: " + sb.substring(3));
|
||||
}
|
||||
}
|
||||
loopPossiblePaths:
|
||||
for (ArrayList<Integer> possibleFlowPath : possibleFlowPaths) {
|
||||
boolean containsSanitizer = false;
|
||||
for (String sanitizerMethod : sanitizer) {
|
||||
for(int nodeId : possibleFlowPath) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> node = sgNodes.get(nodeId);
|
||||
SSAInstruction inst = node.getLastInstruction();
|
||||
if(inst != null) {
|
||||
if(inst.toString().contains(sanitizerMethod)) {
|
||||
containsSanitizer = true;
|
||||
continue loopPossiblePaths;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!containsSanitizer) {
|
||||
return true; // path contains no sanitizer => is direct path between bad source and bad sink
|
||||
}
|
||||
}
|
||||
return false; // every possible path contained at least one sanitizer
|
||||
}
|
||||
|
||||
private static boolean isPossibleFlow(ArrayList<Integer> path,
|
||||
HashMap<Integer, ArrayList<Integer>> finalConditions,
|
||||
HashMap<Integer, Expr> expressions,
|
||||
ValidityChecker vc,
|
||||
ArrayList<Integer> conditionsIdList) {
|
||||
vc.pop();
|
||||
vc.push();
|
||||
List<Expr> allExpr = new ArrayList<Expr>();
|
||||
ArrayList<Integer> allConditions = new ArrayList<Integer>();
|
||||
for (int i=0; i<path.size(); i++) {
|
||||
int node = path.get(i);
|
||||
ArrayList<Integer> conditions = finalConditions.get(node);
|
||||
if(conditionsIdList.contains(node)) {
|
||||
ArrayList<Integer> childConditions = finalConditions.get(path.get(i+1).intValue());
|
||||
if(childConditions == null || childConditions.isEmpty() || !(childConditions.contains(node) | childConditions.contains(-node))) { // jump over if-block without else part => else condition needs to be set
|
||||
allExpr.add(vc.notExpr(expressions.get(node)));
|
||||
}
|
||||
}
|
||||
if(conditions != null) {
|
||||
for (int condId : conditions) {
|
||||
if(!allConditions.contains(condId)) {
|
||||
allConditions.add(condId);
|
||||
if(condId < 0) {
|
||||
allExpr.add(vc.notExpr(expressions.get(Math.abs(condId))));
|
||||
} else {
|
||||
allExpr.add(expressions.get(condId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(allExpr.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Expr completeExpr = vc.andExpr(allExpr);
|
||||
SatResult satResult = vc.checkUnsat(completeExpr);
|
||||
boolean satisfiable = satResult.equals(SatResult.SATISFIABLE);
|
||||
log.info("checking expression [" + (satisfiable?"SAT":"UNSAT") + "]: " + completeExpr);
|
||||
return satisfiable;
|
||||
}
|
||||
|
||||
private static void calculatePaths(int currentId, int target,
|
||||
HashMap<Integer, ArrayList<Integer>> adjList,
|
||||
HashMap<Integer, HashSet<ArrayList<Integer>>> paths) {
|
||||
|
||||
ArrayList<Integer> children = adjList.get(currentId);
|
||||
HashSet<ArrayList<Integer>> currentPaths = new HashSet<ArrayList<Integer>>();
|
||||
|
||||
for(int child : children) {
|
||||
if(child == target) {
|
||||
ArrayList<Integer> last = new ArrayList<Integer>();
|
||||
last.add(child);
|
||||
currentPaths.add(last);
|
||||
continue;
|
||||
}
|
||||
calculatePaths(child, target, adjList, paths);
|
||||
HashSet<ArrayList<Integer>> childPaths = paths.get(child);
|
||||
if(childPaths!= null) {
|
||||
for (ArrayList<Integer> childPath : childPaths) {
|
||||
ArrayList<Integer> newPath = new ArrayList<Integer>();
|
||||
newPath.add(child);
|
||||
newPath.addAll(childPath);
|
||||
currentPaths.add(newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
paths.put(currentId, currentPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, if sink and source node are mutually excluded because of the respective conditions
|
||||
* @param sink
|
||||
* @param source
|
||||
* @param sgNodesInstId
|
||||
* @param finalConditions
|
||||
* @param expressions
|
||||
* @param vc
|
||||
* @return
|
||||
*/
|
||||
private static boolean isNotMutuallyExclusive(SSAInstruction sink,
|
||||
SSAInstruction source,
|
||||
HashMap<SSAInstruction, Integer> sgNodesInstId,
|
||||
HashMap<Integer,ArrayList<Integer>> finalConditions,
|
||||
HashMap<Integer, Expr> expressions, ValidityChecker vc) {
|
||||
vc.pop();
|
||||
vc.push();
|
||||
int sourceId = sgNodesInstId.get(source);
|
||||
int sinkId = sgNodesInstId.get(sink);
|
||||
ArrayList<Integer> combinedConditions = new ArrayList<Integer>();
|
||||
if(finalConditions.containsKey(sourceId)) {
|
||||
combinedConditions.addAll(finalConditions.get(sourceId));
|
||||
}
|
||||
if(finalConditions.containsKey(sinkId)) {
|
||||
combinedConditions.addAll(finalConditions.get(sinkId));
|
||||
}
|
||||
Expr expr = getConditionExpression(combinedConditions, expressions, vc);
|
||||
vc.pop();
|
||||
vc.push();
|
||||
if(expr.toString().equalsIgnoreCase("null")) {
|
||||
return true;
|
||||
}
|
||||
SatResult satResult = vc.checkUnsat(expr);
|
||||
boolean satisfiable = satResult.equals(SatResult.SATISFIABLE);
|
||||
return satisfiable;
|
||||
}
|
||||
|
||||
private static Expr getConditionExpression(ArrayList<Integer> nodeIds, HashMap<Integer, Expr> expressions, ValidityChecker vc) {
|
||||
if(nodeIds.isEmpty()) {
|
||||
return vc.nullExpr();
|
||||
}
|
||||
List<Expr> exprList = new ArrayList<Expr>();
|
||||
for (int i=0; i<nodeIds.size(); i++) {
|
||||
Integer conditionId = nodeIds.get(i);
|
||||
Expr tmpExpr = expressions.get(Math.abs(conditionId));
|
||||
if(conditionId<0) {
|
||||
tmpExpr = vc.notExpr(tmpExpr);
|
||||
}
|
||||
exprList.add(tmpExpr);
|
||||
}
|
||||
return vc.andExpr(exprList);
|
||||
}
|
||||
|
||||
private static void removeEmptyNodes(ArrayList<Integer> emptyNodes,
|
||||
HashMap<Integer, ArrayList<Integer>> adjList,
|
||||
HashMap<Integer, ArrayList<Integer>> adjListReverse, HashMap<Integer,BasicBlockInContext<IExplodedBasicBlock>> sgNodes, HashMap<BasicBlockInContext<IExplodedBasicBlock>,Integer> sgNodesReversed) {
|
||||
|
||||
Collections.sort(emptyNodes);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int integer : emptyNodes) {
|
||||
sb.append(", " + integer);
|
||||
}
|
||||
sb.append(" ");
|
||||
log.debug("empty nodes in supergraph:" + sb.substring(1));
|
||||
|
||||
// remove empty nodes from supergraph
|
||||
log.debug("remove empty nodes from supergraph");
|
||||
for (Integer kill: emptyNodes) {
|
||||
ArrayList<Integer> children = adjList.get(kill);
|
||||
if(children == null) {
|
||||
children = new ArrayList<Integer>();
|
||||
}
|
||||
// insert new edges around removed nodes
|
||||
for(Integer father : adjListReverse.get(kill)) {
|
||||
ArrayList<Integer> tmpList = adjList.get(father);
|
||||
if(tmpList==null) {
|
||||
tmpList = new ArrayList<Integer>();
|
||||
}
|
||||
tmpList.remove(kill);
|
||||
tmpList.addAll(children);
|
||||
for (Integer childId : children) {
|
||||
ArrayList<Integer> childFathers = adjListReverse.get(childId);
|
||||
if(childFathers==null) {
|
||||
childFathers = new ArrayList<Integer>();
|
||||
}
|
||||
childFathers.remove(kill);
|
||||
childFathers.add(father);
|
||||
adjListReverse.put(childId, childFathers);
|
||||
}
|
||||
adjList.put(father, tmpList);
|
||||
}
|
||||
}
|
||||
for (Integer kill: emptyNodes) { // requires two loops to build the new edges correct
|
||||
adjList.remove(kill);
|
||||
sgNodesReversed.remove(sgNodes.get(kill));
|
||||
sgNodes.remove(kill);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void buildAdjacencyLists(
|
||||
ICFGSupergraph sg, HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes,
|
||||
HashMap<BasicBlockInContext<IExplodedBasicBlock>, Integer> sgNodesReversed,
|
||||
HashMap<Integer, ArrayList<Integer>> adjList,
|
||||
HashMap<Integer, ArrayList<Integer>> adjListReverse,
|
||||
ArrayList<Integer> emptyNodes, HashSet<Integer> relevantIDs) {
|
||||
|
||||
for (int key1 : sgNodes.keySet()) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> val1 = sgNodes.get(key1);
|
||||
Iterator<BasicBlockInContext<IExplodedBasicBlock>> sucIt = sg.getSuccNodes(val1);
|
||||
// add 'key1->sucId' to adjList
|
||||
ArrayList<Integer> list = adjList.get(key1);
|
||||
if(list == null) {
|
||||
list = new ArrayList<Integer>();
|
||||
}
|
||||
while (sucIt.hasNext()) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> suc = sucIt.next();
|
||||
if(!sgNodesReversed.containsKey(suc)) {
|
||||
continue;
|
||||
}
|
||||
int sucId = sgNodesReversed.get(suc);
|
||||
|
||||
if(!list.contains(sucId)) {
|
||||
list.add(sucId);
|
||||
}
|
||||
|
||||
// add 'sucId->key1' to adjListReverse
|
||||
ArrayList<Integer> listReverse = adjListReverse.get(sucId);
|
||||
if(listReverse == null) {
|
||||
listReverse = new ArrayList<Integer>();
|
||||
}
|
||||
if(!listReverse.contains(key1)) {
|
||||
listReverse.add(key1);
|
||||
}
|
||||
adjListReverse.put(sucId, listReverse);
|
||||
|
||||
// add empty nodes to list
|
||||
Iterator<SSAInstruction> it = suc.iterator();
|
||||
if(relevantIDs.contains(sucId)) {
|
||||
if(!emptyNodes.contains(sucId)) {
|
||||
if(!it.hasNext() && !suc.isEntryBlock() && !suc.isExitBlock() && !suc.isCatchBlock()) {
|
||||
emptyNodes.add(sucId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
adjList.put(key1, list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the given nodes of the supergraph and fills the list finalConditions
|
||||
* @param sgNodes
|
||||
* @param adjList
|
||||
* @param currentId
|
||||
* @param visited
|
||||
* @param mainEndId
|
||||
* @param currentConditions
|
||||
* @param currentConditionsEndId
|
||||
* @param finalConditions
|
||||
* @param loops
|
||||
* @return
|
||||
*/
|
||||
private static boolean addConditionsToGraph( // boolean return is used in recursion to signalize the existence of an else block
|
||||
HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes,
|
||||
HashMap<Integer, ArrayList<Integer>> adjList,
|
||||
Integer currentId,
|
||||
ArrayList<Integer> visited,
|
||||
Integer mainEndId,
|
||||
ArrayList<Integer> currentConditions,
|
||||
HashMap<Integer, Integer> currentConditionsEndId,
|
||||
HashMap<Integer, ArrayList<Integer>> finalConditions,
|
||||
HashMap<Integer, Integer> loops) {
|
||||
|
||||
if(!visited.contains(currentId)) {
|
||||
visited.add(currentId);
|
||||
}
|
||||
|
||||
if(currentId == mainEndId) {
|
||||
finalConditions.put(mainEndId, new ArrayList<Integer>());
|
||||
return false;
|
||||
}
|
||||
SSAInstruction currentInstruction = sgNodes.get(currentId).getLastInstruction();
|
||||
ArrayList<Integer> children = adjList.get(currentId);
|
||||
|
||||
Integer ifStart = 0;
|
||||
Integer ifEnd = 0;
|
||||
|
||||
if(!currentConditions.isEmpty()) { // inside an if-block
|
||||
|
||||
ifStart = currentConditions.get(currentConditions.size()-1); // last condition is the most inner condition
|
||||
ifEnd = currentConditionsEndId.get(ifStart);
|
||||
|
||||
if(currentId > Math.abs(ifEnd) && sgNodes.get(currentId).isCatchBlock()) { // most inner if block has else AND current node is join
|
||||
return false;
|
||||
}
|
||||
|
||||
if(currentId > Math.abs(ifEnd) && Math.abs(ifEnd) != mainEndId) { // most inner if block has else AND current node is join
|
||||
currentConditionsEndId.put(ifStart,currentId);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(currentId.intValue() == ifEnd.intValue()) { // end of single if block
|
||||
return false;
|
||||
}
|
||||
|
||||
if(currentId == (-ifEnd)) { // end of else block
|
||||
ArrayList<Integer> tmpCond = new ArrayList<Integer>(currentConditions);
|
||||
HashMap<Integer, Integer> tmpCondEnd = new HashMap<Integer, Integer>(currentConditionsEndId);
|
||||
int lastId = currentConditions.size();
|
||||
while(lastId > 0 && currentId == -tmpCondEnd.get(tmpCond.get(--lastId))) { // delete all conditions, which end at this node
|
||||
Integer del = currentConditions.get(lastId);
|
||||
currentConditions.remove(del);
|
||||
currentConditionsEndId.remove(del);
|
||||
}
|
||||
}
|
||||
} // END IF inside an if-block
|
||||
if(currentInstruction instanceof SSAConditionalBranchInstruction) {
|
||||
|
||||
Integer childTrue = Math.min(children.get(0), children.get(1)); // WALA always takes the true branch first
|
||||
Integer childFalse = Math.max(children.get(0), children.get(1));
|
||||
|
||||
ArrayList<Integer> conditions = new ArrayList<Integer>();
|
||||
for(int i =0; i<currentConditions.size(); i++) {
|
||||
conditions.add(currentConditions.get(i));
|
||||
}
|
||||
finalConditions.put(currentId, conditions);
|
||||
|
||||
currentConditions.add(currentId);
|
||||
boolean isLastIfBlock = childTrue.intValue() == mainEndId.intValue(); // => its an if block without else and without any instructions after it
|
||||
if(isLastIfBlock) {
|
||||
childTrue = Math.max(children.get(0), children.get(1));
|
||||
currentConditionsEndId.put(currentId, mainEndId);
|
||||
} else {
|
||||
currentConditionsEndId.put(currentId, childFalse);
|
||||
}
|
||||
|
||||
boolean isRealIfElse = addConditionsToGraph(sgNodes, adjList, childTrue, visited, mainEndId, currentConditions, currentConditionsEndId, finalConditions, loops);
|
||||
|
||||
currentConditions.remove(currentId);
|
||||
Integer newEnd = currentConditionsEndId.remove(currentId);
|
||||
|
||||
if(isRealIfElse) {
|
||||
currentConditions.add(-currentId);
|
||||
currentConditionsEndId.put(-currentId, -newEnd); // last visited is the reached join from if-block
|
||||
}
|
||||
if(!isLastIfBlock) {
|
||||
return addConditionsToGraph(sgNodes, adjList, childFalse, visited, mainEndId, currentConditions, currentConditionsEndId, finalConditions, loops);
|
||||
}
|
||||
return isRealIfElse;
|
||||
} // END IF conditional branch instruction
|
||||
else if(currentInstruction instanceof SSAGotoInstruction) {
|
||||
int child = children.get(0); // goto always points to exactly one child node
|
||||
|
||||
if(currentId == Math.abs(ifEnd)-1) { // last node of if block
|
||||
ArrayList<Integer> conditions = new ArrayList<Integer>();
|
||||
for(int i =0; i<currentConditions.size(); i++) {
|
||||
conditions.add(currentConditions.get(i));
|
||||
}
|
||||
finalConditions.put(currentId, conditions);
|
||||
if(!(Math.abs(ifEnd) == child)) {
|
||||
if(child <= Math.abs(ifStart)) { // is loop
|
||||
loops.put(ifStart, currentId.intValue());
|
||||
return false;
|
||||
}
|
||||
currentConditionsEndId.put(ifStart, child);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // END IF goto instruction
|
||||
else {
|
||||
|
||||
ArrayList<Integer> conditions = new ArrayList<Integer>();
|
||||
for(int i =0; i<currentConditions.size(); i++) {
|
||||
conditions.add(currentConditions.get(i));
|
||||
}
|
||||
finalConditions.put(currentId, conditions);
|
||||
}
|
||||
if (null == currentInstruction) return true;
|
||||
System.out.println(""+currentInstruction);
|
||||
boolean isRealIfElse = false;
|
||||
for(int i=0; i<children.size(); i++) {
|
||||
int child = children.get(i);
|
||||
isRealIfElse = isRealIfElse | addConditionsToGraph(sgNodes, adjList, child, visited, mainEndId, currentConditions, currentConditionsEndId, finalConditions, loops);
|
||||
}
|
||||
return isRealIfElse;
|
||||
}
|
||||
|
||||
private static void generateDotFile(
|
||||
HashMap<Integer, BasicBlockInContext<IExplodedBasicBlock>> sgNodes,
|
||||
HashMap<Integer, ArrayList<Integer>> adjList, String entryClass,
|
||||
String filePath, HashMap<Integer,ArrayList<Integer>> finalConditions) {
|
||||
FileWriter fstream;
|
||||
try {
|
||||
log.debug("start generating dot file");
|
||||
String path = AnalysisUtil.getPropertyString(AnalysisUtil.CONFIG_DOT_PATH) + File.separator;
|
||||
path += "java" + File.separator;
|
||||
|
||||
File sgDir = new File(path + entryClass);
|
||||
sgDir.mkdirs();
|
||||
File sgFile = new File(path + entryClass + File.separator + filePath);
|
||||
fstream = new FileWriter(sgFile);
|
||||
BufferedWriter out = new BufferedWriter(fstream);
|
||||
|
||||
out.write("digraph SuperGraph {");
|
||||
out.newLine();
|
||||
out.write("node [shape=record];");
|
||||
out.newLine();
|
||||
|
||||
// add relevant nodes to dot
|
||||
log.debug("add nodes to dot file");
|
||||
for (Integer key : sgNodes.keySet()) {
|
||||
BasicBlockInContext<IExplodedBasicBlock> val = sgNodes.get(key);
|
||||
Iterator<SSAInstruction> insIt = val.iterator();
|
||||
|
||||
IExplodedBasicBlock del = val.getDelegate();
|
||||
|
||||
|
||||
int key2 = del.getGraphNodeId(); //cfg.getNumber(val);
|
||||
|
||||
// print the labels and define the id (key)
|
||||
out.write(key + " [");
|
||||
out.write("label = \" <f0>" + key + "-" + key2 + "| <f1>" + AnalysisUtil.sanitize(val.getMethod().getSignature()));
|
||||
|
||||
IR ir = val.getNode().getIR();
|
||||
SymbolTable symTab = ir.getSymbolTable();
|
||||
|
||||
int j = 2;
|
||||
|
||||
// print the instruction field of the label
|
||||
while (insIt.hasNext()) {
|
||||
// insCount++;
|
||||
SSAInstruction ins = insIt.next();
|
||||
if(ins instanceof SSAConditionalBranchInstruction) {
|
||||
ins = (SSAConditionalBranchInstruction) ins;
|
||||
SSAInstruction cmp = val.getNode().getDU().getDef(ins.getUse(0));
|
||||
if(cmp instanceof SSABinaryOpInstruction) {
|
||||
SSABinaryOpInstruction bCmp = (SSABinaryOpInstruction) cmp;
|
||||
out.write(" | <f" + j++ + "> " + bCmp.toString(symTab));
|
||||
}
|
||||
} else if(ins instanceof SSAInvokeInstruction) {
|
||||
//TODO
|
||||
}
|
||||
out.write(" | <f" + j++ + "> " + AnalysisUtil.sanitize(ins.toString(symTab)));
|
||||
}
|
||||
if(finalConditions.containsKey(key)) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for(int condition : finalConditions.get(key)) {
|
||||
sb.append(", " + condition);
|
||||
}
|
||||
sb.append(" ");
|
||||
out.write(" | <f" + j++ + "> " + sb.substring(2));
|
||||
}
|
||||
if(val.isEntryBlock()) {
|
||||
out.write(" | <f" + j++ + "> [ENTRY]");
|
||||
} else if(val.isExitBlock()) {
|
||||
out.write(" | <f" + j++ + "> [EXIT]");
|
||||
} else if(val.isCatchBlock()) {
|
||||
out.write(" | <f" + j++ + "> [CATCH]");
|
||||
}
|
||||
out.write("\"];");
|
||||
out.newLine();
|
||||
}
|
||||
|
||||
// add relevant edges to dot
|
||||
log.debug("add edges to dot file");
|
||||
for (Integer src : adjList.keySet()) {
|
||||
for(int dest : adjList.get(src)) {
|
||||
out.write(src + "->" + dest + ";");
|
||||
out.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
// write dot file to file system
|
||||
out.write("}");
|
||||
out.close();
|
||||
log.info("dot file generated (" + sgFile.getAbsolutePath() + ")");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue