KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > detect > SuspiciousThreadInterrupted


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2004-2005 Dave Brosius <dbrosius@users.sourceforge.net>
4  * Copyright (C) 2004-2005 University of Maryland
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */

20
21 package edu.umd.cs.findbugs.detect;
22
23
24 import edu.umd.cs.findbugs.*;
25 import java.util.BitSet JavaDoc;
26 import org.apache.bcel.classfile.Method;
27
28 /**
29  * looks for calls to Thread.interrupted from a non static context, especially when that context is
30  * not 'currentThread()'.
31  */

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 JavaDoc localsWithCurrentThreadValue;
40     private int state;
41
42     public SuspiciousThreadInterrupted(BugReporter bugReporter) {
43         this.bugReporter = bugReporter;
44     }
45
46
47
48     @Override JavaDoc
49     public void visit(Method obj) {
50         localsWithCurrentThreadValue = new BitSet JavaDoc();
51         state = SEEN_NOTHING;
52         super.visit(obj);
53     }
54
55     @Override JavaDoc
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 //vim:ts=4
126
Popular Tags