/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.keshmesh.walaconfig;
import com.ibm.wala.analysis.reflection.JavaTypeContext;
import com.ibm.wala.analysis.typeInference.PointType;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextKey;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.util.intset.EmptyIntSet;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import edu.illinois.keshmesh.detector.util.AnalysisUtils;
/**
*
* @author Mohsen Vakilian
* @author Stas Negara
*
*/
public class KObjectSensitiveContextSelector implements ContextSelector {
private final int objectSensitivityLevel;
public KObjectSensitiveContextSelector(int objectSensitivityLevel) {
this.objectSensitivityLevel = objectSensitivityLevel;
}
public static final ContextKey RECEIVER_STRING = new ContextKey() {
@Override
public String toString() {
return "RECEIVER_STRING_KEY";
}
};
@Override
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
if (actualParameters == null || actualParameters.length == 0 || actualParameters[0] == null) {
// Provide a distinguishing context even when the receiver is null (e.g. in case of an invocation of a static method)
return caller.getContext();
}
InstanceKey receiver = actualParameters[0];
if (AnalysisUtils.isObjectGetClass(callee)) {
return createReceiverContext(receiver, caller.getContext());
} else if (AnalysisUtils.isLibraryClass(callee.getDeclaringClass()) || AnalysisUtils.isJDKClass(callee.getDeclaringClass())) {
return createTypeContext(receiver);
} else if (objectSensitivityLevel == 0) {
return createTypeContext(receiver);
} else {
return createReceiverContext(receiver, caller.getContext());
}
}
private Context createReceiverContext(InstanceKey receiver, Context callerContext) {
ReceiverString receiverString;
if (!(callerContext instanceof ReceiverStringContext)) {
receiverString = new ReceiverString(receiver);
} else {
ReceiverString callerReceiverString = (ReceiverString) ((ReceiverStringContext) callerContext).get(RECEIVER_STRING);
receiverString = new ReceiverString(receiver, objectSensitivityLevel, callerReceiverString);
}
return new ReceiverStringContext(receiverString);
}
private Context createTypeContext(InstanceKey receiver) {
return new JavaTypeContext(new PointType(receiver.getConcreteType()));
}
private static final IntSet receiver = IntSetUtil.make(new int[] { 0 });
@Override
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
if (site.isDispatch() || site.getDeclaredTarget().getNumberOfParameters() > 0) {
return receiver;
} else {
return EmptyIntSet.instance;
}
}
}