1
2
3
4 package net.sourceforge.pmd.lang.java.rule.sunsecure;
5
6 import java.util.ArrayList;
7 import java.util.List;
8
9 import net.sourceforge.pmd.lang.ast.Node;
10 import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
11 import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
12 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
13 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
14 import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
15 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
16 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
17 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters;
18 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
19 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
20 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
21 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
22 import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
23 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
24
25
26
27
28
29
30
31
32
33 public class ArrayIsStoredDirectlyRule extends AbstractSunSecureRule {
34
35 @Override
36 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
37 if (node.isInterface()) {
38 return data;
39 }
40 return super.visit(node, data);
41 }
42
43 @Override
44 public Object visit(ASTConstructorDeclaration node, Object data) {
45 ASTFormalParameter[] arrs = getArrays(node.getParameters());
46 if (arrs != null) {
47
48 List<ASTBlockStatement> bs = node.findDescendantsOfType(ASTBlockStatement.class);
49 checkAll(data, arrs, bs);
50 }
51 return data;
52 }
53
54 @Override
55 public Object visit(ASTMethodDeclaration node, Object data) {
56 final ASTFormalParameters params = node.getFirstDescendantOfType(ASTFormalParameters.class);
57 ASTFormalParameter[] arrs = getArrays(params);
58 if (arrs != null) {
59 checkAll(data, arrs, node.findDescendantsOfType(ASTBlockStatement.class));
60 }
61 return data;
62 }
63
64 private void checkAll(Object context, ASTFormalParameter[] arrs, List<ASTBlockStatement> bs) {
65 for (ASTFormalParameter element : arrs) {
66 checkForDirectAssignment(context, element, bs);
67 }
68 }
69
70 private String getExpressionVarName(Node e) {
71 String assignedVar = getFirstNameImage(e);
72 if (assignedVar == null) {
73 ASTPrimarySuffix suffix = e.getFirstDescendantOfType(ASTPrimarySuffix.class);
74 if (suffix != null) {
75 assignedVar = suffix.getImage();
76 ASTPrimaryPrefix prefix = e.getFirstDescendantOfType(ASTPrimaryPrefix.class);
77 if (prefix != null) {
78 if (prefix.usesThisModifier()) {
79 assignedVar = "this." + assignedVar;
80 } else if (prefix.usesSuperModifier()) {
81 assignedVar = "super." + assignedVar;
82 }
83 }
84 }
85 }
86 return assignedVar;
87 }
88
89
90
91
92 private boolean checkForDirectAssignment(Object ctx, final ASTFormalParameter parameter, final List<ASTBlockStatement> bs) {
93 final ASTVariableDeclaratorId vid = parameter.getFirstDescendantOfType(ASTVariableDeclaratorId.class);
94 final String varName = vid.getImage();
95 for (ASTBlockStatement b: bs) {
96 if (b.hasDescendantOfType(ASTAssignmentOperator.class)) {
97 final ASTStatementExpression se = b.getFirstDescendantOfType(ASTStatementExpression.class);
98 if (se == null || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
99 continue;
100 }
101 ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
102 String assignedVar = getExpressionVarName(pe);
103 if (assignedVar == null) {
104 continue;
105 }
106
107 Node n = pe.getFirstParentOfType(ASTMethodDeclaration.class);
108 if (n == null) {
109 n = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
110 if (n == null) {
111 continue;
112 }
113 }
114 if (!isLocalVariable(assignedVar, n)) {
115
116
117
118 if (se.jjtGetNumChildren() < 3) {
119 continue;
120 }
121 ASTExpression e = (ASTExpression) se.jjtGetChild(2);
122 if (e.hasDescendantOfType(ASTEqualityExpression.class)) {
123 continue;
124 }
125 String val = getExpressionVarName(e);
126 if (val == null) {
127 continue;
128 }
129 ASTPrimarySuffix foo = se.getFirstDescendantOfType(ASTPrimarySuffix.class);
130 if (foo != null && foo.isArrayDereference()) {
131 continue;
132 }
133
134 if (val.equals(varName)) {
135 Node md = parameter.getFirstParentOfType(ASTMethodDeclaration.class);
136 if (md == null) {
137 md = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
138 }
139 if (!isLocalVariable(varName, md)) {
140 addViolation(ctx, parameter, varName);
141 }
142 }
143 }
144 }
145 }
146 return false;
147 }
148
149 private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
150 final List<ASTFormalParameter> l = params.findChildrenOfType(ASTFormalParameter.class);
151 if (l != null && !l.isEmpty()) {
152 List<ASTFormalParameter> l2 = new ArrayList<ASTFormalParameter>();
153 for (ASTFormalParameter fp: l) {
154 if (fp.isArray()) {
155 l2.add(fp);
156 }
157 }
158 return l2.toArray(new ASTFormalParameter[l2.size()]);
159 }
160 return null;
161 }
162
163 }