1
1
/*
2
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
@@ -65,15 +65,15 @@ static String validateBinaryClassName(String name) {
65
65
* @return the name passed if valid
66
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
69
requireNonNull (name );
70
70
if (name .length () == 0 )
71
71
throw new IllegalArgumentException ("zero-length member name" );
72
72
for (int i =0 ; i <name .length (); i ++) {
73
73
char ch = name .charAt (i );
74
74
if (ch == '.' || ch == ';' || ch == '[' || ch == '/' )
75
75
throw new IllegalArgumentException ("Invalid member name: " + name );
76
- if (ch == '<' || ch == '>' ) {
76
+ if (method && ( ch == '<' || ch == '>' ) ) {
77
77
if (!pointyNames .contains (name ))
78
78
throw new IllegalArgumentException ("Invalid member name: " + name );
79
79
}
@@ -126,8 +126,8 @@ static List<String> parseMethodDescriptor(String descriptor) {
126
126
127
127
++cur ; // skip '('
128
128
while (cur < end && descriptor .charAt (cur ) != ')' ) {
129
- int len = matchSig (descriptor , cur , end );
130
- if (len == 0 || descriptor . charAt ( cur ) == 'V' )
129
+ int len = skipOverFieldSignature (descriptor , cur , end , false );
130
+ if (len == 0 )
131
131
throw new IllegalArgumentException ("Bad method descriptor: " + descriptor );
132
132
ptypes .add (descriptor .substring (cur , cur + len ));
133
133
cur += len ;
@@ -136,41 +136,103 @@ static List<String> parseMethodDescriptor(String descriptor) {
136
136
throw new IllegalArgumentException ("Bad method descriptor: " + descriptor );
137
137
++cur ; // skip ')'
138
138
139
- int rLen = matchSig (descriptor , cur , end );
139
+ int rLen = skipOverFieldSignature (descriptor , cur , end , true );
140
140
if (rLen == 0 || cur + rLen != end )
141
141
throw new IllegalArgumentException ("Bad method descriptor: " + descriptor );
142
142
ptypes .add (0 , descriptor .substring (cur , cur + rLen ));
143
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
163
* Validates that the characters at [start, end) within the provided string
148
164
* describe a valid field type descriptor.
149
- *
150
- * @param str the descriptor string
165
+ * @param descriptor the descriptor string
151
166
* @param start the starting index into the string
152
167
* @param end the ending index within the string
168
+ * @param voidOK is void acceptable?
153
169
* @return the length of the descriptor, or 0 if it is not a descriptor
154
170
* @throws IllegalArgumentException if the descriptor string is not valid
155
171
*/
156
- static int matchSig (String str , int start , int end ) {
157
- if (start >= end || start >= str .length () || end > str .length ())
158
- return 0 ;
159
- char c = str .charAt (start );
160
- if (c == 'L' ) {
161
- int endc = str .indexOf (';' , start );
162
- int badc = str .indexOf ('.' , start );
163
- if (badc >= 0 && badc < endc )
164
- return 0 ;
165
- badc = str .indexOf ('[' , start );
166
- if (badc >= 0 && badc < endc )
167
- return 0 ;
168
- return (endc < 0 ) ? 0 : endc - start + 1 ;
169
- } else if (c == '[' ) {
170
- int t = matchSig (str , start +1 , end );
171
- return (t > 0 ) ? t + 1 : 0 ;
172
- } else {
173
- return ("IJCSBFDZV" .indexOf (c ) >= 0 ) ? 1 : 0 ;
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
+ }
174
235
}
236
+ return true ;
175
237
}
176
238
}
0 commit comments