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.List;
24 import java.util.ArrayList;
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(node.getParameters());
40 if (arrs != null) {
41
42 List<ASTBlockStatement> 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 = 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<ASTBlockStatement> 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<ASTBlockStatement> bs) {
67 final ASTVariableDeclaratorId vid = parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
68 final String varName = vid.getImage();
69 for (ASTBlockStatement b: bs) {
70 if (b.containsChildOfType(ASTAssignmentOperator.class)) {
71 final ASTStatementExpression se = b.getFirstChildOfType(ASTStatementExpression.class);
72 if (se == null || !(se.jjtGetChild(0) instanceof ASTPrimaryExpression)) {
73 continue;
74 }
75 ASTPrimaryExpression pe = (ASTPrimaryExpression) se.jjtGetChild(0);
76 String assignedVar = getFirstNameImage(pe);
77 if (assignedVar == null) {
78 ASTPrimarySuffix suffix = se.getFirstChildOfType(ASTPrimarySuffix.class);
79 if (suffix == null) {
80 continue;
81 }
82 assignedVar = suffix.getImage();
83 }
84
85 SimpleNode n = pe.getFirstParentOfType(ASTMethodDeclaration.class);
86 if (n == null) {
87 n = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
88 if (n == null) {
89 continue;
90 }
91 }
92 if (!isLocalVariable(assignedVar, n)) {
93
94
95
96 if (se.jjtGetNumChildren() < 3) {
97 continue;
98 }
99 ASTExpression e = (ASTExpression) se.jjtGetChild(2);
100 if (e.findChildrenOfType(ASTEqualityExpression.class).size() > 0) {
101 continue;
102 }
103 String val = getFirstNameImage(e);
104 if (val == null) {
105 ASTPrimarySuffix foo = se.getFirstChildOfType(ASTPrimarySuffix.class);
106 if (foo == null) {
107 continue;
108 }
109 val = foo.getImage();
110 }
111 if (val == null) {
112 continue;
113 }
114 ASTPrimarySuffix foo = se.getFirstChildOfType(ASTPrimarySuffix.class);
115 if (foo != null && foo.isArrayDereference()) {
116 continue;
117 }
118
119 if (val.equals(varName)) {
120 SimpleNode md = parameter.getFirstParentOfType(ASTMethodDeclaration.class);
121 if (md == null) {
122 md = pe.getFirstParentOfType(ASTConstructorDeclaration.class);
123 }
124 if (!isLocalVariable(varName, md)) {
125 addViolation(ctx, parameter, varName);
126 }
127 }
128 }
129 }
130 }
131 return false;
132 }
133
134 private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
135 final List<ASTFormalParameter> l = params.findChildrenOfType(ASTFormalParameter.class);
136 if (l != null && !l.isEmpty()) {
137 List<ASTFormalParameter> l2 = new ArrayList<ASTFormalParameter>();
138 for (ASTFormalParameter fp: l) {
139 if (fp.isArray())
140 l2.add(fp);
141 }
142 return l2.toArray(new ASTFormalParameter[l2.size()]);
143 }
144 return null;
145 }
146
147 }