1 19 20 package edu.umd.cs.findbugs.detect; 21 22 import edu.umd.cs.findbugs.*; 23 24 import org.apache.bcel.classfile.Method; 25 26 public class FindNonShortCircuit extends BytecodeScanningDetector implements 27 StatelessDetector { 28 29 int stage1 = 0; 30 int stage2 = 0; 31 int distance = 0; 32 int operator; 33 34 boolean sawDanger; 35 boolean sawNullTestOld; 36 boolean sawNullTestVeryOld; 37 boolean sawNullTest; 38 boolean sawDangerOld; 39 boolean sawArrayIndex; 40 boolean sawArrayIndexOld; 41 boolean sawNumericTest, sawNumericTestOld, sawNumericTestVeryOld; 42 boolean sawArrayDanger, sawArrayDangerOld; 43 44 private BugReporter bugReporter; 45 46 public FindNonShortCircuit(BugReporter bugReporter) { 47 this.bugReporter = bugReporter; 48 } 49 50 OpcodeStack stack = new OpcodeStack(); 51 52 @Override 53 public void visit(Method obj) { 54 stack.resetForMethodEntry(this); 55 stage1 = 0; 56 stage2 = 0; 57 distance = 1000000; 58 sawArrayDanger = sawArrayDangerOld = false; 59 sawDanger = sawDangerOld = false; 60 sawNullTest = sawNullTestOld = sawNullTestVeryOld = false; 61 sawNumericTest = sawNumericTestOld = sawNumericTestVeryOld = false; 62 prevOpcode = NOP; 63 } 64 65 int prevOpcode; 66 @Override 67 public void sawOpcode(int seen) { 68 stack.mergeJumps(this); 69 distance++; 72 scanForBooleanValue(seen); 73 scanForDanger(seen); 74 scanForShortCircuit(seen); 75 stack.sawOpcode(this, seen); 76 prevOpcode = seen; 77 } 78 79 private void scanForDanger(int seen) { 80 switch (seen) { 81 case AALOAD: 82 case BALOAD: 83 case SALOAD: 84 case CALOAD: 85 case IALOAD: 86 case LALOAD: 87 case FALOAD: 88 case DALOAD: 89 sawArrayDanger = true; 90 sawDanger = true; 91 break; 92 93 case INVOKEINTERFACE: 94 case INVOKESPECIAL: 95 case INVOKEVIRTUAL: 96 case INVOKESTATIC: 97 case ARRAYLENGTH: 98 case IDIV: 99 case IREM: 100 case GETFIELD: 101 sawDanger = true; 102 break; 103 default: 104 break; 105 } 106 107 } 108 109 private void scanForShortCircuit(int seen) { 110 switch (seen) { 111 case IAND: 112 case IOR: 113 OpcodeStack.Item item0 = stack.getStackItem(0); 115 OpcodeStack.Item item1 = stack.getStackItem(1); 116 if (item0.getConstant() == null && item1.getConstant() == null && distance < 4) { 117 operator = seen; 118 stage2 = 1; 119 } else 120 stage2 = 0; 121 break; 122 case IFEQ: 123 case IFNE: 124 if (stage2 == 1) { 125 reportBug(); 127 } 128 stage2 = 0; 129 break; 130 case PUTFIELD: 131 case PUTSTATIC: 132 case IRETURN: 133 if (operator == IAND && stage2 == 1) { 134 reportBug(); 135 } 136 stage2 = 0; 137 break; 138 default: 139 stage2 = 0; 140 break; 141 } 142 } 143 144 private void reportBug() { 145 int priority = LOW_PRIORITY; 146 if (sawDangerOld) 147 if (sawNullTestVeryOld) priority = HIGH_PRIORITY; 148 else if (sawNumericTestVeryOld && sawArrayDangerOld) priority = HIGH_PRIORITY; 149 else priority = NORMAL_PRIORITY; 150 151 bugReporter.reportBug(new BugInstance(this, "NS_NON_SHORT_CIRCUIT", 152 priority) 153 .addClassAndMethod(this).addSourceLine(this, getPC())); 154 } 155 156 157 private void scanForBooleanValue(int seen) { 158 switch (seen) { 159 160 case ICONST_1: 161 stage1 = 1; 162 switch(prevOpcode) { 163 case IFNONNULL: 164 case IFNULL: 165 sawNullTest = true; 166 break; 167 case IF_ICMPGT: 168 case IF_ICMPGE: 169 case IF_ICMPLT: 170 case IF_ICMPLE: 171 sawNumericTest = true; 172 break; 173 } 174 175 break; 176 case GOTO: 177 if (stage1 == 1) 178 stage1 = 2; 179 else 180 stage1 = 0; 181 break; 182 case ICONST_0: 183 if (stage1 == 2) 184 sawBooleanValue(); 185 stage1 = 0; 186 break; 187 case INVOKEINTERFACE: 188 case INVOKEVIRTUAL: 189 case INVOKESPECIAL: 190 case INVOKESTATIC: 191 String sig = getSigConstantOperand(); 192 if (sig.endsWith(")Z")) 193 sawBooleanValue(); 194 stage1 = 0; 195 break; 196 default: 197 stage1 = 0; 198 } 199 } 200 201 private void sawBooleanValue() { 202 sawDangerOld = sawDanger; 203 sawArrayDangerOld = sawArrayDanger; 204 sawNullTestVeryOld = sawNullTestOld; 205 sawNullTestOld = sawNullTest; 206 sawNumericTestVeryOld = sawNumericTestOld; 207 sawNumericTestOld = sawNumericTest; 208 sawNumericTest = false; 209 sawDanger = false; 210 sawArrayDanger = false; 211 distance = 0; 212 stage1 = 0; 213 214 } 215 } 216 | Popular Tags |