• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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