CheckJni.cpp revision ce0968340f9ddd54f20e38d4946bfd2ef8f1f343
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 26#include "Dalvik.h" 27#include "JniInternal.h" 28 29#include <sys/mman.h> 30#include <zlib.h> 31 32/* 33 * Abort if we are configured to bail out on JNI warnings. 34 */ 35static void abortMaybe() { 36 if (!gDvmJni.warnOnly) { 37 dvmDumpThread(dvmThreadSelf(), false); 38 dvmAbort(); 39 } 40} 41 42/* 43 * =========================================================================== 44 * JNI call bridge wrapper 45 * =========================================================================== 46 */ 47 48/* 49 * Check the result of a native method call that returns an object reference. 50 * 51 * The primary goal here is to verify that native code is returning the 52 * correct type of object. If it's declared to return a String but actually 53 * returns a byte array, things will fail in strange ways later on. 54 * 55 * This can be a fairly expensive operation, since we have to look up the 56 * return type class by name in method->clazz' class loader. We take a 57 * shortcut here and allow the call to succeed if the descriptor strings 58 * match. This will allow some false-positives when a class is redefined 59 * by a class loader, but that's rare enough that it doesn't seem worth 60 * testing for. 61 * 62 * At this point, pResult->l has already been converted to an object pointer. 63 */ 64static void checkCallResultCommon(const u4* args, const JValue* pResult, 65 const Method* method, Thread* self) 66{ 67 assert(pResult->l != NULL); 68 const Object* resultObj = (const Object*) pResult->l; 69 70 if (resultObj == kInvalidIndirectRefObject) { 71 LOGW("JNI WARNING: invalid reference returned from native code"); 72 const Method* method = dvmGetCurrentJNIMethod(); 73 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 74 LOGW(" in %s.%s:%s", method->clazz->descriptor, method->name, desc); 75 free(desc); 76 abortMaybe(); 77 return; 78 } 79 80 ClassObject* objClazz = resultObj->clazz; 81 82 /* 83 * Make sure that pResult->l is an instance of the type this 84 * method was expected to return. 85 */ 86 const char* declType = dexProtoGetReturnType(&method->prototype); 87 const char* objType = objClazz->descriptor; 88 if (strcmp(declType, objType) == 0) { 89 /* names match; ignore class loader issues and allow it */ 90 LOGV("Check %s.%s: %s io %s (FAST-OK)", 91 method->clazz->descriptor, method->name, objType, declType); 92 } else { 93 /* 94 * Names didn't match. We need to resolve declType in the context 95 * of method->clazz->classLoader, and compare the class objects 96 * for equality. 97 * 98 * Since we're returning an instance of declType, it's safe to 99 * assume that it has been loaded and initialized (or, for the case 100 * of an array, generated). However, the current class loader may 101 * not be listed as an initiating loader, so we can't just look for 102 * it in the loaded-classes list. 103 */ 104 ClassObject* declClazz = dvmFindClassNoInit(declType, method->clazz->classLoader); 105 if (declClazz == NULL) { 106 LOGW("JNI WARNING: method declared to return '%s' returned '%s'", 107 declType, objType); 108 LOGW(" failed in %s.%s ('%s' not found)", 109 method->clazz->descriptor, method->name, declType); 110 abortMaybe(); 111 return; 112 } 113 if (!dvmInstanceof(objClazz, declClazz)) { 114 LOGW("JNI WARNING: method declared to return '%s' returned '%s'", 115 declType, objType); 116 LOGW(" failed in %s.%s", 117 method->clazz->descriptor, method->name); 118 abortMaybe(); 119 return; 120 } else { 121 LOGV("Check %s.%s: %s io %s (SLOW-OK)", 122 method->clazz->descriptor, method->name, objType, declType); 123 } 124 } 125} 126 127/* 128 * Determine if we need to check the return type coming out of the call. 129 * 130 * (We don't simply do this at the top of checkCallResultCommon() because 131 * this is on the critical path for native method calls.) 132 */ 133static inline bool callNeedsCheck(const u4* args, JValue* pResult, 134 const Method* method, Thread* self) 135{ 136 return (method->shorty[0] == 'L' && !dvmCheckException(self) && pResult->l != NULL); 137} 138 139/* 140 * Check a call into native code. 141 */ 142void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult, 143 const Method* method, Thread* self) 144{ 145 dvmCallJNIMethod_general(args, pResult, method, self); 146 if (callNeedsCheck(args, pResult, method, self)) { 147 checkCallResultCommon(args, pResult, method, self); 148 } 149} 150 151/* 152 * Check a synchronized call into native code. 153 */ 154void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult, 155 const Method* method, Thread* self) 156{ 157 dvmCallJNIMethod_synchronized(args, pResult, method, self); 158 if (callNeedsCheck(args, pResult, method, self)) { 159 checkCallResultCommon(args, pResult, method, self); 160 } 161} 162 163/* 164 * Check a virtual call with no reference arguments (other than "this"). 165 */ 166void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult, 167 const Method* method, Thread* self) 168{ 169 dvmCallJNIMethod_virtualNoRef(args, pResult, method, self); 170 if (callNeedsCheck(args, pResult, method, self)) { 171 checkCallResultCommon(args, pResult, method, self); 172 } 173} 174 175/* 176 * Check a static call with no reference arguments (other than "clazz"). 177 */ 178void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult, 179 const Method* method, Thread* self) 180{ 181 dvmCallJNIMethod_staticNoRef(args, pResult, method, self); 182 if (callNeedsCheck(args, pResult, method, self)) { 183 checkCallResultCommon(args, pResult, method, self); 184 } 185} 186 187 188/* 189 * =========================================================================== 190 * JNI function helpers 191 * =========================================================================== 192 */ 193 194static inline const JNINativeInterface* baseEnv(JNIEnv* env) { 195 return ((JNIEnvExt*) env)->baseFuncTable; 196} 197 198static inline const JNIInvokeInterface* baseVm(JavaVM* vm) { 199 return ((JavaVMExt*) vm)->baseFuncTable; 200} 201 202/* 203 * Prints trace messages when a native method calls a JNI function such as 204 * NewByteArray. Enabled if both "-Xcheck:jni" and "-verbose:jni" are enabled. 205 */ 206static inline void jniTrace(bool hasMethod, const char* functionName) { 207 static const char* classDescriptor = "???"; 208 static const char* methodName = "???"; 209 if (hasMethod) { 210 const Method* method = dvmGetCurrentJNIMethod(); 211 classDescriptor = method->clazz->descriptor; 212 methodName = method->name; 213 } 214 /* use +6 to drop the leading "Check_" */ 215 LOGI("JNI: %s (from %s.%s)", functionName + 6, classDescriptor, methodName); 216} 217 218class ScopedJniThreadState { 219public: 220 explicit ScopedJniThreadState(JNIEnv* env) { 221 dvmChangeStatus(NULL, THREAD_RUNNING); 222 } 223 224 ~ScopedJniThreadState() { 225 dvmChangeStatus(NULL, THREAD_NATIVE); 226 } 227 228private: 229 // Disallow copy and assignment. 230 ScopedJniThreadState(const ScopedJniThreadState&); 231 void operator=(const ScopedJniThreadState&); 232}; 233 234class ScopedVmCheck { 235public: 236 /* 237 * Set "hasMethod" to true if we have a valid thread with a method pointer. 238 * We won't have one before attaching a thread, after detaching a thread, or 239 * after destroying the VM. 240 */ 241 ScopedVmCheck(bool hasMethod, const char* functionName) { 242 if (gDvm.verboseJni) { 243 jniTrace(hasMethod, functionName); 244 } 245 } 246 247private: 248 // Disallow copy and assignment. 249 ScopedVmCheck(const ScopedVmCheck&); 250 void operator=(const ScopedVmCheck&); 251}; 252 253/* 254 * Flags passed into ScopedCheck. 255 */ 256#define kFlag_Default 0x0000 257 258#define kFlag_CritBad 0x0000 /* calling while in critical is bad */ 259#define kFlag_CritOkay 0x0001 /* ...okay */ 260#define kFlag_CritGet 0x0002 /* this is a critical "get" */ 261#define kFlag_CritRelease 0x0003 /* this is a critical "release" */ 262#define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */ 263 264#define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */ 265#define kFlag_ExcepOkay 0x0004 /* ...okay */ 266 267static const char* indirectRefKindName(IndirectRef iref) 268{ 269 return indirectRefKindToString(indirectRefKind(iref)); 270} 271 272class ScopedCheck { 273public: 274 explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName) 275 : mEnv(env), mFunctionName(functionName) 276 { 277 if (gDvm.verboseJni) { 278 jniTrace(true, mFunctionName); 279 } 280 checkThread(flags); 281 } 282 283 /* 284 * Verify that "array" is non-NULL and points to an Array object. 285 * 286 * Since we're dealing with objects, switch to "running" mode. 287 */ 288 void checkArray(jarray jarr) { 289 if (jarr == NULL) { 290 LOGW("JNI WARNING: received null array"); 291 showLocation(); 292 abortMaybe(); 293 return; 294 } 295 296 ScopedJniThreadState ts(mEnv); 297 bool printWarn = false; 298 299 Object* obj = dvmDecodeIndirectRef(mEnv, jarr); 300 301 if (!dvmIsValidObject(obj)) { 302 LOGW("JNI WARNING: jarray is an invalid %s reference (%p)", 303 indirectRefKindName(jarr), jarr); 304 printWarn = true; 305 } else if (obj->clazz->descriptor[0] != '[') { 306 LOGW("JNI WARNING: jarray arg has wrong type (expected array, got %s)", 307 obj->clazz->descriptor); 308 printWarn = true; 309 } 310 311 if (printWarn) { 312 showLocation(); 313 abortMaybe(); 314 } 315 } 316 317 /* 318 * In some circumstances the VM will screen class names, but it doesn't 319 * for class lookup. When things get bounced through a class loader, they 320 * can actually get normalized a couple of times; as a result, passing in 321 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will 322 * work in some circumstances. 323 * 324 * This is incorrect and could cause strange behavior or compatibility 325 * problems, so we want to screen that out here. 326 * 327 * We expect "full-qualified" class names, like "java/lang/Thread" or 328 * "[Ljava/lang/Object;". 329 */ 330 void checkClassName(const char* className) { 331 if (!dexIsValidClassName(className, false)) { 332 LOGW("JNI WARNING: illegal class name '%s' (%s)", className, mFunctionName); 333 LOGW(" (should be formed like 'dalvik/system/DexFile')"); 334 LOGW(" or '[Ldalvik/system/DexFile;' or '[[B')"); 335 abortMaybe(); 336 } 337 } 338 339 /* 340 * Verify that the field is of the appropriate type. If the field has an 341 * object type, "jobj" is the object we're trying to assign into it. 342 * 343 * Works for both static and instance fields. 344 */ 345 void checkFieldType(jobject jobj, jfieldID fieldID, PrimitiveType prim, bool isStatic) { 346 if (fieldID == NULL) { 347 LOGW("JNI WARNING: null field ID"); 348 showLocation(); 349 abortMaybe(); 350 } 351 352 bool printWarn = false; 353 Field* field = (Field*) fieldID; 354 if ((field->signature[0] == 'L' || field->signature[0] == '[') && jobj != NULL) { 355 ScopedJniThreadState ts(mEnv); 356 Object* obj = dvmDecodeIndirectRef(mEnv, jobj); 357 /* 358 * If jobj is a weak global ref whose referent has been cleared, 359 * obj will be NULL. Otherwise, obj should always be non-NULL 360 * and valid. 361 */ 362 if (obj != NULL && !dvmIsValidObject(obj)) { 363 LOGW("JNI WARNING: field operation on invalid %s reference (%p)", 364 indirectRefKindName(jobj), jobj); 365 printWarn = true; 366 } else { 367 ClassObject* fieldClass = dvmFindLoadedClass(field->signature); 368 ClassObject* objClass = obj->clazz; 369 370 assert(fieldClass != NULL); 371 assert(objClass != NULL); 372 373 if (!dvmInstanceof(objClass, fieldClass)) { 374 LOGW("JNI WARNING: set field '%s' expected type %s, got %s", 375 field->name, field->signature, objClass->descriptor); 376 printWarn = true; 377 } 378 } 379 } else if (dexGetPrimitiveTypeFromDescriptorChar(field->signature[0]) != prim) { 380 LOGW("JNI WARNING: set field '%s' expected type %s, got %s", 381 field->name, field->signature, primitiveTypeToName(prim)); 382 printWarn = true; 383 } else if (isStatic && !dvmIsStaticField(field)) { 384 if (isStatic) { 385 LOGW("JNI WARNING: accessing non-static field %s as static", field->name); 386 } else { 387 LOGW("JNI WARNING: accessing static field %s as non-static", field->name); 388 } 389 printWarn = true; 390 } 391 392 if (printWarn) { 393 showLocation(); 394 abortMaybe(); 395 } 396 } 397 398 /* 399 * Verify that this instance field ID is valid for this object. 400 * 401 * Assumes "jobj" has already been validated. 402 */ 403 void checkInstanceFieldID(jobject jobj, jfieldID fieldID) { 404 ScopedJniThreadState ts(mEnv); 405 406 Object* obj = dvmDecodeIndirectRef(mEnv, jobj); 407 if (!dvmIsValidObject(obj)) { 408 LOGW("JNI ERROR: field operation on invalid reference (%p)", jobj); 409 dvmAbort(); 410 } 411 412 /* 413 * Check this class and all of its superclasses for a matching field. 414 * Don't need to scan interfaces. 415 */ 416 ClassObject* clazz = obj->clazz; 417 while (clazz != NULL) { 418 if ((InstField*) fieldID >= clazz->ifields && 419 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount) { 420 return; 421 } 422 423 clazz = clazz->super; 424 } 425 426 LOGW("JNI WARNING: instance fieldID %p not valid for class %s", 427 fieldID, obj->clazz->descriptor); 428 showLocation(); 429 abortMaybe(); 430 } 431 432 /* 433 * Verify that the length argument to array-creation calls is >= 0. 434 */ 435 void checkLengthPositive(jsize length) { 436 if (length < 0) { 437 LOGW("JNI WARNING: negative length for array allocation (%s)", mFunctionName); 438 abortMaybe(); 439 } 440 } 441 442 /* 443 * Verify that the pointer value is non-NULL. 444 */ 445 void checkNonNull(const void* ptr) { 446 if (ptr == NULL) { 447 LOGW("JNI WARNING: invalid null pointer (%s)", mFunctionName); 448 abortMaybe(); 449 } 450 } 451 452 /* 453 * Verify that "jobj" is a valid object, and that it's an object that JNI 454 * is allowed to know about. We allow NULL references. 455 * 456 * Switches to "running" mode before performing checks. 457 */ 458 void checkObject(jobject jobj) { 459 if (jobj == NULL) { 460 return; 461 } 462 463 ScopedJniThreadState ts(mEnv); 464 465 bool printWarn = false; 466 if (dvmGetJNIRefType(mEnv, jobj) == JNIInvalidRefType) { 467 LOGW("JNI WARNING: %p is not a valid JNI reference", jobj); 468 printWarn = true; 469 } else { 470 Object* obj = dvmDecodeIndirectRef(mEnv, jobj); 471 472 /* 473 * The decoded object will be NULL if this is a weak global ref 474 * with a cleared referent. 475 */ 476 if (obj == kInvalidIndirectRefObject || (obj != NULL && !dvmIsValidObject(obj))) { 477 LOGW("JNI WARNING: native code passing in bad object %p %p", jobj, obj); 478 printWarn = true; 479 } 480 } 481 482 if (printWarn) { 483 showLocation(); 484 abortMaybe(); 485 } 486 } 487 488 /* 489 * Verify that the "mode" argument passed to a primitive array Release 490 * function is one of the valid values. 491 */ 492 void checkReleaseMode(jint mode) { 493 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) { 494 LOGW("JNI WARNING: bad value for mode (%d) (%s)", mode, mFunctionName); 495 abortMaybe(); 496 } 497 } 498 499 /* 500 * Verify that the method's return type matches the type of call. 501 * 502 * "expectedSigByte" will be 'L' for all objects, including arrays. 503 */ 504 void checkSig(jmethodID methodID, char expectedSigByte, bool isStatic) { 505 const Method* method = (const Method*) methodID; 506 bool printWarn = false; 507 508 if (expectedSigByte != method->shorty[0]) { 509 LOGW("JNI WARNING: expected return type '%c'", expectedSigByte); 510 printWarn = true; 511 } else if (isStatic && !dvmIsStaticMethod(method)) { 512 if (isStatic) { 513 LOGW("JNI WARNING: calling non-static method with static call"); 514 } else { 515 LOGW("JNI WARNING: calling static method with non-static call"); 516 } 517 printWarn = true; 518 } 519 520 if (printWarn) { 521 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 522 LOGW(" calling %s.%s %s", method->clazz->descriptor, method->name, desc); 523 free(desc); 524 showLocation(); 525 abortMaybe(); 526 } 527 } 528 529 /* 530 * Verify that this static field ID is valid for this class. 531 * 532 * Assumes "jclazz" has already been validated. 533 */ 534 void checkStaticFieldID(jclass jclazz, jfieldID fieldID) { 535 ScopedJniThreadState ts(mEnv); 536 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(mEnv, jclazz); 537 StaticField* base = &clazz->sfields[0]; 538 int fieldCount = clazz->sfieldCount; 539 if ((StaticField*) fieldID < base || (StaticField*) fieldID >= base + fieldCount) { 540 LOGW("JNI WARNING: static fieldID %p not valid for class %s", 541 fieldID, clazz->descriptor); 542 LOGW(" base=%p count=%d", base, fieldCount); 543 showLocation(); 544 abortMaybe(); 545 } 546 } 547 548 /* 549 * Verify that "methodID" is appropriate for "clazz". 550 * 551 * A mismatch isn't dangerous, because the jmethodID defines the class. In 552 * fact, jclazz is unused in the implementation. It's best if we don't 553 * allow bad code in the system though. 554 * 555 * Instances of "jclazz" must be instances of the method's declaring class. 556 */ 557 void checkStaticMethod(jclass jclazz, jmethodID methodID) { 558 ScopedJniThreadState ts(mEnv); 559 560 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(mEnv, jclazz); 561 const Method* method = (const Method*) methodID; 562 563 if (!dvmInstanceof(clazz, method->clazz)) { 564 LOGW("JNI WARNING: can't call static %s.%s on class %s", 565 method->clazz->descriptor, method->name, clazz->descriptor); 566 showLocation(); 567 // no abort? 568 } 569 } 570 571 void checkString(jstring s) { 572 checkInstance(s, gDvm.classJavaLangString, "jstring"); 573 } 574 575 void checkClass(jclass c) { 576 checkInstance(c, gDvm.classJavaLangClass, "jclass"); 577 } 578 579 /* 580 * Verify that "bytes" points to valid "modified UTF-8" data. 581 * If "identifier" is NULL, "bytes" is allowed to be NULL; otherwise, 582 * "identifier" is the name to use when reporting the null pointer. 583 */ 584 void checkUtfString(const char* bytes, const char* identifier) { 585 if (bytes == NULL) { 586 if (identifier != NULL) { 587 LOGW("JNI WARNING: %s == NULL", identifier); 588 showLocation(); 589 abortMaybe(); 590 } 591 return; 592 } 593 594 const char* errorKind = NULL; 595 u1 utf8 = checkUtfBytes(bytes, &errorKind); 596 if (errorKind != NULL) { 597 LOGW("JNI WARNING: input is not valid UTF-8: illegal %s byte %#x", errorKind, utf8); 598 LOGW(" string: '%s'", bytes); 599 showLocation(); 600 abortMaybe(); 601 } 602 } 603 604 /* 605 * Verify that "methodID" is appropriate for "jobj". 606 * 607 * Make sure the object is an instance of the method's declaring class. 608 * (Note the methodID might point to a declaration in an interface; this 609 * will be handled automatically by the instanceof check.) 610 */ 611 void checkVirtualMethod(jobject jobj, jmethodID methodID) { 612 ScopedJniThreadState ts(mEnv); 613 614 Object* obj = dvmDecodeIndirectRef(mEnv, jobj); 615 const Method* method = (const Method*) methodID; 616 617 if (!dvmInstanceof(obj->clazz, method->clazz)) { 618 LOGW("JNI WARNING: can't call %s.%s on instance of %s", 619 method->clazz->descriptor, method->name, obj->clazz->descriptor); 620 showLocation(); 621 abortMaybe(); 622 } 623 } 624 625private: 626 JNIEnv* mEnv; 627 const char* mFunctionName; 628 629 void checkThread(int flags) { 630 // Get the *correct* JNIEnv by going through our TLS pointer. 631 JNIEnvExt* threadEnv = dvmGetJNIEnvForThread(); 632 633 /* 634 * Verify that the current thread is (a) attached and (b) associated with 635 * this particular instance of JNIEnv. 636 */ 637 bool printWarn = false; 638 if (threadEnv == NULL) { 639 LOGE("JNI ERROR: non-VM thread making JNI calls"); 640 // don't set printWarn -- it'll try to call showLocation() 641 dvmAbort(); 642 } else if ((JNIEnvExt*) mEnv != threadEnv) { 643 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) { 644 LOGE("JNI: threadEnv != thread->env?"); 645 dvmAbort(); 646 } 647 648 LOGW("JNI WARNING: threadid=%d using env from threadid=%d", 649 threadEnv->envThreadId, ((JNIEnvExt*) mEnv)->envThreadId); 650 printWarn = true; 651 652 /* this is a bad idea -- need to throw as we exit, or abort func */ 653 //dvmThrowRuntimeException("invalid use of JNI env ptr"); 654 } else if (((JNIEnvExt*) mEnv)->self != dvmThreadSelf()) { 655 /* correct JNIEnv*; make sure the "self" pointer is correct */ 656 LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)", 657 ((JNIEnvExt*) mEnv)->self, dvmThreadSelf()); 658 dvmAbort(); 659 } 660 661 /* 662 * Verify that, if this thread previously made a critical "get" call, we 663 * do the corresponding "release" call before we try anything else. 664 */ 665 switch (flags & kFlag_CritMask) { 666 case kFlag_CritOkay: // okay to call this method 667 break; 668 case kFlag_CritBad: // not okay to call 669 if (threadEnv->critical) { 670 LOGW("JNI WARNING: threadid=%d using JNI after critical get", 671 threadEnv->envThreadId); 672 printWarn = true; 673 } 674 break; 675 case kFlag_CritGet: // this is a "get" call 676 /* don't check here; we allow nested gets */ 677 threadEnv->critical++; 678 break; 679 case kFlag_CritRelease: // this is a "release" call 680 threadEnv->critical--; 681 if (threadEnv->critical < 0) { 682 LOGW("JNI WARNING: threadid=%d called too many crit releases", 683 threadEnv->envThreadId); 684 printWarn = true; 685 } 686 break; 687 default: 688 assert(false); 689 } 690 691 /* 692 * Verify that, if an exception has been raised, the native code doesn't 693 * make any JNI calls other than the Exception* methods. 694 */ 695 bool printException = false; 696 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) { 697 LOGW("JNI WARNING: JNI method called with exception pending"); 698 printWarn = true; 699 printException = true; 700 } 701 702 if (printWarn) { 703 showLocation(); 704 } 705 if (printException) { 706 LOGW("Pending exception is:"); 707 dvmLogExceptionStackTrace(); 708 } 709 if (printWarn) { 710 abortMaybe(); 711 } 712 } 713 714 /* 715 * Verify that "jobj" is a valid non-NULL object reference, and points to 716 * an instance of expectedClass. 717 * 718 * Because we're looking at an object on the GC heap, we have to switch 719 * to "running" mode before doing the checks. 720 */ 721 void checkInstance(jobject jobj, ClassObject* expectedClass, const char* argName) { 722 if (jobj == NULL) { 723 LOGW("JNI WARNING: received null %s", argName); 724 showLocation(); 725 abortMaybe(); 726 return; 727 } 728 729 ScopedJniThreadState ts(mEnv); 730 bool printWarn = false; 731 732 Object* obj = dvmDecodeIndirectRef(mEnv, jobj); 733 734 if (!dvmIsValidObject(obj)) { 735 LOGW("JNI WARNING: %s is an invalid %s reference (%p)", 736 argName, indirectRefKindName(jobj), jobj); 737 printWarn = true; 738 } else if (obj->clazz != expectedClass) { 739 LOGW("JNI WARNING: %s arg has wrong type (expected %s, got %s)", 740 argName, expectedClass->descriptor, obj->clazz->descriptor); 741 printWarn = true; 742 } 743 744 if (printWarn) { 745 showLocation(); 746 abortMaybe(); 747 } 748 } 749 750 static u1 checkUtfBytes(const char* bytes, const char** errorKind) { 751 while (*bytes != '\0') { 752 u1 utf8 = *(bytes++); 753 // Switch on the high four bits. 754 switch (utf8 >> 4) { 755 case 0x00: 756 case 0x01: 757 case 0x02: 758 case 0x03: 759 case 0x04: 760 case 0x05: 761 case 0x06: 762 case 0x07: 763 // Bit pattern 0xxx. No need for any extra bytes. 764 break; 765 case 0x08: 766 case 0x09: 767 case 0x0a: 768 case 0x0b: 769 case 0x0f: 770 /* 771 * Bit pattern 10xx or 1111, which are illegal start bytes. 772 * Note: 1111 is valid for normal UTF-8, but not the 773 * modified UTF-8 used here. 774 */ 775 *errorKind = "start"; 776 return utf8; 777 case 0x0e: 778 // Bit pattern 1110, so there are two additional bytes. 779 utf8 = *(bytes++); 780 if ((utf8 & 0xc0) != 0x80) { 781 *errorKind = "continuation"; 782 return utf8; 783 } 784 // Fall through to take care of the final byte. 785 case 0x0c: 786 case 0x0d: 787 // Bit pattern 110x, so there is one additional byte. 788 utf8 = *(bytes++); 789 if ((utf8 & 0xc0) != 0x80) { 790 *errorKind = "continuation"; 791 return utf8; 792 } 793 break; 794 } 795 } 796 return 0; 797 } 798 799 /** 800 * Returns a human-readable name for the given primitive type. 801 */ 802 static const char* primitiveTypeToName(PrimitiveType primType) { 803 switch (primType) { 804 case PRIM_VOID: return "void"; 805 case PRIM_BOOLEAN: return "boolean"; 806 case PRIM_BYTE: return "byte"; 807 case PRIM_SHORT: return "short"; 808 case PRIM_CHAR: return "char"; 809 case PRIM_INT: return "int"; 810 case PRIM_LONG: return "long"; 811 case PRIM_FLOAT: return "float"; 812 case PRIM_DOUBLE: return "double"; 813 case PRIM_NOT: return "Object/array"; 814 default: return "???"; 815 } 816 } 817 818 void showLocation() { 819 // mFunctionName looks like "Check_DeleteLocalRef"; we drop the "Check_". 820 const char* name = mFunctionName + 6; 821 const Method* method = dvmGetCurrentJNIMethod(); 822 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 823 LOGW(" in %s.%s:%s (%s)", method->clazz->descriptor, method->name, desc, name); 824 free(desc); 825 } 826 827 // Disallow copy and assignment. 828 ScopedCheck(const ScopedCheck&); 829 void operator=(const ScopedCheck&); 830}; 831 832/* 833 * =========================================================================== 834 * Guarded arrays 835 * =========================================================================== 836 */ 837 838#define kGuardLen 512 /* must be multiple of 2 */ 839#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */ 840#define kGuardMagic 0xffd5aa96 841 842/* this gets tucked in at the start of the buffer; struct size must be even */ 843struct GuardedCopy { 844 u4 magic; 845 uLong adler; 846 size_t originalLen; 847 const void* originalPtr; 848 849 /* find the GuardedCopy given the pointer into the "live" data */ 850 static inline const GuardedCopy* fromData(const void* dataBuf) { 851 return reinterpret_cast<const GuardedCopy*>(actualBuffer(dataBuf)); 852 } 853 854 /* 855 * Create an over-sized buffer to hold the contents of "buf". Copy it in, 856 * filling in the area around it with guard data. 857 * 858 * We use a 16-bit pattern to make a rogue memset less likely to elude us. 859 */ 860 static void* create(const void* buf, size_t len, bool modOkay) { 861 size_t newLen = actualLength(len); 862 u1* newBuf = debugAlloc(newLen); 863 864 /* fill it in with a pattern */ 865 u2* pat = (u2*) newBuf; 866 for (size_t i = 0; i < newLen / 2; i++) { 867 *pat++ = kGuardPattern; 868 } 869 870 /* copy the data in; note "len" could be zero */ 871 memcpy(newBuf + kGuardLen / 2, buf, len); 872 873 /* if modification is not expected, grab a checksum */ 874 uLong adler = 0; 875 if (!modOkay) { 876 adler = adler32(0L, Z_NULL, 0); 877 adler = adler32(adler, (const Bytef*)buf, len); 878 *(uLong*)newBuf = adler; 879 } 880 881 GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf); 882 pExtra->magic = kGuardMagic; 883 pExtra->adler = adler; 884 pExtra->originalPtr = buf; 885 pExtra->originalLen = len; 886 887 return newBuf + kGuardLen / 2; 888 } 889 890 /* 891 * Free up the guard buffer, scrub it, and return the original pointer. 892 */ 893 static void* destroy(void* dataBuf) { 894 const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf); 895 void* originalPtr = (void*) pExtra->originalPtr; 896 size_t len = pExtra->originalLen; 897 debugFree(dataBuf, len); 898 return originalPtr; 899 } 900 901 /* 902 * Verify the guard area and, if "modOkay" is false, that the data itself 903 * has not been altered. 904 * 905 * The caller has already checked that "dataBuf" is non-NULL. 906 */ 907 static bool check(const void* dataBuf, bool modOkay) { 908 static const u4 kMagicCmp = kGuardMagic; 909 const u1* fullBuf = actualBuffer(dataBuf); 910 const GuardedCopy* pExtra = GuardedCopy::fromData(dataBuf); 911 912 /* 913 * Before we do anything with "pExtra", check the magic number. We 914 * do the check with memcmp rather than "==" in case the pointer is 915 * unaligned. If it points to completely bogus memory we're going 916 * to crash, but there's no easy way around that. 917 */ 918 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) { 919 u1 buf[4]; 920 memcpy(buf, &pExtra->magic, 4); 921 LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?", 922 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */ 923 return false; 924 } 925 926 size_t len = pExtra->originalLen; 927 928 /* check bottom half of guard; skip over optional checksum storage */ 929 const u2* pat = (u2*) fullBuf; 930 for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) { 931 if (pat[i] != kGuardPattern) { 932 LOGE("JNI: guard pattern(1) disturbed at %p + %d", fullBuf, i*2); 933 return false; 934 } 935 } 936 937 int offset = kGuardLen / 2 + len; 938 if (offset & 0x01) { 939 /* odd byte; expected value depends on endian-ness of host */ 940 const u2 patSample = kGuardPattern; 941 if (fullBuf[offset] != ((const u1*) &patSample)[1]) { 942 LOGE("JNI: guard pattern disturbed in odd byte after %p (+%d) 0x%02x 0x%02x", 943 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]); 944 return false; 945 } 946 offset++; 947 } 948 949 /* check top half of guard */ 950 pat = (u2*) (fullBuf + offset); 951 for (size_t i = 0; i < kGuardLen / 4; i++) { 952 if (pat[i] != kGuardPattern) { 953 LOGE("JNI: guard pattern(2) disturbed at %p + %d", fullBuf, offset + i*2); 954 return false; 955 } 956 } 957 958 /* 959 * If modification is not expected, verify checksum. Strictly speaking 960 * this is wrong: if we told the client that we made a copy, there's no 961 * reason they can't alter the buffer. 962 */ 963 if (!modOkay) { 964 uLong adler = adler32(0L, Z_NULL, 0); 965 adler = adler32(adler, (const Bytef*)dataBuf, len); 966 if (pExtra->adler != adler) { 967 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p", 968 pExtra->adler, adler, dataBuf); 969 return false; 970 } 971 } 972 973 return true; 974 } 975 976private: 977 static u1* debugAlloc(size_t len) { 978 void* result = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 979 if (result == MAP_FAILED) { 980 LOGE("GuardedCopy::create mmap(%d) failed: %s", len, strerror(errno)); 981 dvmAbort(); 982 } 983 return reinterpret_cast<u1*>(result); 984 } 985 986 static void debugFree(void* dataBuf, size_t len) { 987 u1* fullBuf = actualBuffer(dataBuf); 988 size_t totalByteCount = actualLength(len); 989 // TODO: we could mprotect instead, and keep the allocation around for a while. 990 // This would be even more expensive, but it might catch more errors. 991 // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) { 992 // LOGW("mprotect(PROT_NONE) failed: %s", strerror(errno)); 993 // } 994 if (munmap(fullBuf, totalByteCount) != 0) { 995 LOGW("munmap failed: %s", strerror(errno)); 996 dvmAbort(); 997 } 998 } 999 1000 static const u1* actualBuffer(const void* dataBuf) { 1001 return reinterpret_cast<const u1*>(dataBuf) - kGuardLen / 2; 1002 } 1003 1004 static u1* actualBuffer(void* dataBuf) { 1005 return reinterpret_cast<u1*>(dataBuf) - kGuardLen / 2; 1006 } 1007 1008 // Underlying length of a user allocation of 'length' bytes. 1009 static size_t actualLength(size_t length) { 1010 return (length + kGuardLen + 1) & ~0x01; 1011 } 1012}; 1013 1014/* 1015 * Return the width, in bytes, of a primitive type. 1016 */ 1017static int dvmPrimitiveTypeWidth(PrimitiveType primType) { 1018 switch (primType) { 1019 case PRIM_BOOLEAN: return 1; 1020 case PRIM_BYTE: return 1; 1021 case PRIM_SHORT: return 2; 1022 case PRIM_CHAR: return 2; 1023 case PRIM_INT: return 4; 1024 case PRIM_LONG: return 8; 1025 case PRIM_FLOAT: return 4; 1026 case PRIM_DOUBLE: return 8; 1027 case PRIM_VOID: 1028 default: { 1029 assert(false); 1030 return -1; 1031 } 1032 } 1033} 1034 1035/* 1036 * Create a guarded copy of a primitive array. Modifications to the copied 1037 * data are allowed. Returns a pointer to the copied data. 1038 */ 1039static void* createGuardedPACopy(JNIEnv* env, const jarray jarr, jboolean* isCopy) { 1040 ScopedJniThreadState ts(env); 1041 1042 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr); 1043 PrimitiveType primType = arrObj->clazz->elementClass->primitiveType; 1044 int len = arrObj->length * dvmPrimitiveTypeWidth(primType); 1045 void* result = GuardedCopy::create(arrObj->contents, len, true); 1046 if (isCopy != NULL) { 1047 *isCopy = JNI_TRUE; 1048 } 1049 return result; 1050} 1051 1052/* 1053 * Perform the array "release" operation, which may or may not copy data 1054 * back into the VM, and may or may not release the underlying storage. 1055 */ 1056static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf, int mode) { 1057 ScopedJniThreadState ts(env); 1058 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr); 1059 1060 if (!GuardedCopy::check(dataBuf, true)) { 1061 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy"); 1062 abortMaybe(); 1063 return NULL; 1064 } 1065 1066 if (mode != JNI_ABORT) { 1067 size_t len = GuardedCopy::fromData(dataBuf)->originalLen; 1068 memcpy(arrObj->contents, dataBuf, len); 1069 } 1070 1071 u1* result = NULL; 1072 if (mode != JNI_COMMIT) { 1073 result = (u1*) GuardedCopy::destroy(dataBuf); 1074 } else { 1075 result = (u1*) (void*) GuardedCopy::fromData(dataBuf)->originalPtr; 1076 } 1077 1078 /* pointer is to the array contents; back up to the array object */ 1079 result -= OFFSETOF_MEMBER(ArrayObject, contents); 1080 return result; 1081} 1082 1083 1084/* 1085 * =========================================================================== 1086 * JNI functions 1087 * =========================================================================== 1088 */ 1089 1090static jint Check_GetVersion(JNIEnv* env) { 1091 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1092 return baseEnv(env)->GetVersion(env); 1093} 1094 1095static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader, 1096 const jbyte* buf, jsize bufLen) 1097{ 1098 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1099 sc.checkObject(loader); 1100 sc.checkUtfString(name, "name"); 1101 sc.checkClassName(name); 1102 return baseEnv(env)->DefineClass(env, name, loader, buf, bufLen); 1103} 1104 1105static jclass Check_FindClass(JNIEnv* env, const char* name) { 1106 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1107 sc.checkUtfString(name, "name"); 1108 sc.checkClassName(name); 1109 return baseEnv(env)->FindClass(env, name); 1110} 1111 1112static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz) { 1113 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1114 sc.checkClass(clazz); 1115 return baseEnv(env)->GetSuperclass(env, clazz); 1116} 1117 1118static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1, jclass clazz2) { 1119 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1120 sc.checkClass(clazz1); 1121 sc.checkClass(clazz2); 1122 return baseEnv(env)->IsAssignableFrom(env, clazz1, clazz2); 1123} 1124 1125static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method) { 1126 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1127 sc.checkObject(method); 1128 return baseEnv(env)->FromReflectedMethod(env, method); 1129} 1130 1131static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field) { 1132 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1133 sc.checkObject(field); 1134 return baseEnv(env)->FromReflectedField(env, field); 1135} 1136 1137static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls, 1138 jmethodID methodID, jboolean isStatic) 1139{ 1140 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1141 sc.checkClass(cls); 1142 return baseEnv(env)->ToReflectedMethod(env, cls, methodID, isStatic); 1143} 1144 1145static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, 1146 jfieldID fieldID, jboolean isStatic) 1147{ 1148 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1149 sc.checkClass(cls); 1150 return baseEnv(env)->ToReflectedField(env, cls, fieldID, isStatic); 1151} 1152 1153static jint Check_Throw(JNIEnv* env, jthrowable obj) { 1154 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1155 sc.checkObject(obj); 1156 /* TODO: verify that "obj" is an instance of Throwable */ 1157 return baseEnv(env)->Throw(env, obj); 1158} 1159 1160static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message) { 1161 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1162 sc.checkClass(clazz); 1163 sc.checkUtfString(message, NULL); 1164 return baseEnv(env)->ThrowNew(env, clazz, message); 1165} 1166 1167static jthrowable Check_ExceptionOccurred(JNIEnv* env) { 1168 ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__); 1169 return baseEnv(env)->ExceptionOccurred(env); 1170} 1171 1172static void Check_ExceptionDescribe(JNIEnv* env) { 1173 ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__); 1174 baseEnv(env)->ExceptionDescribe(env); 1175} 1176 1177static void Check_ExceptionClear(JNIEnv* env) { 1178 ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__); 1179 baseEnv(env)->ExceptionClear(env); 1180} 1181 1182static void Check_FatalError(JNIEnv* env, const char* msg) { 1183 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1184 sc.checkUtfString(msg, NULL); 1185 baseEnv(env)->FatalError(env, msg); 1186} 1187 1188static jint Check_PushLocalFrame(JNIEnv* env, jint capacity) { 1189 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1190 return baseEnv(env)->PushLocalFrame(env, capacity); 1191} 1192 1193static jobject Check_PopLocalFrame(JNIEnv* env, jobject res) { 1194 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1195 sc.checkObject(res); 1196 return baseEnv(env)->PopLocalFrame(env, res); 1197} 1198 1199static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj) { 1200 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1201 sc.checkObject(obj); 1202 return baseEnv(env)->NewGlobalRef(env, obj); 1203} 1204 1205static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef) { 1206 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1207 sc.checkObject(globalRef); 1208 if (globalRef != NULL && dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType) { 1209 LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)", 1210 globalRef, dvmGetJNIRefType(env, globalRef)); 1211 abortMaybe(); 1212 } else { 1213 baseEnv(env)->DeleteGlobalRef(env, globalRef); 1214 } 1215} 1216 1217static jobject Check_NewLocalRef(JNIEnv* env, jobject ref) { 1218 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1219 sc.checkObject(ref); 1220 return baseEnv(env)->NewLocalRef(env, ref); 1221} 1222 1223static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef) { 1224 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1225 sc.checkObject(localRef); 1226 if (localRef != NULL && dvmGetJNIRefType(env, localRef) != JNILocalRefType) { 1227 LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)", 1228 localRef, dvmGetJNIRefType(env, localRef)); 1229 abortMaybe(); 1230 } else { 1231 baseEnv(env)->DeleteLocalRef(env, localRef); 1232 } 1233} 1234 1235static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity) { 1236 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1237 return baseEnv(env)->EnsureLocalCapacity(env, capacity); 1238} 1239 1240static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) { 1241 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1242 sc.checkObject(ref1); 1243 sc.checkObject(ref2); 1244 return baseEnv(env)->IsSameObject(env, ref1, ref2); 1245} 1246 1247static jobject Check_AllocObject(JNIEnv* env, jclass clazz) { 1248 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1249 sc.checkClass(clazz); 1250 return baseEnv(env)->AllocObject(env, clazz); 1251} 1252 1253static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID, ...) { 1254 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1255 sc.checkClass(clazz); 1256 va_list args; 1257 1258 va_start(args, methodID); 1259 jobject result = baseEnv(env)->NewObjectV(env, clazz, methodID, args); 1260 va_end(args); 1261 1262 return result; 1263} 1264 1265static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args) { 1266 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1267 sc.checkClass(clazz); 1268 return baseEnv(env)->NewObjectV(env, clazz, methodID, args); 1269} 1270 1271static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue* args) { 1272 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1273 sc.checkClass(clazz); 1274 return baseEnv(env)->NewObjectA(env, clazz, methodID, args); 1275} 1276 1277static jclass Check_GetObjectClass(JNIEnv* env, jobject obj) { 1278 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1279 sc.checkObject(obj); 1280 return baseEnv(env)->GetObjectClass(env, obj); 1281} 1282 1283static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) { 1284 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1285 sc.checkObject(obj); 1286 sc.checkClass(clazz); 1287 return baseEnv(env)->IsInstanceOf(env, obj, clazz); 1288} 1289 1290static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name, const char* sig) { 1291 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1292 sc.checkClass(clazz); 1293 sc.checkUtfString(name, "name"); 1294 sc.checkUtfString(sig, "sig"); 1295 return baseEnv(env)->GetMethodID(env, clazz, name, sig); 1296} 1297 1298static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz, const char* name, const char* sig) { 1299 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1300 sc.checkClass(clazz); 1301 sc.checkUtfString(name, "name"); 1302 sc.checkUtfString(sig, "sig"); 1303 return baseEnv(env)->GetFieldID(env, clazz, name, sig); 1304} 1305 1306static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz, 1307 const char* name, const char* sig) 1308{ 1309 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1310 sc.checkClass(clazz); 1311 sc.checkUtfString(name, "name"); 1312 sc.checkUtfString(sig, "sig"); 1313 return baseEnv(env)->GetStaticMethodID(env, clazz, name, sig); 1314} 1315 1316static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz, 1317 const char* name, const char* sig) 1318{ 1319 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1320 sc.checkClass(clazz); 1321 sc.checkUtfString(name, "name"); 1322 sc.checkUtfString(sig, "sig"); 1323 return baseEnv(env)->GetStaticFieldID(env, clazz, name, sig); 1324} 1325 1326#define GET_STATIC_TYPE_FIELD(_ctype, _jname) \ 1327 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, jfieldID fieldID) \ 1328 { \ 1329 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1330 sc.checkClass(clazz); \ 1331 sc.checkStaticFieldID(clazz, fieldID); \ 1332 return baseEnv(env)->GetStatic##_jname##Field(env, clazz, fieldID); \ 1333 } 1334GET_STATIC_TYPE_FIELD(jobject, Object); 1335GET_STATIC_TYPE_FIELD(jboolean, Boolean); 1336GET_STATIC_TYPE_FIELD(jbyte, Byte); 1337GET_STATIC_TYPE_FIELD(jchar, Char); 1338GET_STATIC_TYPE_FIELD(jshort, Short); 1339GET_STATIC_TYPE_FIELD(jint, Int); 1340GET_STATIC_TYPE_FIELD(jlong, Long); 1341GET_STATIC_TYPE_FIELD(jfloat, Float); 1342GET_STATIC_TYPE_FIELD(jdouble, Double); 1343 1344#define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \ 1345 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \ 1346 jfieldID fieldID, _ctype value) { \ 1347 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1348 sc.checkClass(clazz); \ 1349 sc.checkStaticFieldID(clazz, fieldID); \ 1350 /* "value" arg only used when type == ref */ \ 1351 sc.checkFieldType((jobject)(u4)value, fieldID, _ftype, true); \ 1352 baseEnv(env)->SetStatic##_jname##Field(env, clazz, fieldID, value); \ 1353 } 1354SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT); 1355SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN); 1356SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE); 1357SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR); 1358SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT); 1359SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT); 1360SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG); 1361SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT); 1362SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE); 1363 1364#define GET_TYPE_FIELD(_ctype, _jname) \ 1365 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fieldID) { \ 1366 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1367 sc.checkObject(obj); \ 1368 sc.checkInstanceFieldID(obj, fieldID); \ 1369 return baseEnv(env)->Get##_jname##Field(env, obj, fieldID); \ 1370 } 1371GET_TYPE_FIELD(jobject, Object); 1372GET_TYPE_FIELD(jboolean, Boolean); 1373GET_TYPE_FIELD(jbyte, Byte); 1374GET_TYPE_FIELD(jchar, Char); 1375GET_TYPE_FIELD(jshort, Short); 1376GET_TYPE_FIELD(jint, Int); 1377GET_TYPE_FIELD(jlong, Long); 1378GET_TYPE_FIELD(jfloat, Float); 1379GET_TYPE_FIELD(jdouble, Double); 1380 1381#define SET_TYPE_FIELD(_ctype, _jname, _ftype) \ 1382 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fieldID, _ctype value) \ 1383 { \ 1384 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1385 sc.checkObject(obj); \ 1386 sc.checkInstanceFieldID(obj, fieldID); \ 1387 /* "value" arg only used when type == ref */ \ 1388 sc.checkFieldType((jobject)(u4) value, fieldID, _ftype, false); \ 1389 baseEnv(env)->Set##_jname##Field(env, obj, fieldID, value); \ 1390 } 1391SET_TYPE_FIELD(jobject, Object, PRIM_NOT); 1392SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN); 1393SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE); 1394SET_TYPE_FIELD(jchar, Char, PRIM_CHAR); 1395SET_TYPE_FIELD(jshort, Short, PRIM_SHORT); 1396SET_TYPE_FIELD(jint, Int, PRIM_INT); 1397SET_TYPE_FIELD(jlong, Long, PRIM_LONG); 1398SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT); 1399SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE); 1400 1401#define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \ 1402 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \ 1403 jmethodID methodID, ...) \ 1404 { \ 1405 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1406 sc.checkObject(obj); \ 1407 sc.checkSig(methodID, _retsig, false); \ 1408 sc.checkVirtualMethod(obj, methodID); \ 1409 _retdecl; \ 1410 va_list args; \ 1411 va_start(args, methodID); \ 1412 _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, methodID, \ 1413 args); \ 1414 va_end(args); \ 1415 return _retok; \ 1416 } \ 1417 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \ 1418 jmethodID methodID, va_list args) \ 1419 { \ 1420 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1421 sc.checkObject(obj); \ 1422 sc.checkSig(methodID, _retsig, false); \ 1423 sc.checkVirtualMethod(obj, methodID); \ 1424 _retdecl; \ 1425 _retasgn baseEnv(env)->Call##_jname##MethodV(env, obj, methodID, \ 1426 args); \ 1427 return _retok; \ 1428 } \ 1429 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \ 1430 jmethodID methodID, jvalue* args) \ 1431 { \ 1432 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1433 sc.checkObject(obj); \ 1434 sc.checkSig(methodID, _retsig, false); \ 1435 sc.checkVirtualMethod(obj, methodID); \ 1436 _retdecl; \ 1437 _retasgn baseEnv(env)->Call##_jname##MethodA(env, obj, methodID, \ 1438 args); \ 1439 return _retok; \ 1440 } 1441CALL_VIRTUAL(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L'); 1442CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z'); 1443CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B'); 1444CALL_VIRTUAL(jchar, Char, jchar result, result=, (jchar) result, 'C'); 1445CALL_VIRTUAL(jshort, Short, jshort result, result=, (jshort) result, 'S'); 1446CALL_VIRTUAL(jint, Int, jint result, result=, (jint) result, 'I'); 1447CALL_VIRTUAL(jlong, Long, jlong result, result=, (jlong) result, 'J'); 1448CALL_VIRTUAL(jfloat, Float, jfloat result, result=, (jfloat) result, 'F'); 1449CALL_VIRTUAL(jdouble, Double, jdouble result, result=, (jdouble) result, 'D'); 1450CALL_VIRTUAL(void, Void, , , , 'V'); 1451 1452#define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \ 1453 _retsig) \ 1454 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \ 1455 jobject obj, jclass clazz, jmethodID methodID, ...) \ 1456 { \ 1457 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1458 sc.checkClass(clazz); \ 1459 sc.checkObject(obj); \ 1460 sc.checkSig(methodID, _retsig, false); \ 1461 sc.checkVirtualMethod(obj, methodID); \ 1462 _retdecl; \ 1463 va_list args; \ 1464 va_start(args, methodID); \ 1465 _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, \ 1466 clazz, methodID, args); \ 1467 va_end(args); \ 1468 return _retok; \ 1469 } \ 1470 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \ 1471 jobject obj, jclass clazz, jmethodID methodID, va_list args) \ 1472 { \ 1473 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1474 sc.checkClass(clazz); \ 1475 sc.checkObject(obj); \ 1476 sc.checkSig(methodID, _retsig, false); \ 1477 sc.checkVirtualMethod(obj, methodID); \ 1478 _retdecl; \ 1479 _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, \ 1480 clazz, methodID, args); \ 1481 return _retok; \ 1482 } \ 1483 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \ 1484 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \ 1485 { \ 1486 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1487 sc.checkClass(clazz); \ 1488 sc.checkObject(obj); \ 1489 sc.checkSig(methodID, _retsig, false); \ 1490 sc.checkVirtualMethod(obj, methodID); \ 1491 _retdecl; \ 1492 _retasgn baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, \ 1493 clazz, methodID, args); \ 1494 return _retok; \ 1495 } 1496CALL_NONVIRTUAL(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L'); 1497CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z'); 1498CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B'); 1499CALL_NONVIRTUAL(jchar, Char, jchar result, result=, (jchar) result, 'C'); 1500CALL_NONVIRTUAL(jshort, Short, jshort result, result=, (jshort) result, 'S'); 1501CALL_NONVIRTUAL(jint, Int, jint result, result=, (jint) result, 'I'); 1502CALL_NONVIRTUAL(jlong, Long, jlong result, result=, (jlong) result, 'J'); 1503CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, (jfloat) result, 'F'); 1504CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, (jdouble) result, 'D'); 1505CALL_NONVIRTUAL(void, Void, , , , 'V'); 1506 1507 1508#define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \ 1509 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \ 1510 jclass clazz, jmethodID methodID, ...) \ 1511 { \ 1512 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1513 sc.checkClass(clazz); \ 1514 sc.checkSig(methodID, _retsig, true); \ 1515 sc.checkStaticMethod(clazz, methodID); \ 1516 _retdecl; \ 1517 va_list args; \ 1518 va_start(args, methodID); \ 1519 _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz, \ 1520 methodID, args); \ 1521 va_end(args); \ 1522 return _retok; \ 1523 } \ 1524 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \ 1525 jclass clazz, jmethodID methodID, va_list args) \ 1526 { \ 1527 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1528 sc.checkClass(clazz); \ 1529 sc.checkSig(methodID, _retsig, true); \ 1530 sc.checkStaticMethod(clazz, methodID); \ 1531 _retdecl; \ 1532 _retasgn baseEnv(env)->CallStatic##_jname##MethodV(env, clazz, \ 1533 methodID, args); \ 1534 return _retok; \ 1535 } \ 1536 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \ 1537 jclass clazz, jmethodID methodID, jvalue* args) \ 1538 { \ 1539 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1540 sc.checkClass(clazz); \ 1541 sc.checkSig(methodID, _retsig, true); \ 1542 sc.checkStaticMethod(clazz, methodID); \ 1543 _retdecl; \ 1544 _retasgn baseEnv(env)->CallStatic##_jname##MethodA(env, clazz, \ 1545 methodID, args); \ 1546 return _retok; \ 1547 } 1548CALL_STATIC(jobject, Object, Object* result, result=(Object*), (jobject) result, 'L'); 1549CALL_STATIC(jboolean, Boolean, jboolean result, result=, (jboolean) result, 'Z'); 1550CALL_STATIC(jbyte, Byte, jbyte result, result=, (jbyte) result, 'B'); 1551CALL_STATIC(jchar, Char, jchar result, result=, (jchar) result, 'C'); 1552CALL_STATIC(jshort, Short, jshort result, result=, (jshort) result, 'S'); 1553CALL_STATIC(jint, Int, jint result, result=, (jint) result, 'I'); 1554CALL_STATIC(jlong, Long, jlong result, result=, (jlong) result, 'J'); 1555CALL_STATIC(jfloat, Float, jfloat result, result=, (jfloat) result, 'F'); 1556CALL_STATIC(jdouble, Double, jdouble result, result=, (jdouble) result, 'D'); 1557CALL_STATIC(void, Void, , , , 'V'); 1558 1559static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) { 1560 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1561 return baseEnv(env)->NewString(env, unicodeChars, len); 1562} 1563 1564static jsize Check_GetStringLength(JNIEnv* env, jstring string) { 1565 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1566 sc.checkString(string); 1567 return baseEnv(env)->GetStringLength(env, string); 1568} 1569 1570static const jchar* Check_GetStringChars(JNIEnv* env, jstring string, jboolean* isCopy) { 1571 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1572 sc.checkString(string); 1573 const jchar* result = baseEnv(env)->GetStringChars(env, string, isCopy); 1574 if (gDvmJni.forceCopy && result != NULL) { 1575 ScopedJniThreadState ts(env); 1576 StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string); 1577 int byteCount = strObj->length() * 2; 1578 result = (const jchar*) GuardedCopy::create(result, byteCount, false); 1579 if (isCopy != NULL) { 1580 *isCopy = JNI_TRUE; 1581 } 1582 } 1583 return result; 1584} 1585 1586static void Check_ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) { 1587 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1588 sc.checkString(string); 1589 sc.checkNonNull(chars); 1590 if (gDvmJni.forceCopy) { 1591 if (!GuardedCopy::check(chars, false)) { 1592 LOGE("JNI: failed guarded copy check in ReleaseStringChars"); 1593 abortMaybe(); 1594 return; 1595 } 1596 chars = (const jchar*) GuardedCopy::destroy((jchar*)chars); 1597 } 1598 baseEnv(env)->ReleaseStringChars(env, string, chars); 1599} 1600 1601static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes) { 1602 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1603 sc.checkUtfString(bytes, NULL); 1604 return baseEnv(env)->NewStringUTF(env, bytes); 1605} 1606 1607static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string) { 1608 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1609 sc.checkString(string); 1610 return baseEnv(env)->GetStringUTFLength(env, string); 1611} 1612 1613static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) { 1614 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1615 sc.checkString(string); 1616 const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy); 1617 if (gDvmJni.forceCopy && result != NULL) { 1618 result = (const char*) GuardedCopy::create(result, strlen(result) + 1, false); 1619 if (isCopy != NULL) { 1620 *isCopy = JNI_TRUE; 1621 } 1622 } 1623 return result; 1624} 1625 1626static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) { 1627 ScopedCheck sc(env, kFlag_ExcepOkay, __FUNCTION__); 1628 sc.checkString(string); 1629 sc.checkNonNull(utf); 1630 if (gDvmJni.forceCopy) { 1631 if (!GuardedCopy::check(utf, false)) { 1632 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars"); 1633 abortMaybe(); 1634 return; 1635 } 1636 utf = (const char*) GuardedCopy::destroy((char*)utf); 1637 } 1638 baseEnv(env)->ReleaseStringUTFChars(env, string, utf); 1639} 1640 1641static jsize Check_GetArrayLength(JNIEnv* env, jarray array) { 1642 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1643 sc.checkArray(array); 1644 return baseEnv(env)->GetArrayLength(env, array); 1645} 1646 1647static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length, 1648 jclass elementClass, jobject initialElement) 1649{ 1650 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1651 sc.checkClass(elementClass); 1652 sc.checkObject(initialElement); 1653 sc.checkLengthPositive(length); 1654 return baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement); 1655} 1656 1657static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) { 1658 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1659 sc.checkArray(array); 1660 return baseEnv(env)->GetObjectArrayElement(env, array, index); 1661} 1662 1663static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) 1664{ 1665 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1666 sc.checkArray(array); 1667 baseEnv(env)->SetObjectArrayElement(env, array, index, value); 1668} 1669 1670#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \ 1671 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) { \ 1672 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1673 sc.checkLengthPositive(length); \ 1674 return baseEnv(env)->New##_jname##Array(env, length); \ 1675 } 1676NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean); 1677NEW_PRIMITIVE_ARRAY(jbyteArray, Byte); 1678NEW_PRIMITIVE_ARRAY(jcharArray, Char); 1679NEW_PRIMITIVE_ARRAY(jshortArray, Short); 1680NEW_PRIMITIVE_ARRAY(jintArray, Int); 1681NEW_PRIMITIVE_ARRAY(jlongArray, Long); 1682NEW_PRIMITIVE_ARRAY(jfloatArray, Float); 1683NEW_PRIMITIVE_ARRAY(jdoubleArray, Double); 1684 1685 1686/* 1687 * Hack to allow forcecopy to work with jniGetNonMovableArrayElements. 1688 * The code deliberately uses an invalid sequence of operations, so we 1689 * need to pass it through unmodified. Review that code before making 1690 * any changes here. 1691 */ 1692#define kNoCopyMagic 0xd5aab57f 1693 1694#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \ 1695 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \ 1696 _ctype##Array array, jboolean* isCopy) \ 1697 { \ 1698 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1699 sc.checkArray(array); \ 1700 u4 noCopy = 0; \ 1701 if (gDvmJni.forceCopy && isCopy != NULL) { \ 1702 /* capture this before the base call tramples on it */ \ 1703 noCopy = *(u4*) isCopy; \ 1704 } \ 1705 _ctype* result = baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy); \ 1706 if (gDvmJni.forceCopy && result != NULL) { \ 1707 if (noCopy == kNoCopyMagic) { \ 1708 LOGV("FC: not copying %p %x", array, noCopy); \ 1709 } else { \ 1710 result = (_ctype*) createGuardedPACopy(env, array, isCopy); \ 1711 } \ 1712 } \ 1713 return result; \ 1714 } 1715 1716#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \ 1717 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \ 1718 _ctype##Array array, _ctype* elems, jint mode) \ 1719 { \ 1720 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); \ 1721 sc.checkArray(array); \ 1722 sc.checkNonNull(elems); \ 1723 sc.checkReleaseMode(mode); \ 1724 if (gDvmJni.forceCopy) { \ 1725 if ((uintptr_t)elems == kNoCopyMagic) { \ 1726 LOGV("FC: not freeing %p", array); \ 1727 elems = NULL; /* base JNI call doesn't currently need */ \ 1728 } else { \ 1729 elems = (_ctype*) releaseGuardedPACopy(env, array, elems, \ 1730 mode); \ 1731 } \ 1732 } \ 1733 baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \ 1734 } 1735 1736#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \ 1737 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \ 1738 _ctype##Array array, jsize start, jsize len, _ctype* buf) { \ 1739 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1740 sc.checkArray(array); \ 1741 baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \ 1742 } 1743 1744#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \ 1745 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \ 1746 _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \ 1747 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); \ 1748 sc.checkArray(array); \ 1749 baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \ 1750 } 1751 1752#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \ 1753 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \ 1754 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \ 1755 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \ 1756 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); 1757 1758/* TODO: verify primitive array type matches call type */ 1759PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z'); 1760PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B'); 1761PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C'); 1762PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S'); 1763PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I'); 1764PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J'); 1765PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F'); 1766PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D'); 1767 1768static jint Check_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, 1769 jint nMethods) 1770{ 1771 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1772 sc.checkClass(clazz); 1773 return baseEnv(env)->RegisterNatives(env, clazz, methods, nMethods); 1774} 1775 1776static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz) { 1777 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1778 sc.checkClass(clazz); 1779 return baseEnv(env)->UnregisterNatives(env, clazz); 1780} 1781 1782static jint Check_MonitorEnter(JNIEnv* env, jobject obj) { 1783 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1784 sc.checkObject(obj); 1785 return baseEnv(env)->MonitorEnter(env, obj); 1786} 1787 1788static jint Check_MonitorExit(JNIEnv* env, jobject obj) { 1789 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1790 sc.checkObject(obj); 1791 return baseEnv(env)->MonitorExit(env, obj); 1792} 1793 1794static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm) { 1795 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1796 return baseEnv(env)->GetJavaVM(env, vm); 1797} 1798 1799static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) { 1800 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1801 sc.checkString(str); 1802 baseEnv(env)->GetStringRegion(env, str, start, len, buf); 1803} 1804 1805static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) { 1806 ScopedCheck sc(env, kFlag_CritOkay, __FUNCTION__); 1807 sc.checkString(str); 1808 baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf); 1809} 1810 1811static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) { 1812 ScopedCheck sc(env, kFlag_CritGet, __FUNCTION__); 1813 sc.checkArray(array); 1814 void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy); 1815 if (gDvmJni.forceCopy && result != NULL) { 1816 result = createGuardedPACopy(env, array, isCopy); 1817 } 1818 return result; 1819} 1820 1821static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) 1822{ 1823 ScopedCheck sc(env, kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__); 1824 sc.checkArray(array); 1825 sc.checkNonNull(carray); 1826 sc.checkReleaseMode(mode); 1827 if (gDvmJni.forceCopy) { 1828 carray = releaseGuardedPACopy(env, array, carray, mode); 1829 } 1830 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode); 1831} 1832 1833static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string, jboolean* isCopy) { 1834 ScopedCheck sc(env, kFlag_CritGet, __FUNCTION__); 1835 sc.checkString(string); 1836 const jchar* result = baseEnv(env)->GetStringCritical(env, string, isCopy); 1837 if (gDvmJni.forceCopy && result != NULL) { 1838 ScopedJniThreadState ts(env); 1839 StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, string); 1840 int byteCount = strObj->length() * 2; 1841 result = (const jchar*) GuardedCopy::create(result, byteCount, false); 1842 if (isCopy != NULL) { 1843 *isCopy = JNI_TRUE; 1844 } 1845 } 1846 return result; 1847} 1848 1849static void Check_ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) { 1850 ScopedCheck sc(env, kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__); 1851 sc.checkString(string); 1852 sc.checkNonNull(carray); 1853 if (gDvmJni.forceCopy) { 1854 if (!GuardedCopy::check(carray, false)) { 1855 LOGE("JNI: failed guarded copy check in ReleaseStringCritical"); 1856 abortMaybe(); 1857 return; 1858 } 1859 carray = (const jchar*) GuardedCopy::destroy((jchar*)carray); 1860 } 1861 baseEnv(env)->ReleaseStringCritical(env, string, carray); 1862} 1863 1864static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj) { 1865 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1866 sc.checkObject(obj); 1867 return baseEnv(env)->NewWeakGlobalRef(env, obj); 1868} 1869 1870static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj) { 1871 ScopedCheck sc(env, kFlag_Default | kFlag_ExcepOkay, __FUNCTION__); 1872 sc.checkObject(obj); 1873 baseEnv(env)->DeleteWeakGlobalRef(env, obj); 1874} 1875 1876static jboolean Check_ExceptionCheck(JNIEnv* env) { 1877 ScopedCheck sc(env, kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__); 1878 return baseEnv(env)->ExceptionCheck(env); 1879} 1880 1881static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj) { 1882 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1883 sc.checkObject(obj); 1884 return baseEnv(env)->GetObjectRefType(env, obj); 1885} 1886 1887static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) { 1888 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1889 if (address == NULL || capacity < 0) { 1890 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)", 1891 address, (long) capacity); 1892 abortMaybe(); 1893 return NULL; 1894 } 1895 return baseEnv(env)->NewDirectByteBuffer(env, address, capacity); 1896} 1897 1898static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf) { 1899 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1900 sc.checkObject(buf); 1901 return baseEnv(env)->GetDirectBufferAddress(env, buf); 1902} 1903 1904static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf) { 1905 ScopedCheck sc(env, kFlag_Default, __FUNCTION__); 1906 sc.checkObject(buf); 1907 /* TODO: verify "buf" is an instance of java.nio.Buffer */ 1908 return baseEnv(env)->GetDirectBufferCapacity(env, buf); 1909} 1910 1911 1912/* 1913 * =========================================================================== 1914 * JNI invocation functions 1915 * =========================================================================== 1916 */ 1917 1918static jint Check_DestroyJavaVM(JavaVM* vm) { 1919 ScopedVmCheck svc(false, __FUNCTION__); 1920 return baseVm(vm)->DestroyJavaVM(vm); 1921} 1922 1923static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 1924 ScopedVmCheck svc(false, __FUNCTION__); 1925 return baseVm(vm)->AttachCurrentThread(vm, p_env, thr_args); 1926} 1927 1928static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 1929 ScopedVmCheck svc(false, __FUNCTION__); 1930 return baseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args); 1931} 1932 1933static jint Check_DetachCurrentThread(JavaVM* vm) { 1934 ScopedVmCheck svc(true, __FUNCTION__); 1935 return baseVm(vm)->DetachCurrentThread(vm); 1936} 1937 1938static jint Check_GetEnv(JavaVM* vm, void** env, jint version) { 1939 ScopedVmCheck svc(true, __FUNCTION__); 1940 return baseVm(vm)->GetEnv(vm, env, version); 1941} 1942 1943 1944/* 1945 * =========================================================================== 1946 * Function tables 1947 * =========================================================================== 1948 */ 1949 1950static const struct JNINativeInterface gCheckNativeInterface = { 1951 NULL, 1952 NULL, 1953 NULL, 1954 NULL, 1955 1956 Check_GetVersion, 1957 1958 Check_DefineClass, 1959 Check_FindClass, 1960 1961 Check_FromReflectedMethod, 1962 Check_FromReflectedField, 1963 Check_ToReflectedMethod, 1964 1965 Check_GetSuperclass, 1966 Check_IsAssignableFrom, 1967 1968 Check_ToReflectedField, 1969 1970 Check_Throw, 1971 Check_ThrowNew, 1972 Check_ExceptionOccurred, 1973 Check_ExceptionDescribe, 1974 Check_ExceptionClear, 1975 Check_FatalError, 1976 1977 Check_PushLocalFrame, 1978 Check_PopLocalFrame, 1979 1980 Check_NewGlobalRef, 1981 Check_DeleteGlobalRef, 1982 Check_DeleteLocalRef, 1983 Check_IsSameObject, 1984 Check_NewLocalRef, 1985 Check_EnsureLocalCapacity, 1986 1987 Check_AllocObject, 1988 Check_NewObject, 1989 Check_NewObjectV, 1990 Check_NewObjectA, 1991 1992 Check_GetObjectClass, 1993 Check_IsInstanceOf, 1994 1995 Check_GetMethodID, 1996 1997 Check_CallObjectMethod, 1998 Check_CallObjectMethodV, 1999 Check_CallObjectMethodA, 2000 Check_CallBooleanMethod, 2001 Check_CallBooleanMethodV, 2002 Check_CallBooleanMethodA, 2003 Check_CallByteMethod, 2004 Check_CallByteMethodV, 2005 Check_CallByteMethodA, 2006 Check_CallCharMethod, 2007 Check_CallCharMethodV, 2008 Check_CallCharMethodA, 2009 Check_CallShortMethod, 2010 Check_CallShortMethodV, 2011 Check_CallShortMethodA, 2012 Check_CallIntMethod, 2013 Check_CallIntMethodV, 2014 Check_CallIntMethodA, 2015 Check_CallLongMethod, 2016 Check_CallLongMethodV, 2017 Check_CallLongMethodA, 2018 Check_CallFloatMethod, 2019 Check_CallFloatMethodV, 2020 Check_CallFloatMethodA, 2021 Check_CallDoubleMethod, 2022 Check_CallDoubleMethodV, 2023 Check_CallDoubleMethodA, 2024 Check_CallVoidMethod, 2025 Check_CallVoidMethodV, 2026 Check_CallVoidMethodA, 2027 2028 Check_CallNonvirtualObjectMethod, 2029 Check_CallNonvirtualObjectMethodV, 2030 Check_CallNonvirtualObjectMethodA, 2031 Check_CallNonvirtualBooleanMethod, 2032 Check_CallNonvirtualBooleanMethodV, 2033 Check_CallNonvirtualBooleanMethodA, 2034 Check_CallNonvirtualByteMethod, 2035 Check_CallNonvirtualByteMethodV, 2036 Check_CallNonvirtualByteMethodA, 2037 Check_CallNonvirtualCharMethod, 2038 Check_CallNonvirtualCharMethodV, 2039 Check_CallNonvirtualCharMethodA, 2040 Check_CallNonvirtualShortMethod, 2041 Check_CallNonvirtualShortMethodV, 2042 Check_CallNonvirtualShortMethodA, 2043 Check_CallNonvirtualIntMethod, 2044 Check_CallNonvirtualIntMethodV, 2045 Check_CallNonvirtualIntMethodA, 2046 Check_CallNonvirtualLongMethod, 2047 Check_CallNonvirtualLongMethodV, 2048 Check_CallNonvirtualLongMethodA, 2049 Check_CallNonvirtualFloatMethod, 2050 Check_CallNonvirtualFloatMethodV, 2051 Check_CallNonvirtualFloatMethodA, 2052 Check_CallNonvirtualDoubleMethod, 2053 Check_CallNonvirtualDoubleMethodV, 2054 Check_CallNonvirtualDoubleMethodA, 2055 Check_CallNonvirtualVoidMethod, 2056 Check_CallNonvirtualVoidMethodV, 2057 Check_CallNonvirtualVoidMethodA, 2058 2059 Check_GetFieldID, 2060 2061 Check_GetObjectField, 2062 Check_GetBooleanField, 2063 Check_GetByteField, 2064 Check_GetCharField, 2065 Check_GetShortField, 2066 Check_GetIntField, 2067 Check_GetLongField, 2068 Check_GetFloatField, 2069 Check_GetDoubleField, 2070 Check_SetObjectField, 2071 Check_SetBooleanField, 2072 Check_SetByteField, 2073 Check_SetCharField, 2074 Check_SetShortField, 2075 Check_SetIntField, 2076 Check_SetLongField, 2077 Check_SetFloatField, 2078 Check_SetDoubleField, 2079 2080 Check_GetStaticMethodID, 2081 2082 Check_CallStaticObjectMethod, 2083 Check_CallStaticObjectMethodV, 2084 Check_CallStaticObjectMethodA, 2085 Check_CallStaticBooleanMethod, 2086 Check_CallStaticBooleanMethodV, 2087 Check_CallStaticBooleanMethodA, 2088 Check_CallStaticByteMethod, 2089 Check_CallStaticByteMethodV, 2090 Check_CallStaticByteMethodA, 2091 Check_CallStaticCharMethod, 2092 Check_CallStaticCharMethodV, 2093 Check_CallStaticCharMethodA, 2094 Check_CallStaticShortMethod, 2095 Check_CallStaticShortMethodV, 2096 Check_CallStaticShortMethodA, 2097 Check_CallStaticIntMethod, 2098 Check_CallStaticIntMethodV, 2099 Check_CallStaticIntMethodA, 2100 Check_CallStaticLongMethod, 2101 Check_CallStaticLongMethodV, 2102 Check_CallStaticLongMethodA, 2103 Check_CallStaticFloatMethod, 2104 Check_CallStaticFloatMethodV, 2105 Check_CallStaticFloatMethodA, 2106 Check_CallStaticDoubleMethod, 2107 Check_CallStaticDoubleMethodV, 2108 Check_CallStaticDoubleMethodA, 2109 Check_CallStaticVoidMethod, 2110 Check_CallStaticVoidMethodV, 2111 Check_CallStaticVoidMethodA, 2112 2113 Check_GetStaticFieldID, 2114 2115 Check_GetStaticObjectField, 2116 Check_GetStaticBooleanField, 2117 Check_GetStaticByteField, 2118 Check_GetStaticCharField, 2119 Check_GetStaticShortField, 2120 Check_GetStaticIntField, 2121 Check_GetStaticLongField, 2122 Check_GetStaticFloatField, 2123 Check_GetStaticDoubleField, 2124 2125 Check_SetStaticObjectField, 2126 Check_SetStaticBooleanField, 2127 Check_SetStaticByteField, 2128 Check_SetStaticCharField, 2129 Check_SetStaticShortField, 2130 Check_SetStaticIntField, 2131 Check_SetStaticLongField, 2132 Check_SetStaticFloatField, 2133 Check_SetStaticDoubleField, 2134 2135 Check_NewString, 2136 2137 Check_GetStringLength, 2138 Check_GetStringChars, 2139 Check_ReleaseStringChars, 2140 2141 Check_NewStringUTF, 2142 Check_GetStringUTFLength, 2143 Check_GetStringUTFChars, 2144 Check_ReleaseStringUTFChars, 2145 2146 Check_GetArrayLength, 2147 Check_NewObjectArray, 2148 Check_GetObjectArrayElement, 2149 Check_SetObjectArrayElement, 2150 2151 Check_NewBooleanArray, 2152 Check_NewByteArray, 2153 Check_NewCharArray, 2154 Check_NewShortArray, 2155 Check_NewIntArray, 2156 Check_NewLongArray, 2157 Check_NewFloatArray, 2158 Check_NewDoubleArray, 2159 2160 Check_GetBooleanArrayElements, 2161 Check_GetByteArrayElements, 2162 Check_GetCharArrayElements, 2163 Check_GetShortArrayElements, 2164 Check_GetIntArrayElements, 2165 Check_GetLongArrayElements, 2166 Check_GetFloatArrayElements, 2167 Check_GetDoubleArrayElements, 2168 2169 Check_ReleaseBooleanArrayElements, 2170 Check_ReleaseByteArrayElements, 2171 Check_ReleaseCharArrayElements, 2172 Check_ReleaseShortArrayElements, 2173 Check_ReleaseIntArrayElements, 2174 Check_ReleaseLongArrayElements, 2175 Check_ReleaseFloatArrayElements, 2176 Check_ReleaseDoubleArrayElements, 2177 2178 Check_GetBooleanArrayRegion, 2179 Check_GetByteArrayRegion, 2180 Check_GetCharArrayRegion, 2181 Check_GetShortArrayRegion, 2182 Check_GetIntArrayRegion, 2183 Check_GetLongArrayRegion, 2184 Check_GetFloatArrayRegion, 2185 Check_GetDoubleArrayRegion, 2186 Check_SetBooleanArrayRegion, 2187 Check_SetByteArrayRegion, 2188 Check_SetCharArrayRegion, 2189 Check_SetShortArrayRegion, 2190 Check_SetIntArrayRegion, 2191 Check_SetLongArrayRegion, 2192 Check_SetFloatArrayRegion, 2193 Check_SetDoubleArrayRegion, 2194 2195 Check_RegisterNatives, 2196 Check_UnregisterNatives, 2197 2198 Check_MonitorEnter, 2199 Check_MonitorExit, 2200 2201 Check_GetJavaVM, 2202 2203 Check_GetStringRegion, 2204 Check_GetStringUTFRegion, 2205 2206 Check_GetPrimitiveArrayCritical, 2207 Check_ReleasePrimitiveArrayCritical, 2208 2209 Check_GetStringCritical, 2210 Check_ReleaseStringCritical, 2211 2212 Check_NewWeakGlobalRef, 2213 Check_DeleteWeakGlobalRef, 2214 2215 Check_ExceptionCheck, 2216 2217 Check_NewDirectByteBuffer, 2218 Check_GetDirectBufferAddress, 2219 Check_GetDirectBufferCapacity, 2220 2221 Check_GetObjectRefType 2222}; 2223 2224static const struct JNIInvokeInterface gCheckInvokeInterface = { 2225 NULL, 2226 NULL, 2227 NULL, 2228 2229 Check_DestroyJavaVM, 2230 Check_AttachCurrentThread, 2231 Check_DetachCurrentThread, 2232 2233 Check_GetEnv, 2234 2235 Check_AttachCurrentThreadAsDaemon, 2236}; 2237 2238/* 2239 * Replace the normal table with the checked table. 2240 */ 2241void dvmUseCheckedJniEnv(JNIEnvExt* pEnv) { 2242 assert(pEnv->funcTable != &gCheckNativeInterface); 2243 pEnv->baseFuncTable = pEnv->funcTable; 2244 pEnv->funcTable = &gCheckNativeInterface; 2245} 2246 2247/* 2248 * Replace the normal table with the checked table. 2249 */ 2250void dvmUseCheckedJniVm(JavaVMExt* pVm) { 2251 assert(pVm->funcTable != &gCheckInvokeInterface); 2252 pVm->baseFuncTable = pVm->funcTable; 2253 pVm->funcTable = &gCheckInvokeInterface; 2254} 2255