use of soot.jimple.toolkits.annotation.nullcheck.NullnessAnalysis in project soot by Sable.
the class OnFlyCallGraphBuilder method addInvokeCallSite.
/*
* How type based reflection resolution works:
*
* In general, for each call to invoke(), we record the local of the receiver
* argument and the argument array. Whenever a new type is added to the points
* to set of the receiver argument we add that type to the reachingBaseTypes and
* try to resolve the reflective method call (see addType, addBaseType, and
* updatedNode() in OnFlyCallGraph).
*
* For added precision, we also record the second argument to invoke. If it is
* always null, this means the invoke() call resolves only to nullary methods.
*
* When the second argument is a variable that must not be null we can narrow
* down the called method based on the possible sizes of the argument array and
* the types it contains. Whenever a new allocation reaches this variable we
* record the possible size of the array (by looking at the allocation site) and
* the possible types stored in the array (see updatedNode in OnFlyCallGraph in
* the branch wantInvokeArg()). If the size of the array isn't statically known,
* the analysis considers methods of all possible arities. In addition, we track
* the PAG node corresponding to the array contents. If a new type reaches this
* node, we update the possible argument types. (see propagate() in PropWorklist
* and the visitor, and updatedFieldRef in OnFlyCallGraph).
*
* For details on the method resolution process, see resolveInvoke()
*
* Finally, for cases like o.invoke(b, foo, bar, baz); it is very easy to
* statically determine precisely which types are in which argument positions.
* This is computed using the ConstantArrayAnalysis and are resolved using
* resolveStaticTypes().
*/
private void addInvokeCallSite(Stmt s, SootMethod container, InstanceInvokeExpr d) {
Local l = (Local) d.getArg(0);
Value argArray = d.getArg(1);
InvokeCallSite ics;
if (argArray instanceof NullConstant) {
ics = new InvokeCallSite(s, container, d, l);
} else {
if (analysisKey != container) {
ExceptionalUnitGraph graph = new ExceptionalUnitGraph(container.getActiveBody());
nullnessCache = new NullnessAnalysis(graph);
arrayCache = new ConstantArrayAnalysis(graph, container.getActiveBody());
analysisKey = container;
}
Local argLocal = (Local) argArray;
int nullnessCode;
if (nullnessCache.isAlwaysNonNullBefore(s, argLocal)) {
nullnessCode = InvokeCallSite.MUST_NOT_BE_NULL;
} else if (nullnessCache.isAlwaysNullBefore(s, argLocal)) {
nullnessCode = InvokeCallSite.MUST_BE_NULL;
} else {
nullnessCode = InvokeCallSite.MAY_BE_NULL;
}
if (nullnessCode != InvokeCallSite.MUST_BE_NULL && arrayCache.isConstantBefore(s, argLocal)) {
ArrayTypes reachingArgTypes = arrayCache.getArrayTypesBefore(s, argLocal);
if (nullnessCode == InvokeCallSite.MAY_BE_NULL) {
reachingArgTypes.possibleSizes.add(0);
}
ics = new InvokeCallSite(s, container, d, l, reachingArgTypes, nullnessCode);
} else {
ics = new InvokeCallSite(s, container, d, l, argLocal, nullnessCode);
invokeArgsToInvokeSite.put(argLocal, ics);
}
}
baseToInvokeSite.put(l, ics);
}
Aggregations