}
}
private void analyzeMethod(ClassContext classContext, Method method) {
JavaClass jclass = classContext.getJavaClass();
XMethod xmethod = XFactory.createXMethod(jclass, method);
try {
CFG cfg = classContext.getCFG(method);
ValueNumberDataflow vnaDataflow = classContext.getValueNumberDataflow(method);
UnconditionalValueDerefDataflow dataflow = classContext.getUnconditionalValueDerefDataflow(method);
SignatureParser parser = new SignatureParser(method.getSignature());
int paramLocalOffset = method.isStatic() ? 0 : 1;
// Build BitSet of params that are unconditionally dereferenced
BitSet unconditionalDerefSet = new BitSet();
UnconditionalValueDerefSet entryFact = dataflow.getResultFact(cfg.getEntry());
Iterator<String> paramIterator = parser.parameterSignatureIterator();
int i = 0;
while (paramIterator.hasNext()) {
String paramSig = paramIterator.next();
ValueNumber paramVN = vnaDataflow.getAnalysis().getEntryValue(paramLocalOffset);
handleParameter: if (entryFact.isUnconditionallyDereferenced(paramVN)) {
TypeQualifierAnnotation directTypeQualifierAnnotation = TypeQualifierApplications
.getDirectTypeQualifierAnnotation(xmethod, i, nonnullTypeQualifierValue);
TypeQualifierAnnotation typeQualifierAnnotation = TypeQualifierApplications
.getEffectiveTypeQualifierAnnotation(xmethod, i, nonnullTypeQualifierValue);
boolean implicitNullCheckForEquals = false;
if (directTypeQualifierAnnotation == null && method.getName().equals("equals")
&& method.getSignature().equals("(Ljava/lang/Object;)Z") && !method.isStatic()) {
implicitNullCheckForEquals = true;
Code code = method.getCode();
ConstantPool cp = jclass.getConstantPool();
byte codeBytes[] = code.getCode();
for (CodeException e : code.getExceptionTable()) {
ConstantClass cl = (ConstantClass) cp.getConstant(e.getCatchType());
int endPC = e.getEndPC();
int startPC = e.getStartPC();
int handlerPC = e.getHandlerPC();
if (startPC == 0 && endPC + 1 == handlerPC && handlerPC == codeBytes.length - 3
&& (codeBytes[handlerPC + 1] & 0xff) == Constants.ICONST_0
&& (codeBytes[handlerPC + 2] & 0xff) == Constants.IRETURN
&& FindNullDeref.catchTypesForNull.contains(cl.getBytes(cp))) {
// equals method body contained in try clause
return;
}
}
typeQualifierAnnotation = TypeQualifierAnnotation.getValue(nonnullTypeQualifierValue, When.MAYBE);
}
if (typeQualifierAnnotation != null && typeQualifierAnnotation.when == When.ALWAYS) {
unconditionalDerefSet.set(i);
} else if (isCaught(classContext, method, entryFact, paramVN)) {
// ignore
} else if (typeQualifierAnnotation == null) {
unconditionalDerefSet.set(i);
} else {
int paramLocal = xmethod.isStatic() ? i : i + 1;
int priority = Priorities.NORMAL_PRIORITY;
if (typeQualifierAnnotation.when != When.UNKNOWN) {
priority--;
}
if (xmethod.isStatic() || xmethod.isFinal() || xmethod.isPrivate() || xmethod.getName().equals("<init>")
|| jclass.isFinal()) {
priority--;
}
if (directTypeQualifierAnnotation == null) {
priority++;
}
String bugPattern = implicitNullCheckForEquals ? "NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT"
: "NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE";
reportBug(new BugInstance(this, bugPattern, priority).addClassAndMethod(jclass, method).add(
LocalVariableAnnotation.getParameterLocalVariableAnnotation(method, paramLocal)));
}
}
i++;
if (paramSig.equals("D") || paramSig.equals("J")) {
paramLocalOffset += 2;
} else {
paramLocalOffset += 1;
}
}
// No need to add properties if there are no unconditionally
// dereferenced params
if (unconditionalDerefSet.isEmpty()) {
if (VERBOSE_DEBUG) {
System.out.println("\tResult is empty");
}
return;
}
if (VERBOSE_DEBUG) {
ClassContext.dumpDataflowInformation(method, cfg, vnaDataflow, classContext.getIsNullValueDataflow(method),
dataflow, classContext.getTypeDataflow(method));
}
ParameterProperty property = new ParameterProperty();
property.setParamsWithProperty(unconditionalDerefSet);
AnalysisContext.currentAnalysisContext().getUnconditionalDerefParamDatabase()
.setProperty(xmethod.getMethodDescriptor(), property);
if (DEBUG) {
System.out.println("Unconditional deref: " + xmethod + "=" + property);
}
} catch (CheckedAnalysisException e) {
AnalysisContext.currentAnalysisContext().getLookupFailureCallback()