1 /* 2 * Copyright (c) 1997, 2008, 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 <setjmp.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include "jni.h" 31 #include "jvm.h" 32 33 typedef unsigned short unicode; 34 35 static char * 36 skip_over_fieldname(char *name, jboolean slash_okay, 37 unsigned int len); 38 static char * 39 skip_over_field_signature(char *name, jboolean void_okay, 40 unsigned int len); 41 42 /* 43 * Return non-zero if the character is a valid in JVM class name, zero 44 * otherwise. The only characters currently disallowed from JVM class 45 * names are given in the table below: 46 * 47 * Character Hex Decimal 48 * '.' 0x2e 46 49 * '/' 0x2f 47 50 * ';' 0x3b 59 51 * '[' 0x5b 91 52 * 53 * (Method names have further restrictions dealing with the '<' and 54 * '>' characters.) 55 */ 56 static int isJvmIdentifier(unicode ch) { 57 if( ch > 91 || ch < 46 ) 58 return 1; /* Lowercase ASCII letters are > 91 */ 59 else { /* 46 <= ch <= 91 */ 60 if (ch <= 90 && ch >= 60) { 61 return 1; /* Uppercase ASCII recognized here */ 62 } else { /* ch == 91 || 46 <= ch <= 59 */ 63 if (ch == 91 || ch == 59 || ch <= 47) 64 return 0; 65 else 66 return 1; 67 } 68 } 69 } 70 71 static unicode 72 next_utf2unicode(char **utfstring_ptr, int * valid) 73 { 74 unsigned char *ptr = (unsigned char *)(*utfstring_ptr); 75 unsigned char ch, ch2, ch3; 76 int length = 1; /* default length */ 77 unicode result = 0x80; /* default bad result; */ 78 *valid = 1; 79 switch ((ch = ptr[0]) >> 4) { 80 default: 81 result = ch; 82 break; 83 84 case 0x8: case 0x9: case 0xA: case 0xB: case 0xF: 85 /* Shouldn't happen. */ 86 *valid = 0; 87 break; 88 89 case 0xC: case 0xD: 90 /* 110xxxxx 10xxxxxx */ 91 if (((ch2 = ptr[1]) & 0xC0) == 0x80) { 92 unsigned char high_five = ch & 0x1F; 93 unsigned char low_six = ch2 & 0x3F; 94 result = (high_five << 6) + low_six; 95 length = 2; 96 } 97 break; 98 99 case 0xE: 100 /* 1110xxxx 10xxxxxx 10xxxxxx */ 101 if (((ch2 = ptr[1]) & 0xC0) == 0x80) { 102 if (((ch3 = ptr[2]) & 0xC0) == 0x80) { 103 unsigned char high_four = ch & 0x0f; 104 unsigned char mid_six = ch2 & 0x3f; 105 unsigned char low_six = ch3 & 0x3f; 106 result = (((high_four << 6) + mid_six) << 6) + low_six; 107 length = 3; 108 } else { 109 length = 2; 110 } 111 } 112 break; 113 } /* end of switch */ 114 115 *utfstring_ptr = (char *)(ptr + length); 116 return result; 117 } 118 119 /* Take pointer to a string. Skip over the longest part of the string that 120 * could be taken as a fieldname. Allow '/' if slash_okay is JNI_TRUE. 121 * 122 * Return a pointer to just past the fieldname. Return NULL if no fieldname 123 * at all was found, or in the case of slash_okay being true, we saw 124 * consecutive slashes (meaning we were looking for a qualified path but 125 * found something that was badly-formed). 126 */ 127 static char * 128 skip_over_fieldname(char *name, jboolean slash_okay, 129 unsigned int length) 130 { 131 char *p; 132 unicode ch; 133 unicode last_ch = 0; 134 int valid = 1; 135 /* last_ch == 0 implies we are looking at the first char. */ 136 for (p = name; p != name + length; last_ch = ch) { 137 char *old_p = p; 138 ch = *p; 139 if (ch < 128) { 140 p++; 141 if (isJvmIdentifier(ch)) { 142 continue; 143 } 144 } else { 145 char *tmp_p = p; 146 ch = next_utf2unicode(&tmp_p, &valid); 147 if (valid == 0) 148 return 0; 149 p = tmp_p; 150 if (isJvmIdentifier(ch)) { 151 continue; 152 } 153 } 154 155 if (slash_okay && ch == '/' && last_ch) { 156 if (last_ch == '/') { 157 return 0; /* Don't permit consecutive slashes */ 158 } 159 } else if (ch == '_' || ch == '$') { 160 } else { 161 return last_ch ? old_p : 0; 162 } 163 } 164 return last_ch ? p : 0; 165 } 166 167 /* Take pointer to a string. Skip over the longest part of the string that 168 * could be taken as a field signature. Allow "void" if void_okay. 169 * 170 * Return a pointer to just past the signature. Return NULL if no legal 171 * signature is found. 172 */ 173 174 static char * 175 skip_over_field_signature(char *name, jboolean void_okay, 176 unsigned int length) 177 { 178 unsigned int array_dim = 0; 179 for (;length > 0;) { 180 switch (name[0]) { 181 case JVM_SIGNATURE_VOID: 182 if (!void_okay) return 0; 183 /* FALL THROUGH */ 184 case JVM_SIGNATURE_BOOLEAN: 185 case JVM_SIGNATURE_BYTE: 186 case JVM_SIGNATURE_CHAR: 187 case JVM_SIGNATURE_SHORT: 188 case JVM_SIGNATURE_INT: 189 case JVM_SIGNATURE_FLOAT: 190 case JVM_SIGNATURE_LONG: 191 case JVM_SIGNATURE_DOUBLE: 192 return name + 1; 193 194 case JVM_SIGNATURE_CLASS: { 195 /* Skip over the classname, if one is there. */ 196 char *p = 197 skip_over_fieldname(name + 1, JNI_TRUE, --length); 198 /* The next character better be a semicolon. */ 199 if (p && p - name - 1 > 0 && p[0] == ';') 200 return p + 1; 201 return 0; 202 } 203 204 case JVM_SIGNATURE_ARRAY: 205 array_dim++; 206 /* JVMS 2nd ed. 4.10 */ 207 /* The number of dimensions in an array is limited to 255 ... */ 208 if (array_dim > 255) { 209 return 0; 210 } 211 /* The rest of what's there better be a legal signature. */ 212 name++; 213 length--; 214 void_okay = JNI_FALSE; 215 break; 216 217 default: 218 return 0; 219 } 220 } 221 return 0; 222 } 223 224 225 /* Used in java/lang/Class.c */ 226 /* Determine if the specified name is legal 227 * UTF name for a classname. 228 * 229 * Note that this routine expects the internal form of qualified classes: 230 * the dots should have been replaced by slashes. 231 */ 232 JNIEXPORT jboolean 233 VerifyClassname(char *name, jboolean allowArrayClass) 234 { 235 unsigned int length = strlen(name); 236 char *p; 237 238 if (length > 0 && name[0] == JVM_SIGNATURE_ARRAY) { 239 if (!allowArrayClass) { 240 return JNI_FALSE; 241 } else { 242 /* Everything that's left better be a field signature */ 243 p = skip_over_field_signature(name, JNI_FALSE, length); 244 } 245 } else { 246 /* skip over the fieldname. Slashes are okay */ 247 p = skip_over_fieldname(name, JNI_TRUE, length); 248 } 249 return (p != 0 && p - name == (ptrdiff_t)length); 250 } 251 252 /* 253 * Translates '.' to '/'. Returns JNI_TRUE is any / were present. 254 */ 255 JNIEXPORT jboolean 256 VerifyFixClassname(char *name) 257 { 258 char *p = name; 259 jboolean slashesFound = JNI_FALSE; 260 int valid = 1; 261 262 while (valid != 0 && *p != '\0') { 263 if (*p == '/') { 264 slashesFound = JNI_TRUE; 265 p++; 266 } else if (*p == '.') { 267 *p++ = '/'; 268 } else { 269 next_utf2unicode(&p, &valid); 270 } 271 } 272 273 return slashesFound && valid != 0; 274 }