1 |
| package net.sourceforge.pmd.rules; |
2 |
| |
3 |
| import net.sourceforge.pmd.AbstractRule; |
4 |
| import net.sourceforge.pmd.ast.ASTLiteral; |
5 |
| |
6 |
| public class SuspiciousOctalEscape extends AbstractRule { |
7 |
| |
8 |
2
| public Object visit(ASTLiteral node, Object data) {
|
9 |
2
| String image = node.getImage();
|
10 |
2
| if (image != null && image.startsWith("\""))
|
11 |
| { |
12 |
| |
13 |
1
| String s = image.substring(1, image.length() - 1);
|
14 |
| |
15 |
| |
16 |
1
| int offset = 0;
|
17 |
1
| for (int slash = s.indexOf('\\', offset);
|
18 |
2
| slash != -1 && slash < s.length() - 1;
|
19 |
| slash = s.indexOf('\\', offset)) { |
20 |
1
| String escapeSequence = s.substring(slash + 1);
|
21 |
1
| char first = escapeSequence.charAt(0);
|
22 |
1
| if (isOctal(first)) {
|
23 |
1
| if (escapeSequence.length() > 1) {
|
24 |
1
| char second = escapeSequence.charAt(1);
|
25 |
1
| if (isOctal(second)) {
|
26 |
1
| if (escapeSequence.length() > 2) {
|
27 |
1
| char third = escapeSequence.charAt(2);
|
28 |
1
| if (isOctal(third)) {
|
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
0
| if (first != '0' && first != '1' && first != '2' && first != '3') {
|
34 |
| |
35 |
| |
36 |
0
| addViolation(data, node);
|
37 |
| } else { |
38 |
| |
39 |
| |
40 |
0
| if (escapeSequence.length() > 3) {
|
41 |
0
| char fourth = escapeSequence.charAt(3);
|
42 |
0
| if (isDecimal(fourth)) {
|
43 |
0
| addViolation(data, node);
|
44 |
| } |
45 |
| } |
46 |
| } |
47 |
| |
48 |
1
| } else if (isDecimal(third)) {
|
49 |
| |
50 |
| |
51 |
1
| addViolation(data, node);
|
52 |
| } |
53 |
| } |
54 |
0
| } else if (isDecimal(second)) {
|
55 |
| |
56 |
| |
57 |
0
| addViolation(data, node);
|
58 |
| } |
59 |
| } |
60 |
| } |
61 |
| |
62 |
1
| offset = slash + 1;
|
63 |
| } |
64 |
| } |
65 |
| |
66 |
2
| return super.visit(node, data);
|
67 |
| } |
68 |
| |
69 |
3
| private boolean isOctal(char c) {
|
70 |
3
| switch (c) {
|
71 |
0
| case '0':
|
72 |
1
| case '1':
|
73 |
1
| case '2':
|
74 |
0
| case '3':
|
75 |
0
| case '4':
|
76 |
0
| case '5':
|
77 |
0
| case '6':
|
78 |
0
| case '7':
|
79 |
2
| return true;
|
80 |
1
| default:
|
81 |
1
| return false;
|
82 |
| } |
83 |
| } |
84 |
| |
85 |
1
| private boolean isDecimal(char c) {
|
86 |
1
| switch (c) {
|
87 |
0
| case '0':
|
88 |
0
| case '1':
|
89 |
0
| case '2':
|
90 |
0
| case '3':
|
91 |
0
| case '4':
|
92 |
0
| case '5':
|
93 |
0
| case '6':
|
94 |
0
| case '7':
|
95 |
1
| case '8':
|
96 |
0
| case '9':
|
97 |
1
| return true;
|
98 |
0
| default:
|
99 |
0
| return false;
|
100 |
| } |
101 |
| } |
102 |
| } |