1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include <assert.h>
27 #include <limits.h>
28 #include <setjmp.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "jni.h"
33 #include "jvm.h"
34 #include "check_classname.h"
35
36 typedef unsigned short unicode;
37
38 static char *
39 skip_over_fieldname(char *name, jboolean slash_okay,
40 unsigned int len);
41 static char *
42 skip_over_field_signature(char *name, jboolean void_okay,
43 unsigned int len);
44
45 /*
46 * Return non-zero if the character is a valid in JVM class name, zero
47 * otherwise. The only characters currently disallowed from JVM class
48 * names are given in the table below:
49 *
50 * Character Hex Decimal
51 * '.' 0x2e 46
52 * '/' 0x2f 47
53 * ';' 0x3b 59
54 * '[' 0x5b 91
55 *
56 * (Method names have further restrictions dealing with the '<' and
57 * '>' characters.)
58 */
59 static int isJvmIdentifier(unicode ch) {
60 if( ch > 91 || ch < 46 )
61 return 1; /* Lowercase ASCII letters are > 91 */
62 else { /* 46 <= ch <= 91 */
63 if (ch <= 90 && ch >= 60) {
64 return 1; /* Uppercase ASCII recognized here */
65 } else { /* ch == 91 || 46 <= ch <= 59 */
66 if (ch == 91 || ch == 59 || ch <= 47)
67 return 0;
68 else
69 return 1;
70 }
71 }
72 }
73
74 static unicode
75 next_utf2unicode(char **utfstring_ptr, int * valid)
76 {
77 unsigned char *ptr = (unsigned char *)(*utfstring_ptr);
78 unsigned char ch, ch2, ch3;
79 int length = 1; /* default length */
80 unicode result = 0x80; /* default bad result; */
81 *valid = 1;
82 switch ((ch = ptr[0]) >> 4) {
83 default:
84 result = ch;
85 break;
86
87 case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
88 /* Shouldn't happen. */
89 *valid = 0;
90 break;
91
92 case 0xC: case 0xD:
93 /* 110xxxxx 10xxxxxx */
94 if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
95 unsigned char high_five = ch & 0x1F;
96 unsigned char low_six = ch2 & 0x3F;
97 result = (high_five << 6) + low_six;
98 length = 2;
99 }
100 break;
101
102 case 0xE:
103 /* 1110xxxx 10xxxxxx 10xxxxxx */
104 if (((ch2 = ptr[1]) & 0xC0) == 0x80) {
105 if (((ch3 = ptr[2]) & 0xC0) == 0x80) {
106 unsigned char high_four = ch & 0x0f;
107 unsigned char mid_six = ch2 & 0x3f;
108 unsigned char low_six = ch3 & 0x3f;
109 result = (((high_four << 6) + mid_six) << 6) + low_six;
110 length = 3;
111 } else {
112 length = 2;
113 }
114 }
115 break;
116 } /* end of switch */
117
118 *utfstring_ptr = (char *)(ptr + length);
119 return result;
120 }
121
122 /* Take pointer to a string. Skip over the longest part of the string that
123 * could be taken as a fieldname. Allow '/' if slash_okay is JNI_TRUE.
124 *
125 * Return a pointer to just past the fieldname. Return NULL if no fieldname
126 * at all was found, or in the case of slash_okay being true, we saw
127 * consecutive slashes (meaning we were looking for a qualified path but
128 * found something that was badly-formed).
129 */
130 static char *
131 skip_over_fieldname(char *name, jboolean slash_okay,
132 unsigned int length)
133 {
134 char *p;
135 unicode ch;
136 unicode last_ch = 0;
137 int valid = 1;
138 /* last_ch == 0 implies we are looking at the first char. */
139 for (p = name; p != name + length; last_ch = ch) {
140 char *old_p = p;
141 ch = *p;
142 if (ch < 128) {
143 p++;
144 if (isJvmIdentifier(ch)) {
145 continue;
146 }
147 } else {
148 char *tmp_p = p;
149 ch = next_utf2unicode(&tmp_p, &valid);
150 if (valid == 0)
151 return 0;
152 p = tmp_p;
153 if (isJvmIdentifier(ch)) {
154 continue;
155 }
156 }
157
158 if (slash_okay && ch == '/' && last_ch) {
159 if (last_ch == '/') {
160 return 0; /* Don't permit consecutive slashes */
161 }
162 } else if (ch == '_' || ch == '$') {
163 } else {
164 return last_ch ? old_p : 0;
165 }
166 }
167 return last_ch ? p : 0;
168 }
169
170 /* Take pointer to a string. Skip over the longest part of the string that
171 * could be taken as a field signature. Allow "void" if void_okay.
172 *
173 * Return a pointer to just past the signature. Return NULL if no legal
174 * signature is found.
175 */
176
177 static char *
178 skip_over_field_signature(char *name, jboolean void_okay,
179 unsigned int length)
180 {
181 unsigned int array_dim = 0;
182 for (;length > 0;) {
183 switch (name[0]) {
184 case JVM_SIGNATURE_VOID:
185 if (!void_okay) return 0;
186 /* FALL THROUGH */
187 case JVM_SIGNATURE_BOOLEAN:
188 case JVM_SIGNATURE_BYTE:
189 case JVM_SIGNATURE_CHAR:
190 case JVM_SIGNATURE_SHORT:
191 case JVM_SIGNATURE_INT:
192 case JVM_SIGNATURE_FLOAT:
193 case JVM_SIGNATURE_LONG:
194 case JVM_SIGNATURE_DOUBLE:
195 return name + 1;
196
197 case JVM_SIGNATURE_CLASS: {
198 /* Skip over the classname, if one is there. */
199 char *p =
200 skip_over_fieldname(name + 1, JNI_TRUE, --length);
201 /* The next character better be a semicolon. */
202 if (p && p - name - 1 > 0 && p[0] == ';')
203 return p + 1;
204 return 0;
205 }
206
207 case JVM_SIGNATURE_ARRAY:
208 array_dim++;
209 /* JVMS 2nd ed. 4.10 */
210 /* The number of dimensions in an array is limited to 255 ... */
211 if (array_dim > 255) {
212 return 0;
213 }
214 /* The rest of what's there better be a legal signature. */
215 name++;
216 length--;
217 void_okay = JNI_FALSE;
218 break;
219
220 default:
221 return 0;
222 }
223 }
224 return 0;
225 }
226
227 /* Determine if the specified name is legal
228 * UTF name for a classname.
229 *
230 * Note that this routine expects the internal form of qualified classes:
231 * the dots should have been replaced by slashes.
232 */
233 jboolean verifyClassname(char *name, jboolean allowArrayClass)
234 {
235 size_t s = strlen(name);
236 assert(s <= UINT_MAX);
237 unsigned int length = (unsigned int)s;
238 char *p;
239
240 if (length > 0 && name[0] == JVM_SIGNATURE_ARRAY) {
241 if (!allowArrayClass) {
242 return JNI_FALSE;
243 } else {
244 /* Everything that's left better be a field signature */
245 p = skip_over_field_signature(name, JNI_FALSE, length);
246 }
247 } else {
248 /* skip over the fieldname. Slashes are okay */
249 p = skip_over_fieldname(name, JNI_TRUE, length);
250 }
251 return (p != 0 && p - name == (ptrdiff_t)length);
252 }
253
254 /*
255 * Translates '.' to '/'. Returns JNI_TRUE if any / were present.
256 */
257 jboolean verifyFixClassname(char *name)
258 {
259 char *p = name;
260 jboolean slashesFound = JNI_FALSE;
261 int valid = 1;
262
263 while (valid != 0 && *p != '\0') {
264 if (*p == '/') {
265 slashesFound = JNI_TRUE;
266 p++;
267 } else if (*p == '.') {
268 *p++ = '/';
269 } else {
270 next_utf2unicode(&p, &valid);
271 }
272 }
273
274 return slashesFound && valid != 0;
275 }
276
277 /*
278 * Translates '.' to '/'.
279 */
280 void fixClassname(char *name)
281 {
282 char *p = name;
283 int valid = 1;
284
285 while (valid != 0 && *p != '\0') {
286 if (*p == '.') {
287 *p++ = '/';
288 } else {
289 next_utf2unicode(&p, &valid);
290 }
291 }
292 }
--- EOF ---