1 19 20 package edu.umd.cs.findbugs.detect; 21 22 23 import edu.umd.cs.findbugs.*; 24 import java.util.*; 25 import org.apache.bcel.Repository; 26 import org.apache.bcel.classfile.*; 27 28 public @java.lang.Deprecated class FindBadCast extends BytecodeScanningDetector implements StatelessDetector { 29 30 31 private HashSet<String > castTo = new HashSet<String >(); 32 33 BugReporter bugReporter; 34 35 final static boolean DEBUG = false; 36 37 public FindBadCast(BugReporter bugReporter) { 38 this.bugReporter = bugReporter; 39 abstractCollectionClasses.add("java/util/Collection"); 40 abstractCollectionClasses.add("java/util/List"); 41 abstractCollectionClasses.add("java/util/Set"); 42 abstractCollectionClasses.add("java/util/Map"); 43 concreteCollectionClasses.add("java/util/LinkedHashMap"); 44 concreteCollectionClasses.add("java/util/LinkedHashSet"); 45 concreteCollectionClasses.add("java/util/HashMap"); 46 concreteCollectionClasses.add("java/util/HashSet"); 47 concreteCollectionClasses.add("java/util/TreeMap"); 48 concreteCollectionClasses.add("java/util/TreeSet"); 49 concreteCollectionClasses.add("java/util/ArrayList"); 50 concreteCollectionClasses.add("java/util/LinkedList"); 51 concreteCollectionClasses.add("java/util/Hashtable"); 52 concreteCollectionClasses.add("java/util/Vector"); 53 } 54 55 private Set<String > concreteCollectionClasses = new HashSet<String >(); 56 private Set<String > abstractCollectionClasses = new HashSet<String >(); 57 58 59 60 @Override 61 public void visit(JavaClass obj) { 62 } 63 64 @Override 65 public void visit(Method obj) { 66 } 67 68 74 private int parameters; 75 OpcodeStack stack = new OpcodeStack(); 76 @Override 77 public void visit(Code obj) { 78 if (DEBUG) { 79 System.out.println(getFullyQualifiedMethodName()); 80 } 81 parameters = stack.resetForMethodEntry(this); 82 castTo.clear(); 83 super.visit(obj); 84 } 85 86 87 @Override 88 public void sawOpcode(int seen) { 89 stack.mergeJumps(this); 90 if (DEBUG) { 91 System.out.println(stack); 92 printOpCode(seen); 93 } 94 95 if (stack.getStackDepth() > 0) { 96 if (seen == CHECKCAST || seen == INSTANCEOF) { 97 if (DEBUG) 98 System.out.println(" ... checking ... "); 99 OpcodeStack.Item it = stack.getStackItem(0); 100 String signature = it.getSignature(); 101 if (signature.length() > 0 && signature.charAt(0) == 'L') 102 signature = signature.substring(1, signature.length() - 1); 103 String signatureDot = signature.replace('/', '.'); 104 String to = getClassConstantOperand(); 105 if (to.length() > 0 && to.charAt(0) == 'L') 106 to = to.substring(1, to.length() - 1); 107 String toDot = to.replace('/', '.'); 108 if (signature.length() > 0 109 && !signature.equals("java/lang/Object") 110 && !signature.equals(to)) { 111 112 try { 113 JavaClass toClass = Repository.lookupClass(toDot); 114 JavaClass signatureClass = Repository 115 .lookupClass(signatureDot); 116 if (DEBUG) 117 System.out.println(" ... checking ...... "); 118 if (!castTo.contains(to) 119 && !Repository.instanceOf(signatureClass, 120 toClass)) { 121 if (!Repository.instanceOf(toClass, signatureClass) 122 && ((!toClass.isInterface() && !signatureClass 123 .isInterface()) 124 || signatureClass.isFinal() || toClass 125 .isFinal())) 126 bugReporter 127 .reportBug(new BugInstance( 128 this, 129 seen == CHECKCAST ? "BC_IMPOSSIBLE_CAST" 130 : "BC_IMPOSSIBLE_INSTANCEOF", 131 seen == CHECKCAST ? HIGH_PRIORITY 132 : NORMAL_PRIORITY) 133 .addClassAndMethod(this) 134 .addSourceLine(this).addClass( 135 signatureDot).addClass( 136 toDot)); 137 else if (seen == CHECKCAST) { 138 int priority = NORMAL_PRIORITY; 139 if (DEBUG) { 140 System.out.println("Checking BC in " 141 + getFullyQualifiedMethodName()); 142 System.out.println("to class: " + toClass); 143 System.out.println("from class: " 144 + signatureClass); 145 System.out.println("instanceof : " 146 + Repository.instanceOf(toClass, 147 signatureClass)); 148 } 149 if (Repository.instanceOf(toClass, 150 signatureClass)) 151 priority += 2; 152 if (getThisClass().equals(toClass) 153 || getThisClass() 154 .equals(signatureClass)) 155 priority += 1; 156 if (DEBUG) 157 System.out 158 .println(" priority: " + priority); 159 if (toClass.isInterface()) 160 priority++; 161 if (DEBUG) 162 System.out 163 .println(" priority: " + priority); 164 if (priority <= LOW_PRIORITY 165 && (signatureClass.isInterface() || signatureClass 166 .isAbstract())) 167 priority++; 168 if (DEBUG) 169 System.out 170 .println(" priority: " + priority); 171 if (concreteCollectionClasses 172 .contains(signature) 173 || abstractCollectionClasses 174 .contains(signature)) 175 priority--; 176 if (concreteCollectionClasses.contains(to) 177 || abstractCollectionClasses 178 .contains(to)) 179 priority--; 180 if (DEBUG) 181 System.out 182 .println(" priority: " + priority); 183 int reg = it.getRegisterNumber(); 184 if (reg >= 0 && reg < parameters 185 && it.isInitialParameter() 186 && getMethod().isPublic()) { 187 priority--; 188 if (getPC() < 4 && priority > LOW_PRIORITY) 189 priority--; 190 } 191 if (DEBUG) 192 System.out 193 .println(" priority: " + priority); 194 if (getMethodName().equals("compareTo")) 195 priority++; 196 if (DEBUG) 197 System.out 198 .println(" priority: " + priority); 199 if (priority < HIGH_PRIORITY) 200 priority = HIGH_PRIORITY; 201 if (priority <= LOW_PRIORITY) { 202 String bug = "BC_UNCONFIRMED_CAST"; 203 if (concreteCollectionClasses.contains(to)) 204 bug = "BC_BAD_CAST_TO_CONCRETE_COLLECTION"; 205 else if (abstractCollectionClasses 206 .contains(to) 207 && (signature 208 .equals("java/util/Collection") || signature 209 .equals("java/lang/Iterable"))) 210 bug = "BC_BAD_CAST_TO_ABSTRACT_COLLECTION"; 211 bugReporter.reportBug(new BugInstance(this, 212 bug, priority).addClassAndMethod( 213 this).addSourceLine(this).addClass( 214 signatureDot).addClass(toDot)); 215 } 216 } 217 218 } 219 220 } catch (RuntimeException e) { 221 } catch (ClassNotFoundException e) { 223 } 225 } 226 } 227 if (seen == INSTANCEOF) { 228 String to = getClassConstantOperand(); 229 castTo.add(to); 230 } 231 } 232 stack.sawOpcode(this,seen); 233 234 } 235 236 237 238 239 } 240 | Popular Tags |