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