OSDN Git Service

am af242824: Revert "Fix a type error in the allocation of non-moving arrays." per...
[android-x86/dalvik.git] / vm / CheckJni.c
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)",
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'",
97                 declType, objType);
98             LOGW("             failed in %s.%s ('%s' not found)",
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'",
105                 declType, objType);
106             LOGW("             failed in %s.%s",
107                 method->clazz->descriptor, method->name);
108             abortMaybe();
109             return;
110         } else {
111             LOGV("Check %s.%s: %s io %s (SLOW-OK)",
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 /*
188  * Flags passed into checkThread().
189  */
190 #define kFlag_Default       0x0000
191
192 #define kFlag_CritBad       0x0000      /* calling while in critical is bad */
193 #define kFlag_CritOkay      0x0001      /* ...okay */
194 #define kFlag_CritGet       0x0002      /* this is a critical "get" */
195 #define kFlag_CritRelease   0x0003      /* this is a critical "release" */
196 #define kFlag_CritMask      0x0003      /* bit mask to get "crit" value */
197
198 #define kFlag_ExcepBad      0x0000      /* raised exceptions are bad */
199 #define kFlag_ExcepOkay     0x0004      /* ...okay */
200
201 /*
202  * Enter/exit macros for JNI env "check" functions.  These do not change
203  * the thread state within the VM.
204  */
205 #define CHECK_ENTER(_env, _flags)                                           \
206     do {                                                                    \
207         JNI_TRACE(true, true);                                              \
208         checkThread(_env, _flags, __FUNCTION__);                            \
209     } while(false)
210
211 #define CHECK_EXIT(_env)                                                    \
212     do { JNI_TRACE(false, true); } while(false)
213
214
215 /*
216  * Enter/exit macros for JNI invocation interface "check" functions.  These
217  * do not change the thread state within the VM.
218  *
219  * Set "_hasmeth" to true if we have a valid thread with a method pointer.
220  * We won't have one before attaching a thread, after detaching a thread, or
221  * after destroying the VM.
222  */
223 #define CHECK_VMENTER(_vm, _hasmeth)                                        \
224     do { JNI_TRACE(true, _hasmeth); } while(false)
225 #define CHECK_VMEXIT(_vm, _hasmeth)                                         \
226     do { JNI_TRACE(false, _hasmeth); } while(false)
227
228 #define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic)            \
229     checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
230 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid)                           \
231     checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
232 #define CHECK_CLASS(_env, _clazz)                                           \
233     checkClass(_env, _clazz, __FUNCTION__)
234 #define CHECK_STRING(_env, _str)                                            \
235     checkString(_env, _str, __FUNCTION__)
236 #define CHECK_UTF_STRING(_env, _str)                                        \
237     checkUtfString(_env, _str, #_str, __FUNCTION__)
238 #define CHECK_NULLABLE_UTF_STRING(_env, _str)                               \
239     checkUtfString(_env, _str, NULL, __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)",
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");
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?");
345             dvmAbort();
346         }
347
348         LOGW("JNI WARNING: threadid=%d using env from threadid=%d",
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)",
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",
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",
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");
396         printWarn = true;
397         printException = true;
398     }
399
400     if (printWarn)
401         showLocation(dvmGetCurrentJNIMethod(), func);
402     if (printException) {
403         LOGW("Pending exception is:");
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");
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)",
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)",
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",
455                 field->name);
456         else
457             LOGW("JNI WARNING: accessing static field %s as non-static",
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", 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)",
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");
542         printWarn = true;
543     } else if (!dvmIsValidObject(obj)) {
544         LOGW("JNI WARNING: jclass points to invalid object %p", 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)",
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)", 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)",
584                 jstr, func);
585         else
586             LOGW("JNI WARNING: jstring %p is not a valid object (%s)", jstr,
587                 func);
588         printWarn = true;
589     }
590     JNI_EXIT();
591
592     if (printWarn)
593         abortMaybe();
594     else
595         checkObject(env, jstr, func);
596 }
597
598 /*
599  * Verify that "bytes" points to valid "modified UTF-8" data.
600  * If "identifier" is NULL, "bytes" is allowed to be NULL; otherwise,
601  * "identifier" is the name to use when reporting the null pointer.
602  */
603 static void checkUtfString(JNIEnv* env, const char* bytes,
604     const char* identifier, const char* func)
605 {
606     const char* origBytes = bytes;
607
608     if (bytes == NULL) {
609         if (identifier != NULL) {
610             LOGW("JNI WARNING: %s == NULL", identifier);
611             goto fail;
612         }
613
614         return;
615     }
616
617     const char* errorKind = NULL;
618     u1 utf8;
619     while (*bytes != '\0') {
620         utf8 = *(bytes++);
621         // Switch on the high four bits.
622         switch (utf8 >> 4) {
623             case 0x00:
624             case 0x01:
625             case 0x02:
626             case 0x03:
627             case 0x04:
628             case 0x05:
629             case 0x06:
630             case 0x07: {
631                 // Bit pattern 0xxx. No need for any extra bytes.
632                 break;
633             }
634             case 0x08:
635             case 0x09:
636             case 0x0a:
637             case 0x0b:
638             case 0x0f: {
639                 /*
640                  * Bit pattern 10xx or 1111, which are illegal start bytes.
641                  * Note: 1111 is valid for normal UTF-8, but not the
642                  * modified UTF-8 used here.
643                  */
644                 errorKind = "start";
645                 goto fail_with_string;
646             }
647             case 0x0e: {
648                 // Bit pattern 1110, so there are two additional bytes.
649                 utf8 = *(bytes++);
650                 if ((utf8 & 0xc0) != 0x80) {
651                     errorKind = "continuation";
652                     goto fail_with_string;
653                 }
654                 // Fall through to take care of the final byte.
655             }
656             case 0x0c:
657             case 0x0d: {
658                 // Bit pattern 110x, so there is one additional byte.
659                 utf8 = *(bytes++);
660                 if ((utf8 & 0xc0) != 0x80) {
661                     errorKind = "continuation";
662                     goto fail_with_string;
663                 }
664                 break;
665             }
666         }
667     }
668
669     return;
670
671 fail_with_string:
672     LOGW("JNI WARNING: input is not valid UTF-8: illegal %s byte 0x%x",
673         errorKind, utf8);
674     LOGW("             string: '%s'", origBytes);
675 fail:
676     showLocation(dvmGetCurrentJNIMethod(), func);
677     abortMaybe();
678 }
679
680 /*
681  * In some circumstances the VM will screen class names, but it doesn't
682  * for class lookup.  When things get bounced through a class loader, they
683  * can actually get normalized a couple of times; as a result, passing in
684  * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
685  * work in some circumstances.
686  *
687  * This is incorrect and could cause strange behavior or compatibility
688  * problems, so we want to screen that out here.
689  *
690  * We expect "full-qualified" class names, like "java/lang/Thread" or
691  * "[Ljava/lang/Object;".
692  */
693 static void checkClassName(JNIEnv* env, const char* className, const char* func)
694 {
695     const char* cp;
696
697     /* quick check for illegal chars */
698     cp = className;
699     while (*cp != '\0') {
700         if (*cp == '.')     /* catch "java.lang.String" */
701             goto fail;
702         cp++;
703     }
704     if (*(cp-1) == ';' && *className == 'L')
705         goto fail;         /* catch "Ljava/lang/String;" */
706
707     // TODO: need a more rigorous check here
708
709     return;
710
711 fail:
712     LOGW("JNI WARNING: illegal class name '%s' (%s)", className, func);
713     LOGW("             (should be formed like 'java/lang/String')");
714     abortMaybe();
715 }
716
717 /*
718  * Verify that "array" is non-NULL and points to an Array object.
719  *
720  * Since we're dealing with objects, switch to "running" mode.
721  */
722 static void checkArray(JNIEnv* env, jarray jarr, const char* func)
723 {
724     JNI_ENTER();
725     bool printWarn = false;
726
727     Object* obj = dvmDecodeIndirectRef(env, jarr);
728
729     if (obj == NULL) {
730         LOGW("JNI WARNING: received null array (%s)", func);
731         printWarn = true;
732     } else if (obj->clazz->descriptor[0] != '[') {
733         if (dvmIsValidObject(obj))
734             LOGW("JNI WARNING: jarray %p points to non-array object (%s)",
735                 jarr, obj->clazz->descriptor);
736         else
737             LOGW("JNI WARNING: jarray %p is not a valid object", jarr);
738         printWarn = true;
739     }
740
741     JNI_EXIT();
742
743     if (printWarn)
744         abortMaybe();
745     else
746         checkObject(env, jarr, func);
747 }
748
749 /*
750  * Verify that the "mode" argument passed to a primitive array Release
751  * function is one of the valid values.
752  */
753 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
754 {
755     if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
756         LOGW("JNI WARNING: bad value for mode (%d) (%s)", mode, func);
757         abortMaybe();
758     }
759 }
760
761 /*
762  * Verify that the length argument to array-creation calls is >= 0.
763  */
764 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
765 {
766     if (length < 0) {
767         LOGW("JNI WARNING: negative length for array allocation (%s)", func);
768         abortMaybe();
769     }
770 }
771
772 /*
773  * Verify that the pointer value is non-NULL.
774  */
775 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
776 {
777     if (ptr == NULL) {
778         LOGW("JNI WARNING: invalid null pointer (%s)", func);
779         abortMaybe();
780     }
781 }
782
783 /*
784  * Verify that the method's return type matches the type of call.
785  *
786  * "expectedSigByte" will be 'L' for all objects, including arrays.
787  */
788 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
789     bool isStatic, const char* func)
790 {
791     const Method* meth = (const Method*) methodID;
792     bool printWarn = false;
793
794     if (expectedSigByte != meth->shorty[0]) {
795         LOGW("JNI WARNING: expected return type '%c'", expectedSigByte);
796         printWarn = true;
797     } else if (isStatic && !dvmIsStaticMethod(meth)) {
798         if (isStatic)
799             LOGW("JNI WARNING: calling non-static method with static call");
800         else
801             LOGW("JNI WARNING: calling static method with non-static call");
802         printWarn = true;
803     }
804
805     if (printWarn) {
806         char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
807         LOGW("             calling %s.%s %s",
808             meth->clazz->descriptor, meth->name, desc);
809         free(desc);
810         showLocation(dvmGetCurrentJNIMethod(), func);
811         abortMaybe();
812     }
813 }
814
815 /*
816  * Verify that this static field ID is valid for this class.
817  */
818 static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
819 {
820     ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
821     StaticField* base = &clazz->sfields[0];
822     int fieldCount = clazz->sfieldCount;
823
824     if ((StaticField*) fieldID < base ||
825         (StaticField*) fieldID >= base + fieldCount)
826     {
827         LOGW("JNI WARNING: static fieldID %p not valid for class %s",
828             fieldID, clazz->descriptor);
829         LOGW("             base=%p count=%d", base, fieldCount);
830         abortMaybe();
831     }
832 }
833
834 /*
835  * Verify that this instance field ID is valid for this object.
836  */
837 static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
838     const char* func)
839 {
840     JNI_ENTER();
841
842     if (jobj == NULL) {
843         LOGW("JNI WARNING: invalid null object (%s)", func);
844         abortMaybe();
845         goto bail;
846     }
847
848     Object* obj = dvmDecodeIndirectRef(env, jobj);
849     ClassObject* clazz = obj->clazz;
850
851     /*
852      * Check this class and all of its superclasses for a matching field.
853      * Don't need to scan interfaces.
854      */
855     while (clazz != NULL) {
856         if ((InstField*) fieldID >= clazz->ifields &&
857             (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
858         {
859             goto bail;
860         }
861
862         clazz = clazz->super;
863     }
864
865     LOGW("JNI WARNING: inst fieldID %p not valid for class %s",
866         fieldID, obj->clazz->descriptor);
867     abortMaybe();
868
869 bail:
870     JNI_EXIT();
871 }
872
873 /*
874  * Verify that "methodID" is appropriate for "jobj".
875  *
876  * Make sure the object is an instance of the method's declaring class.
877  * (Note the methodID might point to a declaration in an interface; this
878  * will be handled automatically by the instanceof check.)
879  */
880 static void checkVirtualMethod(JNIEnv* env, jobject jobj, jmethodID methodID,
881     const char* func)
882 {
883     JNI_ENTER();
884
885     Object* obj = dvmDecodeIndirectRef(env, jobj);
886     const Method* meth = (const Method*) methodID;
887
888     if (!dvmInstanceof(obj->clazz, meth->clazz)) {
889         LOGW("JNI WARNING: can't call %s.%s on instance of %s",
890             meth->clazz->descriptor, meth->name, obj->clazz->descriptor);
891         abortMaybe();
892     }
893
894     JNI_EXIT();
895 }
896
897 /*
898  * Verify that "methodID" is appropriate for "clazz".
899  *
900  * A mismatch isn't dangerous, because the method defines the class.  In
901  * fact, jclazz is unused in the implementation.  It's best if we don't
902  * allow bad code in the system though.
903  *
904  * Instances of "jclazz" must be instances of the method's declaring class.
905  */
906 static void checkStaticMethod(JNIEnv* env, jclass jclazz, jmethodID methodID,
907     const char* func)
908 {
909     JNI_ENTER();
910
911     ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
912     const Method* meth = (const Method*) methodID;
913
914     if (!dvmInstanceof(clazz, meth->clazz)) {
915         LOGW("JNI WARNING: can't call static %s.%s on class %s",
916             meth->clazz->descriptor, meth->name, clazz->descriptor);
917         // no abort
918     }
919
920     JNI_EXIT();
921 }
922
923 /*
924  * Verify that the reference arguments being passed in are appropriate for
925  * this method.
926  *
927  * At a minimum we want to make sure that the argument is a valid
928  * reference.  We can also do a class lookup on the method signature
929  * and verify that the object is an instance of the appropriate class,
930  * but that's more expensive.
931  *
932  * The basic tests are redundant when indirect references are enabled,
933  * since reference arguments must always be converted explicitly.  An
934  * instanceof test would not be redundant, but we're not doing that at
935  * this time.
936  */
937 static void checkMethodArgsV(JNIEnv* env, jmethodID methodID, va_list args,
938     const char* func)
939 {
940 #ifndef USE_INDIRECT_REF
941     JNI_ENTER();
942
943     const Method* meth = (const Method*) methodID;
944     const char* desc = meth->shorty;
945
946     LOGV("V-checking %s.%s:%s...", meth->clazz->descriptor, meth->name, desc);
947
948     while (*++desc != '\0') {       /* pre-incr to skip return type */
949         switch (*desc) {
950         case 'L':
951             {     /* 'shorty' descr uses L for all refs, incl array */
952                 jobject argObj = va_arg(args, jobject);
953                 checkObject0(env, argObj, func);
954             }
955             break;
956         case 'D':       /* 8-byte double */
957         case 'J':       /* 8-byte long */
958         case 'F':       /* floats normalized to doubles */
959             (void) va_arg(args, u8);
960             break;
961         default:        /* Z B C S I -- all passed as 32-bit integers */
962             (void) va_arg(args, u4);
963             break;
964         }
965     }
966
967     JNI_EXIT();
968 #endif
969 }
970
971 /*
972  * Same purpose as checkMethodArgsV, but with arguments in an array of
973  * jvalue structs.
974  */
975 static void checkMethodArgsA(JNIEnv* env, jmethodID methodID, jvalue* args,
976     const char* func)
977 {
978 #ifndef USE_INDIRECT_REF
979     JNI_ENTER();
980
981     const Method* meth = (const Method*) methodID;
982     const char* desc = meth->shorty;
983     int idx = 0;
984
985     LOGV("A-checking %s.%s:%s...", meth->clazz->descriptor, meth->name, desc);
986
987     while (*++desc != '\0') {       /* pre-incr to skip return type */
988         if (*desc == 'L') {
989             jobject argObj = args[idx].l;
990             checkObject0(env, argObj, func);
991         }
992
993         idx++;
994     }
995
996     JNI_EXIT();
997 #endif
998 }
999
1000
1001 /*
1002  * ===========================================================================
1003  *      Guarded arrays
1004  * ===========================================================================
1005  */
1006
1007 #define kGuardLen       512         /* must be multiple of 2 */
1008 #define kGuardPattern   0xd5e3      /* uncommon values; d5e3d5e3 invalid addr */
1009 #define kGuardMagic     0xffd5aa96
1010 #define kGuardExtra     sizeof(GuardExtra)
1011
1012 /* this gets tucked in at the start of the buffer; struct size must be even */
1013 typedef struct GuardExtra {
1014     u4          magic;
1015     uLong       adler;
1016     size_t      originalLen;
1017     const void* originalPtr;
1018 } GuardExtra;
1019
1020 /* find the GuardExtra given the pointer into the "live" data */
1021 inline static GuardExtra* getGuardExtra(const void* dataBuf)
1022 {
1023     u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
1024     return (GuardExtra*) fullBuf;
1025 }
1026
1027 /*
1028  * Create an oversized buffer to hold the contents of "buf".  Copy it in,
1029  * filling in the area around it with guard data.
1030  *
1031  * We use a 16-bit pattern to make a rogue memset less likely to elude us.
1032  */
1033 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
1034 {
1035     GuardExtra* pExtra;
1036     size_t newLen = (len + kGuardLen +1) & ~0x01;
1037     u1* newBuf;
1038     u2* pat;
1039     int i;
1040
1041     newBuf = (u1*)malloc(newLen);
1042     if (newBuf == NULL) {
1043         LOGE("createGuardedCopy failed on alloc of %d bytes", newLen);
1044         dvmAbort();
1045     }
1046
1047     /* fill it in with a pattern */
1048     pat = (u2*) newBuf;
1049     for (i = 0; i < (int)newLen / 2; i++)
1050         *pat++ = kGuardPattern;
1051
1052     /* copy the data in; note "len" could be zero */
1053     memcpy(newBuf + kGuardLen / 2, buf, len);
1054
1055     /* if modification is not expected, grab a checksum */
1056     uLong adler = 0;
1057     if (!modOkay) {
1058         adler = adler32(0L, Z_NULL, 0);
1059         adler = adler32(adler, buf, len);
1060         *(uLong*)newBuf = adler;
1061     }
1062
1063     pExtra = (GuardExtra*) newBuf;
1064     pExtra->magic = kGuardMagic;
1065     pExtra->adler = adler;
1066     pExtra->originalPtr = buf;
1067     pExtra->originalLen = len;
1068
1069     return newBuf + kGuardLen / 2;
1070 }
1071
1072 /*
1073  * Verify the guard area and, if "modOkay" is false, that the data itself
1074  * has not been altered.
1075  *
1076  * The caller has already checked that "dataBuf" is non-NULL.
1077  */
1078 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
1079 {
1080     static const u4 kMagicCmp = kGuardMagic;
1081     const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
1082     const GuardExtra* pExtra = getGuardExtra(dataBuf);
1083     size_t len;
1084     const u2* pat;
1085     int i;
1086
1087     /*
1088      * Before we do anything with "pExtra", check the magic number.  We
1089      * do the check with memcmp rather than "==" in case the pointer is
1090      * unaligned.  If it points to completely bogus memory we're going
1091      * to crash, but there's no easy way around that.
1092      */
1093     if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
1094         u1 buf[4];
1095         memcpy(buf, &pExtra->magic, 4);
1096         LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
1097              "-- incorrect data pointer %p?",
1098             buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
1099         return false;
1100     }
1101
1102     len = pExtra->originalLen;
1103
1104     /* check bottom half of guard; skip over optional checksum storage */
1105     pat = (u2*) fullBuf;
1106     for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
1107     {
1108         if (pat[i] != kGuardPattern) {
1109             LOGE("JNI: guard pattern(1) disturbed at %p + %d",
1110                 fullBuf, i*2);
1111             return false;
1112         }
1113     }
1114
1115     int offset = kGuardLen / 2 + len;
1116     if (offset & 0x01) {
1117         /* odd byte; expected value depends on endian-ness of host */
1118         const u2 patSample = kGuardPattern;
1119         if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
1120             LOGE("JNI: guard pattern disturbed in odd byte after %p "
1121                  "(+%d) 0x%02x 0x%02x",
1122                 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
1123             return false;
1124         }
1125         offset++;
1126     }
1127
1128     /* check top half of guard */
1129     pat = (u2*) (fullBuf + offset);
1130     for (i = 0; i < kGuardLen / 4; i++) {
1131         if (pat[i] != kGuardPattern) {
1132             LOGE("JNI: guard pattern(2) disturbed at %p + %d",
1133                 fullBuf, offset + i*2);
1134             return false;
1135         }
1136     }
1137
1138     /*
1139      * If modification is not expected, verify checksum.  Strictly speaking
1140      * this is wrong: if we told the client that we made a copy, there's no
1141      * reason they can't alter the buffer.
1142      */
1143     if (!modOkay) {
1144         uLong adler = adler32(0L, Z_NULL, 0);
1145         adler = adler32(adler, dataBuf, len);
1146         if (pExtra->adler != adler) {
1147             LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p",
1148                 pExtra->adler, adler, dataBuf);
1149             return false;
1150         }
1151     }
1152
1153     return true;
1154 }
1155
1156 /*
1157  * Free up the guard buffer, scrub it, and return the original pointer.
1158  */
1159 static void* freeGuardedCopy(void* dataBuf)
1160 {
1161     u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
1162     const GuardExtra* pExtra = getGuardExtra(dataBuf);
1163     void* originalPtr = (void*) pExtra->originalPtr;
1164     size_t len = pExtra->originalLen;
1165
1166     memset(dataBuf, 0xdd, len);
1167     free(fullBuf);
1168     return originalPtr;
1169 }
1170
1171 /*
1172  * Just pull out the original pointer.
1173  */
1174 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
1175 {
1176     const GuardExtra* pExtra = getGuardExtra(dataBuf);
1177     return (void*) pExtra->originalPtr;
1178 }
1179
1180 /*
1181  * Grab the data length.
1182  */
1183 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
1184 {
1185     const GuardExtra* pExtra = getGuardExtra(dataBuf);
1186     return pExtra->originalLen;
1187 }
1188
1189 /*
1190  * Return the width, in bytes, of a primitive type.
1191  */
1192 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
1193 {
1194     static const int lengths[PRIM_MAX] = {
1195         1,      // boolean
1196         2,      // char
1197         4,      // float
1198         8,      // double
1199         1,      // byte
1200         2,      // short
1201         4,      // int
1202         8,      // long
1203         -1,     // void
1204     };
1205     assert(primType >= 0 && primType < PRIM_MAX);
1206     return lengths[primType];
1207 }
1208
1209 /*
1210  * Create a guarded copy of a primitive array.  Modifications to the copied
1211  * data are allowed.  Returns a pointer to the copied data.
1212  */
1213 static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
1214     jboolean* isCopy)
1215 {
1216     ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1217     PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1218     int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1219     void* result;
1220
1221     result = createGuardedCopy(arrObj->contents, len, true);
1222
1223     if (isCopy != NULL)
1224         *isCopy = JNI_TRUE;
1225
1226     return result;
1227 }
1228
1229 /*
1230  * Perform the array "release" operation, which may or may not copy data
1231  * back into the VM, and may or may not release the underlying storage.
1232  */
1233 static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
1234     int mode)
1235 {
1236     ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1237     bool release, copyBack;
1238     u1* result;
1239
1240     if (!checkGuardedCopy(dataBuf, true)) {
1241         LOGE("JNI: failed guarded copy check in releaseGuardedPACopy");
1242         abortMaybe();
1243         return NULL;
1244     }
1245
1246     switch (mode) {
1247     case 0:
1248         release = copyBack = true;
1249         break;
1250     case JNI_ABORT:
1251         release = true;
1252         copyBack = false;
1253         break;
1254     case JNI_COMMIT:
1255         release = false;
1256         copyBack = true;
1257         break;
1258     default:
1259         LOGE("JNI: bad release mode %d", mode);
1260         dvmAbort();
1261         return NULL;
1262     }
1263
1264     if (copyBack) {
1265         size_t len = getGuardedCopyOriginalLen(dataBuf);
1266         memcpy(arrObj->contents, dataBuf, len);
1267     }
1268
1269     if (release) {
1270         result = (u1*) freeGuardedCopy(dataBuf);
1271     } else {
1272         result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
1273     }
1274
1275     /* pointer is to the array contents; back up to the array object */
1276     result -= offsetof(ArrayObject, contents);
1277
1278     return result;
1279 }
1280
1281
1282 /*
1283  * ===========================================================================
1284  *      JNI functions
1285  * ===========================================================================
1286  */
1287
1288 static jint Check_GetVersion(JNIEnv* env)
1289 {
1290     CHECK_ENTER(env, kFlag_Default);
1291     jint result;
1292     result = BASE_ENV(env)->GetVersion(env);
1293     CHECK_EXIT(env);
1294     return result;
1295 }
1296
1297 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1298     const jbyte* buf, jsize bufLen)
1299 {
1300     CHECK_ENTER(env, kFlag_Default);
1301     CHECK_OBJECT(env, loader);
1302     CHECK_UTF_STRING(env, name);
1303     CHECK_CLASS_NAME(env, name);
1304     jclass result;
1305     result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
1306     CHECK_EXIT(env);
1307     return result;
1308 }
1309
1310 static jclass Check_FindClass(JNIEnv* env, const char* name)
1311 {
1312     CHECK_ENTER(env, kFlag_Default);
1313     CHECK_UTF_STRING(env, name);
1314     CHECK_CLASS_NAME(env, name);
1315     jclass result;
1316     result = BASE_ENV(env)->FindClass(env, name);
1317     CHECK_EXIT(env);
1318     return result;
1319 }
1320
1321 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
1322 {
1323     CHECK_ENTER(env, kFlag_Default);
1324     CHECK_CLASS(env, clazz);
1325     jclass result;
1326     result = BASE_ENV(env)->GetSuperclass(env, clazz);
1327     CHECK_EXIT(env);
1328     return result;
1329 }
1330
1331 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1332     jclass clazz2)
1333 {
1334     CHECK_ENTER(env, kFlag_Default);
1335     CHECK_CLASS(env, clazz1);
1336     CHECK_CLASS(env, clazz2);
1337     jboolean result;
1338     result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1339     CHECK_EXIT(env);
1340     return result;
1341 }
1342
1343 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1344 {
1345     CHECK_ENTER(env, kFlag_Default);
1346     CHECK_OBJECT(env, method);
1347     jmethodID result;
1348     result = BASE_ENV(env)->FromReflectedMethod(env, method);
1349     CHECK_EXIT(env);
1350     return result;
1351 }
1352
1353 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1354 {
1355     CHECK_ENTER(env, kFlag_Default);
1356     CHECK_OBJECT(env, field);
1357     jfieldID result;
1358     result = BASE_ENV(env)->FromReflectedField(env, field);
1359     CHECK_EXIT(env);
1360     return result;
1361 }
1362
1363 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1364     jmethodID methodID, jboolean isStatic)
1365 {
1366     CHECK_ENTER(env, kFlag_Default);
1367     CHECK_CLASS(env, cls);
1368     jobject result;
1369     result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1370     CHECK_EXIT(env);
1371     return result;
1372 }
1373
1374 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1375     jboolean isStatic)
1376 {
1377     CHECK_ENTER(env, kFlag_Default);
1378     CHECK_CLASS(env, cls);
1379     jobject result;
1380     result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1381     CHECK_EXIT(env);
1382     return result;
1383 }
1384
1385 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1386 {
1387     CHECK_ENTER(env, kFlag_Default);
1388     CHECK_OBJECT(env, obj);
1389     jint result;
1390     result = BASE_ENV(env)->Throw(env, obj);
1391     CHECK_EXIT(env);
1392     return result;
1393 }
1394
1395 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1396 {
1397     CHECK_ENTER(env, kFlag_Default);
1398     CHECK_CLASS(env, clazz);
1399     CHECK_NULLABLE_UTF_STRING(env, message);
1400     jint result;
1401     result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1402     CHECK_EXIT(env);
1403     return result;
1404 }
1405
1406 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1407 {
1408     CHECK_ENTER(env, kFlag_ExcepOkay);
1409     jthrowable result;
1410     result = BASE_ENV(env)->ExceptionOccurred(env);
1411     CHECK_EXIT(env);
1412     return result;
1413 }
1414
1415 static void Check_ExceptionDescribe(JNIEnv* env)
1416 {
1417     CHECK_ENTER(env, kFlag_ExcepOkay);
1418     BASE_ENV(env)->ExceptionDescribe(env);
1419     CHECK_EXIT(env);
1420 }
1421
1422 static void Check_ExceptionClear(JNIEnv* env)
1423 {
1424     CHECK_ENTER(env, kFlag_ExcepOkay);
1425     BASE_ENV(env)->ExceptionClear(env);
1426     CHECK_EXIT(env);
1427 }
1428
1429 static void Check_FatalError(JNIEnv* env, const char* msg)
1430 {
1431     CHECK_ENTER(env, kFlag_Default);
1432     CHECK_NULLABLE_UTF_STRING(env, msg);
1433     BASE_ENV(env)->FatalError(env, msg);
1434     CHECK_EXIT(env);
1435 }
1436
1437 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1438 {
1439     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1440     jint result;
1441     result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1442     CHECK_EXIT(env);
1443     return result;
1444 }
1445
1446 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1447 {
1448     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1449     CHECK_OBJECT(env, res);
1450     jobject result;
1451     result = BASE_ENV(env)->PopLocalFrame(env, res);
1452     CHECK_EXIT(env);
1453     return result;
1454 }
1455
1456 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1457 {
1458     CHECK_ENTER(env, kFlag_Default);
1459     CHECK_OBJECT(env, obj);
1460     jobject result;
1461     result = BASE_ENV(env)->NewGlobalRef(env, obj);
1462     CHECK_EXIT(env);
1463     return result;
1464 }
1465
1466 static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
1467 {
1468     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1469     CHECK_OBJECT(env, globalRef);
1470 #ifdef USE_INDIRECT_REF
1471     if (globalRef != NULL &&
1472         dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
1473     {
1474         LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)",
1475             globalRef, dvmGetJNIRefType(env, globalRef));
1476         abortMaybe();
1477     } else
1478 #endif
1479     {
1480         BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
1481     }
1482     CHECK_EXIT(env);
1483 }
1484
1485 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1486 {
1487     CHECK_ENTER(env, kFlag_Default);
1488     CHECK_OBJECT(env, ref);
1489     jobject result;
1490     result = BASE_ENV(env)->NewLocalRef(env, ref);
1491     CHECK_EXIT(env);
1492     return result;
1493 }
1494
1495 static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
1496 {
1497     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1498     CHECK_OBJECT(env, localRef);
1499 #ifdef USE_INDIRECT_REF
1500     if (localRef != NULL &&
1501         dvmGetJNIRefType(env, localRef) != JNILocalRefType)
1502     {
1503         LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)",
1504             localRef, dvmGetJNIRefType(env, localRef));
1505         abortMaybe();
1506     } else
1507 #endif
1508     {
1509         BASE_ENV(env)->DeleteLocalRef(env, localRef);
1510     }
1511     CHECK_EXIT(env);
1512 }
1513
1514 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1515 {
1516     CHECK_ENTER(env, kFlag_Default);
1517     jint result;
1518     result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1519     CHECK_EXIT(env);
1520     return result;
1521 }
1522
1523 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1524 {
1525     CHECK_ENTER(env, kFlag_Default);
1526     CHECK_OBJECT(env, ref1);
1527     CHECK_OBJECT(env, ref2);
1528     jboolean result;
1529     result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1530     CHECK_EXIT(env);
1531     return result;
1532 }
1533
1534 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1535 {
1536     CHECK_ENTER(env, kFlag_Default);
1537     CHECK_CLASS(env, clazz);
1538     jobject result;
1539     result = BASE_ENV(env)->AllocObject(env, clazz);
1540     CHECK_EXIT(env);
1541     return result;
1542 }
1543
1544 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1545     ...)
1546 {
1547     CHECK_ENTER(env, kFlag_Default);
1548     CHECK_CLASS(env, clazz);
1549     jobject result;
1550     va_list args, tmpArgs;
1551
1552     va_start(args, methodID);
1553
1554     va_copy(tmpArgs, args);
1555     CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);
1556     va_end(tmpArgs);
1557
1558     result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1559     va_end(args);
1560
1561     CHECK_EXIT(env);
1562     return result;
1563 }
1564 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1565     va_list args)
1566 {
1567     CHECK_ENTER(env, kFlag_Default);
1568     CHECK_CLASS(env, clazz);
1569     jobject result;
1570
1571     va_list tmpArgs;
1572     va_copy(tmpArgs, args);
1573     CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);
1574     va_end(tmpArgs);
1575
1576     result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1577     CHECK_EXIT(env);
1578     return result;
1579 }
1580 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1581     jvalue* args)
1582 {
1583     CHECK_ENTER(env, kFlag_Default);
1584     CHECK_CLASS(env, clazz);
1585     jobject result;
1586
1587     CHECK_METHOD_ARGS_A(env, methodID, args);
1588     result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1589     CHECK_EXIT(env);
1590     return result;
1591 }
1592
1593 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1594 {
1595     CHECK_ENTER(env, kFlag_Default);
1596     CHECK_OBJECT(env, obj);
1597     jclass result;
1598     result = BASE_ENV(env)->GetObjectClass(env, obj);
1599     CHECK_EXIT(env);
1600     return result;
1601 }
1602
1603 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1604 {
1605     CHECK_ENTER(env, kFlag_Default);
1606     CHECK_OBJECT(env, obj);
1607     CHECK_CLASS(env, clazz);
1608     jboolean result;
1609     result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1610     CHECK_EXIT(env);
1611     return result;
1612 }
1613
1614 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1615     const char* sig)
1616 {
1617     CHECK_ENTER(env, kFlag_Default);
1618     CHECK_CLASS(env, clazz);
1619     CHECK_UTF_STRING(env, name);
1620     CHECK_UTF_STRING(env, sig);
1621     jmethodID result;
1622     result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1623     CHECK_EXIT(env);
1624     return result;
1625 }
1626
1627 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1628     const char* name, const char* sig)
1629 {
1630     CHECK_ENTER(env, kFlag_Default);
1631     CHECK_CLASS(env, clazz);
1632     CHECK_UTF_STRING(env, name);
1633     CHECK_UTF_STRING(env, sig);
1634     jfieldID result;
1635     result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1636     CHECK_EXIT(env);
1637     return result;
1638 }
1639
1640 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1641     const char* name, const char* sig)
1642 {
1643     CHECK_ENTER(env, kFlag_Default);
1644     CHECK_CLASS(env, clazz);
1645     CHECK_UTF_STRING(env, name);
1646     CHECK_UTF_STRING(env, sig);
1647     jmethodID result;
1648     result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1649     CHECK_EXIT(env);
1650     return result;
1651 }
1652
1653 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1654     const char* name, const char* sig)
1655 {
1656     CHECK_ENTER(env, kFlag_Default);
1657     CHECK_CLASS(env, clazz);
1658     CHECK_UTF_STRING(env, name);
1659     CHECK_UTF_STRING(env, sig);
1660     jfieldID result;
1661     result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1662     CHECK_EXIT(env);
1663     return result;
1664 }
1665
1666 #define GET_STATIC_TYPE_FIELD(_ctype, _jname)                               \
1667     static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1668         jfieldID fieldID)                                                   \
1669     {                                                                       \
1670         CHECK_ENTER(env, kFlag_Default);                                    \
1671         CHECK_CLASS(env, clazz);                                            \
1672         _ctype result;                                                      \
1673         checkStaticFieldID(env, clazz, fieldID);                            \
1674         result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz,        \
1675             fieldID);                                                       \
1676         CHECK_EXIT(env);                                                    \
1677         return result;                                                      \
1678     }
1679 GET_STATIC_TYPE_FIELD(jobject, Object);
1680 GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1681 GET_STATIC_TYPE_FIELD(jbyte, Byte);
1682 GET_STATIC_TYPE_FIELD(jchar, Char);
1683 GET_STATIC_TYPE_FIELD(jshort, Short);
1684 GET_STATIC_TYPE_FIELD(jint, Int);
1685 GET_STATIC_TYPE_FIELD(jlong, Long);
1686 GET_STATIC_TYPE_FIELD(jfloat, Float);
1687 GET_STATIC_TYPE_FIELD(jdouble, Double);
1688
1689 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype)                       \
1690     static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz,   \
1691         jfieldID fieldID, _ctype value)                                     \
1692     {                                                                       \
1693         CHECK_ENTER(env, kFlag_Default);                                    \
1694         CHECK_CLASS(env, clazz);                                            \
1695         checkStaticFieldID(env, clazz, fieldID);                            \
1696         /* "value" arg only used when type == ref */                        \
1697         CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true);   \
1698         BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID,        \
1699             value);                                                         \
1700         CHECK_EXIT(env);                                                    \
1701     }
1702 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1703 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1704 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1705 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1706 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1707 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1708 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1709 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1710 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1711
1712 #define GET_TYPE_FIELD(_ctype, _jname)                                      \
1713     static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj,        \
1714         jfieldID fieldID)                                                   \
1715     {                                                                       \
1716         CHECK_ENTER(env, kFlag_Default);                                    \
1717         CHECK_OBJECT(env, obj);                                             \
1718         _ctype result;                                                      \
1719         CHECK_INST_FIELD_ID(env, obj, fieldID);                             \
1720         result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID);      \
1721         CHECK_EXIT(env);                                                    \
1722         return result;                                                      \
1723     }
1724 GET_TYPE_FIELD(jobject, Object);
1725 GET_TYPE_FIELD(jboolean, Boolean);
1726 GET_TYPE_FIELD(jbyte, Byte);
1727 GET_TYPE_FIELD(jchar, Char);
1728 GET_TYPE_FIELD(jshort, Short);
1729 GET_TYPE_FIELD(jint, Int);
1730 GET_TYPE_FIELD(jlong, Long);
1731 GET_TYPE_FIELD(jfloat, Float);
1732 GET_TYPE_FIELD(jdouble, Double);
1733
1734 #define SET_TYPE_FIELD(_ctype, _jname, _ftype)                              \
1735     static void Check_Set##_jname##Field(JNIEnv* env, jobject obj,          \
1736         jfieldID fieldID, _ctype value)                                     \
1737     {                                                                       \
1738         CHECK_ENTER(env, kFlag_Default);                                    \
1739         CHECK_OBJECT(env, obj);                                             \
1740         CHECK_INST_FIELD_ID(env, obj, fieldID);                             \
1741         /* "value" arg only used when type == ref */                        \
1742         CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
1743         BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value);        \
1744         CHECK_EXIT(env);                                                    \
1745     }
1746 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1747 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1748 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1749 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1750 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1751 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1752 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1753 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1754 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1755
1756 #define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)   \
1757     static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj,      \
1758         jmethodID methodID, ...)                                            \
1759     {                                                                       \
1760         CHECK_ENTER(env, kFlag_Default);                                    \
1761         CHECK_OBJECT(env, obj);                                             \
1762         CHECK_SIG(env, methodID, _retsig, false);                           \
1763         CHECK_VIRTUAL_METHOD(env, obj, methodID);                           \
1764         _retdecl;                                                           \
1765         va_list args, tmpArgs;                                              \
1766         va_start(args, methodID);                                           \
1767         va_copy(tmpArgs, args);                                             \
1768         CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);                        \
1769         va_end(tmpArgs);                                                    \
1770         _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID,   \
1771             args);                                                          \
1772         va_end(args);                                                       \
1773         CHECK_EXIT(env);                                                    \
1774         return _retok;                                                      \
1775     }                                                                       \
1776     static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj,     \
1777         jmethodID methodID, va_list args)                                   \
1778     {                                                                       \
1779         CHECK_ENTER(env, kFlag_Default);                                    \
1780         CHECK_OBJECT(env, obj);                                             \
1781         CHECK_SIG(env, methodID, _retsig, false);                           \
1782         CHECK_VIRTUAL_METHOD(env, obj, methodID);                           \
1783         _retdecl;                                                           \
1784         va_list tmpArgs;                                                    \
1785         va_copy(tmpArgs, args);                                             \
1786         CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);                        \
1787         va_end(tmpArgs);                                                    \
1788         _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID,   \
1789             args);                                                          \
1790         CHECK_EXIT(env);                                                    \
1791         return _retok;                                                      \
1792     }                                                                       \
1793     static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj,     \
1794         jmethodID methodID, jvalue* args)                                   \
1795     {                                                                       \
1796         CHECK_ENTER(env, kFlag_Default);                                    \
1797         CHECK_OBJECT(env, obj);                                             \
1798         CHECK_SIG(env, methodID, _retsig, false);                           \
1799         CHECK_VIRTUAL_METHOD(env, obj, methodID);                           \
1800         _retdecl;                                                           \
1801         CHECK_METHOD_ARGS_A(env, methodID, args);                           \
1802         _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID,   \
1803             args);                                                          \
1804         CHECK_EXIT(env);                                                    \
1805         return _retok;                                                      \
1806     }
1807 CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1808 CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1809 CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1810 CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1811 CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1812 CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
1813 CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1814 CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1815 CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1816 CALL_VIRTUAL(void, Void, , , , 'V');
1817
1818 #define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok,         \
1819         _retsig)                                                            \
1820     static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env,         \
1821         jobject obj, jclass clazz, jmethodID methodID, ...)                 \
1822     {                                                                       \
1823         CHECK_ENTER(env, kFlag_Default);                                    \
1824         CHECK_CLASS(env, clazz);                                            \
1825         CHECK_OBJECT(env, obj);                                             \
1826         CHECK_SIG(env, methodID, _retsig, false);                           \
1827         CHECK_VIRTUAL_METHOD(env, obj, methodID);                           \
1828         _retdecl;                                                           \
1829         va_list args, tmpArgs;                                              \
1830         va_start(args, methodID);                                           \
1831         va_copy(tmpArgs, args);                                             \
1832         CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);                        \
1833         va_end(tmpArgs);                                                    \
1834         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1835             clazz, methodID, args);                                         \
1836         va_end(args);                                                       \
1837         CHECK_EXIT(env);                                                    \
1838         return _retok;                                                      \
1839     }                                                                       \
1840     static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env,        \
1841         jobject obj, jclass clazz, jmethodID methodID, va_list args)        \
1842     {                                                                       \
1843         CHECK_ENTER(env, kFlag_Default);                                    \
1844         CHECK_CLASS(env, clazz);                                            \
1845         CHECK_OBJECT(env, obj);                                             \
1846         CHECK_SIG(env, methodID, _retsig, false);                           \
1847         CHECK_VIRTUAL_METHOD(env, obj, methodID);                           \
1848         _retdecl;                                                           \
1849         va_list tmpArgs;                                                    \
1850         va_copy(tmpArgs, args);                                             \
1851         CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);                        \
1852         va_end(tmpArgs);                                                    \
1853         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1854             clazz, methodID, args);                                         \
1855         CHECK_EXIT(env);                                                    \
1856         return _retok;                                                      \
1857     }                                                                       \
1858     static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env,        \
1859         jobject obj, jclass clazz, jmethodID methodID, jvalue* args)        \
1860     {                                                                       \
1861         CHECK_ENTER(env, kFlag_Default);                                    \
1862         CHECK_CLASS(env, clazz);                                            \
1863         CHECK_OBJECT(env, obj);                                             \
1864         CHECK_SIG(env, methodID, _retsig, false);                           \
1865         CHECK_VIRTUAL_METHOD(env, obj, methodID);                           \
1866         _retdecl;                                                           \
1867         CHECK_METHOD_ARGS_A(env, methodID, args);                           \
1868         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj,   \
1869             clazz, methodID, args);                                         \
1870         CHECK_EXIT(env);                                                    \
1871         return _retok;                                                      \
1872     }
1873 CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1874 CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1875 CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1876 CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1877 CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1878 CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
1879 CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1880 CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1881 CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1882 CALL_NONVIRTUAL(void, Void, , , , 'V');
1883
1884
1885 #define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)    \
1886     static _ctype Check_CallStatic##_jname##Method(JNIEnv* env,             \
1887         jclass clazz, jmethodID methodID, ...)                              \
1888     {                                                                       \
1889         CHECK_ENTER(env, kFlag_Default);                                    \
1890         CHECK_CLASS(env, clazz);                                            \
1891         CHECK_SIG(env, methodID, _retsig, true);                            \
1892         CHECK_STATIC_METHOD(env, clazz, methodID);                          \
1893         _retdecl;                                                           \
1894         va_list args, tmpArgs;                                              \
1895         va_start(args, methodID);                                           \
1896         va_copy(tmpArgs, args);                                             \
1897         CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);                        \
1898         va_end(tmpArgs);                                                    \
1899         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz,     \
1900             methodID, args);                                                \
1901         va_end(args);                                                       \
1902         CHECK_EXIT(env);                                                    \
1903         return _retok;                                                      \
1904     }                                                                       \
1905     static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env,            \
1906         jclass clazz, jmethodID methodID, va_list args)                     \
1907     {                                                                       \
1908         CHECK_ENTER(env, kFlag_Default);                                    \
1909         CHECK_CLASS(env, clazz);                                            \
1910         CHECK_SIG(env, methodID, _retsig, true);                            \
1911         CHECK_STATIC_METHOD(env, clazz, methodID);                          \
1912         _retdecl;                                                           \
1913         va_list tmpArgs;                                                    \
1914         va_copy(tmpArgs, args);                                             \
1915         CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);                        \
1916         va_end(tmpArgs);                                                    \
1917         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz,     \
1918             methodID, args);                                                \
1919         CHECK_EXIT(env);                                                    \
1920         return _retok;                                                      \
1921     }                                                                       \
1922     static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env,            \
1923         jclass clazz, jmethodID methodID, jvalue* args)                     \
1924     {                                                                       \
1925         CHECK_ENTER(env, kFlag_Default);                                    \
1926         CHECK_CLASS(env, clazz);                                            \
1927         CHECK_SIG(env, methodID, _retsig, true);                            \
1928         CHECK_STATIC_METHOD(env, clazz, methodID);                          \
1929         _retdecl;                                                           \
1930         CHECK_METHOD_ARGS_A(env, methodID, args);                           \
1931         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz,     \
1932             methodID, args);                                                \
1933         CHECK_EXIT(env);                                                    \
1934         return _retok;                                                      \
1935     }
1936 CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
1937 CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
1938 CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
1939 CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
1940 CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
1941 CALL_STATIC(jint, Int, jint result, result=, result, 'I');
1942 CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
1943 CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
1944 CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
1945 CALL_STATIC(void, Void, , , , 'V');
1946
1947 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1948     jsize len)
1949 {
1950     CHECK_ENTER(env, kFlag_Default);
1951     jstring result;
1952     result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1953     CHECK_EXIT(env);
1954     return result;
1955 }
1956
1957 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1958 {
1959     CHECK_ENTER(env, kFlag_CritOkay);
1960     CHECK_STRING(env, string);
1961     jsize result;
1962     result = BASE_ENV(env)->GetStringLength(env, string);
1963     CHECK_EXIT(env);
1964     return result;
1965 }
1966
1967 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1968     jboolean* isCopy)
1969 {
1970     CHECK_ENTER(env, kFlag_CritOkay);
1971     CHECK_STRING(env, string);
1972     const jchar* result;
1973     result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1974     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1975         // TODO: fix for indirect
1976         int len = dvmStringLen(string) * 2;
1977         result = (const jchar*) createGuardedCopy(result, len, false);
1978         if (isCopy != NULL)
1979             *isCopy = JNI_TRUE;
1980     }
1981     CHECK_EXIT(env);
1982     return result;
1983 }
1984
1985 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1986     const jchar* chars)
1987 {
1988     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1989     CHECK_STRING(env, string);
1990     CHECK_NON_NULL(env, chars);
1991     if (((JNIEnvExt*)env)->forceDataCopy) {
1992         if (!checkGuardedCopy(chars, false)) {
1993             LOGE("JNI: failed guarded copy check in ReleaseStringChars");
1994             abortMaybe();
1995             return;
1996         }
1997         chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1998     }
1999     BASE_ENV(env)->ReleaseStringChars(env, string, chars);
2000     CHECK_EXIT(env);
2001 }
2002
2003 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
2004 {
2005     CHECK_ENTER(env, kFlag_Default);
2006     CHECK_NULLABLE_UTF_STRING(env, bytes);
2007     jstring result;
2008     result = BASE_ENV(env)->NewStringUTF(env, bytes);
2009     CHECK_EXIT(env);
2010     return result;
2011 }
2012
2013 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
2014 {
2015     CHECK_ENTER(env, kFlag_CritOkay);
2016     CHECK_STRING(env, string);
2017     jsize result;
2018     result = BASE_ENV(env)->GetStringUTFLength(env, string);
2019     CHECK_EXIT(env);
2020     return result;
2021 }
2022
2023 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
2024     jboolean* isCopy)
2025 {
2026     CHECK_ENTER(env, kFlag_CritOkay);
2027     CHECK_STRING(env, string);
2028     const char* result;
2029     result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
2030     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2031         // TODO: fix for indirect
2032         int len = dvmStringUtf8ByteLen(string) + 1;
2033         result = (const char*) createGuardedCopy(result, len, false);
2034         if (isCopy != NULL)
2035             *isCopy = JNI_TRUE;
2036     }
2037     CHECK_EXIT(env);
2038     return result;
2039 }
2040
2041 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
2042     const char* utf)
2043 {
2044     CHECK_ENTER(env, kFlag_ExcepOkay);
2045     CHECK_STRING(env, string);
2046     CHECK_NON_NULL(env, utf);
2047     if (((JNIEnvExt*)env)->forceDataCopy) {
2048         //int len = dvmStringUtf8ByteLen(string) + 1;
2049         if (!checkGuardedCopy(utf, false)) {
2050             LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars");
2051             abortMaybe();
2052             return;
2053         }
2054         utf = (const char*) freeGuardedCopy((char*)utf);
2055     }
2056     BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
2057     CHECK_EXIT(env);
2058 }
2059
2060 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
2061 {
2062     CHECK_ENTER(env, kFlag_CritOkay);
2063     CHECK_ARRAY(env, array);
2064     jsize result;
2065     result = BASE_ENV(env)->GetArrayLength(env, array);
2066     CHECK_EXIT(env);
2067     return result;
2068 }
2069
2070 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
2071     jclass elementClass, jobject initialElement)
2072 {
2073     CHECK_ENTER(env, kFlag_Default);
2074     CHECK_CLASS(env, elementClass);
2075     CHECK_OBJECT(env, initialElement);
2076     CHECK_LENGTH_POSITIVE(env, length);
2077     jobjectArray result;
2078     result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
2079                                             initialElement);
2080     CHECK_EXIT(env);
2081     return result;
2082 }
2083
2084 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
2085     jsize index)
2086 {
2087     CHECK_ENTER(env, kFlag_Default);
2088     CHECK_ARRAY(env, array);
2089     jobject result;
2090     result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
2091     CHECK_EXIT(env);
2092     return result;
2093 }
2094
2095 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
2096     jsize index, jobject value)
2097 {
2098     CHECK_ENTER(env, kFlag_Default);
2099     CHECK_ARRAY(env, array);
2100     BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
2101     CHECK_EXIT(env);
2102 }
2103
2104 #define NEW_PRIMITIVE_ARRAY(_artype, _jname)                                \
2105     static _artype Check_New##_jname##Array(JNIEnv* env, jsize length)      \
2106     {                                                                       \
2107         CHECK_ENTER(env, kFlag_Default);                                    \
2108         CHECK_LENGTH_POSITIVE(env, length);                                 \
2109         _artype result;                                                     \
2110         result = BASE_ENV(env)->New##_jname##Array(env, length);            \
2111         CHECK_EXIT(env);                                                    \
2112         return result;                                                      \
2113     }
2114 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
2115 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
2116 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
2117 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
2118 NEW_PRIMITIVE_ARRAY(jintArray, Int);
2119 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
2120 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
2121 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
2122
2123
2124 /*
2125  * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
2126  * The code deliberately uses an invalid sequence of operations, so we
2127  * need to pass it through unmodified.  Review that code before making
2128  * any changes here.
2129  */
2130 #define kNoCopyMagic    0xd5aab57f
2131
2132 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                        \
2133     static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env,            \
2134         _ctype##Array array, jboolean* isCopy)                              \
2135     {                                                                       \
2136         CHECK_ENTER(env, kFlag_Default);                                    \
2137         CHECK_ARRAY(env, array);                                            \
2138         _ctype* result;                                                     \
2139         u4 noCopy = 0;                                                      \
2140         if (((JNIEnvExt*)env)->forceDataCopy && isCopy != NULL) {           \
2141             /* capture this before the base call tramples on it */          \
2142             noCopy = *(u4*) isCopy;                                         \
2143         }                                                                   \
2144         result = BASE_ENV(env)->Get##_jname##ArrayElements(env,             \
2145             array, isCopy);                                                 \
2146         if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {           \
2147             if (noCopy == kNoCopyMagic) {                                   \
2148                 LOGV("FC: not copying %p %x\n", array, noCopy);             \
2149             } else {                                                        \
2150                 result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
2151             }                                                               \
2152         }                                                                   \
2153         CHECK_EXIT(env);                                                    \
2154         return result;                                                      \
2155     }
2156
2157 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                    \
2158     static void Check_Release##_jname##ArrayElements(JNIEnv* env,           \
2159         _ctype##Array array, _ctype* elems, jint mode)                      \
2160     {                                                                       \
2161         CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);                  \
2162         CHECK_ARRAY(env, array);                                            \
2163         CHECK_NON_NULL(env, elems);                                         \
2164         CHECK_RELEASE_MODE(env, mode);                                      \
2165         if (((JNIEnvExt*)env)->forceDataCopy) {                             \
2166             if ((uintptr_t)elems == kNoCopyMagic) {                         \
2167                 LOGV("FC: not freeing %p\n", array);                        \
2168                 elems = NULL;   /* base JNI call doesn't currently need */  \
2169             } else {                                                        \
2170                 elems = (_ctype*) releaseGuardedPACopy(env, array, elems,   \
2171                         mode);                                              \
2172             }                                                               \
2173         }                                                                   \
2174         BASE_ENV(env)->Release##_jname##ArrayElements(env,                  \
2175             array, elems, mode);                                            \
2176         CHECK_EXIT(env);                                                    \
2177     }
2178
2179 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
2180     static void Check_Get##_jname##ArrayRegion(JNIEnv* env,                 \
2181         _ctype##Array array, jsize start, jsize len, _ctype* buf)           \
2182     {                                                                       \
2183         CHECK_ENTER(env, kFlag_Default);                                    \
2184         CHECK_ARRAY(env, array);                                            \
2185         BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start,          \
2186             len, buf);                                                      \
2187         CHECK_EXIT(env);                                                    \
2188     }
2189
2190 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
2191     static void Check_Set##_jname##ArrayRegion(JNIEnv* env,                 \
2192         _ctype##Array array, jsize start, jsize len, const _ctype* buf)     \
2193     {                                                                       \
2194         CHECK_ENTER(env, kFlag_Default);                                    \
2195         CHECK_ARRAY(env, array);                                            \
2196         BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start,          \
2197             len, buf);                                                      \
2198         CHECK_EXIT(env);                                                    \
2199     }
2200
2201 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar)                \
2202     GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                           \
2203     RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                       \
2204     GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);                             \
2205     SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
2206
2207 /* TODO: verify primitive array type matches call type */
2208 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
2209 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
2210 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
2211 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
2212 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
2213 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
2214 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
2215 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
2216
2217 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
2218     const JNINativeMethod* methods, jint nMethods)
2219 {
2220     CHECK_ENTER(env, kFlag_Default);
2221     CHECK_CLASS(env, clazz);
2222     jint result;
2223     result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
2224     CHECK_EXIT(env);
2225     return result;
2226 }
2227
2228 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
2229 {
2230     CHECK_ENTER(env, kFlag_Default);
2231     CHECK_CLASS(env, clazz);
2232     jint result;
2233     result = BASE_ENV(env)->UnregisterNatives(env, clazz);
2234     CHECK_EXIT(env);
2235     return result;
2236 }
2237
2238 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
2239 {
2240     CHECK_ENTER(env, kFlag_Default);
2241     CHECK_OBJECT(env, obj);
2242     jint result;
2243     result = BASE_ENV(env)->MonitorEnter(env, obj);
2244     CHECK_EXIT(env);
2245     return result;
2246 }
2247
2248 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
2249 {
2250     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2251     CHECK_OBJECT(env, obj);
2252     jint result;
2253     result = BASE_ENV(env)->MonitorExit(env, obj);
2254     CHECK_EXIT(env);
2255     return result;
2256 }
2257
2258 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
2259 {
2260     CHECK_ENTER(env, kFlag_Default);
2261     jint result;
2262     result = BASE_ENV(env)->GetJavaVM(env, vm);
2263     CHECK_EXIT(env);
2264     return result;
2265 }
2266
2267 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
2268     jsize len, jchar* buf)
2269 {
2270     CHECK_ENTER(env, kFlag_CritOkay);
2271     CHECK_STRING(env, str);
2272     BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
2273     CHECK_EXIT(env);
2274 }
2275
2276 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
2277     jsize len, char* buf)
2278 {
2279     CHECK_ENTER(env, kFlag_CritOkay);
2280     CHECK_STRING(env, str);
2281     BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
2282     CHECK_EXIT(env);
2283 }
2284
2285 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
2286     jboolean* isCopy)
2287 {
2288     CHECK_ENTER(env, kFlag_CritGet);
2289     CHECK_ARRAY(env, array);
2290     void* result;
2291     result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
2292     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2293         result = createGuardedPACopy(env, array, isCopy);
2294     }
2295     CHECK_EXIT(env);
2296     return result;
2297 }
2298
2299 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
2300     void* carray, jint mode)
2301 {
2302     CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2303     CHECK_ARRAY(env, array);
2304     CHECK_NON_NULL(env, carray);
2305     CHECK_RELEASE_MODE(env, mode);
2306     if (((JNIEnvExt*)env)->forceDataCopy) {
2307         carray = releaseGuardedPACopy(env, array, carray, mode);
2308     }
2309     BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2310     CHECK_EXIT(env);
2311 }
2312
2313 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
2314     jboolean* isCopy)
2315 {
2316     CHECK_ENTER(env, kFlag_CritGet);
2317     CHECK_STRING(env, string);
2318     const jchar* result;
2319     result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
2320     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2321         // TODO: fix for indirect
2322         int len = dvmStringLen(string) * 2;
2323         result = (const jchar*) createGuardedCopy(result, len, false);
2324         if (isCopy != NULL)
2325             *isCopy = JNI_TRUE;
2326     }
2327     CHECK_EXIT(env);
2328     return result;
2329 }
2330
2331 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
2332     const jchar* carray)
2333 {
2334     CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2335     CHECK_STRING(env, string);
2336     CHECK_NON_NULL(env, carray);
2337     if (((JNIEnvExt*)env)->forceDataCopy) {
2338         if (!checkGuardedCopy(carray, false)) {
2339             LOGE("JNI: failed guarded copy check in ReleaseStringCritical");
2340             abortMaybe();
2341             return;
2342         }
2343         carray = (const jchar*) freeGuardedCopy((jchar*)carray);
2344     }
2345     BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
2346     CHECK_EXIT(env);
2347 }
2348
2349 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
2350 {
2351     CHECK_ENTER(env, kFlag_Default);
2352     CHECK_OBJECT(env, obj);
2353     jweak result;
2354     result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
2355     CHECK_EXIT(env);
2356     return result;
2357 }
2358
2359 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
2360 {
2361     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2362     CHECK_OBJECT(env, obj);
2363     BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
2364     CHECK_EXIT(env);
2365 }
2366
2367 static jboolean Check_ExceptionCheck(JNIEnv* env)
2368 {
2369     CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
2370     jboolean result;
2371     result = BASE_ENV(env)->ExceptionCheck(env);
2372     CHECK_EXIT(env);
2373     return result;
2374 }
2375
2376 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
2377 {
2378     CHECK_ENTER(env, kFlag_Default);
2379     CHECK_OBJECT(env, obj);
2380     jobjectRefType result;
2381     result = BASE_ENV(env)->GetObjectRefType(env, obj);
2382     CHECK_EXIT(env);
2383     return result;
2384 }
2385
2386 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
2387     jlong capacity)
2388 {
2389     CHECK_ENTER(env, kFlag_Default);
2390     jobject result;
2391     if (address == NULL || capacity < 0) {
2392         LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)",
2393             address, (long) capacity);
2394         abortMaybe();
2395         return NULL;
2396     }
2397     result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
2398     CHECK_EXIT(env);
2399     return result;
2400 }
2401
2402 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
2403 {
2404     CHECK_ENTER(env, kFlag_Default);
2405     CHECK_OBJECT(env, buf);
2406     void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
2407     CHECK_EXIT(env);
2408     return result;
2409 }
2410
2411 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
2412 {
2413     CHECK_ENTER(env, kFlag_Default);
2414     CHECK_OBJECT(env, buf);
2415     /* TODO: verify "buf" is an instance of java.nio.Buffer */
2416     jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2417     CHECK_EXIT(env);
2418     return result;
2419 }
2420
2421
2422 /*
2423  * ===========================================================================
2424  *      JNI invocation functions
2425  * ===========================================================================
2426  */
2427
2428 static jint Check_DestroyJavaVM(JavaVM* vm)
2429 {
2430     CHECK_VMENTER(vm, false);
2431     jint result;
2432     result = BASE_VM(vm)->DestroyJavaVM(vm);
2433     CHECK_VMEXIT(vm, false);
2434     return result;
2435 }
2436
2437 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2438     void* thr_args)
2439 {
2440     CHECK_VMENTER(vm, false);
2441     jint result;
2442     result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2443     CHECK_VMEXIT(vm, true);
2444     return result;
2445 }
2446
2447 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2448     void* thr_args)
2449 {
2450     CHECK_VMENTER(vm, false);
2451     jint result;
2452     result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2453     CHECK_VMEXIT(vm, true);
2454     return result;
2455 }
2456
2457 static jint Check_DetachCurrentThread(JavaVM* vm)
2458 {
2459     CHECK_VMENTER(vm, true);
2460     jint result;
2461     result = BASE_VM(vm)->DetachCurrentThread(vm);
2462     CHECK_VMEXIT(vm, false);
2463     return result;
2464 }
2465
2466 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2467 {
2468     CHECK_VMENTER(vm, true);
2469     jint result;
2470     result = BASE_VM(vm)->GetEnv(vm, env, version);
2471     CHECK_VMEXIT(vm, true);
2472     return result;
2473 }
2474
2475
2476 /*
2477  * ===========================================================================
2478  *      Function tables
2479  * ===========================================================================
2480  */
2481
2482 static const struct JNINativeInterface gCheckNativeInterface = {
2483     NULL,
2484     NULL,
2485     NULL,
2486     NULL,
2487
2488     Check_GetVersion,
2489
2490     Check_DefineClass,
2491     Check_FindClass,
2492
2493     Check_FromReflectedMethod,
2494     Check_FromReflectedField,
2495     Check_ToReflectedMethod,
2496
2497     Check_GetSuperclass,
2498     Check_IsAssignableFrom,
2499
2500     Check_ToReflectedField,
2501
2502     Check_Throw,
2503     Check_ThrowNew,
2504     Check_ExceptionOccurred,
2505     Check_ExceptionDescribe,
2506     Check_ExceptionClear,
2507     Check_FatalError,
2508
2509     Check_PushLocalFrame,
2510     Check_PopLocalFrame,
2511
2512     Check_NewGlobalRef,
2513     Check_DeleteGlobalRef,
2514     Check_DeleteLocalRef,
2515     Check_IsSameObject,
2516     Check_NewLocalRef,
2517     Check_EnsureLocalCapacity,
2518
2519     Check_AllocObject,
2520     Check_NewObject,
2521     Check_NewObjectV,
2522     Check_NewObjectA,
2523
2524     Check_GetObjectClass,
2525     Check_IsInstanceOf,
2526
2527     Check_GetMethodID,
2528
2529     Check_CallObjectMethod,
2530     Check_CallObjectMethodV,
2531     Check_CallObjectMethodA,
2532     Check_CallBooleanMethod,
2533     Check_CallBooleanMethodV,
2534     Check_CallBooleanMethodA,
2535     Check_CallByteMethod,
2536     Check_CallByteMethodV,
2537     Check_CallByteMethodA,
2538     Check_CallCharMethod,
2539     Check_CallCharMethodV,
2540     Check_CallCharMethodA,
2541     Check_CallShortMethod,
2542     Check_CallShortMethodV,
2543     Check_CallShortMethodA,
2544     Check_CallIntMethod,
2545     Check_CallIntMethodV,
2546     Check_CallIntMethodA,
2547     Check_CallLongMethod,
2548     Check_CallLongMethodV,
2549     Check_CallLongMethodA,
2550     Check_CallFloatMethod,
2551     Check_CallFloatMethodV,
2552     Check_CallFloatMethodA,
2553     Check_CallDoubleMethod,
2554     Check_CallDoubleMethodV,
2555     Check_CallDoubleMethodA,
2556     Check_CallVoidMethod,
2557     Check_CallVoidMethodV,
2558     Check_CallVoidMethodA,
2559
2560     Check_CallNonvirtualObjectMethod,
2561     Check_CallNonvirtualObjectMethodV,
2562     Check_CallNonvirtualObjectMethodA,
2563     Check_CallNonvirtualBooleanMethod,
2564     Check_CallNonvirtualBooleanMethodV,
2565     Check_CallNonvirtualBooleanMethodA,
2566     Check_CallNonvirtualByteMethod,
2567     Check_CallNonvirtualByteMethodV,
2568     Check_CallNonvirtualByteMethodA,
2569     Check_CallNonvirtualCharMethod,
2570     Check_CallNonvirtualCharMethodV,
2571     Check_CallNonvirtualCharMethodA,
2572     Check_CallNonvirtualShortMethod,
2573     Check_CallNonvirtualShortMethodV,
2574     Check_CallNonvirtualShortMethodA,
2575     Check_CallNonvirtualIntMethod,
2576     Check_CallNonvirtualIntMethodV,
2577     Check_CallNonvirtualIntMethodA,
2578     Check_CallNonvirtualLongMethod,
2579     Check_CallNonvirtualLongMethodV,
2580     Check_CallNonvirtualLongMethodA,
2581     Check_CallNonvirtualFloatMethod,
2582     Check_CallNonvirtualFloatMethodV,
2583     Check_CallNonvirtualFloatMethodA,
2584     Check_CallNonvirtualDoubleMethod,
2585     Check_CallNonvirtualDoubleMethodV,
2586     Check_CallNonvirtualDoubleMethodA,
2587     Check_CallNonvirtualVoidMethod,
2588     Check_CallNonvirtualVoidMethodV,
2589     Check_CallNonvirtualVoidMethodA,
2590
2591     Check_GetFieldID,
2592
2593     Check_GetObjectField,
2594     Check_GetBooleanField,
2595     Check_GetByteField,
2596     Check_GetCharField,
2597     Check_GetShortField,
2598     Check_GetIntField,
2599     Check_GetLongField,
2600     Check_GetFloatField,
2601     Check_GetDoubleField,
2602     Check_SetObjectField,
2603     Check_SetBooleanField,
2604     Check_SetByteField,
2605     Check_SetCharField,
2606     Check_SetShortField,
2607     Check_SetIntField,
2608     Check_SetLongField,
2609     Check_SetFloatField,
2610     Check_SetDoubleField,
2611
2612     Check_GetStaticMethodID,
2613
2614     Check_CallStaticObjectMethod,
2615     Check_CallStaticObjectMethodV,
2616     Check_CallStaticObjectMethodA,
2617     Check_CallStaticBooleanMethod,
2618     Check_CallStaticBooleanMethodV,
2619     Check_CallStaticBooleanMethodA,
2620     Check_CallStaticByteMethod,
2621     Check_CallStaticByteMethodV,
2622     Check_CallStaticByteMethodA,
2623     Check_CallStaticCharMethod,
2624     Check_CallStaticCharMethodV,
2625     Check_CallStaticCharMethodA,
2626     Check_CallStaticShortMethod,
2627     Check_CallStaticShortMethodV,
2628     Check_CallStaticShortMethodA,
2629     Check_CallStaticIntMethod,
2630     Check_CallStaticIntMethodV,
2631     Check_CallStaticIntMethodA,
2632     Check_CallStaticLongMethod,
2633     Check_CallStaticLongMethodV,
2634     Check_CallStaticLongMethodA,
2635     Check_CallStaticFloatMethod,
2636     Check_CallStaticFloatMethodV,
2637     Check_CallStaticFloatMethodA,
2638     Check_CallStaticDoubleMethod,
2639     Check_CallStaticDoubleMethodV,
2640     Check_CallStaticDoubleMethodA,
2641     Check_CallStaticVoidMethod,
2642     Check_CallStaticVoidMethodV,
2643     Check_CallStaticVoidMethodA,
2644
2645     Check_GetStaticFieldID,
2646
2647     Check_GetStaticObjectField,
2648     Check_GetStaticBooleanField,
2649     Check_GetStaticByteField,
2650     Check_GetStaticCharField,
2651     Check_GetStaticShortField,
2652     Check_GetStaticIntField,
2653     Check_GetStaticLongField,
2654     Check_GetStaticFloatField,
2655     Check_GetStaticDoubleField,
2656
2657     Check_SetStaticObjectField,
2658     Check_SetStaticBooleanField,
2659     Check_SetStaticByteField,
2660     Check_SetStaticCharField,
2661     Check_SetStaticShortField,
2662     Check_SetStaticIntField,
2663     Check_SetStaticLongField,
2664     Check_SetStaticFloatField,
2665     Check_SetStaticDoubleField,
2666
2667     Check_NewString,
2668
2669     Check_GetStringLength,
2670     Check_GetStringChars,
2671     Check_ReleaseStringChars,
2672
2673     Check_NewStringUTF,
2674     Check_GetStringUTFLength,
2675     Check_GetStringUTFChars,
2676     Check_ReleaseStringUTFChars,
2677
2678     Check_GetArrayLength,
2679     Check_NewObjectArray,
2680     Check_GetObjectArrayElement,
2681     Check_SetObjectArrayElement,
2682
2683     Check_NewBooleanArray,
2684     Check_NewByteArray,
2685     Check_NewCharArray,
2686     Check_NewShortArray,
2687     Check_NewIntArray,
2688     Check_NewLongArray,
2689     Check_NewFloatArray,
2690     Check_NewDoubleArray,
2691
2692     Check_GetBooleanArrayElements,
2693     Check_GetByteArrayElements,
2694     Check_GetCharArrayElements,
2695     Check_GetShortArrayElements,
2696     Check_GetIntArrayElements,
2697     Check_GetLongArrayElements,
2698     Check_GetFloatArrayElements,
2699     Check_GetDoubleArrayElements,
2700
2701     Check_ReleaseBooleanArrayElements,
2702     Check_ReleaseByteArrayElements,
2703     Check_ReleaseCharArrayElements,
2704     Check_ReleaseShortArrayElements,
2705     Check_ReleaseIntArrayElements,
2706     Check_ReleaseLongArrayElements,
2707     Check_ReleaseFloatArrayElements,
2708     Check_ReleaseDoubleArrayElements,
2709
2710     Check_GetBooleanArrayRegion,
2711     Check_GetByteArrayRegion,
2712     Check_GetCharArrayRegion,
2713     Check_GetShortArrayRegion,
2714     Check_GetIntArrayRegion,
2715     Check_GetLongArrayRegion,
2716     Check_GetFloatArrayRegion,
2717     Check_GetDoubleArrayRegion,
2718     Check_SetBooleanArrayRegion,
2719     Check_SetByteArrayRegion,
2720     Check_SetCharArrayRegion,
2721     Check_SetShortArrayRegion,
2722     Check_SetIntArrayRegion,
2723     Check_SetLongArrayRegion,
2724     Check_SetFloatArrayRegion,
2725     Check_SetDoubleArrayRegion,
2726
2727     Check_RegisterNatives,
2728     Check_UnregisterNatives,
2729
2730     Check_MonitorEnter,
2731     Check_MonitorExit,
2732
2733     Check_GetJavaVM,
2734
2735     Check_GetStringRegion,
2736     Check_GetStringUTFRegion,
2737
2738     Check_GetPrimitiveArrayCritical,
2739     Check_ReleasePrimitiveArrayCritical,
2740
2741     Check_GetStringCritical,
2742     Check_ReleaseStringCritical,
2743
2744     Check_NewWeakGlobalRef,
2745     Check_DeleteWeakGlobalRef,
2746
2747     Check_ExceptionCheck,
2748
2749     Check_NewDirectByteBuffer,
2750     Check_GetDirectBufferAddress,
2751     Check_GetDirectBufferCapacity,
2752
2753     Check_GetObjectRefType
2754 };
2755 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2756     NULL,
2757     NULL,
2758     NULL,
2759
2760     Check_DestroyJavaVM,
2761     Check_AttachCurrentThread,
2762     Check_DetachCurrentThread,
2763
2764     Check_GetEnv,
2765
2766     Check_AttachCurrentThreadAsDaemon,
2767 };
2768
2769
2770 /*
2771  * Replace the normal table with the checked table.
2772  */
2773 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2774 {
2775     assert(pEnv->funcTable != &gCheckNativeInterface);
2776     pEnv->baseFuncTable = pEnv->funcTable;
2777     pEnv->funcTable = &gCheckNativeInterface;
2778 }
2779
2780 /*
2781  * Replace the normal table with the checked table.
2782  */
2783 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2784 {
2785     assert(pVm->funcTable != &gCheckInvokeInterface);
2786     pVm->baseFuncTable = pVm->funcTable;
2787     pVm->funcTable = &gCheckInvokeInterface;
2788 }