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 }