1
2
3
4 package net.sourceforge.pmd.lang.java.rule.sunsecure;
5
6 import java.util.List;
7
8 import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
9 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
10 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
11 import net.sourceforge.pmd.lang.java.ast.ASTName;
12 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
13 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
14 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
15 import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
16 import net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration;
17
18
19
20
21
22
23
24
25 public class MethodReturnsInternalArrayRule extends AbstractSunSecureRule {
26
27 @Override
28 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
29 if (node.isInterface()) {
30 return data;
31 }
32 return super.visit(node, data);
33 }
34
35 @Override
36 public Object visit(ASTMethodDeclaration method, Object data) {
37 if (!method.getResultType().returnsArray() || method.isPrivate()) {
38 return data;
39 }
40 List<ASTReturnStatement> returns = method.findDescendantsOfType(ASTReturnStatement.class);
41 ASTTypeDeclaration td = method.getFirstParentOfType(ASTTypeDeclaration.class);
42 for (ASTReturnStatement ret: returns) {
43 final String vn = getReturnedVariableName(ret);
44 if (!isField(vn, td)) {
45 continue;
46 }
47 if (ret.findDescendantsOfType(ASTPrimarySuffix.class).size() > 2) {
48 continue;
49 }
50 if (ret.hasDescendantOfType(ASTAllocationExpression.class)) {
51 continue;
52 }
53 if (hasArraysCopyOf(ret)) {
54 continue;
55 }
56 if (hasClone(ret, vn)) {
57 continue;
58 }
59 if (!isLocalVariable(vn, method)) {
60 addViolation(data, ret, vn);
61 } else {
62
63 final ASTPrimaryPrefix pp = ret.getFirstDescendantOfType(ASTPrimaryPrefix.class);
64 if (pp != null && pp.usesThisModifier()) {
65 final ASTPrimarySuffix ps = ret.getFirstDescendantOfType(ASTPrimarySuffix.class);
66 if (ps.hasImageEqualTo(vn)) {
67 addViolation(data, ret, vn);
68 }
69 }
70 }
71 }
72 return data;
73 }
74
75 private boolean hasClone(ASTReturnStatement ret, String varName) {
76 List<ASTPrimaryExpression> expressions = ret.findDescendantsOfType(ASTPrimaryExpression.class);
77 for (ASTPrimaryExpression e : expressions) {
78 if (e.jjtGetChild(0) instanceof ASTPrimaryPrefix
79 && e.jjtGetNumChildren() == 2
80 && e.jjtGetChild(1) instanceof ASTPrimarySuffix
81 && ((ASTPrimarySuffix) e.jjtGetChild(1)).isArguments()
82 && ((ASTPrimarySuffix) e.jjtGetChild(1)).getArgumentCount() == 0) {
83 ASTName name = e.getFirstDescendantOfType(ASTName.class);
84 if (name != null && name.hasImageEqualTo(varName + ".clone")) {
85 return true;
86 }
87 }
88 }
89 return false;
90 }
91
92 private boolean hasArraysCopyOf(ASTReturnStatement ret) {
93 List<ASTPrimaryExpression> expressions = ret.findDescendantsOfType(ASTPrimaryExpression.class);
94 for (ASTPrimaryExpression e : expressions) {
95 if (e.jjtGetNumChildren() == 2 && e.jjtGetChild(0) instanceof ASTPrimaryPrefix
96 && e.jjtGetChild(0).jjtGetNumChildren() == 1 && e.jjtGetChild(0).jjtGetChild(0) instanceof ASTName
97 && e.jjtGetChild(0).jjtGetChild(0).getImage().endsWith("Arrays.copyOf")) {
98 return true;
99 }
100 }
101 return false;
102 }
103 }