Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Achim D. Brucker 2017-01-07 00:13:50 +00:00
commit da57da4762
23 changed files with 204 additions and 80 deletions

View File

@ -99,7 +99,7 @@ public class PropertyNameContextSelector implements ContextSelector {
@Override
public ContextItem get(ContextKey key) {
if (INSTANCE_KEY_KEY.equals(key)) {
return ((SingleInstanceFilter)super.get(ContextKey.PARAMETERS[index])).getInstance();
return ContextItem.Value.make(((SingleInstanceFilter)super.get(ContextKey.PARAMETERS[index])).getInstance());
} else {
final ContextItem contextItem = super.get(key);
return (contextItem instanceof SingleInstanceFilter) ? null : contextItem;

View File

@ -338,6 +338,7 @@ public abstract class AstMethod implements IMethod {
return debugInfo.getCodeBodyPosition();
}
@Override
public Position getSourcePosition(int instructionIndex) {
return debugInfo.getInstructionPosition(instructionIndex);
}

View File

@ -157,9 +157,10 @@ public interface CAstNode {
public static final int TYPE_LITERAL_EXPR = 127;
public static final int IS_DEFINED_EXPR = 128;
public static final int MACRO_VAR = 129;
public static final int NARY_EXPR = 130;
// new nodes with an explicit enclosing argument, e.g. "outer.new Inner()". They are mostly treated the same, except in JavaCAst2IRTranslator.doNewObject
public static final int NEW_ENCLOSING = 130;
public static final int NEW_ENCLOSING = 131;
// explicit lexical scopes
public static final int LOCAL_SCOPE = 200;

View File

@ -71,6 +71,7 @@ public class CAstOperator implements CAstNode {
public final static CAstOperator OP_LSH = new CAstOperator("<<");
public final static CAstOperator OP_MOD = new CAstOperator("%");
public final static CAstOperator OP_MUL = new CAstOperator("*");
public final static CAstOperator OP_POW = new CAstOperator("^^^");
public final static CAstOperator OP_RSH = new CAstOperator(">>");
public final static CAstOperator OP_URSH = new CAstOperator(">>>");
public final static CAstOperator OP_SUB = new CAstOperator("-");

View File

@ -91,6 +91,7 @@ public class CAstPrinter {
case CAstNode.LIST_EXPR: return "LIST_EXPR";
case CAstNode.EMPTY_LIST_EXPR: return "EMPTY_LIST_EXPR";
case CAstNode.IS_DEFINED_EXPR: return "IS_DEFINED_EXPR";
case CAstNode.NARY_EXPR: return "NARY_EXPR";
// explicit lexical scopes
case CAstNode.LOCAL_SCOPE: return "SCOPE";

View File

@ -13,12 +13,14 @@ package com.ibm.wala.core.tests.basic;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
import com.ibm.wala.core.tests.util.WalaTestCase;
import com.ibm.wala.util.graph.INodeWithNumberedEdges;
import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.graph.impl.DelegatingNumberedGraph;
@ -29,7 +31,7 @@ import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
public class FloydWarshallTest {
public class FloydWarshallTest extends WalaTestCase {
public static class Node implements INodeWithNumberedEdges {
private final int number;
@ -87,11 +89,16 @@ public class FloydWarshallTest {
@Override
public String toString() {
return "["+number+"]";
return "<"+number+">";
}
@Override
public boolean equals(Object o) {
return this == o;
}
}
private static NumberedGraph<Node> makeGraph() {
public static NumberedGraph<Node> makeGraph() {
NumberedGraph<Node> G = new DelegatingNumberedGraph<Node>();
for(int i = 0; i <= 8; i++) {
@ -142,19 +149,29 @@ public class FloydWarshallTest {
@Test
public void TestShortestPath() {
GetPath<Node> result = FloydWarshall.allPairsShortestPath(G);
Assert.assertEquals(result.getPath(G.getNode(1), G.getNode(3)), Collections.singletonList(G.getNode(2)));
Assert.assertEquals(result.getPath(G.getNode(5), G.getNode(8)), Collections.singletonList(G.getNode(7)));
Assert.assertEquals(result.getPath(G.getNode(1), G.getNode(7)), Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(5)));
Assert.assertEquals(result.getPath(G.getNode(1), G.getNode(6)), Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(4)));
assertEquals(result.getPath(G.getNode(1), G.getNode(3)), Collections.singletonList(G.getNode(2)));
assertEquals(result.getPath(G.getNode(5), G.getNode(8)), Collections.singletonList(G.getNode(7)));
assertEquals(result.getPath(G.getNode(1), G.getNode(7)), Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(5)));
assertEquals(result.getPath(G.getNode(1), G.getNode(6)), Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(4)));
}
@Test
public void TestShortestPaths() {
GetPaths<Node> result = FloydWarshall.allPairsShortestPaths(G);
Set<List<Node>> expectedPaths = expectedPaths(G);
Set<List<Node>> resultPaths = result.getPaths(G.getNode(1), G.getNode(8));
assertEquals(resultPaths.size(), expectedPaths.size());
for(List<Node> rp : resultPaths) {
Assert.assertTrue(expectedPaths.contains(rp));
}
}
public static Set<List<Node>> expectedPaths(NumberedGraph<Node> G) {
Set<List<Node>> paths = new HashSet<List<Node>>();
paths.add(Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(4),G.getNode(6)));
paths.add(Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(5),G.getNode(7)));
Assert.assertEquals(result.getPaths(G.getNode(1), G.getNode(8)), paths);
paths.add(new LinkedList<Node>(Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(4),G.getNode(6))));
paths.add(new LinkedList<Node>(Arrays.asList(G.getNode(2),G.getNode(3),G.getNode(5),G.getNode(7))));
return paths;
}
}

View File

@ -106,7 +106,7 @@ public class GraphDataflowTest extends WalaTestCase {
/**
* @return a graph with the expected structure
*/
private static Graph<String> buildGraph() {
public static Graph<String> buildGraph() {
Graph<String> G = SlowSparseNumberedGraph.make();
for (int i = 0; i < nodeNames.length(); i++) {
String n = nodeNames.substring(i, i + 1);
@ -126,10 +126,10 @@ public class GraphDataflowTest extends WalaTestCase {
* Solve the dataflow system and return the result as a string
* @throws CancelException
*/
private static String solveNodeOnly(Graph<String> G) throws CancelException {
public static String solveNodeOnly(Graph<String> G) throws CancelException {
final OrdinalSetMapping<String> values = new MutableMapping<String>(nodes);
ITransferFunctionProvider<String, BitVectorVariable> functions = new ITransferFunctionProvider<String, BitVectorVariable>() {
@Override
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(String node) {
return new BitVectorUnionConstant(values.getMappedIndex(node));
@ -164,7 +164,7 @@ public class GraphDataflowTest extends WalaTestCase {
return result2String(s);
}
private static String solveNodeEdge(Graph<String> G) throws CancelException {
public static String solveNodeEdge(Graph<String> G) throws CancelException {
final OrdinalSetMapping<String> values = new MutableMapping<String>(nodes);
ITransferFunctionProvider<String, BitVectorVariable> functions = new ITransferFunctionProvider<String, BitVectorVariable>() {

View File

@ -13,6 +13,7 @@ package com.ibm.wala.core.tests.util;
import java.io.IOException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.JUnitCore;
@ -83,4 +84,7 @@ public abstract class WalaTestCase {
JUnitCore.runClasses(testClass);
}
protected <T> void assertEquals(T x, T y) {
Assert.assertEquals("Expecting " + x + ", but got " + y, x, y);
}
}

View File

@ -63,6 +63,7 @@ public class ScopeFileCallGraph {
String scopeFile = p.getProperty("scopeFile");
String entryClass = p.getProperty("entryClass");
String mainClass = p.getProperty("mainClass");
String dump = p.getProperty("dump");
if (mainClass != null && entryClass != null) {
throw new IllegalArgumentException("only specify one of mainClass or entryClass");
}
@ -87,6 +88,9 @@ public class ScopeFileCallGraph {
CallGraph cg = builder.makeCallGraph(options, null);
long end = System.currentTimeMillis();
System.out.println("done");
if (dump != null) {
System.err.println(cg);
}
System.out.println("took " + (end-start) + "ms");
System.out.println(CallGraphStats.getStats(cg));
}

View File

@ -439,7 +439,7 @@ public class PropagationGraph implements IFixedPointSystem<PointsToSetVariable>
public void reorder() {
VariableGraphView graph = new VariableGraphView();
Iterator<PointsToSetVariable> order = Topological.makeTopologicalIter(graph);
Iterator<PointsToSetVariable> order = Topological.makeTopologicalIter(graph).iterator();
int number = 0;
while (order.hasNext()) {

View File

@ -556,11 +556,15 @@ public class SDG<T extends InstanceKey> extends AbstractNumberedGraph<Statement>
case PARAM_CALLER: {
ParamCaller pac = (ParamCaller) N;
SSAAbstractInvokeInstruction call = pac.getInstruction();
int numParamsPassed = call.getNumberOfUses();
Collection<Statement> result = HashSetFactory.make(5);
if (!dOptions.equals(DataDependenceOptions.NONE)) {
// data dependence successors
for (CGNode t : cg.getPossibleTargets(N.getNode(), call.getCallSite())) {
for (int i = 0; i < t.getMethod().getNumberOfParameters(); i++) {
// in some languages (*cough* JavaScript *cough*) you can pass
// fewer parameters than the number of formals. So, only loop
// over the parameters actually being passed here
for (int i = 0; i < t.getMethod().getNumberOfParameters() && i < numParamsPassed; i++) {
if (dOptions.isTerminateAtCast() && call.isDispatch() && pac.getValueNumber() == call.getReceiver()) {
// a virtual dispatch is just like a cast.
continue;

View File

@ -64,6 +64,7 @@
<target name="copyDxJar" depends="dxJarPresent" unless="dx.jar.present">
<fail unless="env.ANDROID_HOME" message="ANDROID_HOME is not set! Set the environment variable or copy dx.jar manually." />
<mkdir dir="${basedir}/lib/"/>
<copy tofile="${basedir}/lib/dx.jar">
<first>
<fileset dir="${env.ANDROID_HOME}" includes="build-tools/*/lib/dx.jar"/>

View File

@ -51,14 +51,7 @@
<target name="fetchDexlib" depends="DexlibPresent" unless="dexlib.present">
<mkdir dir="${plugin.destination}/lib"/>
<delete dir="${temp.folder}"/>
<mkdir dir="${temp.folder}"/>
<get src="https://apktool2.googlecode.com/archive/c1659e62c414c96882c49afa72032b504c921b5a.zip" dest="${temp.folder}/dexlib.zip"/>
<unzip src="${temp.folder}/dexlib.zip" dest="${temp.folder}"/>
<copy file="${temp.folder}/apktool2-c1659e62c414/m2-releases/brut/apktool/smali/dexlib/1.3.4-ibot7/dexlib-1.3.4-ibot7.jar" tofile="${plugin.destination}/lib/dexlib-1.3.4.jar"/>
<delete dir="${temp.folder}"/>
<get src="https://github.com/SCanDroid/SCanDroid/raw/master/lib/dexlib-1.3.4-dev.jar" dest="${plugin.destination}/lib/dexlib-1.3.4.jar"/>
</target>
<target name="GuavaPresent" depends="init">

View File

@ -208,7 +208,7 @@ public class DefaultFixedPointSystem<T extends IVariable<?>> implements IFixedPo
checkGraph();
}
Iterator<INodeWithNumber> order = Topological.makeTopologicalIter(graph);
Iterator<INodeWithNumber> order = Topological.makeTopologicalIter(graph).iterator();
int number = 0;
while (order.hasNext()) {
Object elt = order.next();

View File

@ -47,21 +47,21 @@ public class Pair<T,U> implements Serializable {
public Iterator<Object> iterator() {
return new Iterator<Object>() {
byte next = 1;
byte nextFlag = 1;
@Override
public boolean hasNext() {
return next > 0;
return nextFlag > 0;
}
@Override
public Object next() {
switch (next) {
switch (nextFlag) {
case 1 :
next++;
nextFlag++;
return fst;
case 2 :
next = 0;
nextFlag = 0;
return snd;
default :
throw new NoSuchElementException();

View File

@ -69,31 +69,31 @@ public class DelegatingNumberedNodeManager<T extends INodeWithNumber> implements
public Iterator<T> iterator() {
final INodeWithNumber[] arr = nodes;
return new Iterator<T>() {
int next = -1;
int nextCounter = -1;
{
advance();
}
void advance() {
for (int i = next + 1; i < arr.length; i++) {
for (int i = nextCounter + 1; i < arr.length; i++) {
if (arr[i] != null) {
next = i;
nextCounter = i;
return;
}
}
next = -1;
nextCounter = -1;
}
@Override
public boolean hasNext() {
return next != -1;
return nextCounter != -1;
}
@Override
@SuppressWarnings("unchecked")
public T next() {
if (hasNext()) {
int r = next;
int r = nextCounter;
advance();
return (T) arr[r];
} else {

View File

@ -10,6 +10,7 @@
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;
@ -24,7 +25,7 @@ import com.ibm.wala.util.graph.NumberedGraph;
* increasing discover time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be
* changed by overriding the getConnected method.
*/
public abstract class DFSDiscoverTimeIterator<T> extends Stack<T> implements Iterator<T> {
public abstract class DFSDiscoverTimeIterator<T> extends ArrayList<T> implements Iterator<T> {
/**
* an enumeration of all nodes to search from
@ -136,4 +137,23 @@ public abstract class DFSDiscoverTimeIterator<T> extends Stack<T> implements Ite
protected void visitEdge(T from, T to) {
// do nothing. subclasses will override.
}
private boolean empty() {
return size() == 0;
}
private void push(T elt) {
add(elt);
}
private T peek() {
return get(size()-1);
}
private T pop() {
T e = get(size()-1);
remove(size()-1);
return e;
}
}

View File

@ -10,9 +10,9 @@
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.debug.UnimplementedError;
@ -23,7 +23,7 @@ import com.ibm.wala.util.graph.Graph;
* finishing time. This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by
* overriding the getConnected method.
*/
public abstract class DFSFinishTimeIterator<T> extends Stack<T> implements Iterator<T> {
public abstract class DFSFinishTimeIterator<T> extends ArrayList<T> implements Iterator<T> {
/**
* the current next element in finishing time order
@ -53,6 +53,10 @@ public abstract class DFSFinishTimeIterator<T> extends Stack<T> implements Itera
theNextElement = roots.next();
}
private boolean empty() {
return size() == 0;
}
/**
* Return whether there are any more nodes left to enumerate.
*
@ -67,6 +71,20 @@ public abstract class DFSFinishTimeIterator<T> extends Stack<T> implements Itera
abstract void setPendingChildren(T v, Iterator<T> iterator);
private void push(T elt) {
add(elt);
}
private T peek() {
return get(size()-1);
}
private T pop() {
T e = get(size()-1);
remove(size()-1);
return e;
}
/**
* Find the next graph node in finishing time order.
*

View File

@ -28,7 +28,7 @@ import com.ibm.wala.util.graph.Graph;
* This class follows the outNodes of the graph nodes to define the graph, but this behavior can be changed by overriding the
* getConnected method.
*/
public class DFSPathFinder<T> extends Stack<T> {
public class DFSPathFinder<T> extends ArrayList<T> {
public static final long serialVersionUID = 9939900773328288L;
/**
@ -208,4 +208,23 @@ public class DFSPathFinder<T> extends Stack<T> {
protected Iterator<? extends T> getConnected(T n) {
return G.getSuccNodes(n);
}
private boolean empty() {
return size() == 0;
}
private void push(T elt) {
add(elt);
}
private T peek() {
return get(size()-1);
}
private T pop() {
T e = get(size()-1);
remove(size()-1);
return e;
}
}

View File

@ -10,6 +10,7 @@
*******************************************************************************/
package com.ibm.wala.util.graph.traverse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
@ -100,7 +101,7 @@ public class FloydWarshall<T> {
public static <T> GetPath<T> allPairsShortestPath(final NumberedGraph<T> G) {
return new FloydWarshall<T>(G) {
int[][] next = new int[G.getNumberOfNodes()][G.getNumberOfNodes()];
@Override
protected void pathCallback(int i, int j, int k) {
next[i][j] = k;
@ -115,6 +116,22 @@ public class FloydWarshall<T> {
final int[][] paths = allPairsShortestPaths();
return new GetPath<T>() {
@Override
public String toString() {
String s = "";
for(int i = 0; i <= G.getMaxNumber(); i++) {
for(int j = 0; j <= G.getMaxNumber(); j++) {
try {
s += getPath(G.getNode(i), G.getNode(j));
} catch (UnsupportedOperationException e) {
}
}
}
return s;
}
@Override
public List<T> getPath(T from, T to) {
int fn = G.getNumber(from);
@ -154,7 +171,23 @@ public class FloydWarshall<T> {
private GetPaths<T> doit() {
final int[][] paths = allPairsShortestPaths();
return new GetPaths<T>() {
@Override
@Override
public String toString() {
List<Set<List<T>>> x = new ArrayList<Set<List<T>>>();
for(int i = 0; i <= G.getMaxNumber(); i++) {
for(int j = 0; j <= G.getMaxNumber(); j++) {
try {
x.add(getPaths(G.getNode(i), G.getNode(j)));
} catch (UnsupportedOperationException e) {
}
}
}
return x.toString();
}
@Override
public Set<List<T>> getPaths(final T from, final T to) {
int fn = G.getNumber(from);
int tn = G.getNumber(to);

View File

@ -26,29 +26,33 @@ public class Topological {
*
* @throws IllegalArgumentException if graph == null
*/
public static <T> Iterator<T> makeTopologicalIter(Graph<T> graph) throws IllegalArgumentException {
// the following code ensures a topological order over SCCs.
// note that the first two lines of the following give a topological
// order for dags, but that can get screwed up by cycles. so
// instead, we use Tarjan's SCC algorithm, which happens to
// visit nodes in an order consistent with a top. order over SCCs.
public static <T> Iterable<T> makeTopologicalIter(final Graph<T> graph) throws IllegalArgumentException {
if (graph == null) {
throw new IllegalArgumentException("graph == null");
}
// finish time is post-order
// note that if you pay attention only to the first representative
// of each SCC discovered, we have a top. order of these SCC
// representatives
Iterator<T> finishTime = DFS.iterateFinishTime(graph);
// reverse postorder is usual topological sort.
Iterator<T> rev = ReverseIterator.reverse(finishTime);
// the following statement helps out the GC; note that finishTime holds
// on to a large array
finishTime = null;
Graph<T> G_T = GraphInverter.invert(graph);
Iterator<T> order = DFS.iterateFinishTime(G_T, rev);
return order;
}
}
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
// the following code ensures a topological order over SCCs.
// note that the first two lines of the following give a topological
// order for dags, but that can get screwed up by cycles. so
// instead, we use Tarjan's SCC algorithm, which happens to
// visit nodes in an order consistent with a top. order over SCCs.
// finish time is post-order
// note that if you pay attention only to the first representative
// of each SCC discovered, we have a top. order of these SCC
// representatives
Iterator<T> finishTime = DFS.iterateFinishTime(graph);
// reverse postorder is usual topological sort.
Iterator<T> rev = ReverseIterator.reverse(finishTime);
// the following statement helps out the GC; note that finishTime holds
// on to a large array
finishTime = null;
Graph<T> G_T = GraphInverter.invert(graph);
return DFS.iterateFinishTime(G_T, rev);
};
};
}
}

View File

@ -17,10 +17,9 @@ import java.util.SortedSet;
import java.util.TreeSet;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.graph.INodeWithNumber;
import com.ibm.wala.util.graph.NumberedGraph;
public class WelshPowell<T extends INodeWithNumber> {
public class WelshPowell<T> {
public static class ColoredVertices<T> {
private final boolean fullColoring;
@ -59,6 +58,10 @@ public class WelshPowell<T extends INodeWithNumber> {
this.numColors = numColors;
}
@Override
public String toString() {
return colors.toString();
}
}
public static <T> Comparator<T> defaultComparator(final NumberedGraph<T> G) {
@ -101,29 +104,29 @@ public class WelshPowell<T extends INodeWithNumber> {
int colored = 0;
for(T n : vertices) {
int id = n.getGraphNodeId();
int id = G.getNumber(n);
if (colors[id] == -1) {
colors[id] = currentColor;
colored++;
for(T m : vertices) {
if (colors[m.getGraphNodeId()] == -1) {
if (colors[G.getNumber(m)] == -1) {
color_me: {
for(Iterator<T> ps = G.getPredNodes(m); ps.hasNext(); ) {
T p = ps.next();
if (colors[ p.getGraphNodeId() ] == currentColor) {
if (colors[ G.getNumber(p) ] == currentColor) {
break color_me;
}
}
for(Iterator<T> ss = G.getSuccNodes(m); ss.hasNext(); ) {
T s = ss.next();
if (colors[s.getGraphNodeId()] == currentColor) {
if (colors[G.getNumber(s)] == currentColor) {
break color_me;
}
}
colors[m.getGraphNodeId()] = currentColor;
colors[G.getNumber(m)] = currentColor;
colored++;
if (currentColor == maxColors - 1) {

View File

@ -145,11 +145,11 @@ public final class BitSet<T> {
*/
public Iterator<T> iterator() {
return new Iterator<T>() {
private int next = -1;
private int nextCounter = -1;
{
for (int i = 0; i < vector.length(); i++) {
if (vector.get(i)) {
next = i;
nextCounter = i;
break;
}
}
@ -157,17 +157,17 @@ public final class BitSet<T> {
@Override
public boolean hasNext() {
return (next != -1);
return (nextCounter != -1);
}
@Override
public T next() {
T result = map.getMappedObject(next);
int start = next + 1;
next = -1;
T result = map.getMappedObject(nextCounter);
int start = nextCounter + 1;
nextCounter = -1;
for (int i = start; i < vector.length(); i++) {
if (vector.get(i)) {
next = i;
nextCounter = i;
break;
}
}