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 }