001: /*
002: * Created on Jan 17, 2005
003: *
004: * $Id: ArrayIsStoredDirectly.java 5018 2007-01-31 01:37:56Z xlv $
005: */
006: package net.sourceforge.pmd.rules.sunsecure;
007:
008: import net.sourceforge.pmd.ast.ASTAssignmentOperator;
009: import net.sourceforge.pmd.ast.ASTBlockStatement;
010: import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
011: import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
012: import net.sourceforge.pmd.ast.ASTEqualityExpression;
013: import net.sourceforge.pmd.ast.ASTExpression;
014: import net.sourceforge.pmd.ast.ASTFormalParameter;
015: import net.sourceforge.pmd.ast.ASTFormalParameters;
016: import net.sourceforge.pmd.ast.ASTMethodDeclaration;
017: import net.sourceforge.pmd.ast.ASTPrimaryExpression;
018: import net.sourceforge.pmd.ast.ASTPrimarySuffix;
019: import net.sourceforge.pmd.ast.ASTStatementExpression;
020: import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
021: import net.sourceforge.pmd.ast.SimpleNode;
022:
023: import java.util.List;
024: import java.util.ArrayList;
025:
026: /**
027: * @author mgriffa
028: */
029: public class ArrayIsStoredDirectly extends AbstractSunSecureRule {
030:
031: public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
032: if (node.isInterface()) {
033: return data;
034: }
035: return super .visit(node, data);
036: }
037:
038: public Object visit(ASTConstructorDeclaration node, Object data) {
039: ASTFormalParameter[] arrs = getArrays(node.getParameters());
040: if (arrs != null) {
041: //TODO check if one of these arrays is stored in a non local variable
042: List<ASTBlockStatement> bs = node
043: .findChildrenOfType(ASTBlockStatement.class);
044: checkAll(data, arrs, bs);
045: }
046: return data;
047: }
048:
049: public Object visit(ASTMethodDeclaration node, Object data) {
050: final ASTFormalParameters params = node
051: .getFirstChildOfType(ASTFormalParameters.class);
052: ASTFormalParameter[] arrs = getArrays(params);
053: if (arrs != null) {
054: checkAll(data, arrs, node
055: .findChildrenOfType(ASTBlockStatement.class));
056: }
057: return data;
058: }
059:
060: private void checkAll(Object context, ASTFormalParameter[] arrs,
061: List<ASTBlockStatement> bs) {
062: for (int i = 0; i < arrs.length; i++) {
063: checkForDirectAssignment(context, arrs[i], bs);
064: }
065: }
066:
067: /**
068: * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
069: */
070: private boolean checkForDirectAssignment(Object ctx,
071: final ASTFormalParameter parameter,
072: final List<ASTBlockStatement> bs) {
073: final ASTVariableDeclaratorId vid = parameter
074: .getFirstChildOfType(ASTVariableDeclaratorId.class);
075: final String varName = vid.getImage();
076: for (ASTBlockStatement b : bs) {
077: if (b.containsChildOfType(ASTAssignmentOperator.class)) {
078: final ASTStatementExpression se = b
079: .getFirstChildOfType(ASTStatementExpression.class);
080: if (se == null
081: || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
082: continue;
083: }
084: ASTPrimaryExpression pe = (ASTPrimaryExpression) se
085: .jjtGetChild(0);
086: String assignedVar = getFirstNameImage(pe);
087: if (assignedVar == null) {
088: ASTPrimarySuffix suffix = se
089: .getFirstChildOfType(ASTPrimarySuffix.class);
090: if (suffix == null) {
091: continue;
092: }
093: assignedVar = suffix.getImage();
094: }
095:
096: SimpleNode n = pe
097: .getFirstParentOfType(ASTMethodDeclaration.class);
098: if (n == null) {
099: n = pe
100: .getFirstParentOfType(ASTConstructorDeclaration.class);
101: if (n == null) {
102: continue;
103: }
104: }
105: if (!isLocalVariable(assignedVar, n)) {
106: // TODO could this be more clumsy? We really
107: // need to build out the PMD internal framework more
108: // to support simply queries like "isAssignedTo()" or something
109: if (se.jjtGetNumChildren() < 3) {
110: continue;
111: }
112: ASTExpression e = (ASTExpression) se.jjtGetChild(2);
113: if (e.findChildrenOfType(
114: ASTEqualityExpression.class).size() > 0) {
115: continue;
116: }
117: String val = getFirstNameImage(e);
118: if (val == null) {
119: ASTPrimarySuffix foo = se
120: .getFirstChildOfType(ASTPrimarySuffix.class);
121: if (foo == null) {
122: continue;
123: }
124: val = foo.getImage();
125: }
126: if (val == null) {
127: continue;
128: }
129: ASTPrimarySuffix foo = se
130: .getFirstChildOfType(ASTPrimarySuffix.class);
131: if (foo != null && foo.isArrayDereference()) {
132: continue;
133: }
134:
135: if (val.equals(varName)) {
136: SimpleNode md = parameter
137: .getFirstParentOfType(ASTMethodDeclaration.class);
138: if (md == null) {
139: md = pe
140: .getFirstParentOfType(ASTConstructorDeclaration.class);
141: }
142: if (!isLocalVariable(varName, md)) {
143: addViolation(ctx, parameter, varName);
144: }
145: }
146: }
147: }
148: }
149: return false;
150: }
151:
152: private final ASTFormalParameter[] getArrays(
153: ASTFormalParameters params) {
154: final List<ASTFormalParameter> l = params
155: .findChildrenOfType(ASTFormalParameter.class);
156: if (l != null && !l.isEmpty()) {
157: List<ASTFormalParameter> l2 = new ArrayList<ASTFormalParameter>();
158: for (ASTFormalParameter fp : l) {
159: if (fp.isArray())
160: l2.add(fp);
161: }
162: return l2.toArray(new ASTFormalParameter[l2.size()]);
163: }
164: return null;
165: }
166:
167: }
|