Initial commit.

This commit is contained in:
Achim D. Brucker 2015-06-14 09:04:57 +02:00
parent 228120c6c9
commit 73d1bd37e6
26 changed files with 2967 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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) {
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 &lt;graphs folder&gt;/<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();
}
}
}