View Javadoc

1   /*
2    * Created on Jan 17, 2005 
3    *
4    * $Id: ArrayIsStoredDirectly.java,v 1.17 2006/10/25 19:40:45 xlv Exp $
5    */
6   package net.sourceforge.pmd.rules.sunsecure;
7   
8   import net.sourceforge.pmd.ast.ASTAssignmentOperator;
9   import net.sourceforge.pmd.ast.ASTBlockStatement;
10  import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
11  import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
12  import net.sourceforge.pmd.ast.ASTEqualityExpression;
13  import net.sourceforge.pmd.ast.ASTExpression;
14  import net.sourceforge.pmd.ast.ASTFormalParameter;
15  import net.sourceforge.pmd.ast.ASTFormalParameters;
16  import net.sourceforge.pmd.ast.ASTMethodDeclaration;
17  import net.sourceforge.pmd.ast.ASTPrimaryExpression;
18  import net.sourceforge.pmd.ast.ASTPrimarySuffix;
19  import net.sourceforge.pmd.ast.ASTStatementExpression;
20  import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
21  import net.sourceforge.pmd.ast.SimpleNode;
22  
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Vector;
26  
27  /***
28   * @author mgriffa
29   */
30  public class ArrayIsStoredDirectly extends AbstractSunSecureRule {
31  
32      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
33          if (node.isInterface()) {
34              return data;
35          }
36          return super.visit(node, data);
37      }
38  
39      public Object visit(ASTConstructorDeclaration node, Object data) {
40          ASTFormalParameter[] arrs = getArrays(node.getParameters());
41          if (arrs != null) {
42              //TODO check if one of these arrays is stored in a non local variable
43              List bs = node.findChildrenOfType(ASTBlockStatement.class);
44              checkAll(data, arrs, bs);
45          }
46          return data;
47      }
48  
49      public Object visit(ASTMethodDeclaration node, Object data) {
50          final ASTFormalParameters params = (ASTFormalParameters) node.getFirstChildOfType(ASTFormalParameters.class);
51          ASTFormalParameter[] arrs = getArrays(params);
52          if (arrs != null) {
53              checkAll(data, arrs, node.findChildrenOfType(ASTBlockStatement.class));
54          }
55          return data;
56      }
57  
58      private void checkAll(Object context, ASTFormalParameter[] arrs, List bs) {
59          for (int i = 0; i < arrs.length; i++) {
60              checkForDirectAssignment(context, arrs[i], bs);
61          }
62      }
63  
64      /***
65       * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
66       */
67      private boolean checkForDirectAssignment(Object ctx, final ASTFormalParameter parameter, final List bs) {
68          final ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
69          final String varName = vid.getImage();
70          for (Iterator it = bs.iterator(); it.hasNext();) {
71              final ASTBlockStatement b = (ASTBlockStatement) it.next();
72              if (b.containsChildOfType(ASTAssignmentOperator.class)) {
73                  final ASTStatementExpression se = (ASTStatementExpression) b.getFirstChildOfType(ASTStatementExpression.class);
74                  if (se == null || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
75                      continue;
76                  }
77                  ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
78                  String assignedVar = getFirstNameImage(pe);
79                  if (assignedVar == null) {
80                      ASTPrimarySuffix suffix = (ASTPrimarySuffix) se.getFirstChildOfType(ASTPrimarySuffix.class);
81                      if (suffix == null) {
82                          continue;
83                      }
84                      assignedVar = suffix.getImage();
85                  }
86  
87                  SimpleNode n = (ASTMethodDeclaration) pe.getFirstParentOfType(ASTMethodDeclaration.class);
88                  if (n == null) {
89  					n = (ASTConstructorDeclaration) pe.getFirstParentOfType(ASTConstructorDeclaration.class);
90  					if (n == null) {
91  						continue;
92  					}
93  				}
94                  if (!isLocalVariable(assignedVar, n)) {
95                      // TODO could this be more clumsy?  We really
96                      // need to build out the PMD internal framework more
97                      // to support simply queries like "isAssignedTo()" or something
98                      if (se.jjtGetNumChildren() < 3) {
99                          continue;
100                     }
101                     ASTExpression e = (ASTExpression) se.jjtGetChild(2);
102                     if (e.findChildrenOfType(ASTEqualityExpression.class).size() > 0) {
103                         continue;
104                     }
105                     String val = getFirstNameImage(e);
106                     if (val == null) {
107                         ASTPrimarySuffix foo = (ASTPrimarySuffix) se.getFirstChildOfType(ASTPrimarySuffix.class);
108                         if (foo == null) {
109                             continue;
110                         }
111                         val = foo.getImage();
112                     }
113                     if (val == null) {
114                         continue;
115                     }
116                     ASTPrimarySuffix foo = (ASTPrimarySuffix) se.getFirstChildOfType(ASTPrimarySuffix.class);
117                     if (foo != null && foo.isArrayDereference()) {
118                         continue;
119                     }
120 
121                     if (val.equals(varName)) {
122                         SimpleNode md = (ASTMethodDeclaration) parameter.getFirstParentOfType(ASTMethodDeclaration.class);
123                         if (md == null) {
124                         	md = (ASTConstructorDeclaration) pe.getFirstParentOfType(ASTConstructorDeclaration.class);
125         				}
126                         if (!isLocalVariable(varName, md)) {
127                             addViolation(ctx, parameter, varName);
128                         }
129                     }
130                 }
131             }
132         }
133         return false;
134     }
135 
136     private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
137         final List l = params.findChildrenOfType(ASTFormalParameter.class);
138         if (l != null && !l.isEmpty()) {
139             Vector v = new Vector();
140             for (Iterator it = l.iterator(); it.hasNext();) {
141                 ASTFormalParameter fp = (ASTFormalParameter) it.next();
142                 if (fp.isArray())
143                     v.add(fp);
144             }
145             return (ASTFormalParameter[]) v.toArray(new ASTFormalParameter[v.size()]);
146         }
147         return null;
148     }
149 
150 }