[Fb-contrib-commit] SF.net SVN: fb-contrib:[1101] trunk/fb-contrib/src/com/mebigfatguy/ fbcontrib/
Brought to you by:
dbrosius
From: <dbr...@us...> - 2009-02-22 03:48:07
|
Revision: 1101 http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=1101&view=rev Author: dbrosius Date: 2009-02-22 03:48:02 +0000 (Sun, 22 Feb 2009) Log Message: ----------- CLI ignores array access from strings arrays returned from String.split Modified Paths: -------------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConstantListIndex.java Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConstantListIndex.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConstantListIndex.java 2009-02-22 03:20:25 UTC (rev 1100) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConstantListIndex.java 2009-02-22 03:48:02 UTC (rev 1101) @@ -31,7 +31,9 @@ import edu.umd.cs.findbugs.BugInstance; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.BytecodeScanningDetector; +import edu.umd.cs.findbugs.OpcodeStack; import edu.umd.cs.findbugs.ba.ClassContext; +import edu.umd.cs.findbugs.ba.XMethod; /** * looks for methods that access arrays or classes that implement java.util.List @@ -45,11 +47,17 @@ private static final int SEEN_NOTHING = 0; private static final int SEEN_CONSTANT_0 = 1; private static final int SEEN_CONSTANT = 2; + private static final Set<String> ubiquitousMethods = new HashSet<String>(); + static { + ubiquitousMethods.add("java.lang.String.split(Ljava/lang/String;)[Ljava/lang/String;"); + } - private BugReporter bugReporter; + + private final BugReporter bugReporter; private int state; private Set<Integer> iConst0Looped; - private int max_iConst0LoopDistance; + private final int max_iConst0LoopDistance; + private OpcodeStack stack; /** * constructs a CLI detector given the reporter to report bugs on @@ -69,9 +77,11 @@ public void visitClassContext(ClassContext classContext) { try { iConst0Looped = new HashSet<Integer>(); + stack = new OpcodeStack(); super.visitClassContext(classContext); } finally { iConst0Looped = null; + stack = null; } } @@ -84,6 +94,7 @@ public void visitMethod(Method obj) { state = SEEN_NOTHING; iConst0Looped.clear(); + stack.resetForMethodEntry(this); } /** @@ -93,79 +104,104 @@ */ @Override public void sawOpcode(int seen) { - - switch (state) { - case SEEN_NOTHING: - if (seen == ICONST_0) - state = SEEN_CONSTANT_0; - else if ((seen >= ICONST_1) && (seen <= ICONST_5)) - state = SEEN_CONSTANT; - else if ((seen == LDC) || (seen == LDC_W)) { - Constant c = getConstantRefOperand(); - if (c instanceof ConstantInteger) + try { + switch (state) { + case SEEN_NOTHING: + if (seen == ICONST_0) + state = SEEN_CONSTANT_0; + else if ((seen >= ICONST_1) && (seen <= ICONST_5)) state = SEEN_CONSTANT; - } - break; - - case SEEN_CONSTANT_0: - case SEEN_CONSTANT: - switch (seen) { - case AALOAD: - if ("main".equals(this.getMethodName())) - break; - //FALL THRU - case IALOAD: - case LALOAD: - case FALOAD: - case DALOAD: - //case BALOAD: byte and char indexing seems prevalent, and - //case CALOAD: usually harmless so ignore - case SALOAD: - if (state == SEEN_CONSTANT_0) - iConst0Looped.add(Integer14.valueOf(getPC())); - else { - bugReporter.reportBug(new BugInstance(this, "CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY) + else if ((seen == LDC) || (seen == LDC_W)) { + Constant c = getConstantRefOperand(); + if (c instanceof ConstantInteger) + state = SEEN_CONSTANT; + } + break; + + case SEEN_CONSTANT_0: + case SEEN_CONSTANT: + switch (seen) { + case AALOAD: + if ("main".equals(this.getMethodName())) + break; + //FALL THRU + case IALOAD: + case LALOAD: + case FALOAD: + case DALOAD: + //case BALOAD: byte and char indexing seems prevalent, and + //case CALOAD: usually harmless so ignore + case SALOAD: + if (state == SEEN_CONSTANT_0) + iConst0Looped.add(Integer14.valueOf(getPC())); + else { + if (stack.getStackDepth() > 1) { + OpcodeStack.Item item = stack.getStackItem(1); + if (!isArrayFromUbiquitousMethod(item)) { + bugReporter.reportBug(new BugInstance(this, "CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this)); - } - break; - - case INVOKEVIRTUAL: - if ("java/util/List".equals(getClassConstantOperand())) { - String methodName = getNameConstantOperand(); - if ("get".equals(methodName)) { - if (state == SEEN_CONSTANT_0) - iConst0Looped.add(Integer14.valueOf(getPC())); - else { - bugReporter.reportBug(new BugInstance(this, "CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); + } } + } + break; + + case INVOKEVIRTUAL: + if ("java/util/List".equals(getClassConstantOperand())) { + String methodName = getNameConstantOperand(); + if ("get".equals(methodName)) { + if (state == SEEN_CONSTANT_0) + iConst0Looped.add(Integer14.valueOf(getPC())); + else { + bugReporter.reportBug(new BugInstance(this, "CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this)); + } + } + } + break; + } + state = SEEN_NOTHING; + break; + } + + if (((seen >= IFEQ) && (seen <= GOTO)) || (seen == GOTO_W)) { + int branchTarget = this.getBranchTarget(); + Iterator<Integer> it = iConst0Looped.iterator(); + while (it.hasNext()) { + int bugPC = it.next().intValue(); + if (branchTarget < bugPC) { + if ((bugPC - branchTarget) < max_iConst0LoopDistance) { + bugReporter.reportBug(new BugInstance(this, "CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this, bugPC)); } - break; - } - state = SEEN_NOTHING; - break; - } - - if (((seen >= IFEQ) && (seen <= GOTO)) || (seen == GOTO_W)) { - int branchTarget = this.getBranchTarget(); - Iterator<Integer> it = iConst0Looped.iterator(); - while (it.hasNext()) { - int bugPC = it.next().intValue(); - if (branchTarget < bugPC) { - if ((bugPC - branchTarget) < max_iConst0LoopDistance) { - bugReporter.reportBug(new BugInstance(this, "CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this, bugPC)); + it.remove(); } - it.remove(); } } + } finally { + stack.sawOpcode(this, seen); } } + + /** + * returns whether the array item was returned from a common method that the user can't do anything about + * and so don't report CLI in this case. + * + * @param item the stack item representing the array + * @return if the array was returned from a common method + */ + private boolean isArrayFromUbiquitousMethod(OpcodeStack.Item item) { + XMethod method = item.getReturnValueOf(); + if (method == null) + return false; + + String methodDesc = method.getClassName() + '.' + method.getName() + method.getSignature(); + return ubiquitousMethods.contains(methodDesc); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |