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
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
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
88
89
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 }