KickJava   Java API By Example, From Geeks To Geeks.

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


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

19
20 package edu.umd.cs.findbugs.detect;
21
22 import java.util.regex.Pattern JavaDoc;
23 import java.util.regex.PatternSyntaxException JavaDoc;
24
25 import org.apache.bcel.classfile.Code;
26 import org.apache.bcel.classfile.JavaClass;
27 import org.apache.bcel.classfile.Method;
28
29 import edu.umd.cs.findbugs.BugInstance;
30 import edu.umd.cs.findbugs.BugReporter;
31 import edu.umd.cs.findbugs.BytecodeScanningDetector;
32 import edu.umd.cs.findbugs.OpcodeStack;
33 import edu.umd.cs.findbugs.StatelessDetector;
34
35 public class BadSyntaxForRegularExpression
36 extends BytecodeScanningDetector {
37
38     BugReporter bugReporter;
39
40     public BadSyntaxForRegularExpression(BugReporter bugReporter) {
41         this.bugReporter = bugReporter;
42     }
43
44
45
46     @Override JavaDoc
47     public void visit(JavaClass obj) {
48     }
49
50     @Override JavaDoc
51     public void visit(Method obj) {
52     }
53
54     OpcodeStack stack = new OpcodeStack();
55     @Override JavaDoc
56     public void visit(Code obj) {
57     stack.resetForMethodEntry(this);
58         super.visit(obj);
59     }
60
61     private void singleDotPatternWouldBeSilly(int stackDepth, boolean ignorePasswordMasking) {
62         if (ignorePasswordMasking && stackDepth != 1)
63             throw new IllegalArgumentException JavaDoc("Password masking requires stack depth 1, but is " + stackDepth);
64         if (stack.getStackDepth() < stackDepth) return;
65         OpcodeStack.Item it = stack.getStackItem(stackDepth);
66         Object JavaDoc value = it.getConstant();
67         if (value == null || !(value instanceof String JavaDoc)) return;
68         String JavaDoc regex = (String JavaDoc) value;
69         if (!regex.equals(".")) return;
70         if (ignorePasswordMasking) {
71               OpcodeStack.Item top = stack.getStackItem(0);
72               Object JavaDoc topValue = top.getConstant();
73               if (topValue instanceof String JavaDoc) {
74                   String JavaDoc replacementString = (String JavaDoc) topValue;
75                   if (replacementString.length() == 1 && replacementString.toLowerCase().equals("x") || replacementString.equals("*") || replacementString.equals("\\*")) return;
76               }
77               
78         }
79         
80         
81        bugReporter.reportBug(new BugInstance(this, "RE_POSSIBLE_UNINTENDED_PATTERN",
82                 NORMAL_PRIORITY)
83                                 .addClassAndMethod(this)
84                                 .addSourceLine(this)
85                 );
86     }
87
88     private void sawRegExPattern(int stackDepth) {
89         sawRegExPattern(stackDepth, 0);
90     }
91     private void sawRegExPattern(int stackDepth, int flags) {
92         if (stack.getStackDepth() < stackDepth) return;
93         OpcodeStack.Item it = stack.getStackItem(stackDepth);
94         if (it.getSpecialKind() == OpcodeStack.Item.FILE_SEPARATOR_STRING && (flags & Pattern.LITERAL) == 0) {
95               bugReporter.reportBug(new BugInstance(this, "RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION",
96                     HIGH_PRIORITY)
97                                       .addClassAndMethod(this)
98                                       .addSourceLine(this)
99                     );
100               return;
101         }
102         Object JavaDoc value = it.getConstant();
103         if (value == null || !(value instanceof String JavaDoc)) return;
104         String JavaDoc regex = (String JavaDoc) value;
105         try {
106             Pattern.compile(regex, flags);
107         } catch (PatternSyntaxException JavaDoc e) {
108           bugReporter.reportBug(new BugInstance(this, "RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION",
109                 HIGH_PRIORITY)
110                                 .addClassAndMethod(this)
111                                 .addSourceLine(this)
112                 );
113         }
114     }
115
116     /** return an int on the stack, or 'defaultValue' if can't determine */
117     private int getIntValue(int stackDepth, int defaultValue) {
118         if (stack.getStackDepth() < stackDepth) return defaultValue;
119         OpcodeStack.Item it = stack.getStackItem(stackDepth);
120         Object JavaDoc value = it.getConstant();
121         if (value == null || !(value instanceof Integer JavaDoc)) return defaultValue;
122         return ((Number JavaDoc)value).intValue();
123     }
124
125     @Override JavaDoc
126     public void sawOpcode(int seen) {
127         stack.mergeJumps(this);
128         if (seen == INVOKESTATIC
129             && getClassConstantOperand().equals("java/util/regex/Pattern")
130             && getNameConstantOperand().equals("compile")
131             && getSigConstantOperand().startsWith("(Ljava/lang/String;I)")
132             )
133             sawRegExPattern(1, getIntValue(0, 0));
134         else if (seen == INVOKESTATIC
135             && getClassConstantOperand().equals("java/util/regex/Pattern")
136             && getNameConstantOperand().equals("compile")
137             && getSigConstantOperand().startsWith("(Ljava/lang/String;)")
138             )
139             sawRegExPattern(0);
140         else if (seen == INVOKESTATIC
141             && getClassConstantOperand().equals("java/util/regex/Pattern")
142             && getNameConstantOperand().equals("matches")
143             )
144             sawRegExPattern(1);
145         else if (seen == INVOKEVIRTUAL
146             && getClassConstantOperand().equals("java/lang/String")
147             && getNameConstantOperand().equals("replaceAll")
148             ) {
149             sawRegExPattern(1);
150             singleDotPatternWouldBeSilly(1, true);
151             }
152         else if (seen == INVOKEVIRTUAL
153             && getClassConstantOperand().equals("java/lang/String")
154             && getNameConstantOperand().equals("replaceFirst")
155             )
156         {
157             sawRegExPattern(1);
158             singleDotPatternWouldBeSilly(1, false);
159             }
160         else if (seen == INVOKEVIRTUAL
161             && getClassConstantOperand().equals("java/lang/String")
162             && getNameConstantOperand().equals("matches")
163             )
164         {
165             sawRegExPattern(0);
166             singleDotPatternWouldBeSilly(0, false);
167             }
168         else if (seen == INVOKEVIRTUAL
169             && getClassConstantOperand().equals("java/lang/String")
170             && getNameConstantOperand().equals("split")
171             )
172         {
173             sawRegExPattern(0);
174             singleDotPatternWouldBeSilly(0, false);
175             }
176
177         stack.sawOpcode(this,seen);
178     }
179
180 }
181
Popular Tags