Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/native/libjava/check_classname.c
41149 views
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
}
293
294