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