View Javadoc

    1   /*
    2    * Created on Jan 17, 2005
    3    *
    4    * $Id: ArrayIsStoredDirectly.java,v 1.17 2006/10/25 19:40:45 xlv 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  import net.sourceforge.pmd.ast.SimpleNode;
    22
    23  import java.util.Iterator;
    24  import java.util.List;
    25  import java.util.Vector;
    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(node.getParameters());
    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              checkAll(data, arrs, node.findChildrenOfType(ASTBlockStatement.class));
    54          }
    55          return data;
    56      }
    57
    58      private void checkAll(Object context, ASTFormalParameter[] arrs, List bs) {
    59          for (int i = 0; i < arrs.length; i++) {
    60              checkForDirectAssignment(context, arrs[i], bs);
    61          }
    62      }
    63
    64      /***
    65       * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
    66       */
    67      private boolean checkForDirectAssignment(Object ctx, final ASTFormalParameter parameter, final List bs) {
    68          final ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
    69          final String varName = vid.getImage();
    70          for (Iterator it = bs.iterator(); it.hasNext();) {
    71              final ASTBlockStatement b = (ASTBlockStatement) it.next();
    72              if (b.containsChildOfType(ASTAssignmentOperator.class)) {
    73                  final ASTStatementExpression se = (ASTStatementExpression) b.getFirstChildOfType(ASTStatementExpression.class);
    74                  if (se == null || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
    75                      continue;
    76                  }
    77                  ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
    78                  String assignedVar = getFirstNameImage(pe);
    79                  if (assignedVar == null) {
    80                      ASTPrimarySuffix suffix = (ASTPrimarySuffix) se.getFirstChildOfType(ASTPrimarySuffix.class);
    81                      if (suffix == null) {
    82                          continue;
    83                      }
    84                      assignedVar = suffix.getImage();
    85                  }
    86
    87                  SimpleNode n = (ASTMethodDeclaration) pe.getFirstParentOfType(ASTMethodDeclaration.class);
    88                  if (n == null) {
    89  					n = (ASTConstructorDeclaration) pe.getFirstParentOfType(ASTConstructorDeclaration.class);
    90  					if (n == null) {
    91  						continue;
    92  					}
    93  				}
    94                  if (!isLocalVariable(assignedVar, n)) {
    95                      // TODO could this be more clumsy?  We really
    96                      // need to build out the PMD internal framework more
    97                      // to support simply queries like "isAssignedTo()" or something
    98                      if (se.jjtGetNumChildren() < 3) {
    99                          continue;
    100                     }
    101                     ASTExpression e = (ASTExpression) se.jjtGetChild(2);
    102                     if (e.findChildrenOfType(ASTEqualityExpression.class).size() > 0) {
    103                         continue;
    104                     }
    105                     String val = getFirstNameImage(e);
    106                     if (val == null) {
    107                         ASTPrimarySuffix foo = (ASTPrimarySuffix) se.getFirstChildOfType(ASTPrimarySuffix.class);
    108                         if (foo == null) {
    109                             continue;
    110                         }
    111                         val = foo.getImage();
    112                     }
    113                     if (val == null) {
    114                         continue;
    115                     }
    116                     ASTPrimarySuffix foo = (ASTPrimarySuffix) se.getFirstChildOfType(ASTPrimarySuffix.class);
    117                     if (foo != null && foo.isArrayDereference()) {
    118                         continue;
    119                     }
    120
    121                     if (val.equals(varName)) {
    122                         SimpleNode md = (ASTMethodDeclaration) parameter.getFirstParentOfType(ASTMethodDeclaration.class);
    123                         if (md == null) {
    124                         	md = (ASTConstructorDeclaration) pe.getFirstParentOfType(ASTConstructorDeclaration.class);
    125         				}
    126                         if (!isLocalVariable(varName, md)) {
    127                             addViolation(ctx, parameter, varName);
    128                         }
    129                     }
    130                 }
    131             }
    132         }
    133         return false;
    134     }
    135
    136     private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
    137         final List l = params.findChildrenOfType(ASTFormalParameter.class);
    138         if (l != null && !l.isEmpty()) {
    139             Vector v = new Vector();
    140             for (Iterator it = l.iterator(); it.hasNext();) {
    141                 ASTFormalParameter fp = (ASTFormalParameter) it.next();
    142                 if (fp.isArray())
    143                     v.add(fp);
    144             }
    145             return (ASTFormalParameter[]) v.toArray(new ASTFormalParameter[v.size()]);
    146         }
    147         return null;
    148     }
    149
    150 }