return;
}
BugAccumulator accumulator = new BugAccumulator(bugReporter);
CFG cfg = classContext.getCFG(method);
TypeDataflow typeDataflow = classContext.getTypeDataflow(method);
IsNullValueDataflow isNullDataflow = classContext.getIsNullValueDataflow(method);
Set<ValueNumber> paramValueNumberSet = null;
ValueNumberDataflow vnaDataflow = null;
ConstantPoolGen cpg = classContext.getConstantPoolGen();
MethodGen methodGen = classContext.getMethodGen(method);
if (methodGen == null) {
return;
}
String methodName = methodGen.getClassName() + "." + methodGen.getName();
String sourceFile = classContext.getJavaClass().getSourceFileName();
if (DEBUG) {
System.out.println("Checking " + methodName);
}
Set<SourceLineAnnotation> haveInstanceOf = new HashSet<SourceLineAnnotation>();
Set<SourceLineAnnotation> haveCast = new HashSet<SourceLineAnnotation>();
Set<SourceLineAnnotation> haveMultipleInstanceOf = new HashSet<SourceLineAnnotation>();
Set<SourceLineAnnotation> haveMultipleCast = new HashSet<SourceLineAnnotation>();
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF)) {
continue;
}
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, handle);
if (ins instanceof CHECKCAST) {
if (!haveCast.add(sourceLineAnnotation)) {
haveMultipleCast.add(sourceLineAnnotation);
if (DEBUG) {
System.out.println("Have multiple casts for " + sourceLineAnnotation);
}
}
} else {
if (!haveInstanceOf.add(sourceLineAnnotation)) {
haveMultipleInstanceOf.add(sourceLineAnnotation);
if (DEBUG) {
System.out.println("Have multiple instanceof for " + sourceLineAnnotation);
}
}
}
}
BitSet linesMentionedMultipleTimes = classContext.linesMentionedMultipleTimes(method);
LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool());
Map<BugAnnotation, String> instanceOfChecks = new HashMap<BugAnnotation, String>();
String constantClass = null;
boolean methodInvocationWasGeneric = false;
int pcForConstantClass = -1;
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
InstructionHandle handle = location.getHandle();
int pc = handle.getPosition();
Instruction ins = handle.getInstruction();
boolean wasMethodInvocationWasGeneric = methodInvocationWasGeneric;
methodInvocationWasGeneric = false;
if (ins instanceof InvokeInstruction) {
InvokeInstruction iinv = (InvokeInstruction) ins;
XMethod m = XFactory.createXMethod(iinv, cpg);
if (m != null) {
String sourceSignature = m.getSourceSignature();
methodInvocationWasGeneric = sourceSignature != null
&& (sourceSignature.startsWith("<") || sourceSignature.indexOf("java/lang/Class") >= 0);
if (DEBUG && methodInvocationWasGeneric) {
System.out.println(m + " has source signature " + sourceSignature);
}
}
}
if (ins instanceof LDC) {
LDC ldc = (LDC) ins;
Object value = ldc.getValue(cpg);
if (value instanceof ConstantClass) {
ConstantClass cc = (ConstantClass) value;
constantClass = cc.getBytes(classContext.getJavaClass().getConstantPool());
pcForConstantClass = pc;
}
}
if (!(ins instanceof CHECKCAST) && !(ins instanceof INSTANCEOF)) {
continue;
}
boolean isCast = ins instanceof CHECKCAST;
int occurrences = cfg.getLocationsContainingInstructionWithOffset(pc).size();
boolean split = occurrences > 1;
if (lineNumberTable != null) {
int line = lineNumberTable.getSourceLine(handle.getPosition());
if (line > 0 && linesMentionedMultipleTimes.get(line)) {
split = true;
}
}
IsNullValueFrame nullFrame = isNullDataflow.getFactAtLocation(location);
if (!nullFrame.isValid()) {
continue;
}
IsNullValue operandNullness = nullFrame.getTopValue();
if (DEBUG) {
String kind = isCast ? "checkedCast" : "instanceof";
System.out.println(kind + " at pc: " + pc + " in " + methodName);
System.out.println(" occurrences: " + occurrences);
System.out.println("XXX: " + operandNullness);
}
if (split && !isCast) {
// don't report this case; it might be infeasible due to
// inlining
continue;
}
TypeFrame frame = typeDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
// This basic block is probably dead
continue;
}
Type operandType = frame.getTopValue();
if (operandType.equals(TopType.instance())) {
// unreachable
continue;
}
boolean operandTypeIsExact = frame.isExact(frame.getStackLocation(0));
final Type castType = ((TypedInstruction) ins).getType(cpg);
if (!(castType instanceof ReferenceType)) {
// This shouldn't happen either
continue;
}
String castSig = castType.getSignature();
if (operandType.equals(NullType.instance()) || operandNullness.isDefinitelyNull()) {
SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen,
sourceFile, handle);
assert castSig.length() > 1;
if (!isCast) {
accumulator.accumulateBug(new BugInstance(this, "NP_NULL_INSTANCEOF", split ? LOW_PRIORITY : NORMAL_PRIORITY)
.addClassAndMethod(methodGen, sourceFile).addType(castSig), sourceLineAnnotation);
}
continue;
}
if (!(operandType instanceof ReferenceType)) {
// Shouldn't happen - illegal bytecode
continue;
}
final ReferenceType refType = (ReferenceType) operandType;
boolean impliesByGenerics = typeDataflow.getAnalysis().isImpliedByGenericTypes(refType);
if (impliesByGenerics && !isCast) {
continue;
}