1 20 21 package edu.umd.cs.findbugs.detect; 22 23 24 import edu.umd.cs.findbugs.*; 25 import java.util.BitSet ; 26 import org.apache.bcel.classfile.Method; 27 28 32 public class SuspiciousThreadInterrupted extends BytecodeScanningDetector implements StatelessDetector { 33 public static final int SEEN_NOTHING = 0; 34 public static final int SEEN_CURRENTTHREAD = 1; 35 public static final int SEEN_POP_AFTER_CURRENTTHREAD = 2; 36 public static final int SEEN_UNKNOWNCONTEXT_POP = 3; 37 public static final int SEEN_POSSIBLE_THREAD = 4; 38 private BugReporter bugReporter; 39 private BitSet localsWithCurrentThreadValue; 40 private int state; 41 42 public SuspiciousThreadInterrupted(BugReporter bugReporter) { 43 this.bugReporter = bugReporter; 44 } 45 46 47 48 @Override 49 public void visit(Method obj) { 50 localsWithCurrentThreadValue = new BitSet (); 51 state = SEEN_NOTHING; 52 super.visit(obj); 53 } 54 55 @Override 56 public void sawOpcode(int seen) { 57 58 if (state == SEEN_POSSIBLE_THREAD) { 59 if (seen == POP) { 60 state = SEEN_UNKNOWNCONTEXT_POP; 61 return; 62 } 63 else state = SEEN_NOTHING; 64 } 65 switch (state) { 66 case SEEN_NOTHING: 67 if ((seen == INVOKESTATIC) 68 && getClassConstantOperand().equals("java/lang/Thread") 69 && getNameConstantOperand().equals("currentThread") 70 && getSigConstantOperand().equals("()Ljava/lang/Thread;")) 71 state = SEEN_CURRENTTHREAD; 72 else if ((seen == INVOKESTATIC || seen == INVOKEINTERFACE 73 || seen == INVOKEVIRTUAL || seen == INVOKESPECIAL) 74 && getSigConstantOperand().endsWith("Ljava/lang/Thread;")) 75 state = SEEN_POSSIBLE_THREAD; 76 else if (seen == ALOAD) { 77 if (localsWithCurrentThreadValue.get(getRegisterOperand())) { 78 state = SEEN_CURRENTTHREAD; 79 } else state = SEEN_POSSIBLE_THREAD; 80 } else if ((seen >= ALOAD_0) && (seen <= ALOAD_3)) { 81 if (localsWithCurrentThreadValue.get(seen - ALOAD_0)) { 82 state = SEEN_CURRENTTHREAD; 83 } else state = SEEN_POSSIBLE_THREAD; 84 } else if ((seen == GETFIELD || seen == GETSTATIC) 85 && getSigConstantOperand().equals("Ljava/lang/Thread;")) 86 state = SEEN_POSSIBLE_THREAD; 87 break; 88 89 case SEEN_CURRENTTHREAD: 90 if (seen == POP) { 91 state = SEEN_POP_AFTER_CURRENTTHREAD; 92 } 93 else if (seen == ASTORE) { 94 localsWithCurrentThreadValue.set(getRegisterOperand()); 95 state = SEEN_NOTHING; 96 } else if ((seen >= ASTORE_0) && (seen <= ASTORE_3)) { 97 localsWithCurrentThreadValue.set(seen - ASTORE_0); 98 state = SEEN_NOTHING; 99 } else { 100 state = SEEN_NOTHING; 101 } 102 break; 103 104 default: 105 if ((seen == INVOKESTATIC) 106 && getClassConstantOperand().equals("java/lang/Thread") 107 && getNameConstantOperand().equals("interrupted") 108 && getSigConstantOperand().equals("()Z")) { 109 if (state == SEEN_POP_AFTER_CURRENTTHREAD) { 110 bugReporter.reportBug(new BugInstance(this, "STI_INTERRUPTED_ON_CURRENTTHREAD", LOW_PRIORITY) 111 .addClassAndMethod(this) 112 .addSourceLine(this)); 113 } else if (state == SEEN_UNKNOWNCONTEXT_POP) { 114 bugReporter.reportBug(new BugInstance(this, "STI_INTERRUPTED_ON_UNKNOWNTHREAD", NORMAL_PRIORITY) 115 .addClassAndMethod(this) 116 .addSourceLine(this)); 117 } 118 } 119 state = SEEN_NOTHING; 120 break; 121 } 122 } 123 } 124 125 | Popular Tags |