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             case JVM_SIGNATURE_INLINE_TYPE: {
199                 /* Skip over the classname, if one is there. */
200                 char *p =
201                     skip_over_fieldname(name + 1, JNI_TRUE, --length);
202                 /* The next character better be a semicolon. */
203                 if (p && p - name - 1 > 0 && p[0] == ';')
204                     return p + 1;
205                 return 0;
206             }
207 
208             case JVM_SIGNATURE_ARRAY:
209                 array_dim++;
210                 /* JVMS 2nd ed. 4.10 */
211                 /*   The number of dimensions in an array is limited to 255 ... */
212                 if (array_dim > 255) {
213                     return 0;
214                 }
215                 /* The rest of what's there better be a legal signature.  */
216                 name++;
217                 length--;
218                 void_okay = JNI_FALSE;
219                 break;
220 
221             default:
222                 return 0;
223         }
224     }
225     return 0;
226 }
227 
228 /* Determine if the specified name is legal
229  * UTF name for a classname.
230  *
231  * Note that this routine expects the internal form of qualified classes:
232  * the dots should have been replaced by slashes.
233  */
234 jboolean verifyClassname(char *name, jboolean allowArrayClass)
235 {
236     size_t s = strlen(name);
237     assert(s <= UINT_MAX);
238     unsigned int length = (unsigned int)s;
239     char *p;
240 
241     if (length > 0 && name[0] == JVM_SIGNATURE_ARRAY) {
242         if (!allowArrayClass) {
243             return JNI_FALSE;
244         } else {
245             /* Everything that's left better be a field signature */
246             p = skip_over_field_signature(name, JNI_FALSE, length);
247         }
248     } else {
249         /* skip over the fieldname.  Slashes are okay */
250         p = skip_over_fieldname(name, JNI_TRUE, length);
251     }
252     return (p != 0 && p - name == (ptrdiff_t)length);
253 }
254 
255 /*
256  * Translates '.' to '/'.  Returns JNI_TRUE if any / were present.
257  */
258 jboolean verifyFixClassname(char *name)
259 {
260     char *p = name;
261     jboolean slashesFound = JNI_FALSE;
262     int valid = 1;
263 
264     while (valid != 0 && *p != '\0') {
265         if (*p == '/') {
266             slashesFound = JNI_TRUE;
267             p++;
268         } else if (*p == '.') {
269             *p++ = '/';
270         } else {
271             next_utf2unicode(&p, &valid);
272         }
273     }
274 
275     return slashesFound && valid != 0;
276 }
277 
278 /*
279  * Translates '.' to '/'.
280  */
281 void fixClassname(char *name)
282 {
283     char *p = name;
284     int valid = 1;
285 
286     while (valid != 0 && *p != '\0') {
287         if (*p == '.') {
288             *p++ = '/';
289         } else {
290             next_utf2unicode(&p, &valid);
291         }
292     }
293 }