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