1
2
3
4
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
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
96
97
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 }