View Javadoc

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