1 /* 2 * Copyright (c) 1996, 2020, 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 <stdlib.h> 27 #include <assert.h> 28 29 #include "jni.h" 30 #include "jni_util.h" 31 #include "jlong.h" 32 #include "jvm.h" 33 #include "check_classname.h" 34 #include "java_lang_ClassLoader.h" 35 #include <string.h> 36 37 static JNINativeMethod methods[] = { 38 {"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives} 39 }; 40 41 JNIEXPORT void JNICALL 42 Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls) 43 { 44 (*env)->RegisterNatives(env, cls, methods, 45 sizeof(methods)/sizeof(JNINativeMethod)); 46 } 47 48 /* Convert java string to UTF char*. Use local buffer if possible, 49 otherwise malloc new memory. Returns null IFF malloc failed. */ 50 static char* 51 getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize) 52 { 53 char* utfStr = NULL; 54 55 int len = (*env)->GetStringUTFLength(env, str); 56 int unicode_len = (*env)->GetStringLength(env, str); 57 if (len >= bufSize) { 58 utfStr = malloc(len + 1); 59 if (utfStr == NULL) { 60 JNU_ThrowOutOfMemoryError(env, NULL); 61 return NULL; 62 } 63 } else { 64 utfStr = localBuf; 65 } 66 (*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr); 67 68 return utfStr; 69 } 70 71 JNIEXPORT jclass JNICALL 72 Java_java_lang_ClassLoader_defineClass1(JNIEnv *env, 73 jclass cls, 74 jobject loader, 75 jstring name, 76 jbyteArray data, 77 jint offset, 78 jint length, 79 jobject pd, 80 jstring source) 81 { 82 jbyte *body; 83 char *utfName; 84 jclass result = 0; 85 char buf[128]; 86 char* utfSource; 87 char sourceBuf[1024]; 88 89 if (data == NULL) { 90 JNU_ThrowNullPointerException(env, 0); 91 return 0; 92 } 93 94 /* Work around 4153825. malloc crashes on Solaris when passed a 95 * negative size. 96 */ 97 if (length < 0) { 98 JNU_ThrowArrayIndexOutOfBoundsException(env, 0); 99 return 0; 100 } 101 102 body = (jbyte *)malloc(length); 103 104 if (body == 0) { 105 JNU_ThrowOutOfMemoryError(env, 0); 106 return 0; 107 } 108 109 (*env)->GetByteArrayRegion(env, data, offset, length, body); 110 111 if ((*env)->ExceptionOccurred(env)) 112 goto free_body; 113 114 if (name != NULL) { 115 utfName = getUTF(env, name, buf, sizeof(buf)); 116 if (utfName == NULL) { 117 goto free_body; 118 } 119 fixClassname(utfName); 120 } else { 121 utfName = NULL; 122 } 123 124 if (source != NULL) { 125 utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf)); 126 if (utfSource == NULL) { 127 goto free_utfName; 128 } 129 } else { 130 utfSource = NULL; 131 } 132 result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource); 133 134 if (utfSource && utfSource != sourceBuf) 135 free(utfSource); 136 137 free_utfName: 138 if (utfName && utfName != buf) 139 free(utfName); 140 141 free_body: 142 free(body); 143 return result; 144 } 145 146 JNIEXPORT jclass JNICALL 147 Java_java_lang_ClassLoader_defineClass2(JNIEnv *env, 148 jclass cls, 149 jobject loader, 150 jstring name, 151 jobject data, 152 jint offset, 153 jint length, 154 jobject pd, 155 jstring source) 156 { 157 jbyte *body; 158 char *utfName; 159 jclass result = 0; 160 char buf[128]; 161 char* utfSource; 162 char sourceBuf[1024]; 163 164 assert(data != NULL); // caller fails if data is null. 165 assert(length >= 0); // caller passes ByteBuffer.remaining() for length, so never neg. 166 // caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining() 167 assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length)); 168 169 body = (*env)->GetDirectBufferAddress(env, data); 170 171 if (body == 0) { 172 JNU_ThrowNullPointerException(env, 0); 173 return 0; 174 } 175 176 body += offset; 177 178 if (name != NULL) { 179 utfName = getUTF(env, name, buf, sizeof(buf)); 180 if (utfName == NULL) { 181 JNU_ThrowOutOfMemoryError(env, NULL); 182 return result; 183 } 184 fixClassname(utfName); 185 } else { 186 utfName = NULL; 187 } 188 189 if (source != NULL) { 190 utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf)); 191 if (utfSource == NULL) { 192 JNU_ThrowOutOfMemoryError(env, NULL); 193 goto free_utfName; 194 } 195 } else { 196 utfSource = NULL; 197 } 198 result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource); 199 200 if (utfSource && utfSource != sourceBuf) 201 free(utfSource); 202 203 free_utfName: 204 if (utfName && utfName != buf) 205 free(utfName); 206 207 return result; 208 } 209 210 JNIEXPORT jclass JNICALL 211 Java_java_lang_ClassLoader_defineClass0(JNIEnv *env, 212 jclass cls, 213 jobject loader, 214 jclass lookup, 215 jstring name, 216 jbyteArray data, 217 jint offset, 218 jint length, 219 jobject pd, 220 jboolean initialize, 221 jint flags, 222 jobject classData) 223 { 224 jbyte *body; 225 char *utfName; 226 jclass result = 0; 227 char buf[128]; 228 229 if (data == NULL) { 230 JNU_ThrowNullPointerException(env, 0); 231 return 0; 232 } 233 234 /* Work around 4153825. malloc crashes on Solaris when passed a 235 * negative size. 236 */ 237 if (length < 0) { 238 JNU_ThrowArrayIndexOutOfBoundsException(env, 0); 239 return 0; 240 } 241 242 body = (jbyte *)malloc(length); 243 if (body == 0) { 244 JNU_ThrowOutOfMemoryError(env, 0); 245 return 0; 246 } 247 248 (*env)->GetByteArrayRegion(env, data, offset, length, body); 249 250 if ((*env)->ExceptionOccurred(env)) 251 goto free_body; 252 253 if (name != NULL) { 254 utfName = getUTF(env, name, buf, sizeof(buf)); 255 if (utfName == NULL) { 256 goto free_body; 257 } 258 fixClassname(utfName); 259 } else { 260 utfName = NULL; 261 } 262 263 return JVM_LookupDefineClass(env, lookup, utfName, body, length, pd, initialize, flags, classData); 264 265 free_body: 266 free(body); 267 return result; 268 } 269 270 /* 271 * Returns NULL if class not found. 272 */ 273 JNIEXPORT jclass JNICALL 274 Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, 275 jstring classname) 276 { 277 char *clname; 278 jclass cls = 0; 279 char buf[128]; 280 281 if (classname == NULL) { 282 return 0; 283 } 284 285 clname = getUTF(env, classname, buf, sizeof(buf)); 286 if (clname == NULL) { 287 JNU_ThrowOutOfMemoryError(env, NULL); 288 return NULL; 289 } 290 fixClassname(clname); 291 292 if (!verifyClassname(clname, JNI_TRUE)) { /* expects slashed name */ 293 goto done; 294 } 295 296 cls = JVM_FindClassFromBootLoader(env, clname); 297 298 done: 299 if (clname != buf) { 300 free(clname); 301 } 302 303 return cls; 304 } 305 306 JNIEXPORT jclass JNICALL 307 Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader, 308 jstring name) 309 { 310 if (name == NULL) { 311 return 0; 312 } else { 313 return JVM_FindLoadedClass(env, loader, name); 314 } 315 }