1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import org.apache.bcel.classfile.Code; 23 import org.apache.bcel.classfile.JavaClass; 24 import org.apache.bcel.classfile.Method; 25 26 import edu.umd.cs.findbugs.BugInstance; 27 import edu.umd.cs.findbugs.BugReporter; 28 import edu.umd.cs.findbugs.BytecodeScanningDetector; 29 import edu.umd.cs.findbugs.FieldAnnotation; 30 import edu.umd.cs.findbugs.LocalVariableAnnotation; 31 import edu.umd.cs.findbugs.OpcodeStack; 32 import edu.umd.cs.findbugs.ba.SignatureParser; 33 import edu.umd.cs.findbugs.ba.XField; 34 35 public class FindSelfComparison extends BytecodeScanningDetector { 36 37 BugReporter bugReporter; 38 39 OpcodeStack stack = new OpcodeStack(); 40 41 public FindSelfComparison(BugReporter bugReporter) { 42 this.bugReporter = bugReporter; 43 } 44 45 @Override 46 public void visit(JavaClass obj) { 47 } 48 49 @Override 50 public void visit(Method obj) { 51 } 52 53 @Override 54 public void visit(Code obj) { 55 whichRegister = -1; 56 registerLoadCount = 0; 57 stack.resetForMethodEntry(this); 58 super.visit(obj); 59 } 60 61 @Override 62 public void sawOpcode(int seen) { 63 stack.mergeJumps(this); 65 66 switch (seen) { 67 case INVOKEVIRTUAL: 68 case INVOKEINTERFACE: 69 if (getClassName().toLowerCase().indexOf("test") >= 0) break; 70 if (getMethodName().toLowerCase().indexOf("test") >= 0) break; 71 if (getSuperclassName().toLowerCase().indexOf("test") >= 0) break; 72 73 String name = getNameConstantOperand(); 74 if (name.equals("equals") || 75 name.equals("compareTo")) { 76 String sig = getSigConstantOperand(); 77 SignatureParser parser = new SignatureParser(sig); 78 if (parser.getNumParameters() == 1 && 79 (name.equals("equals") && sig.endsWith(";)Z") 80 || name.equals("compareTo") && sig.endsWith(";)I"))) 81 checkForSelfOperation(seen, "COMPARISON"); 82 } 83 break; 84 85 case LOR: 86 case LAND: 87 case LXOR: 88 case LSUB: 89 case IOR: 90 case IAND: 91 case IXOR: 92 case ISUB: 93 checkForSelfOperation(seen, "COMPUTATION"); 94 break; 95 case FCMPG: 96 case DCMPG: 97 case DCMPL: 98 case FCMPL: 99 break; 100 case LCMP: 101 case IF_ACMPEQ: 102 case IF_ACMPNE: 103 case IF_ICMPNE: 104 case IF_ICMPEQ: 105 case IF_ICMPGT: 106 case IF_ICMPLE: 107 case IF_ICMPLT: 108 case IF_ICMPGE: 109 checkForSelfOperation(seen, "COMPARISON"); 110 } 111 stack.sawOpcode(this, seen); 112 if (isRegisterLoad() && seen != IINC) { 113 if (getRegisterOperand() == whichRegister) registerLoadCount++; 114 else { 115 whichRegister = getRegisterOperand(); 116 registerLoadCount = 1; 117 } 118 } else { 119 whichRegister = -1; 120 registerLoadCount = 0; 121 } 122 } 123 int whichRegister; 124 int registerLoadCount; 125 126 127 128 private void checkForSelfOperation(int opCode, String op) { 129 { 130 131 OpcodeStack.Item item0 = stack.getStackItem(0); 132 OpcodeStack.Item item1 = stack.getStackItem(1); 133 134 if (item0.getSignature().equals("D") 135 || item0.getSignature().equals("F")) 136 return; 137 if (item1.getSignature().equals("D") 138 || item1.getSignature().equals("F")) 139 return; 140 141 XField field0 = item0.getXField(); 142 XField field1 = item1.getXField(); 143 int fr0 = item0.getFieldLoadedFromRegister(); 144 int fr1 = item1.getFieldLoadedFromRegister(); 145 if (field0 != null && field0.equals(field1) && fr0 != -1 && fr0 == fr1) 146 bugReporter.reportBug(new BugInstance(this, 147 "SA_FIELD_SELF_" + op, NORMAL_PRIORITY) 148 .addClassAndMethod(this).addField(field0) 149 .addSourceLine(this)); 150 151 else if (opCode == ISUB && registerLoadCount >= 2) { bugReporter.reportBug(new BugInstance(this, 153 "SA_LOCAL_SELF_" + op, (opCode == ISUB || opCode == LSUB || opCode == INVOKEINTERFACE || opCode == INVOKEVIRTUAL) ? NORMAL_PRIORITY : HIGH_PRIORITY) 154 .addClassAndMethod(this).add( 155 LocalVariableAnnotation 156 .getLocalVariableAnnotation( 157 getMethod(), whichRegister, getPC(), 158 getPC() - 1)) 159 .addSourceLine(this)); 160 } 161 } 162 } 163 } | Popular Tags |