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