View Javadoc

1   /*
2    * Created on Jan 17, 2005 
3    *
4    * $Id: ArrayIsStoredDirectly.java,v 1.6 2005/03/08 20:23:27 tomcopeland Exp $
5    */
6   package net.sourceforge.pmd.rules.sunsecure;
7   
8   import net.sourceforge.pmd.RuleContext;
9   import net.sourceforge.pmd.ast.ASTAssignmentOperator;
10  import net.sourceforge.pmd.ast.ASTBlockStatement;
11  import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
12  import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
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   * 
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      /***
40       * Overriden method.
41       * 
42       * @see net.sourceforge.pmd.ast.JavaParserVisitor#visit(net.sourceforge.pmd.ast.ASTConstructorDeclaration, java.lang.Object)
43       */
44      public Object visit(ASTConstructorDeclaration node, Object data) {
45          ASTFormalParameter[] arrs = getArrays((ASTFormalParameters) node.jjtGetChild(0));
46          if (arrs!=null) {
47              //TODO check if one of these arrays is stored in a non local variable
48              List bs = node.findChildrenOfType(ASTBlockStatement.class);
49              checkDirectlyAssigned((RuleContext)data, arrs, bs);
50          }
51          return data;
52      }
53      
54      private void checkDirectlyAssigned(RuleContext context, ASTFormalParameter[] arrs, List bs) {
55          for (int i=0;i<arrs.length;i++) {
56              if (isDirectlyAssigned(arrs[i], bs)) {
57                  addViolation(context, arrs[i]);
58              }   
59          }
60      }
61      
62      /***
63       * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
64       */
65      private boolean isDirectlyAssigned(final ASTFormalParameter parameter, final List bs) {
66          final ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
67          final String varName = vid.getImage();
68          for (Iterator it = bs.iterator() ; it.hasNext() ; ) {
69              final ASTBlockStatement b = (ASTBlockStatement) it.next();
70              if (b.containsChildOfType(ASTAssignmentOperator.class)) {
71                  final ASTStatementExpression se = (ASTStatementExpression) b.getFirstChildOfType(ASTStatementExpression.class);
72                  if (se == null) {
73                      continue;
74                  }
75                  if (!(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
76                      continue;
77                  }
78                  ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
79                  String assignedVar = getFirstNameImage(pe);
80                  if (assignedVar==null) {
81                      assignedVar = ((ASTPrimarySuffix)se.getFirstChildOfType(ASTPrimarySuffix.class)).getImage();
82                  }
83  
84                  ASTMethodDeclaration n = (ASTMethodDeclaration) pe.getFirstParentOfType(ASTMethodDeclaration.class);
85                  if (n == null) {
86                      continue;
87                  }
88                  if (!isLocalVariable(assignedVar, n)) {
89                      if (se.jjtGetNumChildren() < 3) {
90                          continue;
91                      }
92                      ASTExpression e = (ASTExpression) se.jjtGetChild(2);
93                      String val = getFirstNameImage(e);
94                      if (val==null) {
95                          ASTPrimarySuffix foo = (ASTPrimarySuffix)se.getFirstChildOfType(ASTPrimarySuffix.class);
96                          if (foo == null) {
97                              continue;
98                          }
99                          val = foo.getImage();
100                     }
101                     if (val == null) {
102                         continue;
103                     }
104 
105                     if (val.equals(varName)) {
106                         ASTMethodDeclaration md = (ASTMethodDeclaration) parameter.getFirstParentOfType(ASTMethodDeclaration.class);
107                         if (!isLocalVariable(varName, md)) {
108                             return true;
109                         }
110                     }
111                 }
112             }            
113         }
114         return false;
115     }
116 
117     public Object visit(ASTMethodDeclaration node, Object data) {
118         final ASTFormalParameters params = (ASTFormalParameters) node.getFirstChildOfType(ASTFormalParameters.class);
119         ASTFormalParameter[] arrs = getArrays(params);
120         if (arrs!=null) {
121             List bs = node.findChildrenOfType(ASTBlockStatement.class);
122             checkDirectlyAssigned((RuleContext)data, arrs, bs);
123         }
124         return data;
125     }
126 
127     private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
128         final List l = params.findChildrenOfType(ASTFormalParameter.class);
129         if (l!=null && !l.isEmpty()) {
130             Vector v = new Vector();
131             for (Iterator it = l.iterator() ; it.hasNext() ; ) {
132                 ASTFormalParameter fp = (ASTFormalParameter) it.next();
133                 if (fp.isArray())
134                     v.add(fp);
135             }
136             return (ASTFormalParameter[]) v.toArray(new ASTFormalParameter[v.size()]);
137         }
138         return null;
139     }
140 
141 }