This commit is contained in:
Julian Dolby 2017-11-11 20:32:14 -05:00
commit 8fc5a35c91
3 changed files with 53 additions and 20 deletions

View File

@ -71,7 +71,8 @@ public class AnalysisOptions {
NO_METHOD_INVOKE("no_method_invoke", Integer.MAX_VALUE, true, false, false),
NO_FLOW_TO_CASTS_NO_METHOD_INVOKE("no_flow_to_casts_no_method_invoke", 0, true, false, false),
ONE_FLOW_TO_CASTS_NO_METHOD_INVOKE("one_flow_to_casts_no_method_invoke", 1, true, false, false),
ONE_FLOW_TO_CASTS_APPLICATION_GET_METHOD("one_flow_to_casts_application_get_method", 1, false, false, true),
ONE_FLOW_TO_CASTS_APPLICATION_GET_METHOD("one_flow_to_casts_application_get_method", 1, false, false, true),
MULTI_FLOW_TO_CASTS_APPLICATION_GET_METHOD("multi_flow_to_casts_application_get_method", 100, false, false, true),
NO_STRING_CONSTANTS("no_string_constants", Integer.MAX_VALUE, false, true, false),
NONE("none", 0, true, true, true);
@ -190,7 +191,12 @@ public class AnalysisOptions {
* {@link ExplicitCallGraph}.
*/
private long maxNumberOfNodes = -1;
/**
* Should call graph construction handle arrays of zero-length differently?
*/
private boolean handleZeroLengthArray = true;
// SJF: I'm not sure these factories and caches belong here.
// TODO: figure out how to clean this up.
@ -418,4 +424,18 @@ public class AnalysisOptions {
public void setHandleStaticInit(boolean handleStaticInit) {
this.handleStaticInit = handleStaticInit;
}
/**
* Should call graph construction handle arrays of zero-length differently?
*/
public boolean getHandleZeroLengthArray() {
return handleZeroLengthArray;
}
/**
* Should call graph construction handle arrays of zero-length differently?
*/
public void setHandleZeroLengthArray(boolean handleZeroLengthArray) {
this.handleZeroLengthArray = handleZeroLengthArray;
}
}

View File

@ -25,15 +25,20 @@ import com.ibm.wala.ssa.SSANewInstruction;
import com.ibm.wala.types.TypeReference;
/**
* A factory which tries by default to create {@link InstanceKey}s which are {@link AllocationSiteInNode}s.
* A factory which tries by default to create {@link InstanceKey}s which are
* {@link AllocationSiteInNode}s.
*
* Notes:
* <ul>
* <li>This class checks to avoid creating recursive contexts when {@link CGNode}s are based on {@link ReceiverInstanceContext}, as
* in object-sensitivity.
* <li>Up till recursion, this class will happily create unlimited object sensitivity, so be careful.
* <li>This class resorts to {@link ClassBasedInstanceKeys} for exceptions from PEIs and class objects.
* <li>This class consults the {@link AnalysisOptions} to determine whether to disambiguate individual constants.
* <li>This class checks to avoid creating recursive contexts when
* {@link CGNode}s are based on {@link ReceiverInstanceContext}, as in
* object-sensitivity.
* <li>Up till recursion, this class will happily create unlimited object
* sensitivity, so be careful.
* <li>This class resorts to {@link ClassBasedInstanceKeys} for exceptions from
* PEIs and class objects.
* <li>This class consults the {@link AnalysisOptions} to determine whether to
* disambiguate individual constants.
* </ul>
*/
public class AllocationSiteInNodeFactory implements InstanceKeyFactory {
@ -51,7 +56,8 @@ public class AllocationSiteInNodeFactory implements InstanceKeyFactory {
private final ClassBasedInstanceKeys classBased;
/**
* @param options Governing call graph construction options
* @param options
* Governing call graph construction options
*/
public AllocationSiteInNodeFactory(AnalysisOptions options, IClassHierarchy cha) {
this.options = options;
@ -67,7 +73,7 @@ public class AllocationSiteInNodeFactory implements InstanceKeyFactory {
}
CGNode nodeToUse = node;
// disallow recursion in contexts.
if (node.getContext() instanceof ReceiverInstanceContext || node.getContext() instanceof CallerContext) {
IMethod m = node.getMethod();
@ -85,11 +91,15 @@ public class AllocationSiteInNodeFactory implements InstanceKeyFactory {
if (ir.getSymbolTable().isIntegerConstant(lengthVN)) {
Integer c = (Integer) ir.getSymbolTable().getConstantValue(lengthVN);
if (c.intValue() == 0) {
return new ZeroLengthArrayInNode(nodeToUse, allocation, type);
if (options.getHandleZeroLengthArray()) {
return new ZeroLengthArrayInNode(nodeToUse, allocation, type);
} else {
return new NormalAllocationInNode(nodeToUse, allocation, type);
}
}
}
}
}
InstanceKey key = new NormalAllocationInNode(nodeToUse, allocation, type);
return key;

View File

@ -53,7 +53,7 @@ public class Runtime {
private PrintWriter output;
private SetOfClasses filter;
private Policy handleCallback;
private String currentSite;
private ThreadLocal<String> currentSite = new ThreadLocal<>();
private ThreadLocal<Stack<String>> callStacks = new ThreadLocal<Stack<String>>() {
@ -120,7 +120,7 @@ public class Runtime {
}
public static void execution(String klass, String method, Object receiver) {
runtime.currentSite = null;
runtime.currentSite.set(null);
if (runtime.filter == null || ! runtime.filter.contains(bashToDescriptor(klass))) {
if (runtime.output != null) {
String caller = runtime.callStacks.get().peek();
@ -164,23 +164,26 @@ public class Runtime {
}
public static void pop() {
if (runtime.currentSite != null) {
if (runtime.currentSite.get() != null) {
synchronized (runtime) {
if (runtime.output != null) {
runtime.output.printf("return from " + runtime.currentSite + "\n");
runtime.output.printf("return from " + runtime.currentSite.get() + "\n");
runtime.output.flush();
}
}
runtime.currentSite = null;
runtime.currentSite.set(null);
}
}
public static void addToCallStack(String klass, String method, Object receiver) {
runtime.currentSite = klass + "\t" + method + "\t" + receiver;
String callerClass = runtime.callStacks.get().isEmpty() ? "BLOB" : runtime.callStacks.get().peek().split("\t")[0];
String callerMethod = runtime.callStacks.get().isEmpty() ? "BLOB" : runtime.callStacks.get().peek().split("\t")[1];
runtime.currentSite.set(callerClass + "\t" + callerMethod + "\t" + klass + "\t" + method + "\t" + receiver);
// runtime.currentSite = klass + "\t" + method + "\t" + receiver;
synchronized (runtime) {
if (runtime.output != null) {
runtime.output.printf("call to " + runtime.currentSite + "\n");
runtime.output.printf("call to " + runtime.currentSite.get() + "\n");
runtime.output.flush();
}
}