1 package edu.umd.cs.findbugs.detect; 2 3 import java.util.BitSet ; 4 import java.util.IdentityHashMap ; 5 import java.util.Iterator ; 6 7 import org.apache.bcel.classfile.LineNumberTable; 8 import org.apache.bcel.classfile.Method; 9 import org.apache.bcel.generic.ALOAD; 10 import org.apache.bcel.generic.ARETURN; 11 import org.apache.bcel.generic.Instruction; 12 import org.apache.bcel.generic.InstructionHandle; 13 import org.apache.bcel.generic.MethodGen; 14 15 import edu.umd.cs.findbugs.BugInstance; 16 import edu.umd.cs.findbugs.BugReporter; 17 import edu.umd.cs.findbugs.Detector; 18 import edu.umd.cs.findbugs.SourceLineAnnotation; 19 import edu.umd.cs.findbugs.SystemProperties; 20 import edu.umd.cs.findbugs.ba.CFG; 21 import edu.umd.cs.findbugs.ba.CFGBuilderException; 22 import edu.umd.cs.findbugs.ba.ClassContext; 23 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 24 import edu.umd.cs.findbugs.ba.Location; 25 import edu.umd.cs.findbugs.ba.MethodUnprofitableException; 26 import edu.umd.cs.findbugs.ba.npe.IsNullValue; 27 import edu.umd.cs.findbugs.ba.npe.IsNullValueDataflow; 28 import edu.umd.cs.findbugs.ba.npe.IsNullValueFrame; 29 30 public class LoadOfKnownNullValue implements Detector { 31 32 private BugReporter bugReporter; 33 34 public LoadOfKnownNullValue(BugReporter bugReporter) { 35 this.bugReporter = bugReporter; 36 } 37 38 public void visitClassContext(ClassContext classContext) { 39 Method[] methodList = classContext.getJavaClass().getMethods(); 40 41 for (Method method : methodList) { 42 if (method.getCode() == null) 43 continue; 44 45 try { 46 analyzeMethod(classContext, method); 47 } catch (MethodUnprofitableException mue) { 48 if (SystemProperties.getBoolean("unprofitable.debug")) bugReporter.logError("skipping unprofitable method in " + getClass().getName()); 50 } catch (CFGBuilderException e) { 51 bugReporter.logError("Detector " + this.getClass().getName() 52 + " caught exception", e); 53 } catch (DataflowAnalysisException e) { 54 bugReporter.logError("Detector " + this.getClass().getName() 55 + " caught exception", e); 56 } 57 } 58 } 59 60 private void analyzeMethod(ClassContext classContext, Method method) 61 throws CFGBuilderException, DataflowAnalysisException { 62 BitSet lineMentionedMultipleTimes = ClassContext.linesMentionedMultipleTimes(method); 63 BitSet linesWithLoadsOfNotDefinitelyNullValues = null; 64 65 CFG cfg = classContext.getCFG(method); 66 IsNullValueDataflow nullValueDataflow = classContext 67 .getIsNullValueDataflow(method); 68 MethodGen methodGen = classContext.getMethodGen(method); 69 String sourceFile = classContext.getJavaClass().getSourceFileName(); 70 71 if (lineMentionedMultipleTimes.cardinality() > 0) { 72 linesWithLoadsOfNotDefinitelyNullValues = new BitSet (); 73 LineNumberTable lineNumbers = method.getLineNumberTable(); 74 for (Iterator <Location> i = cfg.locationIterator(); i.hasNext();) { 75 Location location = i.next(); 76 77 InstructionHandle handle = location.getHandle(); 78 Instruction ins = handle.getInstruction(); 79 if (!(ins instanceof ALOAD)) 80 continue; 81 82 IsNullValueFrame frame = nullValueDataflow 83 .getFactAtLocation(location); 84 if (!frame.isValid()) { 85 continue; 87 } 88 90 ALOAD load = (ALOAD) ins; 91 92 int index = load.getIndex(); 93 IsNullValue v = frame.getValue(index); 94 if (!v.isDefinitelyNull()) { 95 int sourceLine = lineNumbers.getSourceLine(handle.getPosition()); 96 if (sourceLine > 0) 97 linesWithLoadsOfNotDefinitelyNullValues.set(sourceLine); 98 } 99 } 100 } 101 102 103 IdentityHashMap <InstructionHandle, Object > sometimesGood = new IdentityHashMap <InstructionHandle, Object >(); 104 105 for (Iterator <Location> i = cfg.locationIterator(); i.hasNext();) { 106 Location location = i.next(); 107 InstructionHandle handle = location.getHandle(); 108 Instruction ins = handle.getInstruction(); 109 if (!(ins instanceof ALOAD)) continue; 110 IsNullValueFrame frame = nullValueDataflow.getFactAtLocation(location); 111 if (!frame.isValid()) { 112 continue; 114 } 115 117 ALOAD load = (ALOAD) ins; 118 119 int index = load.getIndex(); 120 IsNullValue v = frame.getValue(index); 121 if (!v.isDefinitelyNull()) sometimesGood.put(handle, null); 122 } 123 124 for (Iterator <Location> i = cfg.locationIterator(); i.hasNext();) { 126 Location location = i.next(); 127 128 InstructionHandle handle = location.getHandle(); 129 Instruction ins = handle.getInstruction(); 130 if (!(ins instanceof ALOAD)) 131 continue; 132 133 if (sometimesGood.containsKey(handle)) continue; 134 IsNullValueFrame frame = nullValueDataflow 135 .getFactAtLocation(location); 136 if (!frame.isValid()) { 137 continue; 139 } 140 142 ALOAD load = (ALOAD) ins; 143 144 int index = load.getIndex(); 145 IsNullValue v = frame.getValue(index); 146 if (v.isDefinitelyNull()) { 147 Instruction next = handle.getNext().getInstruction(); 148 InstructionHandle prevHandle = handle.getPrev(); 149 SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation 150 .fromVisitedInstruction(classContext, methodGen, sourceFile, handle); 151 SourceLineAnnotation prevSourceLineAnnotation = SourceLineAnnotation 152 .fromVisitedInstruction(classContext, methodGen, sourceFile, prevHandle); 153 154 if (next instanceof ARETURN) { 155 continue; 157 } 158 int startLine = sourceLineAnnotation.getStartLine(); 159 if (startLine > 0 && lineMentionedMultipleTimes.get(startLine) && linesWithLoadsOfNotDefinitelyNullValues.get(startLine)) 160 continue; 161 162 if (startLine > prevSourceLineAnnotation.getEndLine()) { 163 continue; 166 } 167 int priority = NORMAL_PRIORITY; 168 169 if (!v.isChecked()) priority++; 170 173 bugReporter.reportBug(new BugInstance(this, 174 "NP_LOAD_OF_KNOWN_NULL_VALUE", 175 priority) 176 .addClassAndMethod(methodGen, sourceFile) 177 .addSourceLine(sourceLineAnnotation)); 178 } 179 180 } 181 } 182 183 public void report() { 184 } 185 186 } 187 | Popular Tags |