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