diff --git a/pmd/etc/changelog.txt b/pmd/etc/changelog.txt index 23d9bafc08..31ac20ce27 100644 --- a/pmd/etc/changelog.txt +++ b/pmd/etc/changelog.txt @@ -1,5 +1,6 @@ ????? ??, 2013 - 5.0.3: +Fixed bug 942: CheckResultSet False Positive and Negative Fixed bug 943: PreserveStackTrace false positive if a StringBuffer exists Fixed bug 945: PMD generates RuleSets it cannot read. Fixed bug 958: Intermittent NullPointerException while loading XPath node attributes diff --git a/pmd/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/CheckResultSetRule.java b/pmd/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/CheckResultSetRule.java new file mode 100644 index 0000000000..7dc925cbd5 --- /dev/null +++ b/pmd/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/CheckResultSetRule.java @@ -0,0 +1,81 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.lang.java.rule.basic; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; +import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; +import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTName; +import net.sourceforge.pmd.lang.java.ast.ASTType; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; + +/** + * Rule that verifies, that the return values of next(), first(), last(), etc. + * calls to a java.sql.ResultSet are actually verified. + * + */ +public class CheckResultSetRule extends AbstractJavaRule { + + private Map resultSetVariables = new HashMap(); + + private static Set methods = new HashSet(); + static { + methods.add(".next"); + methods.add(".previous"); + methods.add(".last"); + methods.add(".first"); + } + + @Override + public Object visit(ASTLocalVariableDeclaration node, Object data) { + ASTClassOrInterfaceType type = node.getFirstChildOfType(ASTType.class).getFirstDescendantOfType(ASTClassOrInterfaceType.class); + if (type != null + && ((type.getType() != null && "java.sql.ResultSet".equals(type.getType().getName())) || "ResultSet" + .equals(type.getImage()))) { + ASTVariableDeclarator declarator = node.getFirstChildOfType(ASTVariableDeclarator.class); + if (declarator != null) { + ASTName name = declarator.getFirstDescendantOfType(ASTName.class); + if (name != null && name.getImage().endsWith("executeQuery")) { + + ASTVariableDeclaratorId id = declarator.getFirstChildOfType(ASTVariableDeclaratorId.class); + resultSetVariables.put(id.getImage(), node); + } + } + } + return super.visit(node, data); + } + + @Override + public Object visit(ASTName node, Object data) { + String image = node.getImage(); + String var = getResultSetVariableName(image); + if (var != null && resultSetVariables.containsKey(var) + && node.getFirstParentOfType(ASTIfStatement.class)== null + && node.getFirstParentOfType(ASTWhileStatement.class) == null) { + + addViolation(data, resultSetVariables.get(var)); + } + return super.visit(node, data); + } + + private String getResultSetVariableName(String image) { + if (image.contains(".")) { + for (String method : methods) { + if (image.endsWith(method)) { + return image.substring(0, image.lastIndexOf(method)); + } + } + } + return null; + } +} diff --git a/pmd/src/main/resources/rulesets/java/basic.xml b/pmd/src/main/resources/rulesets/java/basic.xml index 9a23eae381..9a98ee5c20 100644 --- a/pmd/src/main/resources/rulesets/java/basic.xml +++ b/pmd/src/main/resources/rulesets/java/basic.xml @@ -553,7 +553,7 @@ public class Foo { @@ -563,47 +563,6 @@ If the value return is 'false', it should be handled properly. ]]> 3 - - - - - - - 0) { + _count--; + } while (rst.next()) { firsString = rst.getString(1); @@ -98,4 +102,63 @@ ]]> + + + #942 CheckResultSet False Positive + 1 + +