63 * |
63 * |
64 * @param name the name of the member |
64 * @param name the name of the member |
65 * @return the name passed if valid |
65 * @return the name passed if valid |
66 * @throws IllegalArgumentException if the member name is invalid |
66 * @throws IllegalArgumentException if the member name is invalid |
67 */ |
67 */ |
68 public static String validateMemberName(String name) { |
68 public static String validateMemberName(String name, boolean method) { |
69 requireNonNull(name); |
69 requireNonNull(name); |
70 if (name.length() == 0) |
70 if (name.length() == 0) |
71 throw new IllegalArgumentException("zero-length member name"); |
71 throw new IllegalArgumentException("zero-length member name"); |
72 for (int i=0; i<name.length(); i++) { |
72 for (int i=0; i<name.length(); i++) { |
73 char ch = name.charAt(i); |
73 char ch = name.charAt(i); |
74 if (ch == '.' || ch == ';' || ch == '[' || ch == '/') |
74 if (ch == '.' || ch == ';' || ch == '[' || ch == '/') |
75 throw new IllegalArgumentException("Invalid member name: " + name); |
75 throw new IllegalArgumentException("Invalid member name: " + name); |
76 if (ch == '<' || ch == '>') { |
76 if (method && (ch == '<' || ch == '>')) { |
77 if (!pointyNames.contains(name)) |
77 if (!pointyNames.contains(name)) |
78 throw new IllegalArgumentException("Invalid member name: " + name); |
78 throw new IllegalArgumentException("Invalid member name: " + name); |
79 } |
79 } |
80 } |
80 } |
81 return name; |
81 return name; |
124 if (cur >= end || descriptor.charAt(cur) != '(') |
124 if (cur >= end || descriptor.charAt(cur) != '(') |
125 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
125 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
126 |
126 |
127 ++cur; // skip '(' |
127 ++cur; // skip '(' |
128 while (cur < end && descriptor.charAt(cur) != ')') { |
128 while (cur < end && descriptor.charAt(cur) != ')') { |
129 int len = matchSig(descriptor, cur, end); |
129 int len = skipOverFieldSignature(descriptor, cur, end, false); |
130 if (len == 0 || descriptor.charAt(cur) == 'V') |
130 if (len == 0) |
131 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
131 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
132 ptypes.add(descriptor.substring(cur, cur + len)); |
132 ptypes.add(descriptor.substring(cur, cur + len)); |
133 cur += len; |
133 cur += len; |
134 } |
134 } |
135 if (cur >= end) |
135 if (cur >= end) |
136 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
136 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
137 ++cur; // skip ')' |
137 ++cur; // skip ')' |
138 |
138 |
139 int rLen = matchSig(descriptor, cur, end); |
139 int rLen = skipOverFieldSignature(descriptor, cur, end, true); |
140 if (rLen == 0 || cur + rLen != end) |
140 if (rLen == 0 || cur + rLen != end) |
141 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
141 throw new IllegalArgumentException("Bad method descriptor: " + descriptor); |
142 ptypes.add(0, descriptor.substring(cur, cur + rLen)); |
142 ptypes.add(0, descriptor.substring(cur, cur + rLen)); |
143 return ptypes; |
143 return ptypes; |
144 } |
144 } |
145 |
145 |
|
146 private static final char JVM_SIGNATURE_ARRAY = '['; |
|
147 private static final char JVM_SIGNATURE_BYTE = 'B'; |
|
148 private static final char JVM_SIGNATURE_CHAR = 'C'; |
|
149 private static final char JVM_SIGNATURE_CLASS = 'L'; |
|
150 private static final char JVM_SIGNATURE_ENDCLASS = ';'; |
|
151 private static final char JVM_SIGNATURE_ENUM = 'E'; |
|
152 private static final char JVM_SIGNATURE_FLOAT = 'F'; |
|
153 private static final char JVM_SIGNATURE_DOUBLE = 'D'; |
|
154 private static final char JVM_SIGNATURE_FUNC = '('; |
|
155 private static final char JVM_SIGNATURE_ENDFUNC = ')'; |
|
156 private static final char JVM_SIGNATURE_INT = 'I'; |
|
157 private static final char JVM_SIGNATURE_LONG = 'J'; |
|
158 private static final char JVM_SIGNATURE_SHORT = 'S'; |
|
159 private static final char JVM_SIGNATURE_VOID = 'V'; |
|
160 private static final char JVM_SIGNATURE_BOOLEAN = 'Z'; |
|
161 |
146 /** |
162 /** |
147 * Validates that the characters at [start, end) within the provided string |
163 * Validates that the characters at [start, end) within the provided string |
148 * describe a valid field type descriptor. |
164 * describe a valid field type descriptor. |
149 * |
165 * @param descriptor the descriptor string |
150 * @param str the descriptor string |
|
151 * @param start the starting index into the string |
166 * @param start the starting index into the string |
152 * @param end the ending index within the string |
167 * @param end the ending index within the string |
|
168 * @param voidOK is void acceptable? |
153 * @return the length of the descriptor, or 0 if it is not a descriptor |
169 * @return the length of the descriptor, or 0 if it is not a descriptor |
154 * @throws IllegalArgumentException if the descriptor string is not valid |
170 * @throws IllegalArgumentException if the descriptor string is not valid |
155 */ |
171 */ |
156 static int matchSig(String str, int start, int end) { |
172 @SuppressWarnings("fallthrough") |
157 if (start >= end || start >= str.length() || end > str.length()) |
173 static int skipOverFieldSignature(String descriptor, int start, int end, boolean voidOK) { |
158 return 0; |
174 int arrayDim = 0; |
159 char c = str.charAt(start); |
175 int index = start; |
160 if (c == 'L') { |
176 while (index < end) { |
161 int endc = str.indexOf(';', start); |
177 switch (descriptor.charAt(index)) { |
162 int badc = str.indexOf('.', start); |
178 case JVM_SIGNATURE_VOID: if (!voidOK) { return index; } |
163 if (badc >= 0 && badc < endc) |
179 case JVM_SIGNATURE_BOOLEAN: |
164 return 0; |
180 case JVM_SIGNATURE_BYTE: |
165 badc = str.indexOf('[', start); |
181 case JVM_SIGNATURE_CHAR: |
166 if (badc >= 0 && badc < endc) |
182 case JVM_SIGNATURE_SHORT: |
167 return 0; |
183 case JVM_SIGNATURE_INT: |
168 return (endc < 0) ? 0 : endc - start + 1; |
184 case JVM_SIGNATURE_FLOAT: |
169 } else if (c == '[') { |
185 case JVM_SIGNATURE_LONG: |
170 int t = matchSig(str, start+1, end); |
186 case JVM_SIGNATURE_DOUBLE: |
171 return (t > 0) ? t + 1 : 0; |
187 return index - start + 1; |
172 } else { |
188 case JVM_SIGNATURE_CLASS: |
173 return ("IJCSBFDZV".indexOf(c) >= 0) ? 1 : 0; |
189 // Skip leading 'L' and ignore first appearance of ';' |
174 } |
190 index++; |
|
191 int indexOfSemi = descriptor.indexOf(';', index); |
|
192 if (indexOfSemi != -1) { |
|
193 String unqualifiedName = descriptor.substring(index, indexOfSemi); |
|
194 boolean legal = verifyUnqualifiedClassName(unqualifiedName); |
|
195 if (!legal) { |
|
196 return 0; |
|
197 } |
|
198 return index - start + unqualifiedName.length() + 1; |
|
199 } |
|
200 return 0; |
|
201 case JVM_SIGNATURE_ARRAY: |
|
202 arrayDim++; |
|
203 if (arrayDim > MAX_ARRAY_TYPE_DESC_DIMENSIONS) { |
|
204 throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions", |
|
205 ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS)); |
|
206 } |
|
207 // The rest of what's there better be a legal descriptor |
|
208 index++; |
|
209 voidOK = false; |
|
210 break; |
|
211 default: |
|
212 return 0; |
|
213 } |
|
214 } |
|
215 return 0; |
|
216 } |
|
217 |
|
218 static boolean verifyUnqualifiedClassName(String name) { |
|
219 for (int index = 0; index < name.length(); index++) { |
|
220 char ch = name.charAt(index); |
|
221 if (ch < 128) { |
|
222 if (ch == '.' || ch == ';' || ch == '[' ) { |
|
223 return false; // do not permit '.', ';', or '[' |
|
224 } |
|
225 if (ch == '/') { |
|
226 // check for '//' or leading or trailing '/' which are not legal |
|
227 // unqualified name must not be empty |
|
228 if (index == 0 || index + 1 >= name.length() || name.charAt(index + 1) == '/') { |
|
229 return false; |
|
230 } |
|
231 } |
|
232 } else { |
|
233 index ++; |
|
234 } |
|
235 } |
|
236 return true; |
175 } |
237 } |
176 } |
238 } |