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