1 package edu.umd.cs.findbugs.detect; 2 3 import static org.apache.bcel.Constants.*; 4 5 import java.util.BitSet ; 6 import java.util.Iterator ; 7 8 import org.apache.bcel.classfile.Method; 9 import org.apache.bcel.generic.ConstantPoolGen; 10 import org.apache.bcel.generic.Instruction; 11 import org.apache.bcel.generic.InvokeInstruction; 12 import org.apache.bcel.generic.MethodGen; 13 14 import edu.umd.cs.findbugs.BugAnnotation; 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.FieldAnnotation; 19 import edu.umd.cs.findbugs.LocalVariableAnnotation; 20 import edu.umd.cs.findbugs.SourceLineAnnotation; 21 import edu.umd.cs.findbugs.SystemProperties; 22 import edu.umd.cs.findbugs.ba.CFG; 23 import edu.umd.cs.findbugs.ba.CFGBuilderException; 24 import edu.umd.cs.findbugs.ba.ClassContext; 25 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 26 import edu.umd.cs.findbugs.ba.Location; 27 import edu.umd.cs.findbugs.ba.MethodUnprofitableException; 28 import edu.umd.cs.findbugs.ba.SignatureParser; 29 import edu.umd.cs.findbugs.ba.XFactory; 30 import edu.umd.cs.findbugs.ba.XField; 31 import edu.umd.cs.findbugs.ba.vna.ValueNumber; 32 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow; 33 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame; 34 35 public class FindSelfComparison2 implements Detector { 36 37 private BugReporter bugReporter; 38 39 public FindSelfComparison2(BugReporter bugReporter) { 40 this.bugReporter = bugReporter; 41 } 42 43 public void visitClassContext(ClassContext classContext) { 44 Method[] methodList = classContext.getJavaClass().getMethods(); 45 46 for (Method method : methodList) { 47 if (method.getCode() == null) 48 continue; 49 50 try { 51 analyzeMethod(classContext, method); 52 } catch (MethodUnprofitableException mue) { 53 if (SystemProperties.getBoolean("unprofitable.debug")) bugReporter.logError("skipping unprofitable method in " + getClass().getName()); 55 } catch (CFGBuilderException e) { 56 bugReporter.logError("Detector " + this.getClass().getName() 57 + " caught exception", e); 58 } catch (DataflowAnalysisException e) { 59 bugReporter.logError("Detector " + this.getClass().getName() 60 + " caught exception", e); 61 } 62 } 63 } 64 65 private void analyzeMethod(ClassContext classContext, Method method) 66 throws CFGBuilderException, DataflowAnalysisException { 67 CFG cfg = classContext.getCFG(method); 68 ValueNumberDataflow valueNumberDataflow = classContext 69 .getValueNumberDataflow(method); 70 ConstantPoolGen cpg = classContext.getConstantPoolGen(); 71 MethodGen methodGen = classContext.getMethodGen(method); 72 String sourceFile = classContext.getJavaClass().getSourceFileName(); 73 74 for (Iterator <Location> i = cfg.locationIterator(); i.hasNext();) { 75 Location location = i.next(); 76 77 Instruction ins = location.getHandle().getInstruction(); 78 switch(ins.getOpcode()) { 79 case INVOKEVIRTUAL: 80 case INVOKEINTERFACE: 81 InvokeInstruction iins = (InvokeInstruction) ins; 82 String invoking = iins.getName(cpg); 83 if (invoking.equals("equals") || invoking.equals("compareTo")) { 84 if (methodGen.getName().toLowerCase().indexOf("test") >= 0) break; 85 if (methodGen.getClassName().toLowerCase().indexOf("test") >= 0) break; 86 if (classContext.getJavaClass().getSuperclassName().toLowerCase().indexOf("test") >= 0) break; 87 88 String sig = iins.getSignature(cpg); 89 90 SignatureParser parser = new SignatureParser(sig); 91 if (parser.getNumParameters() == 1 && 92 (invoking.equals("equals") && sig.endsWith(";)Z") 93 || invoking.equals("compareTo") && sig.endsWith(";)I"))) 94 checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPARISON", methodGen, sourceFile); 95 96 97 } 98 break; 99 100 case LOR: 101 case LAND: 102 case LXOR: 103 case LSUB: 104 case IOR: 105 case IAND: 106 case IXOR: 107 case ISUB: 108 checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPUTATION", methodGen, sourceFile); 109 break; 110 case FCMPG: 111 case DCMPG: 112 case DCMPL: 113 case FCMPL: 114 break; 115 case LCMP: 116 case IF_ACMPEQ: 117 case IF_ACMPNE: 118 case IF_ICMPNE: 119 case IF_ICMPEQ: 120 case IF_ICMPGT: 121 case IF_ICMPLE: 122 case IF_ICMPLT: 123 case IF_ICMPGE: 124 checkForSelfOperation(classContext, location, valueNumberDataflow, "COMPARISON", methodGen, sourceFile); 125 126 } 127 128 129 } 130 } 131 132 140 private void checkForSelfOperation(ClassContext classContext, Location location, ValueNumberDataflow valueNumberDataflow, String op, MethodGen methodGen, String sourceFile) throws DataflowAnalysisException { 141 ValueNumberFrame frame = valueNumberDataflow.getFactAtLocation(location); 142 if (!frame.isValid()) return; 143 Instruction ins = location.getHandle().getInstruction(); 144 int opcode = ins.getOpcode(); 145 int offset = 1; 146 if (opcode == LCMP || opcode == LXOR || opcode == LAND || opcode == LOR || opcode == LSUB) 147 offset = 2; 148 ValueNumber v0 = frame.getStackValue(0); 149 ValueNumber v1 = frame.getStackValue(offset); 150 if (!v1.equals(v0)) return; 151 152 int priority = HIGH_PRIORITY; 153 if (opcode == ISUB || opcode == LSUB || opcode == INVOKEINTERFACE || opcode == INVOKEVIRTUAL) 154 priority = NORMAL_PRIORITY; 155 XField field = FindNullDeref.findXFieldFromValueNumber(methodGen.getMethod(), location, v0, frame); 156 BugAnnotation annotation; 157 String prefix; 158 if (field != null) { 159 if (field.isVolatile()) return; 160 annotation = FieldAnnotation.fromXField(field); 161 prefix = "SA_FIELD_SELF_"; 162 if (true) return; } else { 164 annotation = FindNullDeref.findLocalAnnotationFromValueNumber(methodGen.getMethod(), location, v0, frame); 165 prefix = "SA_LOCAL_SELF_" ; 166 if (opcode == ISUB) return; } 168 if (annotation == null) return; 169 SourceLineAnnotation sourceLine = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, location.getHandle()); 170 int line = sourceLine.getStartLine(); 171 BitSet occursMultipleTimes = classContext.linesMentionedMultipleTimes(methodGen.getMethod()); 172 if (line > 0 && occursMultipleTimes.get(line)) return; 173 BugInstance bug = new BugInstance(this, prefix + op, priority).addClassAndMethod(methodGen, sourceFile) 174 .add(annotation).addSourceLine(classContext, methodGen, sourceFile, location.getHandle()); 175 bugReporter.reportBug(bug); 176 } 177 178 public void report() { 179 } 180 181 } 182 | Popular Tags |