View Javadoc

1   /*
2    * Created on Jan 17, 2005 
3    *
4    * $Id: ArrayIsStoredDirectly.java,v 1.11 2005/09/02 19:36:22 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   * 
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((ASTFormalParameters) node.jjtGetChild(0));
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              List bs = node.findChildrenOfType(ASTBlockStatement.class);
54              checkAll(data, arrs, bs);
55          }
56          return data;
57      }
58  
59      private void checkAll(Object context, ASTFormalParameter[] arrs, List bs) {
60          for (int i=0;i<arrs.length;i++) {
61              checkForDirectAssignment(context, arrs[i], bs);
62          }
63      }
64      
65      /***
66       * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
67       */
68      private boolean checkForDirectAssignment(Object ctx, final ASTFormalParameter parameter, final List bs) {
69          final ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
70          final String varName = vid.getImage();
71          for (Iterator it = bs.iterator() ; it.hasNext() ; ) {
72              final ASTBlockStatement b = (ASTBlockStatement) it.next();
73              if (b.containsChildOfType(ASTAssignmentOperator.class)) {
74                  final ASTStatementExpression se = (ASTStatementExpression) b.getFirstChildOfType(ASTStatementExpression.class);
75                  if (se == null || !(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                      if (e.findChildrenOfType(ASTEqualityExpression.class).size() > 0) {
94                          continue;
95                      }
96                      String val = getFirstNameImage(e);
97                      if (val==null) {
98                          ASTPrimarySuffix foo = (ASTPrimarySuffix)se.getFirstChildOfType(ASTPrimarySuffix.class);
99                          if (foo == null) {
100                             continue;
101                         }
102                         val = foo.getImage();
103                     }
104                     if (val == null) {
105                         continue;
106                     }
107 
108                     if (val.equals(varName)) {
109                         ASTMethodDeclaration md = (ASTMethodDeclaration) parameter.getFirstParentOfType(ASTMethodDeclaration.class);
110                         if (!isLocalVariable(varName, md)) {
111                             addViolation(ctx, parameter, varName);
112                         }
113                     }
114                 }
115             }            
116         }
117         return false;
118     }
119 
120     private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
121         final List l = params.findChildrenOfType(ASTFormalParameter.class);
122         if (l!=null && !l.isEmpty()) {
123             Vector v = new Vector();
124             for (Iterator it = l.iterator() ; it.hasNext() ; ) {
125                 ASTFormalParameter fp = (ASTFormalParameter) it.next();
126                 if (fp.isArray())
127                     v.add(fp);
128             }
129             return (ASTFormalParameter[]) v.toArray(new ASTFormalParameter[v.size()]);
130         }
131         return null;
132     }
133 
134 }