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
Java_java_lang_ClassLoader_registerNatives(JNIEnv * env,jclass cls)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*
getUTF(JNIEnv * env,jstring str,char * localBuf,int bufSize)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
Java_java_lang_ClassLoader_defineClass1(JNIEnv * env,jclass cls,jobject loader,jstring name,jbyteArray data,jint offset,jint length,jobject pd,jstring source)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
Java_java_lang_ClassLoader_defineClass2(JNIEnv * env,jclass cls,jobject loader,jstring name,jobject data,jint offset,jint length,jobject pd,jstring source)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
Java_java_lang_ClassLoader_defineClass0(JNIEnv * env,jclass cls,jobject loader,jclass lookup,jstring name,jbyteArray data,jint offset,jint length,jobject pd,jboolean initialize,jint flags,jobject classData)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 result = 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
Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv * env,jobject loader,jstring classname)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
Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv * env,jobject loader,jstring name)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 }
316