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