1 20 21 package edu.umd.cs.findbugs.detect; 22 23 24 import edu.umd.cs.findbugs.*; 25 import org.apache.bcel.classfile.Method; 26 27 public class WrongMapIterator extends BytecodeScanningDetector implements StatelessDetector { 28 private BugReporter bugReporter; 29 private static final int SAW_NOTHING = 0; 30 private static final int SAW_MAP_LOAD1 = 1; 31 private static final int SAW_KEYSET = 2; 32 private static final int SAW_KEYSET_STORE = 3; 33 private static final int SAW_ITERATOR = 4; 34 private static final int SAW_ITERATOR_STORE = 5; 35 private static final int SAW_ITERATOR_LOAD = 6; 36 private static final int SAW_NEXT = 7; 37 private static final int SAW_CHECKCAST_ON_NEXT = 8; 38 private static final int SAW_KEY_STORE = 9; 39 private static final int NEED_KEYSET_LOAD = 10; 40 private static final int SAW_MAP_LOAD2 = 11; 41 private static final int SAW_KEY_LOAD = 12; 42 43 private int state; 44 private int loadedRegister; 45 private int mapRegister; 46 private int keySetRegister; 47 private int iteratorRegister; 48 private int keyRegister; 49 50 51 public WrongMapIterator(BugReporter bugReporter) { 52 this.bugReporter = bugReporter; 53 } 54 55 56 57 @Override 58 public void visit(Method obj) { 59 state = SAW_NOTHING; 60 loadedRegister = -1; 61 mapRegister = -1; 62 keySetRegister = -1; 63 iteratorRegister = -1; 64 keyRegister = -1; 65 } 66 67 @Override 68 public void sawOpcode(int seen) { 69 switch (state) 70 { 71 case SAW_NOTHING: 72 loadedRegister = getLoadStoreRegister( seen, true ); 73 if (loadedRegister >= 0) 74 state = SAW_MAP_LOAD1; 75 break; 76 77 case SAW_MAP_LOAD1: 78 if (((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL)) 79 && ("keySet".equals(getNameConstantOperand())) 80 && ("()Ljava/util/Set;".equals(getSigConstantOperand()))) { 81 mapRegister = loadedRegister; 82 state = SAW_KEYSET; 83 } 84 else { 85 state = SAW_NOTHING; 86 } 87 break; 88 89 case SAW_KEYSET: 90 keySetRegister = getLoadStoreRegister( seen, false ); 91 if (keySetRegister >= 0) 92 state = SAW_KEYSET_STORE; 93 else if ((seen == INVOKEINTERFACE) 94 && ("iterator".equals(getNameConstantOperand())) 95 && ("()Ljava/util/Iterator;".equals(getSigConstantOperand()))) 96 state = SAW_ITERATOR; 97 else 98 state = SAW_NOTHING; 99 break; 100 101 case SAW_KEYSET_STORE: 102 if ((seen == INVOKEINTERFACE) 103 && ("iterator".equals(getNameConstantOperand())) 104 && ("()Ljava/util/Iterator;".equals(getSigConstantOperand()))) 105 state = SAW_ITERATOR; 106 else 107 state = NEED_KEYSET_LOAD; 108 break; 109 110 case NEED_KEYSET_LOAD: 111 loadedRegister = getLoadStoreRegister( seen, true ); 112 if (loadedRegister == iteratorRegister) 113 state = SAW_ITERATOR; 114 break; 115 116 case SAW_ITERATOR: 117 iteratorRegister = getLoadStoreRegister( seen, false ); 118 if (iteratorRegister >= 0) 119 state = SAW_ITERATOR_STORE; 120 else 121 state = SAW_NOTHING; 122 break; 123 124 case SAW_ITERATOR_STORE: 125 loadedRegister = getLoadStoreRegister( seen, true ); 126 if (loadedRegister == iteratorRegister) 127 state = SAW_ITERATOR_LOAD; 128 break; 129 130 case SAW_ITERATOR_LOAD: 131 if ((seen == INVOKEINTERFACE) 132 && ("next".equals(getNameConstantOperand())) 133 && ("()Ljava/lang/Object;".equals(getSigConstantOperand()))) 134 state = SAW_NEXT; 135 else 136 state = SAW_ITERATOR_STORE; 137 break; 138 139 case SAW_NEXT: 140 if (seen == CHECKCAST) 141 state = SAW_CHECKCAST_ON_NEXT; 142 else { 143 keyRegister = getLoadStoreRegister( seen, false ); 144 if (keyRegister >= 0) 145 state = SAW_KEY_STORE; 146 else 147 seen = SAW_NOTHING; 148 } 149 break; 150 151 case SAW_CHECKCAST_ON_NEXT: 152 keyRegister = getLoadStoreRegister( seen, false ); 153 if (keyRegister >= 0) 154 state = SAW_KEY_STORE; 155 break; 156 157 case SAW_KEY_STORE: 158 loadedRegister = getLoadStoreRegister( seen, true ); 159 if (loadedRegister == mapRegister) 160 state = SAW_MAP_LOAD2; 161 break; 162 163 case SAW_MAP_LOAD2: 164 loadedRegister = getLoadStoreRegister( seen, true ); 165 if (loadedRegister == keyRegister) 166 state = SAW_KEY_LOAD; 167 else 168 state = SAW_KEY_STORE; 169 break; 170 171 case SAW_KEY_LOAD: 172 if (((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL)) 173 && ("get".equals(getNameConstantOperand())) 174 && ("(Ljava/lang/Object;)Ljava/lang/Object;".equals(getSigConstantOperand()))) { 175 MethodAnnotation ma = MethodAnnotation.fromVisitedMethod(this); 176 bugReporter.reportBug( 177 new BugInstance("WMI_WRONG_MAP_ITERATOR", NORMAL_PRIORITY) 178 .addClass(this) 179 .addMethod(ma) 180 .addSourceLine(this, getPC())); 181 state = SAW_NOTHING; 182 } 183 break; 184 } 185 } 186 187 private int getLoadStoreRegister(int seen, boolean doLoad) 188 { 189 switch (seen) 190 { 191 case ALOAD_0: 192 case ALOAD_1: 193 case ALOAD_2: 194 case ALOAD_3: 195 if (doLoad) 196 return seen - ALOAD_0; 197 break; 198 199 case ALOAD: 200 if (doLoad) 201 return getRegisterOperand(); 202 break; 203 204 case ASTORE_0: 205 case ASTORE_1: 206 case ASTORE_2: 207 case ASTORE_3: 208 if (!doLoad) 209 return seen - ASTORE_0; 210 break; 211 212 case ASTORE: 213 if (!doLoad) 214 return getRegisterOperand(); 215 break; 216 } 217 218 return -1; 219 } 220 } 221 | Popular Tags |