001 /*
002 * Created on Jan 17, 2005
003 *
004 * $Id: ArrayIsStoredDirectlyRule.java 6245 2008-06-22 18:07:30Z xlv $
005 */
006 package net.sourceforge.pmd.lang.java.rule.sunsecure;
007
008 import java.util.ArrayList;
009 import java.util.List;
010
011 import net.sourceforge.pmd.lang.ast.Node;
012 import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
013 import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
014 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
015 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
016 import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
017 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
018 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
019 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters;
020 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
021 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
022 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
023 import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
024 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
025
026 /**
027 * @author mgriffa
028 */
029 public class ArrayIsStoredDirectlyRule extends AbstractSunSecureRule {
030
031 @Override
032 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
033 if (node.isInterface()) {
034 return data;
035 }
036 return super.visit(node, data);
037 }
038
039 @Override
040 public Object visit(ASTConstructorDeclaration node, Object data) {
041 ASTFormalParameter[] arrs = getArrays(node.getParameters());
042 if (arrs != null) {
043 //TODO check if one of these arrays is stored in a non local variable
044 List<ASTBlockStatement> bs = node.findDescendantsOfType(ASTBlockStatement.class);
045 checkAll(data, arrs, bs);
046 }
047 return data;
048 }
049
050 @Override
051 public Object visit(ASTMethodDeclaration node, Object data) {
052 final ASTFormalParameters params = node.getFirstDescendantOfType(ASTFormalParameters.class);
053 ASTFormalParameter[] arrs = getArrays(params);
054 if (arrs != null) {
055 checkAll(data, arrs, node.findDescendantsOfType(ASTBlockStatement.class));
056 }
057 return data;
058 }
059
060 private void checkAll(Object context, ASTFormalParameter[] arrs, List<ASTBlockStatement> bs) {
061 for (ASTFormalParameter element : arrs) {
062 checkForDirectAssignment(context, element, bs);
063 }
064 }
065
066 /**
067 * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
068 */
069 private boolean checkForDirectAssignment(Object ctx, final ASTFormalParameter parameter, final List<ASTBlockStatement> bs) {
070 final ASTVariableDeclaratorId vid = parameter.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
071 final String varName = vid.getImage();
072 for (ASTBlockStatement b: bs) {
073 if (b.hasDescendantOfType(ASTAssignmentOperator.class)) {
074 final ASTStatementExpression se = b.getFirstDescendantOfType(ASTStatementExpression.class);
075 if (se == null || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
076 continue;
077 }
078 ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
079 String assignedVar = getFirstNameImage(pe);
080 if (assignedVar == null) {
081 ASTPrimarySuffix suffix = se.getFirstDescendantOfType(ASTPrimarySuffix.class);
082 if (suffix == null) {
083 continue;
084 }
085 assignedVar = suffix.getImage();
086 }
087
088 Node n = pe.getFirstParentOfType(ASTMethodDeclaration.class);
089 if (n == null) {
090 n = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
091 if (n == null) {
092 continue;
093 }
094 }
095 if (!isLocalVariable(assignedVar, n)) {
096 // TODO could this be more clumsy? We really
097 // need to build out the PMD internal framework more
098 // to support simply queries like "isAssignedTo()" or something
099 if (se.jjtGetNumChildren() < 3) {
100 continue;
101 }
102 ASTExpression e = (ASTExpression) se.jjtGetChild(2);
103 if (e.hasDescendantOfType(ASTEqualityExpression.class)) {
104 continue;
105 }
106 String val = getFirstNameImage(e);
107 if (val == null) {
108 ASTPrimarySuffix foo = se.getFirstDescendantOfType(ASTPrimarySuffix.class);
109 if (foo == null) {
110 continue;
111 }
112 val = foo.getImage();
113 }
114 if (val == null) {
115 continue;
116 }
117 ASTPrimarySuffix foo = se.getFirstDescendantOfType(ASTPrimarySuffix.class);
118 if (foo != null && foo.isArrayDereference()) {
119 continue;
120 }
121
122 if (val.equals(varName)) {
123 Node md = parameter.getFirstParentOfType(ASTMethodDeclaration.class);
124 if (md == null) {
125 md = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
126 }
127 if (!isLocalVariable(varName, md)) {
128 addViolation(ctx, parameter, varName);
129 }
130 }
131 }
132 }
133 }
134 return false;
135 }
136
137 private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
138 final List<ASTFormalParameter> l = params.findChildrenOfType(ASTFormalParameter.class);
139 if (l != null && !l.isEmpty()) {
140 List<ASTFormalParameter> l2 = new ArrayList<ASTFormalParameter>();
141 for (ASTFormalParameter fp: l) {
142 if (fp.isArray()) {
143 l2.add(fp);
144 }
145 }
146 return l2.toArray(new ASTFormalParameter[l2.size()]);
147 }
148 return null;
149 }
150
151 }
|