View Javadoc

    1   /*
    2    * Created on Jan 17, 2005
    3    *
    4    * $Id: ArrayIsStoredDirectly.java 5018 2007-01-31 01:37:56Z xlv $
    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.List;
    24  import java.util.ArrayList;
    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(node.getParameters());
    40          if (arrs != null) {
    41              //TODO check if one of these arrays is stored in a non local variable
    42              List<ASTBlockStatement> 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 = 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<ASTBlockStatement> 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<ASTBlockStatement> bs) {
    67          final ASTVariableDeclaratorId vid = parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
    68          final String varName = vid.getImage();
    69          for (ASTBlockStatement b: bs) {
    70              if (b.containsChildOfType(ASTAssignmentOperator.class)) {
    71                  final ASTStatementExpression se = b.getFirstChildOfType(ASTStatementExpression.class);
    72                  if (se == null || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
    73                      continue;
    74                  }
    75                  ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
    76                  String assignedVar = getFirstNameImage(pe);
    77                  if (assignedVar == null) {
    78                      ASTPrimarySuffix suffix = se.getFirstChildOfType(ASTPrimarySuffix.class);
    79                      if (suffix == null) {
    80                          continue;
    81                      }
    82                      assignedVar = suffix.getImage();
    83                  }
    84
    85                  SimpleNode n = pe.getFirstParentOfType(ASTMethodDeclaration.class);
    86                  if (n == null) {
    87  					n = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
    88  					if (n == null) {
    89  						continue;
    90  					}
    91  				}
    92                  if (!isLocalVariable(assignedVar, n)) {
    93                      // TODO could this be more clumsy?  We really
    94                      // need to build out the PMD internal framework more
    95                      // to support simply queries like "isAssignedTo()" or something
    96                      if (se.jjtGetNumChildren() < 3) {
    97                          continue;
    98                      }
    99                      ASTExpression e = (ASTExpression) se.jjtGetChild(2);
    100                     if (e.findChildrenOfType(ASTEqualityExpression.class).size() > 0) {
    101                         continue;
    102                     }
    103                     String val = getFirstNameImage(e);
    104                     if (val == null) {
    105                         ASTPrimarySuffix foo = se.getFirstChildOfType(ASTPrimarySuffix.class);
    106                         if (foo == null) {
    107                             continue;
    108                         }
    109                         val = foo.getImage();
    110                     }
    111                     if (val == null) {
    112                         continue;
    113                     }
    114                     ASTPrimarySuffix foo = se.getFirstChildOfType(ASTPrimarySuffix.class);
    115                     if (foo != null && foo.isArrayDereference()) {
    116                         continue;
    117                     }
    118
    119                     if (val.equals(varName)) {
    120                         SimpleNode md = parameter.getFirstParentOfType(ASTMethodDeclaration.class);
    121                         if (md == null) {
    122                         	md = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
    123         				}
    124                         if (!isLocalVariable(varName, md)) {
    125                             addViolation(ctx, parameter, varName);
    126                         }
    127                     }
    128                 }
    129             }
    130         }
    131         return false;
    132     }
    133
    134     private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
    135         final List<ASTFormalParameter> l = params.findChildrenOfType(ASTFormalParameter.class);
    136         if (l != null && !l.isEmpty()) {
    137             List<ASTFormalParameter> l2 = new ArrayList<ASTFormalParameter>();
    138             for (ASTFormalParameter fp: l) {
    139                 if (fp.isArray())
    140                     l2.add(fp);
    141             }
    142             return l2.toArray(new ASTFormalParameter[l2.size()]);
    143         }
    144         return null;
    145     }
    146
    147 }