1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
19 *
20 * We want to verify types, make sure class and field IDs are valid, and
21 * ensure that JNI's semantic expectations are being met. JNI seems to
22 * be relatively lax when it comes to requirements for permission checks,
23 * e.g. access to private methods is generally allowed from anywhere.
24 *
25 * TODO: keep a counter on global Get/Release. Report a warning if some Gets
26 * were not Released. Do not count explicit Add/DeleteGlobalRef calls (or
27 * count them separately, so we can complain if they exceed a certain
28 * threshold).
29 *
30 * TODO: verify that the methodID passed into the Call functions is for
31 * a method in the specified class.
32 */
33 #include "Dalvik.h"
34 #include "JniInternal.h"
35
36 #include <zlib.h>
37
38 static void abortMaybe(void); // fwd
39
40
41 /*
42 * ===========================================================================
43 * JNI call bridge wrapper
44 * ===========================================================================
45 */
46
47 /*
48 * Check the result of a native method call that returns an object reference.
49 *
50 * The primary goal here is to verify that native code is returning the
51 * correct type of object. If it's declared to return a String but actually
52 * returns a byte array, things will fail in strange ways later on.
53 *
54 * This can be a fairly expensive operation, since we have to look up the
55 * return type class by name in method->clazz' class loader. We take a
56 * shortcut here and allow the call to succeed if the descriptor strings
57 * match. This will allow some false-positives when a class is redefined
58 * by a class loader, but that's rare enough that it doesn't seem worth
59 * testing for.
60 *
61 * At this point, pResult->l has already been converted to an object pointer.
62 */
checkCallCommon(const u4 * args,JValue * pResult,const Method * method,Thread * self)63 static void checkCallCommon(const u4* args, JValue* pResult,
64 const Method* method, Thread* self)
65 {
66 assert(pResult->l != NULL);
67 Object* resultObj = (Object*) pResult->l;
68 ClassObject* objClazz = resultObj->clazz;
69
70 /*
71 * Make sure that pResult->l is an instance of the type this
72 * method was expected to return.
73 */
74 const char* declType = dexProtoGetReturnType(&method->prototype);
75 const char* objType = objClazz->descriptor;
76 if (strcmp(declType, objType) == 0) {
77 /* names match; ignore class loader issues and allow it */
78 LOGV("Check %s.%s: %s io %s (FAST-OK)\n",
79 method->clazz->descriptor, method->name, objType, declType);
80 } else {
81 /*
82 * Names didn't match. We need to resolve declType in the context
83 * of method->clazz->classLoader, and compare the class objects
84 * for equality.
85 *
86 * Since we're returning an instance of declType, it's safe to
87 * assume that it has been loaded and initialized (or, for the case
88 * of an array, generated), so we can just look for it in the
89 * loaded-classes list.
90 */
91 ClassObject* declClazz;
92
93 declClazz = dvmLookupClass(declType, method->clazz->classLoader, false);
94 if (declClazz == NULL) {
95 LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
96 declType, objType);
97 LOGW(" failed in %s.%s ('%s' not found)\n",
98 method->clazz->descriptor, method->name, declType);
99 abortMaybe();
100 return;
101 }
102 if (!dvmInstanceof(objClazz, declClazz)) {
103 LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
104 declType, objType);
105 LOGW(" failed in %s.%s\n",
106 method->clazz->descriptor, method->name);
107 abortMaybe();
108 return;
109 } else {
110 LOGV("Check %s.%s: %s io %s (SLOW-OK)\n",
111 method->clazz->descriptor, method->name, objType, declType);
112 }
113 }
114 }
115
116 /*
117 * Determine if we need to check the return type coming out of the call.
118 *
119 * (We don't do this at the top of checkCallCommon() because this is on
120 * the critical path for native method calls.)
121 */
callNeedsCheck(const u4 * args,JValue * pResult,const Method * method,Thread * self)122 static inline bool callNeedsCheck(const u4* args, JValue* pResult,
123 const Method* method, Thread* self)
124 {
125 return (method->shorty[0] == 'L' && !dvmCheckException(self) &&
126 pResult->l != NULL);
127 }
128
129 /*
130 * Check a call into native code.
131 */
dvmCheckCallJNIMethod_general(const u4 * args,JValue * pResult,const Method * method,Thread * self)132 void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
133 const Method* method, Thread* self)
134 {
135 dvmCallJNIMethod_general(args, pResult, method, self);
136 if (callNeedsCheck(args, pResult, method, self))
137 checkCallCommon(args, pResult, method, self);
138 }
139
140 /*
141 * Check a synchronized call into native code.
142 */
dvmCheckCallJNIMethod_synchronized(const u4 * args,JValue * pResult,const Method * method,Thread * self)143 void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
144 const Method* method, Thread* self)
145 {
146 dvmCallJNIMethod_synchronized(args, pResult, method, self);
147 if (callNeedsCheck(args, pResult, method, self))
148 checkCallCommon(args, pResult, method, self);
149 }
150
151 /*
152 * Check a virtual call with no reference arguments (other than "this").
153 */
dvmCheckCallJNIMethod_virtualNoRef(const u4 * args,JValue * pResult,const Method * method,Thread * self)154 void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
155 const Method* method, Thread* self)
156 {
157 dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
158 if (callNeedsCheck(args, pResult, method, self))
159 checkCallCommon(args, pResult, method, self);
160 }
161
162 /*
163 * Check a static call with no reference arguments (other than "clazz").
164 */
dvmCheckCallJNIMethod_staticNoRef(const u4 * args,JValue * pResult,const Method * method,Thread * self)165 void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
166 const Method* method, Thread* self)
167 {
168 dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
169 if (callNeedsCheck(args, pResult, method, self))
170 checkCallCommon(args, pResult, method, self);
171 }
172
173
174 /*
175 * ===========================================================================
176 * JNI function helpers
177 * ===========================================================================
178 */
179
180 #define JNI_ENTER() dvmChangeStatus(NULL, THREAD_RUNNING)
181 #define JNI_EXIT() dvmChangeStatus(NULL, THREAD_NATIVE)
182
183 #define BASE_ENV(_env) (((JNIEnvExt*)_env)->baseFuncTable)
184 #define BASE_VM(_vm) (((JavaVMExt*)_vm)->baseFuncTable)
185
186 #define kRedundantDirectBufferTest false
187
188 /*
189 * Flags passed into checkThread().
190 */
191 #define kFlag_Default 0x0000
192
193 #define kFlag_CritBad 0x0000 /* calling while in critical is bad */
194 #define kFlag_CritOkay 0x0001 /* ...okay */
195 #define kFlag_CritGet 0x0002 /* this is a critical "get" */
196 #define kFlag_CritRelease 0x0003 /* this is a critical "release" */
197 #define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
198
199 #define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
200 #define kFlag_ExcepOkay 0x0004 /* ...okay */
201
202 /*
203 * Enter/exit macros for JNI env "check" functions. These do not change
204 * the thread state within the VM.
205 */
206 #define CHECK_ENTER(_env, _flags) \
207 do { \
208 JNI_TRACE(true, true); \
209 checkThread(_env, _flags, __FUNCTION__); \
210 } while(false)
211
212 #define CHECK_EXIT(_env) \
213 do { JNI_TRACE(false, true); } while(false)
214
215
216 /*
217 * Enter/exit macros for JNI invocation interface "check" functions. These
218 * do not change the thread state within the VM.
219 *
220 * Set "_hasmeth" to true if we have a valid thread with a method pointer.
221 * We won't have one before attaching a thread, after detaching a thread, or
222 * after destroying the VM.
223 */
224 #define CHECK_VMENTER(_vm, _hasmeth) \
225 do { JNI_TRACE(true, _hasmeth); } while(false)
226 #define CHECK_VMEXIT(_vm, _hasmeth) \
227 do { JNI_TRACE(false, _hasmeth); } while(false)
228
229 #define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic) \
230 checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
231 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid) \
232 checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
233 #define CHECK_CLASS(_env, _clazz) \
234 checkClass(_env, _clazz, __FUNCTION__)
235 #define CHECK_STRING(_env, _str) \
236 checkString(_env, _str, __FUNCTION__)
237 #define CHECK_UTF_STRING(_env, _str, _nullok) \
238 checkUtfString(_env, _str, _nullok, __FUNCTION__)
239 #define CHECK_CLASS_NAME(_env, _str) \
240 checkClassName(_env, _str, __FUNCTION__)
241 #define CHECK_OBJECT(_env, _obj) \
242 checkObject(_env, _obj, __FUNCTION__)
243 #define CHECK_ARRAY(_env, _array) \
244 checkArray(_env, _array, __FUNCTION__)
245 #define CHECK_RELEASE_MODE(_env, _mode) \
246 checkReleaseMode(_env, _mode, __FUNCTION__)
247 #define CHECK_LENGTH_POSITIVE(_env, _length) \
248 checkLengthPositive(_env, _length, __FUNCTION__)
249 #define CHECK_NON_NULL(_env, _ptr) \
250 checkNonNull(_env, _ptr, __FUNCTION__)
251
252 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic) \
253 checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
254
255 /*
256 * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
257 */
258 #define JNI_TRACE(_entry, _hasmeth) \
259 do { \
260 if (gDvm.verboseJni && (_entry)) { \
261 static const char* classDescriptor = "???"; \
262 static const char* methodName = "???"; \
263 if (_hasmeth) { \
264 const Method* meth = dvmGetCurrentJNIMethod(); \
265 classDescriptor = meth->clazz->descriptor; \
266 methodName = meth->name; \
267 } \
268 /* use +6 to drop the leading "Check_" */ \
269 LOGI("JNI: %s (from %s.%s)", \
270 (__FUNCTION__)+6, classDescriptor, methodName); \
271 } \
272 } while(false)
273
274 /*
275 * Log the current location.
276 *
277 * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
278 */
showLocation(const Method * meth,const char * func)279 static void showLocation(const Method* meth, const char* func)
280 {
281 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
282 LOGW(" in %s.%s %s (%s)\n",
283 meth->clazz->descriptor, meth->name, desc, func + 6);
284 free(desc);
285 }
286
287 /*
288 * Abort if we are configured to bail out on JNI warnings.
289 */
abortMaybe(void)290 static void abortMaybe(void)
291 {
292 JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
293 if (vm->warnError) {
294 dvmDumpThread(dvmThreadSelf(), false);
295 dvmAbort();
296 }
297 }
298
299 /*
300 * Verify that the current thread is (a) attached and (b) associated with
301 * this particular instance of JNIEnv.
302 *
303 * Verify that, if this thread previously made a critical "get" call, we
304 * do the corresponding "release" call before we try anything else.
305 *
306 * Verify that, if an exception has been raised, the native code doesn't
307 * make any JNI calls other than the Exception* methods.
308 *
309 * TODO? if we add support for non-JNI native calls, make sure that the
310 * method at the top of the interpreted stack is a JNI method call. (Or
311 * set a flag in the Thread/JNIEnv when the call is made and clear it on
312 * return?)
313 *
314 * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
315 */
checkThread(JNIEnv * env,int flags,const char * func)316 static void checkThread(JNIEnv* env, int flags, const char* func)
317 {
318 JNIEnvExt* threadEnv;
319 bool printWarn = false;
320 bool printException = false;
321
322 /* get the *correct* JNIEnv by going through our TLS pointer */
323 threadEnv = dvmGetJNIEnvForThread();
324
325 /*
326 * Verify that the JNIEnv we've been handed matches what we expected
327 * to receive.
328 */
329 if (threadEnv == NULL) {
330 LOGE("JNI ERROR: non-VM thread making JNI calls\n");
331 // don't set printWarn -- it'll try to call showLocation()
332 dvmAbort();
333 } else if ((JNIEnvExt*) env != threadEnv) {
334 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
335 LOGE("JNI: threadEnv != thread->env?\n");
336 dvmAbort();
337 }
338
339 LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
340 threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
341 printWarn = true;
342
343 /* this is a bad idea -- need to throw as we exit, or abort func */
344 //dvmThrowException("Ljava/lang/RuntimeException;",
345 // "invalid use of JNI env ptr");
346 } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
347 /* correct JNIEnv*; make sure the "self" pointer is correct */
348 LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)\n",
349 ((JNIEnvExt*) env)->self, dvmThreadSelf());
350 dvmAbort();
351 }
352
353 /*
354 * Check for critical resource misuse.
355 */
356 switch (flags & kFlag_CritMask) {
357 case kFlag_CritOkay: // okay to call this method
358 break;
359 case kFlag_CritBad: // not okay to call
360 if (threadEnv->critical) {
361 LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
362 threadEnv->envThreadId);
363 printWarn = true;
364 }
365 break;
366 case kFlag_CritGet: // this is a "get" call
367 /* don't check here; we allow nested gets */
368 threadEnv->critical++;
369 break;
370 case kFlag_CritRelease: // this is a "release" call
371 threadEnv->critical--;
372 if (threadEnv->critical < 0) {
373 LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
374 threadEnv->envThreadId);
375 printWarn = true;
376 }
377 break;
378 default:
379 assert(false);
380 }
381
382 /*
383 * Check for raised exceptions.
384 */
385 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
386 LOGW("JNI WARNING: JNI method called with exception raised\n");
387 printWarn = true;
388 printException = true;
389 }
390
391 if (printWarn)
392 showLocation(dvmGetCurrentJNIMethod(), func);
393 if (printException) {
394 LOGW("Pending exception is:\n");
395 dvmLogExceptionStackTrace();
396 }
397 if (printWarn)
398 abortMaybe();
399 }
400
401 /*
402 * Verify that the field is of the appropriate type. If the field has an
403 * object type, "obj" is the object we're trying to assign into it.
404 *
405 * Works for both static and instance fields.
406 */
checkFieldType(JNIEnv * env,jobject jobj,jfieldID fieldID,PrimitiveType prim,bool isStatic,const char * func)407 static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
408 PrimitiveType prim, bool isStatic, const char* func)
409 {
410 static const char* primNameList[] = {
411 "Object/Array", "boolean", "char", "float", "double",
412 "byte", "short", "int", "long", "void"
413 };
414 const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
415 Field* field = (Field*) fieldID;
416 bool printWarn = false;
417
418 if (fieldID == NULL) {
419 LOGE("JNI ERROR: null field ID\n");
420 abortMaybe();
421 }
422
423 if (field->signature[0] == 'L' || field->signature[0] == '[') {
424 Object* obj = dvmDecodeIndirectRef(env, jobj);
425 if (obj != NULL) {
426 ClassObject* fieldClass =
427 dvmFindLoadedClass(field->signature);
428 ClassObject* objClass = obj->clazz;
429
430 assert(fieldClass != NULL);
431 assert(objClass != NULL);
432
433 if (!dvmInstanceof(objClass, fieldClass)) {
434 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
435 field->name, field->signature, objClass->descriptor);
436 printWarn = true;
437 }
438 }
439 } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
440 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
441 field->name, field->signature, primNames[prim]);
442 printWarn = true;
443 } else if (isStatic && !dvmIsStaticField(field)) {
444 if (isStatic)
445 LOGW("JNI WARNING: accessing non-static field %s as static\n",
446 field->name);
447 else
448 LOGW("JNI WARNING: accessing static field %s as non-static\n",
449 field->name);
450 printWarn = true;
451 }
452
453 if (printWarn) {
454 showLocation(dvmGetCurrentJNIMethod(), func);
455 abortMaybe();
456 }
457 }
458
459 /*
460 * Verify that "jobj" is a valid object, and that it's an object that JNI
461 * is allowed to know about. We allow NULL references.
462 *
463 * Switches to "running" mode before performing checks.
464 */
checkObject(JNIEnv * env,jobject jobj,const char * func)465 static void checkObject(JNIEnv* env, jobject jobj, const char* func)
466 {
467 UNUSED_PARAMETER(env);
468 bool printWarn = false;
469
470 if (jobj == NULL)
471 return;
472
473 JNI_ENTER();
474
475 if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
476 LOGW("JNI WARNING: %p is not a valid JNI reference\n", jobj);
477 printWarn = true;
478 } else {
479 Object* obj = dvmDecodeIndirectRef(env, jobj);
480
481 if (obj == NULL || !dvmIsValidObject(obj)) {
482 LOGW("JNI WARNING: native code passing in bad object %p %p (%s)\n",
483 jobj, obj, func);
484 printWarn = true;
485 }
486 }
487
488 if (printWarn) {
489 showLocation(dvmGetCurrentJNIMethod(), func);
490 abortMaybe();
491 }
492
493 JNI_EXIT();
494 }
495
496 /*
497 * Verify that "clazz" actually points to a class object. (Also performs
498 * checkObject.)
499 *
500 * We probably don't need to identify where we're being called from,
501 * because the VM is most likely about to crash and leave a core dump
502 * if something is wrong.
503 *
504 * Because we're looking at an object on the GC heap, we have to switch
505 * to "running" mode before doing the checks.
506 */
checkClass(JNIEnv * env,jclass jclazz,const char * func)507 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
508 {
509 JNI_ENTER();
510 bool printWarn = false;
511
512 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
513
514 if (clazz == NULL) {
515 LOGW("JNI WARNING: received null jclass\n");
516 printWarn = true;
517 } else if (!dvmIsValidObject((Object*) clazz)) {
518 LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
519 printWarn = true;
520 } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
521 LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
522 jclazz, clazz->descriptor);
523 printWarn = true;
524 }
525 JNI_EXIT();
526
527 if (printWarn)
528 abortMaybe();
529 else
530 checkObject(env, jclazz, func);
531 }
532
533 /*
534 * Verify that "str" is non-NULL and points to a String object.
535 *
536 * Since we're dealing with objects, switch to "running" mode.
537 */
checkString(JNIEnv * env,jstring jstr,const char * func)538 static void checkString(JNIEnv* env, jstring jstr, const char* func)
539 {
540 JNI_ENTER();
541 bool printWarn = false;
542
543 Object* obj = dvmDecodeIndirectRef(env, jstr);
544
545 if (obj == NULL) {
546 LOGW("JNI WARNING: received null jstring (%s)\n", func);
547 printWarn = true;
548 } else if (obj->clazz != gDvm.classJavaLangString) {
549 /*
550 * TODO: we probably should test dvmIsValidObject first, because
551 * this will crash if "obj" is non-null but pointing to an invalid
552 * memory region. However, the "is valid" test is a little slow,
553 * we're doing it again over in checkObject().
554 */
555 if (dvmIsValidObject(obj))
556 LOGW("JNI WARNING: jstring %p points to non-string object (%s)\n",
557 jstr, func);
558 else
559 LOGW("JNI WARNING: jstring %p is bogus (%s)\n", jstr, func);
560 printWarn = true;
561 }
562 JNI_EXIT();
563
564 if (printWarn)
565 abortMaybe();
566 else
567 checkObject(env, jstr, func);
568 }
569
570 /*
571 * Verify that "bytes" points to valid "modified UTF-8" data.
572 */
checkUtfString(JNIEnv * env,const char * bytes,bool nullOk,const char * func)573 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
574 const char* func)
575 {
576 const char* origBytes = bytes;
577
578 if (bytes == NULL) {
579 if (!nullOk) {
580 LOGW("JNI WARNING: unexpectedly null UTF string\n");
581 goto fail;
582 }
583
584 return;
585 }
586
587 while (*bytes != '\0') {
588 u1 utf8 = *(bytes++);
589 // Switch on the high four bits.
590 switch (utf8 >> 4) {
591 case 0x00:
592 case 0x01:
593 case 0x02:
594 case 0x03:
595 case 0x04:
596 case 0x05:
597 case 0x06:
598 case 0x07: {
599 // Bit pattern 0xxx. No need for any extra bytes.
600 break;
601 }
602 case 0x08:
603 case 0x09:
604 case 0x0a:
605 case 0x0b:
606 case 0x0f: {
607 /*
608 * Bit pattern 10xx or 1111, which are illegal start bytes.
609 * Note: 1111 is valid for normal UTF-8, but not the
610 * modified UTF-8 used here.
611 */
612 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
613 goto fail;
614 }
615 case 0x0e: {
616 // Bit pattern 1110, so there are two additional bytes.
617 utf8 = *(bytes++);
618 if ((utf8 & 0xc0) != 0x80) {
619 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
620 goto fail;
621 }
622 // Fall through to take care of the final byte.
623 }
624 case 0x0c:
625 case 0x0d: {
626 // Bit pattern 110x, so there is one additional byte.
627 utf8 = *(bytes++);
628 if ((utf8 & 0xc0) != 0x80) {
629 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
630 goto fail;
631 }
632 break;
633 }
634 }
635 }
636
637 return;
638
639 fail:
640 LOGW(" string: '%s'\n", origBytes);
641 showLocation(dvmGetCurrentJNIMethod(), func);
642 abortMaybe();
643 }
644
645 /*
646 * In some circumstances the VM will screen class names, but it doesn't
647 * for class lookup. When things get bounced through a class loader, they
648 * can actually get normalized a couple of times; as a result, passing in
649 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
650 * work in some circumstances.
651 *
652 * This is incorrect and could cause strange behavior or compatibility
653 * problems, so we want to screen that out here.
654 *
655 * We expect "full-qualified" class names, like "java/lang/Thread" or
656 * "[Ljava/lang/Object;".
657 */
checkClassName(JNIEnv * env,const char * className,const char * func)658 static void checkClassName(JNIEnv* env, const char* className, const char* func)
659 {
660 const char* cp;
661
662 /* quick check for illegal chars */
663 cp = className;
664 while (*cp != '\0') {
665 if (*cp == '.')
666 goto fail;
667 cp++;
668 }
669
670 // TODO: need a more rigorous check here
671
672 return;
673
674 fail:
675 LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
676 abortMaybe();
677 }
678
679 /*
680 * Verify that "array" is non-NULL and points to an Array object.
681 *
682 * Since we're dealing with objects, switch to "running" mode.
683 */
checkArray(JNIEnv * env,jarray jarr,const char * func)684 static void checkArray(JNIEnv* env, jarray jarr, const char* func)
685 {
686 JNI_ENTER();
687 bool printWarn = false;
688
689 Object* obj = dvmDecodeIndirectRef(env, jarr);
690
691 if (obj == NULL) {
692 LOGW("JNI WARNING: received null array (%s)\n", func);
693 printWarn = true;
694 } else if (obj->clazz->descriptor[0] != '[') {
695 if (dvmIsValidObject(obj))
696 LOGW("JNI WARNING: jarray %p points to non-array object (%s)\n",
697 jarr, obj->clazz->descriptor);
698 else
699 LOGW("JNI WARNING: jarray %p is bogus\n", jarr);
700 printWarn = true;
701 }
702
703 JNI_EXIT();
704
705 if (printWarn)
706 abortMaybe();
707 else
708 checkObject(env, jarr, func);
709 }
710
711 /*
712 * Verify that the "mode" argument passed to a primitive array Release
713 * function is one of the valid values.
714 */
checkReleaseMode(JNIEnv * env,jint mode,const char * func)715 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
716 {
717 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
718 LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
719 abortMaybe();
720 }
721 }
722
723 /*
724 * Verify that the length argument to array-creation calls is >= 0.
725 */
checkLengthPositive(JNIEnv * env,jsize length,const char * func)726 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
727 {
728 if (length < 0) {
729 LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
730 abortMaybe();
731 }
732 }
733
734 /*
735 * Verify that the pointer value is non-NULL.
736 */
checkNonNull(JNIEnv * env,const void * ptr,const char * func)737 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
738 {
739 if (ptr == NULL) {
740 LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
741 abortMaybe();
742 }
743 }
744
745 /*
746 * Verify that the method's return type matches the type of call.
747 *
748 * "expectedSigByte" will be 'L' for all objects, including arrays.
749 */
checkSig(JNIEnv * env,jmethodID methodID,char expectedSigByte,bool isStatic,const char * func)750 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
751 bool isStatic, const char* func)
752 {
753 const Method* meth = (const Method*) methodID;
754 bool printWarn = false;
755
756 if (expectedSigByte != meth->shorty[0]) {
757 LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
758 printWarn = true;
759 } else if (isStatic && !dvmIsStaticMethod(meth)) {
760 if (isStatic)
761 LOGW("JNI WARNING: calling non-static method with static call\n");
762 else
763 LOGW("JNI WARNING: calling static method with non-static call\n");
764 printWarn = true;
765 }
766
767 if (printWarn) {
768 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
769 LOGW(" calling %s.%s %s\n",
770 meth->clazz->descriptor, meth->name, desc);
771 free(desc);
772 showLocation(dvmGetCurrentJNIMethod(), func);
773 abortMaybe();
774 }
775 }
776
777 /*
778 * Verify that this static field ID is valid for this class.
779 */
checkStaticFieldID(JNIEnv * env,jclass jclazz,jfieldID fieldID)780 static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
781 {
782 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
783 StaticField* base = clazz->sfields;
784 int fieldCount = clazz->sfieldCount;
785
786 if ((StaticField*) fieldID < base ||
787 (StaticField*) fieldID >= base + fieldCount)
788 {
789 LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
790 fieldID, clazz->descriptor);
791 LOGW(" base=%p count=%d\n", base, fieldCount);
792 abortMaybe();
793 }
794 }
795
796 /*
797 * Verify that this instance field ID is valid for this object.
798 */
checkInstanceFieldID(JNIEnv * env,jobject jobj,jfieldID fieldID,const char * func)799 static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
800 const char* func)
801 {
802 JNI_ENTER();
803
804 if (jobj == NULL) {
805 LOGW("JNI WARNING: invalid null object (%s)\n", func);
806 abortMaybe();
807 goto bail;
808 }
809
810 Object* obj = dvmDecodeIndirectRef(env, jobj);
811 ClassObject* clazz = obj->clazz;
812
813 /*
814 * Check this class and all of its superclasses for a matching field.
815 * Don't need to scan interfaces.
816 */
817 while (clazz != NULL) {
818 if ((InstField*) fieldID >= clazz->ifields &&
819 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
820 {
821 goto bail;
822 }
823
824 clazz = clazz->super;
825 }
826
827 LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
828 fieldID, obj->clazz->descriptor);
829 abortMaybe();
830
831 bail:
832 JNI_EXIT();
833 }
834
835
836 /*
837 * ===========================================================================
838 * Guarded arrays
839 * ===========================================================================
840 */
841
842 #define kGuardLen 512 /* must be multiple of 2 */
843 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
844 #define kGuardMagic 0xffd5aa96
845 #define kGuardExtra sizeof(GuardExtra)
846
847 /* this gets tucked in at the start of the buffer; struct size must be even */
848 typedef struct GuardExtra {
849 u4 magic;
850 uLong adler;
851 size_t originalLen;
852 const void* originalPtr;
853 } GuardExtra;
854
855 /* find the GuardExtra given the pointer into the "live" data */
getGuardExtra(const void * dataBuf)856 inline static GuardExtra* getGuardExtra(const void* dataBuf)
857 {
858 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
859 return (GuardExtra*) fullBuf;
860 }
861
862 /*
863 * Create an oversized buffer to hold the contents of "buf". Copy it in,
864 * filling in the area around it with guard data.
865 *
866 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
867 */
createGuardedCopy(const void * buf,size_t len,bool modOkay)868 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
869 {
870 GuardExtra* pExtra;
871 size_t newLen = (len + kGuardLen +1) & ~0x01;
872 u1* newBuf;
873 u2* pat;
874 int i;
875
876 newBuf = (u1*)malloc(newLen);
877 if (newBuf == NULL) {
878 LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
879 dvmAbort();
880 }
881
882 /* fill it in with a pattern */
883 pat = (u2*) newBuf;
884 for (i = 0; i < (int)newLen / 2; i++)
885 *pat++ = kGuardPattern;
886
887 /* copy the data in; note "len" could be zero */
888 memcpy(newBuf + kGuardLen / 2, buf, len);
889
890 /* if modification is not expected, grab a checksum */
891 uLong adler = 0;
892 if (!modOkay) {
893 adler = adler32(0L, Z_NULL, 0);
894 adler = adler32(adler, buf, len);
895 *(uLong*)newBuf = adler;
896 }
897
898 pExtra = (GuardExtra*) newBuf;
899 pExtra->magic = kGuardMagic;
900 pExtra->adler = adler;
901 pExtra->originalPtr = buf;
902 pExtra->originalLen = len;
903
904 return newBuf + kGuardLen / 2;
905 }
906
907 /*
908 * Verify the guard area and, if "modOkay" is false, that the data itself
909 * has not been altered.
910 *
911 * The caller has already checked that "dataBuf" is non-NULL.
912 */
checkGuardedCopy(const void * dataBuf,bool modOkay)913 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
914 {
915 static const u4 kMagicCmp = kGuardMagic;
916 const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
917 const GuardExtra* pExtra = getGuardExtra(dataBuf);
918 size_t len;
919 const u2* pat;
920 int i;
921
922 /*
923 * Before we do anything with "pExtra", check the magic number. We
924 * do the check with memcmp rather than "==" in case the pointer is
925 * unaligned. If it points to completely bogus memory we're going
926 * to crash, but there's no easy way around that.
927 */
928 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
929 u1 buf[4];
930 memcpy(buf, &pExtra->magic, 4);
931 LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
932 "-- incorrect data pointer %p?\n",
933 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
934 return false;
935 }
936
937 len = pExtra->originalLen;
938
939 /* check bottom half of guard; skip over optional checksum storage */
940 pat = (u2*) fullBuf;
941 for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
942 {
943 if (pat[i] != kGuardPattern) {
944 LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
945 fullBuf, i*2);
946 return false;
947 }
948 }
949
950 int offset = kGuardLen / 2 + len;
951 if (offset & 0x01) {
952 /* odd byte; expected value depends on endian-ness of host */
953 const u2 patSample = kGuardPattern;
954 if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
955 LOGE("JNI: guard pattern disturbed in odd byte after %p "
956 "(+%d) 0x%02x 0x%02x\n",
957 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
958 return false;
959 }
960 offset++;
961 }
962
963 /* check top half of guard */
964 pat = (u2*) (fullBuf + offset);
965 for (i = 0; i < kGuardLen / 4; i++) {
966 if (pat[i] != kGuardPattern) {
967 LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
968 fullBuf, offset + i*2);
969 return false;
970 }
971 }
972
973 /*
974 * If modification is not expected, verify checksum. Strictly speaking
975 * this is wrong: if we told the client that we made a copy, there's no
976 * reason they can't alter the buffer.
977 */
978 if (!modOkay) {
979 uLong adler = adler32(0L, Z_NULL, 0);
980 adler = adler32(adler, dataBuf, len);
981 if (pExtra->adler != adler) {
982 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
983 pExtra->adler, adler, dataBuf);
984 return false;
985 }
986 }
987
988 return true;
989 }
990
991 /*
992 * Free up the guard buffer, scrub it, and return the original pointer.
993 */
freeGuardedCopy(void * dataBuf)994 static void* freeGuardedCopy(void* dataBuf)
995 {
996 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
997 const GuardExtra* pExtra = getGuardExtra(dataBuf);
998 void* originalPtr = (void*) pExtra->originalPtr;
999 size_t len = pExtra->originalLen;
1000
1001 memset(dataBuf, 0xdd, len);
1002 free(fullBuf);
1003 return originalPtr;
1004 }
1005
1006 /*
1007 * Just pull out the original pointer.
1008 */
getGuardedCopyOriginalPtr(const void * dataBuf)1009 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
1010 {
1011 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1012 return (void*) pExtra->originalPtr;
1013 }
1014
1015 /*
1016 * Grab the data length.
1017 */
getGuardedCopyOriginalLen(const void * dataBuf)1018 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
1019 {
1020 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1021 return pExtra->originalLen;
1022 }
1023
1024 /*
1025 * Return the width, in bytes, of a primitive type.
1026 */
dvmPrimitiveTypeWidth(PrimitiveType primType)1027 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
1028 {
1029 static const int lengths[PRIM_MAX] = {
1030 1, // boolean
1031 2, // char
1032 4, // float
1033 8, // double
1034 1, // byte
1035 2, // short
1036 4, // int
1037 8, // long
1038 -1, // void
1039 };
1040 assert(primType >= 0 && primType < PRIM_MAX);
1041 return lengths[primType];
1042 }
1043
1044 /*
1045 * Create a guarded copy of a primitive array. Modifications to the copied
1046 * data are allowed. Returns a pointer to the copied data.
1047 */
createGuardedPACopy(JNIEnv * env,const jarray jarr,jboolean * isCopy)1048 static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
1049 jboolean* isCopy)
1050 {
1051 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1052 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1053 int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1054 void* result;
1055
1056 result = createGuardedCopy(arrObj->contents, len, true);
1057
1058 if (isCopy != NULL)
1059 *isCopy = JNI_TRUE;
1060
1061 return result;
1062 }
1063
1064 /*
1065 * Perform the array "release" operation, which may or may not copy data
1066 * back into the VM, and may or may not release the underlying storage.
1067 */
releaseGuardedPACopy(JNIEnv * env,jarray jarr,void * dataBuf,int mode)1068 static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
1069 int mode)
1070 {
1071 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1072 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1073 //int len = array->length * dvmPrimitiveTypeWidth(primType);
1074 bool release, copyBack;
1075 u1* result;
1076
1077 if (!checkGuardedCopy(dataBuf, true)) {
1078 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
1079 abortMaybe();
1080 return NULL;
1081 }
1082
1083 switch (mode) {
1084 case 0:
1085 release = copyBack = true;
1086 break;
1087 case JNI_ABORT:
1088 release = true;
1089 copyBack = false;
1090 break;
1091 case JNI_COMMIT:
1092 release = false;
1093 copyBack = true;
1094 break;
1095 default:
1096 LOGE("JNI: bad release mode %d\n", mode);
1097 dvmAbort();
1098 return NULL;
1099 }
1100
1101 if (copyBack) {
1102 size_t len = getGuardedCopyOriginalLen(dataBuf);
1103 memcpy(arrObj->contents, dataBuf, len);
1104 }
1105
1106 if (release) {
1107 result = (u1*) freeGuardedCopy(dataBuf);
1108 } else {
1109 result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
1110 }
1111
1112 /* pointer is to the array contents; back up to the array object */
1113 result -= offsetof(ArrayObject, contents);
1114
1115 return result;
1116 }
1117
1118
1119 /*
1120 * ===========================================================================
1121 * JNI functions
1122 * ===========================================================================
1123 */
1124
Check_GetVersion(JNIEnv * env)1125 static jint Check_GetVersion(JNIEnv* env)
1126 {
1127 CHECK_ENTER(env, kFlag_Default);
1128 jint result;
1129 result = BASE_ENV(env)->GetVersion(env);
1130 CHECK_EXIT(env);
1131 return result;
1132 }
1133
Check_DefineClass(JNIEnv * env,const char * name,jobject loader,const jbyte * buf,jsize bufLen)1134 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1135 const jbyte* buf, jsize bufLen)
1136 {
1137 CHECK_ENTER(env, kFlag_Default);
1138 CHECK_OBJECT(env, loader);
1139 CHECK_UTF_STRING(env, name, false);
1140 CHECK_CLASS_NAME(env, name);
1141 jclass result;
1142 result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
1143 CHECK_EXIT(env);
1144 return result;
1145 }
1146
Check_FindClass(JNIEnv * env,const char * name)1147 static jclass Check_FindClass(JNIEnv* env, const char* name)
1148 {
1149 CHECK_ENTER(env, kFlag_Default);
1150 CHECK_UTF_STRING(env, name, false);
1151 CHECK_CLASS_NAME(env, name);
1152 jclass result;
1153 result = BASE_ENV(env)->FindClass(env, name);
1154 CHECK_EXIT(env);
1155 return result;
1156 }
1157
Check_GetSuperclass(JNIEnv * env,jclass clazz)1158 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
1159 {
1160 CHECK_ENTER(env, kFlag_Default);
1161 CHECK_CLASS(env, clazz);
1162 jclass result;
1163 result = BASE_ENV(env)->GetSuperclass(env, clazz);
1164 CHECK_EXIT(env);
1165 return result;
1166 }
1167
Check_IsAssignableFrom(JNIEnv * env,jclass clazz1,jclass clazz2)1168 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1169 jclass clazz2)
1170 {
1171 CHECK_ENTER(env, kFlag_Default);
1172 CHECK_CLASS(env, clazz1);
1173 CHECK_CLASS(env, clazz2);
1174 jboolean result;
1175 result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1176 CHECK_EXIT(env);
1177 return result;
1178 }
1179
Check_FromReflectedMethod(JNIEnv * env,jobject method)1180 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1181 {
1182 CHECK_ENTER(env, kFlag_Default);
1183 CHECK_OBJECT(env, method);
1184 jmethodID result;
1185 result = BASE_ENV(env)->FromReflectedMethod(env, method);
1186 CHECK_EXIT(env);
1187 return result;
1188 }
1189
Check_FromReflectedField(JNIEnv * env,jobject field)1190 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1191 {
1192 CHECK_ENTER(env, kFlag_Default);
1193 CHECK_OBJECT(env, field);
1194 jfieldID result;
1195 result = BASE_ENV(env)->FromReflectedField(env, field);
1196 CHECK_EXIT(env);
1197 return result;
1198 }
1199
Check_ToReflectedMethod(JNIEnv * env,jclass cls,jmethodID methodID,jboolean isStatic)1200 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1201 jmethodID methodID, jboolean isStatic)
1202 {
1203 CHECK_ENTER(env, kFlag_Default);
1204 CHECK_CLASS(env, cls);
1205 jobject result;
1206 result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1207 CHECK_EXIT(env);
1208 return result;
1209 }
1210
Check_ToReflectedField(JNIEnv * env,jclass cls,jfieldID fieldID,jboolean isStatic)1211 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1212 jboolean isStatic)
1213 {
1214 CHECK_ENTER(env, kFlag_Default);
1215 CHECK_CLASS(env, cls);
1216 jobject result;
1217 result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1218 CHECK_EXIT(env);
1219 return result;
1220 }
1221
Check_Throw(JNIEnv * env,jthrowable obj)1222 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1223 {
1224 CHECK_ENTER(env, kFlag_Default);
1225 CHECK_OBJECT(env, obj);
1226 jint result;
1227 result = BASE_ENV(env)->Throw(env, obj);
1228 CHECK_EXIT(env);
1229 return result;
1230 }
1231
Check_ThrowNew(JNIEnv * env,jclass clazz,const char * message)1232 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1233 {
1234 CHECK_ENTER(env, kFlag_Default);
1235 CHECK_CLASS(env, clazz);
1236 CHECK_UTF_STRING(env, message, true);
1237 jint result;
1238 result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1239 CHECK_EXIT(env);
1240 return result;
1241 }
1242
Check_ExceptionOccurred(JNIEnv * env)1243 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1244 {
1245 CHECK_ENTER(env, kFlag_ExcepOkay);
1246 jthrowable result;
1247 result = BASE_ENV(env)->ExceptionOccurred(env);
1248 CHECK_EXIT(env);
1249 return result;
1250 }
1251
Check_ExceptionDescribe(JNIEnv * env)1252 static void Check_ExceptionDescribe(JNIEnv* env)
1253 {
1254 CHECK_ENTER(env, kFlag_ExcepOkay);
1255 BASE_ENV(env)->ExceptionDescribe(env);
1256 CHECK_EXIT(env);
1257 }
1258
Check_ExceptionClear(JNIEnv * env)1259 static void Check_ExceptionClear(JNIEnv* env)
1260 {
1261 CHECK_ENTER(env, kFlag_ExcepOkay);
1262 BASE_ENV(env)->ExceptionClear(env);
1263 CHECK_EXIT(env);
1264 }
1265
Check_FatalError(JNIEnv * env,const char * msg)1266 static void Check_FatalError(JNIEnv* env, const char* msg)
1267 {
1268 CHECK_ENTER(env, kFlag_Default);
1269 CHECK_UTF_STRING(env, msg, true);
1270 BASE_ENV(env)->FatalError(env, msg);
1271 CHECK_EXIT(env);
1272 }
1273
Check_PushLocalFrame(JNIEnv * env,jint capacity)1274 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1275 {
1276 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1277 jint result;
1278 result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1279 CHECK_EXIT(env);
1280 return result;
1281 }
1282
Check_PopLocalFrame(JNIEnv * env,jobject res)1283 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1284 {
1285 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1286 CHECK_OBJECT(env, res);
1287 jobject result;
1288 result = BASE_ENV(env)->PopLocalFrame(env, res);
1289 CHECK_EXIT(env);
1290 return result;
1291 }
1292
Check_NewGlobalRef(JNIEnv * env,jobject obj)1293 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1294 {
1295 CHECK_ENTER(env, kFlag_Default);
1296 CHECK_OBJECT(env, obj);
1297 jobject result;
1298 result = BASE_ENV(env)->NewGlobalRef(env, obj);
1299 CHECK_EXIT(env);
1300 return result;
1301 }
1302
Check_DeleteGlobalRef(JNIEnv * env,jobject globalRef)1303 static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
1304 {
1305 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1306 CHECK_OBJECT(env, globalRef);
1307 #ifdef USE_INDIRECT_REF
1308 if (globalRef != NULL &&
1309 dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
1310 {
1311 LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)\n",
1312 globalRef, dvmGetJNIRefType(env, globalRef));
1313 abortMaybe();
1314 } else
1315 #endif
1316 {
1317 BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
1318 }
1319 CHECK_EXIT(env);
1320 }
1321
Check_NewLocalRef(JNIEnv * env,jobject ref)1322 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1323 {
1324 CHECK_ENTER(env, kFlag_Default);
1325 CHECK_OBJECT(env, ref);
1326 jobject result;
1327 result = BASE_ENV(env)->NewLocalRef(env, ref);
1328 CHECK_EXIT(env);
1329 return result;
1330 }
1331
Check_DeleteLocalRef(JNIEnv * env,jobject localRef)1332 static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
1333 {
1334 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1335 CHECK_OBJECT(env, localRef);
1336 #ifdef USE_INDIRECT_REF
1337 if (localRef != NULL &&
1338 dvmGetJNIRefType(env, localRef) != JNILocalRefType)
1339 {
1340 LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)\n",
1341 localRef, dvmGetJNIRefType(env, localRef));
1342 abortMaybe();
1343 } else
1344 #endif
1345 {
1346 BASE_ENV(env)->DeleteLocalRef(env, localRef);
1347 }
1348 CHECK_EXIT(env);
1349 }
1350
Check_EnsureLocalCapacity(JNIEnv * env,jint capacity)1351 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1352 {
1353 CHECK_ENTER(env, kFlag_Default);
1354 jint result;
1355 result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1356 CHECK_EXIT(env);
1357 return result;
1358 }
1359
Check_IsSameObject(JNIEnv * env,jobject ref1,jobject ref2)1360 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1361 {
1362 CHECK_ENTER(env, kFlag_Default);
1363 CHECK_OBJECT(env, ref1);
1364 CHECK_OBJECT(env, ref2);
1365 jboolean result;
1366 result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1367 CHECK_EXIT(env);
1368 return result;
1369 }
1370
Check_AllocObject(JNIEnv * env,jclass clazz)1371 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1372 {
1373 CHECK_ENTER(env, kFlag_Default);
1374 CHECK_CLASS(env, clazz);
1375 jobject result;
1376 result = BASE_ENV(env)->AllocObject(env, clazz);
1377 CHECK_EXIT(env);
1378 return result;
1379 }
1380
Check_NewObject(JNIEnv * env,jclass clazz,jmethodID methodID,...)1381 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1382 ...)
1383 {
1384 CHECK_ENTER(env, kFlag_Default);
1385 CHECK_CLASS(env, clazz);
1386 jobject result;
1387 va_list args;
1388
1389 va_start(args, methodID);
1390 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1391 va_end(args);
1392
1393 CHECK_EXIT(env);
1394 return result;
1395 }
Check_NewObjectV(JNIEnv * env,jclass clazz,jmethodID methodID,va_list args)1396 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1397 va_list args)
1398 {
1399 CHECK_ENTER(env, kFlag_Default);
1400 CHECK_CLASS(env, clazz);
1401 jobject result;
1402 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1403 CHECK_EXIT(env);
1404 return result;
1405 }
Check_NewObjectA(JNIEnv * env,jclass clazz,jmethodID methodID,jvalue * args)1406 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1407 jvalue* args)
1408 {
1409 CHECK_ENTER(env, kFlag_Default);
1410 CHECK_CLASS(env, clazz);
1411 jobject result;
1412 result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1413 CHECK_EXIT(env);
1414 return result;
1415 }
1416
Check_GetObjectClass(JNIEnv * env,jobject obj)1417 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1418 {
1419 CHECK_ENTER(env, kFlag_Default);
1420 CHECK_OBJECT(env, obj);
1421 jclass result;
1422 result = BASE_ENV(env)->GetObjectClass(env, obj);
1423 CHECK_EXIT(env);
1424 return result;
1425 }
1426
Check_IsInstanceOf(JNIEnv * env,jobject obj,jclass clazz)1427 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1428 {
1429 CHECK_ENTER(env, kFlag_Default);
1430 CHECK_OBJECT(env, obj);
1431 CHECK_CLASS(env, clazz);
1432 jboolean result;
1433 result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1434 CHECK_EXIT(env);
1435 return result;
1436 }
1437
Check_GetMethodID(JNIEnv * env,jclass clazz,const char * name,const char * sig)1438 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1439 const char* sig)
1440 {
1441 CHECK_ENTER(env, kFlag_Default);
1442 CHECK_CLASS(env, clazz);
1443 CHECK_UTF_STRING(env, name, false);
1444 CHECK_UTF_STRING(env, sig, false);
1445 jmethodID result;
1446 result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1447 CHECK_EXIT(env);
1448 return result;
1449 }
1450
Check_GetFieldID(JNIEnv * env,jclass clazz,const char * name,const char * sig)1451 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1452 const char* name, const char* sig)
1453 {
1454 CHECK_ENTER(env, kFlag_Default);
1455 CHECK_CLASS(env, clazz);
1456 CHECK_UTF_STRING(env, name, false);
1457 CHECK_UTF_STRING(env, sig, false);
1458 jfieldID result;
1459 result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1460 CHECK_EXIT(env);
1461 return result;
1462 }
1463
Check_GetStaticMethodID(JNIEnv * env,jclass clazz,const char * name,const char * sig)1464 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1465 const char* name, const char* sig)
1466 {
1467 CHECK_ENTER(env, kFlag_Default);
1468 CHECK_CLASS(env, clazz);
1469 CHECK_UTF_STRING(env, name, false);
1470 CHECK_UTF_STRING(env, sig, false);
1471 jmethodID result;
1472 result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1473 CHECK_EXIT(env);
1474 return result;
1475 }
1476
Check_GetStaticFieldID(JNIEnv * env,jclass clazz,const char * name,const char * sig)1477 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1478 const char* name, const char* sig)
1479 {
1480 CHECK_ENTER(env, kFlag_Default);
1481 CHECK_CLASS(env, clazz);
1482 CHECK_UTF_STRING(env, name, false);
1483 CHECK_UTF_STRING(env, sig, false);
1484 jfieldID result;
1485 result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1486 CHECK_EXIT(env);
1487 return result;
1488 }
1489
1490 #define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
1491 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1492 jfieldID fieldID) \
1493 { \
1494 CHECK_ENTER(env, kFlag_Default); \
1495 CHECK_CLASS(env, clazz); \
1496 _ctype result; \
1497 checkStaticFieldID(env, clazz, fieldID); \
1498 result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
1499 fieldID); \
1500 CHECK_EXIT(env); \
1501 return result; \
1502 }
1503 GET_STATIC_TYPE_FIELD(jobject, Object);
1504 GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1505 GET_STATIC_TYPE_FIELD(jbyte, Byte);
1506 GET_STATIC_TYPE_FIELD(jchar, Char);
1507 GET_STATIC_TYPE_FIELD(jshort, Short);
1508 GET_STATIC_TYPE_FIELD(jint, Int);
1509 GET_STATIC_TYPE_FIELD(jlong, Long);
1510 GET_STATIC_TYPE_FIELD(jfloat, Float);
1511 GET_STATIC_TYPE_FIELD(jdouble, Double);
1512
1513 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1514 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1515 jfieldID fieldID, _ctype value) \
1516 { \
1517 CHECK_ENTER(env, kFlag_Default); \
1518 CHECK_CLASS(env, clazz); \
1519 checkStaticFieldID(env, clazz, fieldID); \
1520 /* "value" arg only used when type == ref */ \
1521 CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true); \
1522 BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
1523 value); \
1524 CHECK_EXIT(env); \
1525 }
1526 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1527 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1528 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1529 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1530 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1531 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1532 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1533 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1534 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1535
1536 #define GET_TYPE_FIELD(_ctype, _jname) \
1537 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
1538 jfieldID fieldID) \
1539 { \
1540 CHECK_ENTER(env, kFlag_Default); \
1541 CHECK_OBJECT(env, obj); \
1542 _ctype result; \
1543 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1544 result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
1545 CHECK_EXIT(env); \
1546 return result; \
1547 }
1548 GET_TYPE_FIELD(jobject, Object);
1549 GET_TYPE_FIELD(jboolean, Boolean);
1550 GET_TYPE_FIELD(jbyte, Byte);
1551 GET_TYPE_FIELD(jchar, Char);
1552 GET_TYPE_FIELD(jshort, Short);
1553 GET_TYPE_FIELD(jint, Int);
1554 GET_TYPE_FIELD(jlong, Long);
1555 GET_TYPE_FIELD(jfloat, Float);
1556 GET_TYPE_FIELD(jdouble, Double);
1557
1558 #define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1559 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
1560 jfieldID fieldID, _ctype value) \
1561 { \
1562 CHECK_ENTER(env, kFlag_Default); \
1563 CHECK_OBJECT(env, obj); \
1564 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1565 /* "value" arg only used when type == ref */ \
1566 CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
1567 BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
1568 CHECK_EXIT(env); \
1569 }
1570 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1571 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1572 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1573 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1574 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1575 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1576 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1577 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1578 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1579
1580 #define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1581 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
1582 jmethodID methodID, ...) \
1583 { \
1584 CHECK_ENTER(env, kFlag_Default); \
1585 CHECK_OBJECT(env, obj); \
1586 CHECK_SIG(env, methodID, _retsig, false); \
1587 _retdecl; \
1588 va_list args; \
1589 va_start(args, methodID); \
1590 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1591 args); \
1592 va_end(args); \
1593 CHECK_EXIT(env); \
1594 return _retok; \
1595 } \
1596 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1597 jmethodID methodID, va_list args) \
1598 { \
1599 CHECK_ENTER(env, kFlag_Default); \
1600 CHECK_OBJECT(env, obj); \
1601 CHECK_SIG(env, methodID, _retsig, false); \
1602 _retdecl; \
1603 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1604 args); \
1605 CHECK_EXIT(env); \
1606 return _retok; \
1607 } \
1608 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1609 jmethodID methodID, jvalue* args) \
1610 { \
1611 CHECK_ENTER(env, kFlag_Default); \
1612 CHECK_OBJECT(env, obj); \
1613 CHECK_SIG(env, methodID, _retsig, false); \
1614 _retdecl; \
1615 _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
1616 args); \
1617 CHECK_EXIT(env); \
1618 return _retok; \
1619 }
1620 CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1621 CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1622 CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1623 CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1624 CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1625 CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
1626 CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1627 CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1628 CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1629 CALL_VIRTUAL(void, Void, , , , 'V');
1630
1631 #define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \
1632 _retsig) \
1633 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
1634 jobject obj, jclass clazz, jmethodID methodID, ...) \
1635 { \
1636 CHECK_ENTER(env, kFlag_Default); \
1637 CHECK_CLASS(env, clazz); \
1638 CHECK_OBJECT(env, obj); \
1639 CHECK_SIG(env, methodID, _retsig, false); \
1640 _retdecl; \
1641 va_list args; \
1642 va_start(args, methodID); \
1643 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1644 clazz, methodID, args); \
1645 va_end(args); \
1646 CHECK_EXIT(env); \
1647 return _retok; \
1648 } \
1649 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1650 jobject obj, jclass clazz, jmethodID methodID, va_list args) \
1651 { \
1652 CHECK_ENTER(env, kFlag_Default); \
1653 CHECK_CLASS(env, clazz); \
1654 CHECK_OBJECT(env, obj); \
1655 CHECK_SIG(env, methodID, _retsig, false); \
1656 _retdecl; \
1657 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1658 clazz, methodID, args); \
1659 CHECK_EXIT(env); \
1660 return _retok; \
1661 } \
1662 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1663 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
1664 { \
1665 CHECK_ENTER(env, kFlag_Default); \
1666 CHECK_CLASS(env, clazz); \
1667 CHECK_OBJECT(env, obj); \
1668 CHECK_SIG(env, methodID, _retsig, false); \
1669 _retdecl; \
1670 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
1671 clazz, methodID, args); \
1672 CHECK_EXIT(env); \
1673 return _retok; \
1674 }
1675 CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1676 CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1677 CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1678 CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1679 CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1680 CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
1681 CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1682 CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1683 CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1684 CALL_NONVIRTUAL(void, Void, , , , 'V');
1685
1686
1687 #define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1688 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
1689 jclass clazz, jmethodID methodID, ...) \
1690 { \
1691 CHECK_ENTER(env, kFlag_Default); \
1692 CHECK_CLASS(env, clazz); \
1693 CHECK_SIG(env, methodID, _retsig, true); \
1694 _retdecl; \
1695 va_list args; \
1696 va_start(args, methodID); \
1697 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1698 methodID, args); \
1699 va_end(args); \
1700 CHECK_EXIT(env); \
1701 return _retok; \
1702 } \
1703 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
1704 jclass clazz, jmethodID methodID, va_list args) \
1705 { \
1706 CHECK_ENTER(env, kFlag_Default); \
1707 CHECK_CLASS(env, clazz); \
1708 CHECK_SIG(env, methodID, _retsig, true); \
1709 _retdecl; \
1710 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1711 methodID, args); \
1712 CHECK_EXIT(env); \
1713 return _retok; \
1714 } \
1715 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
1716 jclass clazz, jmethodID methodID, jvalue* args) \
1717 { \
1718 CHECK_ENTER(env, kFlag_Default); \
1719 CHECK_CLASS(env, clazz); \
1720 CHECK_SIG(env, methodID, _retsig, true); \
1721 _retdecl; \
1722 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
1723 methodID, args); \
1724 CHECK_EXIT(env); \
1725 return _retok; \
1726 }
1727 CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
1728 CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
1729 CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
1730 CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
1731 CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
1732 CALL_STATIC(jint, Int, jint result, result=, result, 'I');
1733 CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
1734 CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
1735 CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
1736 CALL_STATIC(void, Void, , , , 'V');
1737
Check_NewString(JNIEnv * env,const jchar * unicodeChars,jsize len)1738 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1739 jsize len)
1740 {
1741 CHECK_ENTER(env, kFlag_Default);
1742 jstring result;
1743 result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1744 CHECK_EXIT(env);
1745 return result;
1746 }
1747
Check_GetStringLength(JNIEnv * env,jstring string)1748 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1749 {
1750 CHECK_ENTER(env, kFlag_CritOkay);
1751 CHECK_STRING(env, string);
1752 jsize result;
1753 result = BASE_ENV(env)->GetStringLength(env, string);
1754 CHECK_EXIT(env);
1755 return result;
1756 }
1757
Check_GetStringChars(JNIEnv * env,jstring string,jboolean * isCopy)1758 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1759 jboolean* isCopy)
1760 {
1761 CHECK_ENTER(env, kFlag_CritOkay);
1762 CHECK_STRING(env, string);
1763 const jchar* result;
1764 result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1765 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1766 // TODO: fix for indirect
1767 int len = dvmStringLen(string) * 2;
1768 result = (const jchar*) createGuardedCopy(result, len, false);
1769 if (isCopy != NULL)
1770 *isCopy = JNI_TRUE;
1771 }
1772 CHECK_EXIT(env);
1773 return result;
1774 }
1775
Check_ReleaseStringChars(JNIEnv * env,jstring string,const jchar * chars)1776 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1777 const jchar* chars)
1778 {
1779 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1780 CHECK_STRING(env, string);
1781 CHECK_NON_NULL(env, chars);
1782 if (((JNIEnvExt*)env)->forceDataCopy) {
1783 if (!checkGuardedCopy(chars, false)) {
1784 LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1785 abortMaybe();
1786 return;
1787 }
1788 chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1789 }
1790 BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1791 CHECK_EXIT(env);
1792 }
1793
Check_NewStringUTF(JNIEnv * env,const char * bytes)1794 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1795 {
1796 CHECK_ENTER(env, kFlag_Default);
1797 CHECK_UTF_STRING(env, bytes, true);
1798 jstring result;
1799 result = BASE_ENV(env)->NewStringUTF(env, bytes);
1800 CHECK_EXIT(env);
1801 return result;
1802 }
1803
Check_GetStringUTFLength(JNIEnv * env,jstring string)1804 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1805 {
1806 CHECK_ENTER(env, kFlag_CritOkay);
1807 CHECK_STRING(env, string);
1808 jsize result;
1809 result = BASE_ENV(env)->GetStringUTFLength(env, string);
1810 CHECK_EXIT(env);
1811 return result;
1812 }
1813
Check_GetStringUTFChars(JNIEnv * env,jstring string,jboolean * isCopy)1814 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1815 jboolean* isCopy)
1816 {
1817 CHECK_ENTER(env, kFlag_CritOkay);
1818 CHECK_STRING(env, string);
1819 const char* result;
1820 result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1821 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1822 // TODO: fix for indirect
1823 int len = dvmStringUtf8ByteLen(string) + 1;
1824 result = (const char*) createGuardedCopy(result, len, false);
1825 if (isCopy != NULL)
1826 *isCopy = JNI_TRUE;
1827 }
1828 CHECK_EXIT(env);
1829 return result;
1830 }
1831
Check_ReleaseStringUTFChars(JNIEnv * env,jstring string,const char * utf)1832 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1833 const char* utf)
1834 {
1835 CHECK_ENTER(env, kFlag_ExcepOkay);
1836 CHECK_STRING(env, string);
1837 CHECK_NON_NULL(env, utf);
1838 if (((JNIEnvExt*)env)->forceDataCopy) {
1839 //int len = dvmStringUtf8ByteLen(string) + 1;
1840 if (!checkGuardedCopy(utf, false)) {
1841 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1842 abortMaybe();
1843 return;
1844 }
1845 utf = (const char*) freeGuardedCopy((char*)utf);
1846 }
1847 BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1848 CHECK_EXIT(env);
1849 }
1850
Check_GetArrayLength(JNIEnv * env,jarray array)1851 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1852 {
1853 CHECK_ENTER(env, kFlag_CritOkay);
1854 CHECK_ARRAY(env, array);
1855 jsize result;
1856 result = BASE_ENV(env)->GetArrayLength(env, array);
1857 CHECK_EXIT(env);
1858 return result;
1859 }
1860
Check_NewObjectArray(JNIEnv * env,jsize length,jclass elementClass,jobject initialElement)1861 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1862 jclass elementClass, jobject initialElement)
1863 {
1864 CHECK_ENTER(env, kFlag_Default);
1865 CHECK_CLASS(env, elementClass);
1866 CHECK_OBJECT(env, initialElement);
1867 CHECK_LENGTH_POSITIVE(env, length);
1868 jobjectArray result;
1869 result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
1870 initialElement);
1871 CHECK_EXIT(env);
1872 return result;
1873 }
1874
Check_GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)1875 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
1876 jsize index)
1877 {
1878 CHECK_ENTER(env, kFlag_Default);
1879 CHECK_ARRAY(env, array);
1880 jobject result;
1881 result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
1882 CHECK_EXIT(env);
1883 return result;
1884 }
1885
Check_SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject value)1886 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
1887 jsize index, jobject value)
1888 {
1889 CHECK_ENTER(env, kFlag_Default);
1890 CHECK_ARRAY(env, array);
1891 BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
1892 CHECK_EXIT(env);
1893 }
1894
1895 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1896 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
1897 { \
1898 CHECK_ENTER(env, kFlag_Default); \
1899 CHECK_LENGTH_POSITIVE(env, length); \
1900 _artype result; \
1901 result = BASE_ENV(env)->New##_jname##Array(env, length); \
1902 CHECK_EXIT(env); \
1903 return result; \
1904 }
1905 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1906 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1907 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1908 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1909 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1910 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1911 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1912 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1913
1914
1915 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1916 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
1917 _ctype##Array array, jboolean* isCopy) \
1918 { \
1919 CHECK_ENTER(env, kFlag_Default); \
1920 CHECK_ARRAY(env, array); \
1921 _ctype* result; \
1922 result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
1923 array, isCopy); \
1924 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
1925 result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
1926 } \
1927 CHECK_EXIT(env); \
1928 return result; \
1929 }
1930
1931 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1932 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
1933 _ctype##Array array, _ctype* elems, jint mode) \
1934 { \
1935 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
1936 CHECK_ARRAY(env, array); \
1937 CHECK_NON_NULL(env, elems); \
1938 CHECK_RELEASE_MODE(env, mode); \
1939 if (((JNIEnvExt*)env)->forceDataCopy) { \
1940 elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
1941 } \
1942 BASE_ENV(env)->Release##_jname##ArrayElements(env, \
1943 array, elems, mode); \
1944 CHECK_EXIT(env); \
1945 }
1946
1947 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1948 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
1949 _ctype##Array array, jsize start, jsize len, _ctype* buf) \
1950 { \
1951 CHECK_ENTER(env, kFlag_Default); \
1952 CHECK_ARRAY(env, array); \
1953 BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
1954 len, buf); \
1955 CHECK_EXIT(env); \
1956 }
1957
1958 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1959 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
1960 _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
1961 { \
1962 CHECK_ENTER(env, kFlag_Default); \
1963 CHECK_ARRAY(env, array); \
1964 BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
1965 len, buf); \
1966 CHECK_EXIT(env); \
1967 }
1968
1969 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1970 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1971 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1972 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1973 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1974
1975 /* TODO: verify primitive array type matches call type */
1976 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1977 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1978 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1979 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1980 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1981 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1982 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1983 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1984
Check_RegisterNatives(JNIEnv * env,jclass clazz,const JNINativeMethod * methods,jint nMethods)1985 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
1986 const JNINativeMethod* methods, jint nMethods)
1987 {
1988 CHECK_ENTER(env, kFlag_Default);
1989 CHECK_CLASS(env, clazz);
1990 jint result;
1991 result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
1992 CHECK_EXIT(env);
1993 return result;
1994 }
1995
Check_UnregisterNatives(JNIEnv * env,jclass clazz)1996 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
1997 {
1998 CHECK_ENTER(env, kFlag_Default);
1999 CHECK_CLASS(env, clazz);
2000 jint result;
2001 result = BASE_ENV(env)->UnregisterNatives(env, clazz);
2002 CHECK_EXIT(env);
2003 return result;
2004 }
2005
Check_MonitorEnter(JNIEnv * env,jobject obj)2006 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
2007 {
2008 CHECK_ENTER(env, kFlag_Default);
2009 CHECK_OBJECT(env, obj);
2010 jint result;
2011 result = BASE_ENV(env)->MonitorEnter(env, obj);
2012 CHECK_EXIT(env);
2013 return result;
2014 }
2015
Check_MonitorExit(JNIEnv * env,jobject obj)2016 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
2017 {
2018 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2019 CHECK_OBJECT(env, obj);
2020 jint result;
2021 result = BASE_ENV(env)->MonitorExit(env, obj);
2022 CHECK_EXIT(env);
2023 return result;
2024 }
2025
Check_GetJavaVM(JNIEnv * env,JavaVM ** vm)2026 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
2027 {
2028 CHECK_ENTER(env, kFlag_Default);
2029 jint result;
2030 result = BASE_ENV(env)->GetJavaVM(env, vm);
2031 CHECK_EXIT(env);
2032 return result;
2033 }
2034
Check_GetStringRegion(JNIEnv * env,jstring str,jsize start,jsize len,jchar * buf)2035 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
2036 jsize len, jchar* buf)
2037 {
2038 CHECK_ENTER(env, kFlag_CritOkay);
2039 CHECK_STRING(env, str);
2040 BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
2041 CHECK_EXIT(env);
2042 }
2043
Check_GetStringUTFRegion(JNIEnv * env,jstring str,jsize start,jsize len,char * buf)2044 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
2045 jsize len, char* buf)
2046 {
2047 CHECK_ENTER(env, kFlag_CritOkay);
2048 CHECK_STRING(env, str);
2049 BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
2050 CHECK_EXIT(env);
2051 }
2052
Check_GetPrimitiveArrayCritical(JNIEnv * env,jarray array,jboolean * isCopy)2053 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
2054 jboolean* isCopy)
2055 {
2056 CHECK_ENTER(env, kFlag_CritGet);
2057 CHECK_ARRAY(env, array);
2058 void* result;
2059 result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
2060 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2061 result = createGuardedPACopy(env, array, isCopy);
2062 }
2063 CHECK_EXIT(env);
2064 return result;
2065 }
2066
Check_ReleasePrimitiveArrayCritical(JNIEnv * env,jarray array,void * carray,jint mode)2067 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
2068 void* carray, jint mode)
2069 {
2070 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2071 CHECK_ARRAY(env, array);
2072 CHECK_NON_NULL(env, carray);
2073 CHECK_RELEASE_MODE(env, mode);
2074 if (((JNIEnvExt*)env)->forceDataCopy) {
2075 carray = releaseGuardedPACopy(env, array, carray, mode);
2076 }
2077 BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2078 CHECK_EXIT(env);
2079 }
2080
Check_GetStringCritical(JNIEnv * env,jstring string,jboolean * isCopy)2081 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
2082 jboolean* isCopy)
2083 {
2084 CHECK_ENTER(env, kFlag_CritGet);
2085 CHECK_STRING(env, string);
2086 const jchar* result;
2087 result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
2088 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2089 // TODO: fix for indirect
2090 int len = dvmStringLen(string) * 2;
2091 result = (const jchar*) createGuardedCopy(result, len, false);
2092 if (isCopy != NULL)
2093 *isCopy = JNI_TRUE;
2094 }
2095 CHECK_EXIT(env);
2096 return result;
2097 }
2098
Check_ReleaseStringCritical(JNIEnv * env,jstring string,const jchar * carray)2099 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
2100 const jchar* carray)
2101 {
2102 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2103 CHECK_STRING(env, string);
2104 CHECK_NON_NULL(env, carray);
2105 if (((JNIEnvExt*)env)->forceDataCopy) {
2106 if (!checkGuardedCopy(carray, false)) {
2107 LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
2108 abortMaybe();
2109 return;
2110 }
2111 carray = (const jchar*) freeGuardedCopy((jchar*)carray);
2112 }
2113 BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
2114 CHECK_EXIT(env);
2115 }
2116
Check_NewWeakGlobalRef(JNIEnv * env,jobject obj)2117 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
2118 {
2119 CHECK_ENTER(env, kFlag_Default);
2120 CHECK_OBJECT(env, obj);
2121 jweak result;
2122 result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
2123 CHECK_EXIT(env);
2124 return result;
2125 }
2126
Check_DeleteWeakGlobalRef(JNIEnv * env,jweak obj)2127 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
2128 {
2129 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2130 CHECK_OBJECT(env, obj);
2131 BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
2132 CHECK_EXIT(env);
2133 }
2134
Check_ExceptionCheck(JNIEnv * env)2135 static jboolean Check_ExceptionCheck(JNIEnv* env)
2136 {
2137 CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
2138 jboolean result;
2139 result = BASE_ENV(env)->ExceptionCheck(env);
2140 CHECK_EXIT(env);
2141 return result;
2142 }
2143
Check_GetObjectRefType(JNIEnv * env,jobject obj)2144 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
2145 {
2146 CHECK_ENTER(env, kFlag_Default);
2147 CHECK_OBJECT(env, obj);
2148 jobjectRefType result;
2149 result = BASE_ENV(env)->GetObjectRefType(env, obj);
2150 CHECK_EXIT(env);
2151 return result;
2152 }
2153
Check_NewDirectByteBuffer(JNIEnv * env,void * address,jlong capacity)2154 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
2155 jlong capacity)
2156 {
2157 CHECK_ENTER(env, kFlag_Default);
2158 jobject result;
2159 if (address == NULL || capacity < 0) {
2160 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
2161 address, (long) capacity);
2162 abortMaybe();
2163 return NULL;
2164 }
2165 result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
2166 CHECK_EXIT(env);
2167 return result;
2168 }
2169
Check_GetDirectBufferAddress(JNIEnv * env,jobject buf)2170 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
2171 {
2172 CHECK_ENTER(env, kFlag_Default);
2173 CHECK_OBJECT(env, buf);
2174 void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
2175 CHECK_EXIT(env);
2176
2177 /* optional - check result vs. "safe" implementation */
2178 if (kRedundantDirectBufferTest) {
2179 jobject platformAddr = NULL;
2180 void* checkResult = NULL;
2181
2182 /*
2183 * Start by determining if the object supports the DirectBuffer
2184 * interfaces. Note this does not guarantee that it's a direct buffer.
2185 */
2186 if (JNI_FALSE == (*env)->IsInstanceOf(env, buf,
2187 gDvm.jclassOrgApacheHarmonyNioInternalDirectBuffer))
2188 {
2189 goto bail;
2190 }
2191
2192 /*
2193 * Get the PlatformAddress object.
2194 *
2195 * If this isn't a direct buffer, platformAddr will be NULL and/or an
2196 * exception will have been thrown.
2197 */
2198 platformAddr = (*env)->CallObjectMethod(env, buf,
2199 (jmethodID) gDvm.methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress);
2200
2201 if ((*env)->ExceptionCheck(env)) {
2202 (*env)->ExceptionClear(env);
2203 platformAddr = NULL;
2204 }
2205 if (platformAddr == NULL) {
2206 LOGV("Got request for address of non-direct buffer\n");
2207 goto bail;
2208 }
2209
2210 jclass platformAddrClass = (*env)->FindClass(env,
2211 "org/apache/harmony/luni/platform/PlatformAddress");
2212 jmethodID toLongMethod = (*env)->GetMethodID(env, platformAddrClass,
2213 "toLong", "()J");
2214 checkResult = (void*)(u4)(*env)->CallLongMethod(env, platformAddr,
2215 toLongMethod);
2216
2217 bail:
2218 if (platformAddr != NULL)
2219 (*env)->DeleteLocalRef(env, platformAddr);
2220
2221 if (result != checkResult) {
2222 LOGW("JNI WARNING: direct buffer result mismatch (%p vs %p)\n",
2223 result, checkResult);
2224 abortMaybe();
2225 /* keep going */
2226 }
2227 }
2228
2229 return result;
2230 }
2231
Check_GetDirectBufferCapacity(JNIEnv * env,jobject buf)2232 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
2233 {
2234 CHECK_ENTER(env, kFlag_Default);
2235 CHECK_OBJECT(env, buf);
2236 /* TODO: verify "buf" is an instance of java.nio.Buffer */
2237 jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2238 CHECK_EXIT(env);
2239 return result;
2240 }
2241
2242
2243 /*
2244 * ===========================================================================
2245 * JNI invocation functions
2246 * ===========================================================================
2247 */
2248
Check_DestroyJavaVM(JavaVM * vm)2249 static jint Check_DestroyJavaVM(JavaVM* vm)
2250 {
2251 CHECK_VMENTER(vm, false);
2252 jint result;
2253 result = BASE_VM(vm)->DestroyJavaVM(vm);
2254 CHECK_VMEXIT(vm, false);
2255 return result;
2256 }
2257
Check_AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2258 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2259 void* thr_args)
2260 {
2261 CHECK_VMENTER(vm, false);
2262 jint result;
2263 result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2264 CHECK_VMEXIT(vm, true);
2265 return result;
2266 }
2267
Check_AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2268 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2269 void* thr_args)
2270 {
2271 CHECK_VMENTER(vm, false);
2272 jint result;
2273 result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2274 CHECK_VMEXIT(vm, true);
2275 return result;
2276 }
2277
Check_DetachCurrentThread(JavaVM * vm)2278 static jint Check_DetachCurrentThread(JavaVM* vm)
2279 {
2280 CHECK_VMENTER(vm, true);
2281 jint result;
2282 result = BASE_VM(vm)->DetachCurrentThread(vm);
2283 CHECK_VMEXIT(vm, false);
2284 return result;
2285 }
2286
Check_GetEnv(JavaVM * vm,void ** env,jint version)2287 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2288 {
2289 CHECK_VMENTER(vm, true);
2290 jint result;
2291 result = BASE_VM(vm)->GetEnv(vm, env, version);
2292 CHECK_VMEXIT(vm, true);
2293 return result;
2294 }
2295
2296
2297 /*
2298 * ===========================================================================
2299 * Function tables
2300 * ===========================================================================
2301 */
2302
2303 static const struct JNINativeInterface gCheckNativeInterface = {
2304 NULL,
2305 NULL,
2306 NULL,
2307 NULL,
2308
2309 Check_GetVersion,
2310
2311 Check_DefineClass,
2312 Check_FindClass,
2313
2314 Check_FromReflectedMethod,
2315 Check_FromReflectedField,
2316 Check_ToReflectedMethod,
2317
2318 Check_GetSuperclass,
2319 Check_IsAssignableFrom,
2320
2321 Check_ToReflectedField,
2322
2323 Check_Throw,
2324 Check_ThrowNew,
2325 Check_ExceptionOccurred,
2326 Check_ExceptionDescribe,
2327 Check_ExceptionClear,
2328 Check_FatalError,
2329
2330 Check_PushLocalFrame,
2331 Check_PopLocalFrame,
2332
2333 Check_NewGlobalRef,
2334 Check_DeleteGlobalRef,
2335 Check_DeleteLocalRef,
2336 Check_IsSameObject,
2337 Check_NewLocalRef,
2338 Check_EnsureLocalCapacity,
2339
2340 Check_AllocObject,
2341 Check_NewObject,
2342 Check_NewObjectV,
2343 Check_NewObjectA,
2344
2345 Check_GetObjectClass,
2346 Check_IsInstanceOf,
2347
2348 Check_GetMethodID,
2349
2350 Check_CallObjectMethod,
2351 Check_CallObjectMethodV,
2352 Check_CallObjectMethodA,
2353 Check_CallBooleanMethod,
2354 Check_CallBooleanMethodV,
2355 Check_CallBooleanMethodA,
2356 Check_CallByteMethod,
2357 Check_CallByteMethodV,
2358 Check_CallByteMethodA,
2359 Check_CallCharMethod,
2360 Check_CallCharMethodV,
2361 Check_CallCharMethodA,
2362 Check_CallShortMethod,
2363 Check_CallShortMethodV,
2364 Check_CallShortMethodA,
2365 Check_CallIntMethod,
2366 Check_CallIntMethodV,
2367 Check_CallIntMethodA,
2368 Check_CallLongMethod,
2369 Check_CallLongMethodV,
2370 Check_CallLongMethodA,
2371 Check_CallFloatMethod,
2372 Check_CallFloatMethodV,
2373 Check_CallFloatMethodA,
2374 Check_CallDoubleMethod,
2375 Check_CallDoubleMethodV,
2376 Check_CallDoubleMethodA,
2377 Check_CallVoidMethod,
2378 Check_CallVoidMethodV,
2379 Check_CallVoidMethodA,
2380
2381 Check_CallNonvirtualObjectMethod,
2382 Check_CallNonvirtualObjectMethodV,
2383 Check_CallNonvirtualObjectMethodA,
2384 Check_CallNonvirtualBooleanMethod,
2385 Check_CallNonvirtualBooleanMethodV,
2386 Check_CallNonvirtualBooleanMethodA,
2387 Check_CallNonvirtualByteMethod,
2388 Check_CallNonvirtualByteMethodV,
2389 Check_CallNonvirtualByteMethodA,
2390 Check_CallNonvirtualCharMethod,
2391 Check_CallNonvirtualCharMethodV,
2392 Check_CallNonvirtualCharMethodA,
2393 Check_CallNonvirtualShortMethod,
2394 Check_CallNonvirtualShortMethodV,
2395 Check_CallNonvirtualShortMethodA,
2396 Check_CallNonvirtualIntMethod,
2397 Check_CallNonvirtualIntMethodV,
2398 Check_CallNonvirtualIntMethodA,
2399 Check_CallNonvirtualLongMethod,
2400 Check_CallNonvirtualLongMethodV,
2401 Check_CallNonvirtualLongMethodA,
2402 Check_CallNonvirtualFloatMethod,
2403 Check_CallNonvirtualFloatMethodV,
2404 Check_CallNonvirtualFloatMethodA,
2405 Check_CallNonvirtualDoubleMethod,
2406 Check_CallNonvirtualDoubleMethodV,
2407 Check_CallNonvirtualDoubleMethodA,
2408 Check_CallNonvirtualVoidMethod,
2409 Check_CallNonvirtualVoidMethodV,
2410 Check_CallNonvirtualVoidMethodA,
2411
2412 Check_GetFieldID,
2413
2414 Check_GetObjectField,
2415 Check_GetBooleanField,
2416 Check_GetByteField,
2417 Check_GetCharField,
2418 Check_GetShortField,
2419 Check_GetIntField,
2420 Check_GetLongField,
2421 Check_GetFloatField,
2422 Check_GetDoubleField,
2423 Check_SetObjectField,
2424 Check_SetBooleanField,
2425 Check_SetByteField,
2426 Check_SetCharField,
2427 Check_SetShortField,
2428 Check_SetIntField,
2429 Check_SetLongField,
2430 Check_SetFloatField,
2431 Check_SetDoubleField,
2432
2433 Check_GetStaticMethodID,
2434
2435 Check_CallStaticObjectMethod,
2436 Check_CallStaticObjectMethodV,
2437 Check_CallStaticObjectMethodA,
2438 Check_CallStaticBooleanMethod,
2439 Check_CallStaticBooleanMethodV,
2440 Check_CallStaticBooleanMethodA,
2441 Check_CallStaticByteMethod,
2442 Check_CallStaticByteMethodV,
2443 Check_CallStaticByteMethodA,
2444 Check_CallStaticCharMethod,
2445 Check_CallStaticCharMethodV,
2446 Check_CallStaticCharMethodA,
2447 Check_CallStaticShortMethod,
2448 Check_CallStaticShortMethodV,
2449 Check_CallStaticShortMethodA,
2450 Check_CallStaticIntMethod,
2451 Check_CallStaticIntMethodV,
2452 Check_CallStaticIntMethodA,
2453 Check_CallStaticLongMethod,
2454 Check_CallStaticLongMethodV,
2455 Check_CallStaticLongMethodA,
2456 Check_CallStaticFloatMethod,
2457 Check_CallStaticFloatMethodV,
2458 Check_CallStaticFloatMethodA,
2459 Check_CallStaticDoubleMethod,
2460 Check_CallStaticDoubleMethodV,
2461 Check_CallStaticDoubleMethodA,
2462 Check_CallStaticVoidMethod,
2463 Check_CallStaticVoidMethodV,
2464 Check_CallStaticVoidMethodA,
2465
2466 Check_GetStaticFieldID,
2467
2468 Check_GetStaticObjectField,
2469 Check_GetStaticBooleanField,
2470 Check_GetStaticByteField,
2471 Check_GetStaticCharField,
2472 Check_GetStaticShortField,
2473 Check_GetStaticIntField,
2474 Check_GetStaticLongField,
2475 Check_GetStaticFloatField,
2476 Check_GetStaticDoubleField,
2477
2478 Check_SetStaticObjectField,
2479 Check_SetStaticBooleanField,
2480 Check_SetStaticByteField,
2481 Check_SetStaticCharField,
2482 Check_SetStaticShortField,
2483 Check_SetStaticIntField,
2484 Check_SetStaticLongField,
2485 Check_SetStaticFloatField,
2486 Check_SetStaticDoubleField,
2487
2488 Check_NewString,
2489
2490 Check_GetStringLength,
2491 Check_GetStringChars,
2492 Check_ReleaseStringChars,
2493
2494 Check_NewStringUTF,
2495 Check_GetStringUTFLength,
2496 Check_GetStringUTFChars,
2497 Check_ReleaseStringUTFChars,
2498
2499 Check_GetArrayLength,
2500 Check_NewObjectArray,
2501 Check_GetObjectArrayElement,
2502 Check_SetObjectArrayElement,
2503
2504 Check_NewBooleanArray,
2505 Check_NewByteArray,
2506 Check_NewCharArray,
2507 Check_NewShortArray,
2508 Check_NewIntArray,
2509 Check_NewLongArray,
2510 Check_NewFloatArray,
2511 Check_NewDoubleArray,
2512
2513 Check_GetBooleanArrayElements,
2514 Check_GetByteArrayElements,
2515 Check_GetCharArrayElements,
2516 Check_GetShortArrayElements,
2517 Check_GetIntArrayElements,
2518 Check_GetLongArrayElements,
2519 Check_GetFloatArrayElements,
2520 Check_GetDoubleArrayElements,
2521
2522 Check_ReleaseBooleanArrayElements,
2523 Check_ReleaseByteArrayElements,
2524 Check_ReleaseCharArrayElements,
2525 Check_ReleaseShortArrayElements,
2526 Check_ReleaseIntArrayElements,
2527 Check_ReleaseLongArrayElements,
2528 Check_ReleaseFloatArrayElements,
2529 Check_ReleaseDoubleArrayElements,
2530
2531 Check_GetBooleanArrayRegion,
2532 Check_GetByteArrayRegion,
2533 Check_GetCharArrayRegion,
2534 Check_GetShortArrayRegion,
2535 Check_GetIntArrayRegion,
2536 Check_GetLongArrayRegion,
2537 Check_GetFloatArrayRegion,
2538 Check_GetDoubleArrayRegion,
2539 Check_SetBooleanArrayRegion,
2540 Check_SetByteArrayRegion,
2541 Check_SetCharArrayRegion,
2542 Check_SetShortArrayRegion,
2543 Check_SetIntArrayRegion,
2544 Check_SetLongArrayRegion,
2545 Check_SetFloatArrayRegion,
2546 Check_SetDoubleArrayRegion,
2547
2548 Check_RegisterNatives,
2549 Check_UnregisterNatives,
2550
2551 Check_MonitorEnter,
2552 Check_MonitorExit,
2553
2554 Check_GetJavaVM,
2555
2556 Check_GetStringRegion,
2557 Check_GetStringUTFRegion,
2558
2559 Check_GetPrimitiveArrayCritical,
2560 Check_ReleasePrimitiveArrayCritical,
2561
2562 Check_GetStringCritical,
2563 Check_ReleaseStringCritical,
2564
2565 Check_NewWeakGlobalRef,
2566 Check_DeleteWeakGlobalRef,
2567
2568 Check_ExceptionCheck,
2569
2570 Check_NewDirectByteBuffer,
2571 Check_GetDirectBufferAddress,
2572 Check_GetDirectBufferCapacity,
2573
2574 Check_GetObjectRefType
2575 };
2576 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2577 NULL,
2578 NULL,
2579 NULL,
2580
2581 Check_DestroyJavaVM,
2582 Check_AttachCurrentThread,
2583 Check_DetachCurrentThread,
2584
2585 Check_GetEnv,
2586
2587 Check_AttachCurrentThreadAsDaemon,
2588 };
2589
2590
2591 /*
2592 * Replace the normal table with the checked table.
2593 */
dvmUseCheckedJniEnv(JNIEnvExt * pEnv)2594 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2595 {
2596 assert(pEnv->funcTable != &gCheckNativeInterface);
2597 pEnv->baseFuncTable = pEnv->funcTable;
2598 pEnv->funcTable = &gCheckNativeInterface;
2599 }
2600
2601 /*
2602 * Replace the normal table with the checked table.
2603 */
dvmUseCheckedJniVm(JavaVMExt * pVm)2604 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2605 {
2606 assert(pVm->funcTable != &gCheckInvokeInterface);
2607 pVm->baseFuncTable = pVm->funcTable;
2608 pVm->funcTable = &gCheckInvokeInterface;
2609 }
2610