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 *
28 * @author mgriffa
29 */
30 public class ArrayIsStoredDirectly extends AbstractSunSecureRule {
31
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 public Object visit(ASTConstructorDeclaration node, Object data) {
40 ASTFormalParameter[] arrs = getArrays((ASTFormalParameters) node.jjtGetChild(0));
41 if (arrs!=null) {
42
43 List bs = node.findChildrenOfType(ASTBlockStatement.class);
44 checkAll(data, arrs, bs);
45 }
46 return data;
47 }
48
49 public Object visit(ASTMethodDeclaration node, Object data) {
50 final ASTFormalParameters params = (ASTFormalParameters) node.getFirstChildOfType(ASTFormalParameters.class);
51 ASTFormalParameter[] arrs = getArrays(params);
52 if (arrs!=null) {
53 List bs = node.findChildrenOfType(ASTBlockStatement.class);
54 checkAll(data, arrs, bs);
55 }
56 return data;
57 }
58
59 private void checkAll(Object context, ASTFormalParameter[] arrs, List bs) {
60 for (int i=0;i<arrs.length;i++) {
61 checkForDirectAssignment(context, arrs[i], bs);
62 }
63 }
64
65 /***
66 * Checks if the variable designed in parameter is written to a field (not local variable) in the statements.
67 */
68 private boolean checkForDirectAssignment(Object ctx, final ASTFormalParameter parameter, final List bs) {
69 final ASTVariableDeclaratorId vid = (ASTVariableDeclaratorId) parameter.getFirstChildOfType(ASTVariableDeclaratorId.class);
70 final String varName = vid.getImage();
71 for (Iterator it = bs.iterator() ; it.hasNext() ; ) {
72 final ASTBlockStatement b = (ASTBlockStatement) it.next();
73 if (b.containsChildOfType(ASTAssignmentOperator.class)) {
74 final ASTStatementExpression se = (ASTStatementExpression) b.getFirstChildOfType(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 assignedVar = ((ASTPrimarySuffix)se.getFirstChildOfType(ASTPrimarySuffix.class)).getImage();
82 }
83
84 ASTMethodDeclaration n = (ASTMethodDeclaration) pe.getFirstParentOfType(ASTMethodDeclaration.class);
85 if (n == null) {
86 continue;
87 }
88 if (!isLocalVariable(assignedVar, n)) {
89 if (se.jjtGetNumChildren() < 3) {
90 continue;
91 }
92 ASTExpression e = (ASTExpression) se.jjtGetChild(2);
93 if (e.findChildrenOfType(ASTEqualityExpression.class).size() > 0) {
94 continue;
95 }
96 String val = getFirstNameImage(e);
97 if (val==null) {
98 ASTPrimarySuffix foo = (ASTPrimarySuffix)se.getFirstChildOfType(ASTPrimarySuffix.class);
99 if (foo == null) {
100 continue;
101 }
102 val = foo.getImage();
103 }
104 if (val == null) {
105 continue;
106 }
107
108 if (val.equals(varName)) {
109 ASTMethodDeclaration md = (ASTMethodDeclaration) parameter.getFirstParentOfType(ASTMethodDeclaration.class);
110 if (!isLocalVariable(varName, md)) {
111 addViolation(ctx, parameter, varName);
112 }
113 }
114 }
115 }
116 }
117 return false;
118 }
119
120 private final ASTFormalParameter[] getArrays(ASTFormalParameters params) {
121 final List l = params.findChildrenOfType(ASTFormalParameter.class);
122 if (l!=null && !l.isEmpty()) {
123 Vector v = new Vector();
124 for (Iterator it = l.iterator() ; it.hasNext() ; ) {
125 ASTFormalParameter fp = (ASTFormalParameter) it.next();
126 if (fp.isArray())
127 v.add(fp);
128 }
129 return (ASTFormalParameter[]) v.toArray(new ASTFormalParameter[v.size()]);
130 }
131 return null;
132 }
133
134 }