MethodAnnotation invokedMethod = null;
XMethod invokedXMethod = null;
int parameterNumber = -1;
if (derefLocationSet.size() == 1) {
Location loc = derefLocationSet.iterator().next();
PointerUsageRequiringNonNullValue pu = null;
try {
UsagesRequiringNonNullValues usages = classContext.getUsagesRequiringNonNullValues(method);
pu = usages.get(loc, refValue, vnaDataflow);
} catch (DataflowAnalysisException e) {
AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
} catch (CFGBuilderException e) {
AnalysisContext.logError("Error getting UsagesRequiringNonNullValues for " + method, e);
}
if (pu == null) {
assert true; // nothing to do
} else if (deref.isReadlineValue()) {
bugType = "NP_DEREFERENCE_OF_READLINE_VALUE";
priority = NORMAL_PRIORITY;
} else if (deref.isMethodReturnValue() && !deref.isReadlineValue()) {
bugType = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE";
priority = NORMAL_PRIORITY;
} else if (pu.isReturnFromNonNullMethod()) {
bugType = "NP_NONNULL_RETURN_VIOLATION";
String methodName = method.getName();
String methodSig = method.getSignature();
if (methodName.equals("clone") && methodSig.equals("()Ljava/lang/Object;")) {
bugType = "NP_CLONE_COULD_RETURN_NULL";
priority = NORMAL_PRIORITY;
} else if (methodName.equals("toString") && methodSig.equals("()Ljava/lang/String;")) {
bugType = "NP_TOSTRING_COULD_RETURN_NULL";
priority = NORMAL_PRIORITY;
}
} else {
XField f = pu.getNonNullField();
if (f != null) {
storedField = FieldAnnotation.fromXField(f);
bugType = "NP_STORE_INTO_NONNULL_FIELD";
} else {
XMethodParameter mp = pu.getNonNullParameter();
if (mp != null) {
invokedXMethod = mp.getMethod();
for (Location derefLoc : derefLocationSet) {
if (safeCallToPrimateParseMethod(invokedXMethod, derefLoc)) {
return;
}
}
invokedMethod = MethodAnnotation.fromXMethod(mp.getMethod());
if (mp.getParameterNumber() == 0
&& TypeQualifierNullnessAnnotationDatabase.assertsFirstParameterIsNonnull(invokedXMethod)) {
return;
}
parameterNumber = mp.getParameterNumber();
bugType = "NP_NULL_PARAM_DEREF";
}
}
}
}
boolean hasManyNullTests = true;
for (SourceLineAnnotation sourceLineAnnotation : knownNullLocations) {
if (!hasManyPreceedingNullTests(sourceLineAnnotation.getStartBytecode())) {
hasManyNullTests = false;
}
}
if (hasManyNullTests) {
if (bugType.equals("NP_NULL_ON_SOME_PATH") || bugType.equals("NP_GUARANTEED_DEREF")) {
bugType = "NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE";
} else {
priority++;
}
}
BugInstance bugInstance = new BugInstance(this, bugType, priority).addClassAndMethod(classContext.getJavaClass(), method);
if (invokedMethod != null) {
assert invokedXMethod != null;
XMethod i = invokedXMethod.resolveAccessMethodForMethod();
if (i != invokedXMethod) {
bugInstance.addMethod(i).describe(MethodAnnotation.METHOD_CALLED);
} else {
bugInstance.addMethod(invokedMethod).describe(MethodAnnotation.METHOD_CALLED)
.addParameterAnnotation(parameterNumber, "INT_MAYBE_NULL_ARG");
}
}
if (storedField != null) {
bugInstance.addField(storedField).describe("FIELD_STORED");
}
bugInstance.addOptionalAnnotation(variableAnnotation);
if (variableAnnotation instanceof FieldAnnotation) {
bugInstance.describe("FIELD_CONTAINS_VALUE");
}
addPropertiesForDereferenceLocations(propertySet, derefLocationSet, false);
if (deref.isAlwaysOnExceptionPath()) {
propertySet.addProperty(NullDerefProperty.ALWAYS_ON_EXCEPTION_PATH);
}
if (!assignedNullLocationSet.isEmpty() && distance > 100) {
propertySet.addProperty(NullDerefProperty.LONG_RANGE_NULL_SOURCE);
}
propertySet.decorateBugInstance(bugInstance);
if (bugType.equals("NP_DEREFERENCE_OF_READLINE_VALUE")) {
int source = -9999;
if (knownNullLocations.size() == 1) {
source = knownNullLocations.iterator().next().getEndBytecode();
}
for (Location loc : derefLocationSet) {
int pos = loc.getHandle().getPosition();
if (pos != source + 3) {
// another detector
bugAccumulator.accumulateBug(bugInstance,
SourceLineAnnotation.fromVisitedInstruction(classContext, method, loc));
}
}
} else {
for (Location loc : derefLocationSet) {
bugInstance.addSourceLine(classContext, method, loc).describe(getDescription(loc, refValue));
}
if (sourceLocations == doomedLocations && assignedNullLocationSet.size() == 1) {
Location assignedNull = assignedNullLocationSet.iterator().next();
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, method,
assignedNull);
if (sourceLineAnnotation != null) {
int startLine = sourceLineAnnotation.getStartLine();
if (startLine > 0 && !knownNull.get(startLine)) {