130 if (len == 0)
131 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
132 ptypes.add(descriptor.substring(cur, cur + len));
133 cur += len;
134 }
135 if (cur >= end)
136 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
137 ++cur; // skip ')'
138
139 int rLen = skipOverFieldSignature(descriptor, cur, end, true);
140 if (rLen == 0 || cur + rLen != end)
141 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
142 ptypes.add(0, descriptor.substring(cur, cur + rLen));
143 return ptypes;
144 }
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
162 /**
163 * Validates that the characters at [start, end) within the provided string
164 * describe a valid field type descriptor.
165 * @param descriptor the descriptor string
166 * @param start the starting index into the string
167 * @param end the ending index within the string
168 * @param voidOK is void acceptable?
169 * @return the length of the descriptor, or 0 if it is not a descriptor
170 * @throws IllegalArgumentException if the descriptor string is not valid
171 */
172 @SuppressWarnings("fallthrough")
173 static int skipOverFieldSignature(String descriptor, int start, int end, boolean voidOK) {
174 int arrayDim = 0;
175 int index = start;
176 while (index < end) {
177 switch (descriptor.charAt(index)) {
178 case JVM_SIGNATURE_VOID: if (!voidOK) { return index; }
179 case JVM_SIGNATURE_BOOLEAN:
180 case JVM_SIGNATURE_BYTE:
181 case JVM_SIGNATURE_CHAR:
182 case JVM_SIGNATURE_SHORT:
183 case JVM_SIGNATURE_INT:
184 case JVM_SIGNATURE_FLOAT:
185 case JVM_SIGNATURE_LONG:
186 case JVM_SIGNATURE_DOUBLE:
187 return index - start + 1;
188 case JVM_SIGNATURE_CLASS:
189 // Skip leading 'L' and ignore first appearance of ';'
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;
237 }
|
130 if (len == 0)
131 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
132 ptypes.add(descriptor.substring(cur, cur + len));
133 cur += len;
134 }
135 if (cur >= end)
136 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
137 ++cur; // skip ')'
138
139 int rLen = skipOverFieldSignature(descriptor, cur, end, true);
140 if (rLen == 0 || cur + rLen != end)
141 throw new IllegalArgumentException("Bad method descriptor: " + descriptor);
142 ptypes.add(0, descriptor.substring(cur, cur + rLen));
143 return ptypes;
144 }
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_VALUE_TYPE = 'Q';
151 private static final char JVM_SIGNATURE_ENDCLASS = ';';
152 private static final char JVM_SIGNATURE_ENUM = 'E';
153 private static final char JVM_SIGNATURE_FLOAT = 'F';
154 private static final char JVM_SIGNATURE_DOUBLE = 'D';
155 private static final char JVM_SIGNATURE_FUNC = '(';
156 private static final char JVM_SIGNATURE_ENDFUNC = ')';
157 private static final char JVM_SIGNATURE_INT = 'I';
158 private static final char JVM_SIGNATURE_LONG = 'J';
159 private static final char JVM_SIGNATURE_SHORT = 'S';
160 private static final char JVM_SIGNATURE_VOID = 'V';
161 private static final char JVM_SIGNATURE_BOOLEAN = 'Z';
162
163 /**
164 * Validates that the characters at [start, end) within the provided string
165 * describe a valid field type descriptor.
166 * @param descriptor the descriptor string
167 * @param start the starting index into the string
168 * @param end the ending index within the string
169 * @param voidOK is void acceptable?
170 * @return the length of the descriptor, or 0 if it is not a descriptor
171 * @throws IllegalArgumentException if the descriptor string is not valid
172 */
173 @SuppressWarnings("fallthrough")
174 static int skipOverFieldSignature(String descriptor, int start, int end, boolean voidOK) {
175 int arrayDim = 0;
176 int index = start;
177 while (index < end) {
178 switch (descriptor.charAt(index)) {
179 case JVM_SIGNATURE_VOID: if (!voidOK) { return index; }
180 case JVM_SIGNATURE_BOOLEAN:
181 case JVM_SIGNATURE_BYTE:
182 case JVM_SIGNATURE_CHAR:
183 case JVM_SIGNATURE_SHORT:
184 case JVM_SIGNATURE_INT:
185 case JVM_SIGNATURE_FLOAT:
186 case JVM_SIGNATURE_LONG:
187 case JVM_SIGNATURE_DOUBLE:
188 return index - start + 1;
189 case JVM_SIGNATURE_CLASS:
190 case JVM_SIGNATURE_VALUE_TYPE:
191 // Skip leading 'L' or 'Q' and ignore first appearance of ';'
192 index++;
193 int indexOfSemi = descriptor.indexOf(';', index);
194 if (indexOfSemi != -1) {
195 String unqualifiedName = descriptor.substring(index, indexOfSemi);
196 boolean legal = verifyUnqualifiedClassName(unqualifiedName);
197 if (!legal) {
198 return 0;
199 }
200 return index - start + unqualifiedName.length() + 1;
201 }
202 return 0;
203 case JVM_SIGNATURE_ARRAY:
204 arrayDim++;
205 if (arrayDim > MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
206 throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions",
207 ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
208 }
209 // The rest of what's there better be a legal descriptor
210 index++;
211 voidOK = false;
212 break;
213 default:
214 return 0;
215 }
216 }
217 return 0;
218 }
219
220 /**
221 * Returns the basic type of the given descriptor. If {@code verifyClassName}
222 * is true, then this method will validate that the characters at [start, end)
223 * within the given string describe a valid field type descriptor.
224 *
225 * @return the character represents the basic type that the descriptor string
226 * references
227 * @throws IllegalArgumentException if the descriptor string is not valid
228 */
229 static char basicType(String descriptor, int start, int end, boolean verifyClassName) {
230 int arrayDim = 0;
231 int index = start;
232 while (index < end) {
233 char c = descriptor.charAt(index);
234 switch (c) {
235 case JVM_SIGNATURE_VOID:
236 case JVM_SIGNATURE_BOOLEAN:
237 case JVM_SIGNATURE_BYTE:
238 case JVM_SIGNATURE_CHAR:
239 case JVM_SIGNATURE_SHORT:
240 case JVM_SIGNATURE_INT:
241 case JVM_SIGNATURE_FLOAT:
242 case JVM_SIGNATURE_LONG:
243 case JVM_SIGNATURE_DOUBLE:
244 return c;
245 case JVM_SIGNATURE_CLASS:
246 case JVM_SIGNATURE_VALUE_TYPE:
247 index++;
248 int indexOfSemi = descriptor.indexOf(';', index);
249 if (indexOfSemi != -1) {
250 if (verifyClassName) {
251 String unqualifiedName = descriptor.substring(index, indexOfSemi);
252 boolean legal = verifyUnqualifiedClassName(unqualifiedName);
253 if (!legal) {
254 throw new IllegalArgumentException(String.format("not a valid type descriptor: %s", descriptor));
255 }
256 }
257 return c;
258 }
259 throw new IllegalArgumentException(String.format("not a valid type descriptor: %s", descriptor));
260 case JVM_SIGNATURE_ARRAY:
261 arrayDim++;
262 if (arrayDim > MAX_ARRAY_TYPE_DESC_DIMENSIONS) {
263 throw new IllegalArgumentException(String.format("Cannot create an array type descriptor with more than %d dimensions",
264 ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS));
265 }
266 // The rest of what's there better be a legal descriptor
267 index++;
268 break;
269 default:
270 throw new IllegalArgumentException(String.format("not a valid type descriptor: %s", descriptor));
271 }
272 }
273 throw new IllegalArgumentException(String.format("not a valid type descriptor: %s", descriptor));
274 }
275
276 static boolean verifyUnqualifiedClassName(String name) {
277 for (int index = 0; index < name.length(); index++) {
278 char ch = name.charAt(index);
279 if (ch < 128) {
280 if (ch == '.' || ch == ';' || ch == '[' ) {
281 return false; // do not permit '.', ';', or '['
282 }
283 if (ch == '/') {
284 // check for '//' or leading or trailing '/' which are not legal
285 // unqualified name must not be empty
286 if (index == 0 || index + 1 >= name.length() || name.charAt(index + 1) == '/') {
287 return false;
288 }
289 }
290 } else {
291 index ++;
292 }
293 }
294 return true;
295 }
|