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 #include "check_jni.h" 18 19 #include <iomanip> 20 #include <sys/mman.h> 21 #include <zlib.h> 22 23 #include "android-base/stringprintf.h" 24 25 #include "art_field-inl.h" 26 #include "art_method-inl.h" 27 #include "base/logging.h" 28 #include "base/to_str.h" 29 #include "class_linker.h" 30 #include "class_linker-inl.h" 31 #include "dex_file-inl.h" 32 #include "gc/space/space.h" 33 #include "java_vm_ext.h" 34 #include "jni_internal.h" 35 #include "mirror/class-inl.h" 36 #include "mirror/object-inl.h" 37 #include "mirror/object_array-inl.h" 38 #include "mirror/string-inl.h" 39 #include "mirror/throwable.h" 40 #include "runtime.h" 41 #include "scoped_thread_state_change-inl.h" 42 #include "thread.h" 43 #include "well_known_classes.h" 44 45 namespace art { 46 47 using android::base::StringAppendF; 48 using android::base::StringPrintf; 49 50 /* 51 * =========================================================================== 52 * JNI function helpers 53 * =========================================================================== 54 */ 55 56 // Flags passed into ScopedCheck. 57 #define kFlag_Default 0x0000 58 59 #define kFlag_CritBad 0x0000 // Calling while in critical is not allowed. 60 #define kFlag_CritOkay 0x0001 // Calling while in critical is allowed. 61 #define kFlag_CritGet 0x0002 // This is a critical "get". 62 #define kFlag_CritRelease 0x0003 // This is a critical "release". 63 #define kFlag_CritMask 0x0003 // Bit mask to get "crit" value. 64 65 #define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed. 66 #define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed. 67 68 #define kFlag_Release 0x0010 // Are we in a non-critical release function? 69 #define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable? 70 71 #define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*). 72 73 #define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call. 74 75 class VarArgs; 76 /* 77 * Java primitive types: 78 * B - jbyte 79 * C - jchar 80 * D - jdouble 81 * F - jfloat 82 * I - jint 83 * J - jlong 84 * S - jshort 85 * Z - jboolean (shown as true and false) 86 * V - void 87 * 88 * Java reference types: 89 * L - jobject 90 * a - jarray 91 * c - jclass 92 * s - jstring 93 * t - jthrowable 94 * 95 * JNI types: 96 * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 97 * f - jfieldID 98 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION) 99 * m - jmethodID 100 * p - void* 101 * r - jint (for release mode arguments) 102 * u - const char* (Modified UTF-8) 103 * z - jsize (for lengths; use i if negative values are okay) 104 * v - JavaVM* 105 * w - jobjectRefType 106 * E - JNIEnv* 107 * . - no argument; just print "..." (used for varargs JNI calls) 108 * 109 */ 110 union JniValueType { 111 jarray a; 112 jboolean b; 113 jclass c; 114 jfieldID f; 115 jint i; 116 jmethodID m; 117 const void* p; // Pointer. 118 jint r; // Release mode. 119 jstring s; 120 jthrowable t; 121 const char* u; // Modified UTF-8. 122 JavaVM* v; 123 jobjectRefType w; 124 jsize z; 125 jbyte B; 126 jchar C; 127 jdouble D; 128 JNIEnv* E; 129 jfloat F; 130 jint I; 131 jlong J; 132 jobject L; 133 jshort S; 134 const void* V; // void 135 jboolean Z; 136 const VarArgs* va; 137 }; 138 139 /* 140 * A structure containing all the information needed to validate varargs arguments. 141 * 142 * Note that actually getting the arguments from this structure mutates it so should only be done on 143 * owned copies. 144 */ 145 class VarArgs { 146 public: 147 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) { 148 va_copy(vargs_, var); 149 } 150 151 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {} 152 153 ~VarArgs() { 154 if (type_ == kTypeVaList) { 155 va_end(vargs_); 156 } 157 } 158 159 VarArgs(VarArgs&& other) { 160 m_ = other.m_; 161 cnt_ = other.cnt_; 162 type_ = other.type_; 163 if (other.type_ == kTypeVaList) { 164 va_copy(vargs_, other.vargs_); 165 } else { 166 ptr_ = other.ptr_; 167 } 168 } 169 170 // This method is const because we need to ensure that one only uses the GetValue method on an 171 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a 172 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when 173 // we want to use one we need to Clone() it. 174 VarArgs Clone() const { 175 if (type_ == kTypeVaList) { 176 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is 177 // messed up if the source argument is not the exact type 'va_list'. 178 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_); 179 } else { 180 return VarArgs(m_, cnt_, ptr_); 181 } 182 } 183 184 jmethodID GetMethodID() const { 185 return m_; 186 } 187 188 JniValueType GetValue(char fmt) { 189 JniValueType o; 190 if (type_ == kTypeVaList) { 191 switch (fmt) { 192 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break; 193 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break; 194 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break; 195 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break; 196 case 'I': o.I = va_arg(vargs_, jint); break; 197 case 'J': o.J = va_arg(vargs_, jlong); break; 198 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break; 199 case 'D': o.D = va_arg(vargs_, jdouble); break; 200 case 'L': o.L = va_arg(vargs_, jobject); break; 201 default: 202 LOG(FATAL) << "Illegal type format char " << fmt; 203 UNREACHABLE(); 204 } 205 } else { 206 CHECK(type_ == kTypePtr); 207 jvalue v = ptr_[cnt_]; 208 cnt_++; 209 switch (fmt) { 210 case 'Z': o.Z = v.z; break; 211 case 'B': o.B = v.b; break; 212 case 'C': o.C = v.c; break; 213 case 'S': o.S = v.s; break; 214 case 'I': o.I = v.i; break; 215 case 'J': o.J = v.j; break; 216 case 'F': o.F = v.f; break; 217 case 'D': o.D = v.d; break; 218 case 'L': o.L = v.l; break; 219 default: 220 LOG(FATAL) << "Illegal type format char " << fmt; 221 UNREACHABLE(); 222 } 223 } 224 return o; 225 } 226 227 private: 228 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) { 229 va_copy(vargs_, var); 230 } 231 232 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {} 233 234 enum VarArgsType { 235 kTypeVaList, 236 kTypePtr, 237 }; 238 239 jmethodID m_; 240 VarArgsType type_; 241 uint32_t cnt_; 242 union { 243 va_list vargs_; 244 const jvalue* ptr_; 245 }; 246 }; 247 248 class ScopedCheck { 249 public: 250 ScopedCheck(int flags, const char* functionName, bool has_method = true) 251 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) { 252 } 253 254 ~ScopedCheck() {} 255 256 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread" 257 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of 258 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some 259 // circumstances, but this is incorrect. 260 bool CheckClassName(const char* class_name) { 261 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) { 262 AbortF("illegal class name '%s'\n" 263 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')", 264 class_name); 265 return false; 266 } 267 return true; 268 } 269 270 /* 271 * Verify that this instance field ID is valid for this object. 272 * 273 * Assumes "jobj" has already been validated. 274 */ 275 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid) 276 REQUIRES_SHARED(Locks::mutator_lock_) { 277 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object); 278 if (o == nullptr) { 279 AbortF("field operation on NULL object: %p", java_object); 280 return false; 281 } 282 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) { 283 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 284 AbortF("field operation on invalid %s: %p", 285 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)), 286 java_object); 287 return false; 288 } 289 290 ArtField* f = CheckFieldID(fid); 291 if (f == nullptr) { 292 return false; 293 } 294 mirror::Class* c = o->GetClass(); 295 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) { 296 AbortF("jfieldID %s not valid for an object of class %s", 297 f->PrettyField().c_str(), o->PrettyTypeOf().c_str()); 298 return false; 299 } 300 return true; 301 } 302 303 /* 304 * Verify that the pointer value is non-null. 305 */ 306 bool CheckNonNull(const void* ptr) { 307 if (UNLIKELY(ptr == nullptr)) { 308 AbortF("non-nullable argument was NULL"); 309 return false; 310 } 311 return true; 312 } 313 314 /* 315 * Verify that the method's return type matches the type of call. 316 * 'expectedType' will be "L" for all objects, including arrays. 317 */ 318 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc, 319 jmethodID mid, Primitive::Type type, InvokeType invoke) 320 REQUIRES_SHARED(Locks::mutator_lock_) { 321 ArtMethod* m = CheckMethodID(mid); 322 if (m == nullptr) { 323 return false; 324 } 325 if (type != Primitive::GetType(m->GetShorty()[0])) { 326 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str()); 327 return false; 328 } 329 bool is_static = (invoke == kStatic); 330 if (is_static != m->IsStatic()) { 331 if (is_static) { 332 AbortF("calling non-static method %s with %s", 333 m->PrettyMethod().c_str(), function_name_); 334 } else { 335 AbortF("calling static method %s with %s", 336 m->PrettyMethod().c_str(), function_name_); 337 } 338 return false; 339 } 340 if (invoke != kVirtual) { 341 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 342 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 343 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual", 344 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str()); 345 return false; 346 } 347 } 348 if (invoke != kStatic) { 349 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj); 350 if (o == nullptr) { 351 AbortF("can't call %s on null object", m->PrettyMethod().c_str()); 352 return false; 353 } else if (!o->InstanceOf(m->GetDeclaringClass())) { 354 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(), 355 o->PrettyTypeOf().c_str()); 356 return false; 357 } 358 } 359 return true; 360 } 361 362 /* 363 * Verify that this static field ID is valid for this class. 364 * 365 * Assumes "java_class" has already been validated. 366 */ 367 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid) 368 REQUIRES_SHARED(Locks::mutator_lock_) { 369 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class); 370 ArtField* f = CheckFieldID(fid); 371 if (f == nullptr) { 372 return false; 373 } 374 if (c != f->GetDeclaringClass()) { 375 AbortF("static jfieldID %p not valid for class %s", fid, 376 mirror::Class::PrettyClass(c).c_str()); 377 return false; 378 } 379 return true; 380 } 381 382 /* 383 * Verify that "mid" is appropriate for "java_class". 384 * 385 * A mismatch isn't dangerous, because the jmethodID defines the class. In 386 * fact, java_class is unused in the implementation. It's best if we don't 387 * allow bad code in the system though. 388 * 389 * Instances of "java_class" must be instances of the method's declaring class. 390 */ 391 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid) 392 REQUIRES_SHARED(Locks::mutator_lock_) { 393 ArtMethod* m = CheckMethodID(mid); 394 if (m == nullptr) { 395 return false; 396 } 397 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class); 398 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 399 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(), 400 mirror::Class::PrettyClass(c).c_str()); 401 return false; 402 } 403 return true; 404 } 405 406 /* 407 * Verify that "mid" is appropriate for "jobj". 408 * 409 * Make sure the object is an instance of the method's declaring class. 410 * (Note the mid might point to a declaration in an interface; this 411 * will be handled automatically by the instanceof check.) 412 */ 413 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid) 414 REQUIRES_SHARED(Locks::mutator_lock_) { 415 ArtMethod* m = CheckMethodID(mid); 416 if (m == nullptr) { 417 return false; 418 } 419 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object); 420 if (o == nullptr) { 421 AbortF("can't call %s on null object", m->PrettyMethod().c_str()); 422 return false; 423 } else if (!o->InstanceOf(m->GetDeclaringClass())) { 424 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(), 425 o->PrettyTypeOf().c_str()); 426 return false; 427 } 428 return true; 429 } 430 431 /** 432 * The format string is a sequence of the following characters, 433 * and must be followed by arguments of the corresponding types 434 * in the same order. 435 * 436 * Java primitive types: 437 * B - jbyte 438 * C - jchar 439 * D - jdouble 440 * F - jfloat 441 * I - jint 442 * J - jlong 443 * S - jshort 444 * Z - jboolean (shown as true and false) 445 * V - void 446 * 447 * Java reference types: 448 * L - jobject 449 * a - jarray 450 * c - jclass 451 * s - jstring 452 * 453 * JNI types: 454 * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 455 * f - jfieldID 456 * m - jmethodID 457 * p - void* 458 * r - jint (for release mode arguments) 459 * u - const char* (Modified UTF-8) 460 * z - jsize (for lengths; use i if negative values are okay) 461 * v - JavaVM* 462 * E - JNIEnv* 463 * . - VarArgs* for Jni calls with variable length arguments 464 * 465 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable. 466 */ 467 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args) 468 REQUIRES_SHARED(Locks::mutator_lock_) { 469 ArtMethod* traceMethod = nullptr; 470 if (has_method_ && soa.Vm()->IsTracingEnabled()) { 471 // We need to guard some of the invocation interface's calls: a bad caller might 472 // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 473 Thread* self = Thread::Current(); 474 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 475 traceMethod = self->GetCurrentMethod(nullptr); 476 } 477 } 478 479 if (((flags_ & kFlag_ForceTrace) != 0) || 480 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) { 481 std::string msg; 482 for (size_t i = 0; fmt[i] != '\0'; ++i) { 483 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg); 484 if (fmt[i + 1] != '\0') { 485 StringAppendF(&msg, ", "); 486 } 487 } 488 489 if ((flags_ & kFlag_ForceTrace) != 0) { 490 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 491 } else if (entry) { 492 if (has_method_) { 493 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false)); 494 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 495 indent_ = methodName.size() + 1; 496 } else { 497 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 498 indent_ = 0; 499 } 500 } else { 501 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 502 } 503 } 504 505 // We always do the thorough checks on entry, and never on exit... 506 if (entry) { 507 for (size_t i = 0; fmt[i] != '\0'; ++i) { 508 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) { 509 return false; 510 } 511 } 512 } 513 return true; 514 } 515 516 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) { 517 bool should_trace = (flags_ & kFlag_ForceTrace) != 0; 518 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) { 519 // We need to guard some of the invocation interface's calls: a bad caller might 520 // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 521 Thread* self = Thread::Current(); 522 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 523 ScopedObjectAccess soa(self); 524 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr); 525 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod)); 526 } 527 } 528 if (should_trace) { 529 std::string msg; 530 for (size_t i = 0; fmt[i] != '\0'; ++i) { 531 TraceNonHeapValue(fmt[i], args[i], &msg); 532 if (fmt[i + 1] != '\0') { 533 StringAppendF(&msg, ", "); 534 } 535 } 536 537 if ((flags_ & kFlag_ForceTrace) != 0) { 538 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 539 } else if (entry) { 540 if (has_method_) { 541 Thread* self = Thread::Current(); 542 ScopedObjectAccess soa(self); 543 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr); 544 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false)); 545 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 546 indent_ = methodName.size() + 1; 547 } else { 548 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 549 indent_ = 0; 550 } 551 } else { 552 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 553 } 554 } 555 556 // We always do the thorough checks on entry, and never on exit... 557 if (entry) { 558 for (size_t i = 0; fmt[i] != '\0'; ++i) { 559 if (!CheckNonHeapValue(fmt[i], args[i])) { 560 return false; 561 } 562 } 563 } 564 return true; 565 } 566 567 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod) 568 REQUIRES_SHARED(Locks::mutator_lock_) { 569 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod); 570 if (method == nullptr) { 571 AbortF("expected non-null method"); 572 return false; 573 } 574 mirror::Class* c = method->GetClass(); 575 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c && 576 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) { 577 AbortF("expected java.lang.reflect.Method or " 578 "java.lang.reflect.Constructor but got object of type %s: %p", 579 method->PrettyTypeOf().c_str(), jmethod); 580 return false; 581 } 582 return true; 583 } 584 585 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) { 586 ArtMethod* method = jni::DecodeArtMethod(mid); 587 if (method == nullptr) { 588 AbortF("expected non-null constructor"); 589 return false; 590 } 591 if (!method->IsConstructor() || method->IsStatic()) { 592 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid); 593 return false; 594 } 595 return true; 596 } 597 598 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield) 599 REQUIRES_SHARED(Locks::mutator_lock_) { 600 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield); 601 if (field == nullptr) { 602 AbortF("expected non-null java.lang.reflect.Field"); 603 return false; 604 } 605 mirror::Class* c = field->GetClass(); 606 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) { 607 AbortF("expected java.lang.reflect.Field but got object of type %s: %p", 608 field->PrettyTypeOf().c_str(), jfield); 609 return false; 610 } 611 return true; 612 } 613 614 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj) 615 REQUIRES_SHARED(Locks::mutator_lock_) { 616 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj); 617 if (!obj->GetClass()->IsThrowableClass()) { 618 AbortF("expected java.lang.Throwable but got object of type " 619 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr()); 620 return false; 621 } 622 return true; 623 } 624 625 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc) 626 REQUIRES_SHARED(Locks::mutator_lock_) { 627 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 628 if (!c->IsThrowableClass()) { 629 AbortF("expected java.lang.Throwable class but got object of " 630 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr()); 631 return false; 632 } 633 return true; 634 } 635 636 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) { 637 IndirectRefKind found_kind; 638 if (expected_kind == kLocal) { 639 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj); 640 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) { 641 found_kind = kLocal; 642 } 643 } else { 644 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj); 645 } 646 if (obj != nullptr && found_kind != expected_kind) { 647 AbortF("expected reference of kind %s but found %s: %p", 648 GetIndirectRefKindString(expected_kind), 649 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)), 650 obj); 651 return false; 652 } 653 return true; 654 } 655 656 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc) 657 REQUIRES_SHARED(Locks::mutator_lock_) { 658 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 659 if (!c->IsInstantiableNonArray()) { 660 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr()); 661 return false; 662 } 663 return true; 664 } 665 666 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type) 667 REQUIRES_SHARED(Locks::mutator_lock_) { 668 if (!CheckArray(soa, array)) { 669 return false; 670 } 671 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array); 672 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) { 673 AbortF("incompatible array type %s expected %s[]: %p", 674 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array); 675 return false; 676 } 677 return true; 678 } 679 680 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static, 681 Primitive::Type type) 682 REQUIRES_SHARED(Locks::mutator_lock_) { 683 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) { 684 return false; 685 } 686 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) { 687 return false; 688 } 689 ArtField* field = jni::DecodeArtField(fid); 690 DCHECK(field != nullptr); // Already checked by Check. 691 if (is_static != field->IsStatic()) { 692 AbortF("attempt to access %s field %s: %p", 693 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid); 694 return false; 695 } 696 if (type != field->GetTypeAsPrimitiveType()) { 697 AbortF("attempt to access field %s of type %s with the wrong type %s: %p", 698 field->PrettyField().c_str(), 699 PrettyDescriptor(field->GetTypeDescriptor()).c_str(), 700 PrettyDescriptor(type).c_str(), fid); 701 return false; 702 } 703 if (is_static) { 704 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj); 705 if (o == nullptr || !o->IsClass()) { 706 AbortF("attempt to access static field %s with a class argument of type %s: %p", 707 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid); 708 return false; 709 } 710 ObjPtr<mirror::Class> c = o->AsClass(); 711 if (c != field->GetDeclaringClass()) { 712 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p", 713 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid); 714 return false; 715 } 716 } else { 717 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj); 718 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) { 719 AbortF("attempt to access field %s from an object argument of type %s: %p", 720 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid); 721 return false; 722 } 723 } 724 return true; 725 } 726 727 private: 728 enum InstanceKind { 729 kClass, 730 kDirectByteBuffer, 731 kObject, 732 kString, 733 kThrowable, 734 }; 735 736 /* 737 * Verify that "jobj" is a valid non-null object reference, and points to 738 * an instance of expectedClass. 739 * 740 * Because we're looking at an object on the GC heap, we have to switch 741 * to "running" mode before doing the checks. 742 */ 743 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok) 744 REQUIRES_SHARED(Locks::mutator_lock_) { 745 const char* what = nullptr; 746 switch (kind) { 747 case kClass: 748 what = "jclass"; 749 break; 750 case kDirectByteBuffer: 751 what = "direct ByteBuffer"; 752 break; 753 case kObject: 754 what = "jobject"; 755 break; 756 case kString: 757 what = "jstring"; 758 break; 759 case kThrowable: 760 what = "jthrowable"; 761 break; 762 default: 763 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind); 764 } 765 766 if (java_object == nullptr) { 767 if (null_ok) { 768 return true; 769 } else { 770 AbortF("%s received NULL %s", function_name_, what); 771 return false; 772 } 773 } 774 775 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object); 776 if (obj == nullptr) { 777 // Either java_object is invalid or is a cleared weak. 778 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object); 779 bool okay; 780 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) { 781 okay = false; 782 } else { 783 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref); 784 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj); 785 } 786 if (!okay) { 787 AbortF("%s is an invalid %s: %p (%p)", 788 what, 789 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)), 790 java_object, 791 obj.Ptr()); 792 return false; 793 } 794 } 795 796 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) { 797 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 798 AbortF("%s is an invalid %s: %p (%p)", 799 what, 800 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)), 801 java_object, 802 obj.Ptr()); 803 return false; 804 } 805 806 bool okay = true; 807 switch (kind) { 808 case kClass: 809 okay = obj->IsClass(); 810 break; 811 case kDirectByteBuffer: 812 UNIMPLEMENTED(FATAL); 813 break; 814 case kString: 815 okay = obj->GetClass()->IsStringClass(); 816 break; 817 case kThrowable: 818 okay = obj->GetClass()->IsThrowableClass(); 819 break; 820 case kObject: 821 break; 822 } 823 if (!okay) { 824 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str()); 825 return false; 826 } 827 828 return true; 829 } 830 831 /* 832 * Verify that the "mode" argument passed to a primitive array Release 833 * function is one of the valid values. 834 */ 835 bool CheckReleaseMode(jint mode) { 836 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) { 837 AbortF("unknown value for release mode: %d", mode); 838 return false; 839 } 840 return true; 841 } 842 843 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg) 844 REQUIRES_SHARED(Locks::mutator_lock_) { 845 switch (fmt) { 846 case 'a': // jarray 847 return CheckArray(soa, arg.a); 848 case 'c': // jclass 849 return CheckInstance(soa, kClass, arg.c, false); 850 case 'f': // jfieldID 851 return CheckFieldID(arg.f) != nullptr; 852 case 'm': // jmethodID 853 return CheckMethodID(arg.m) != nullptr; 854 case 'r': // release int 855 return CheckReleaseMode(arg.r); 856 case 's': // jstring 857 return CheckInstance(soa, kString, arg.s, false); 858 case 't': // jthrowable 859 return CheckInstance(soa, kThrowable, arg.t, false); 860 case 'E': // JNIEnv* 861 return CheckThread(arg.E); 862 case 'L': // jobject 863 return CheckInstance(soa, kObject, arg.L, true); 864 case '.': // A VarArgs list 865 return CheckVarArgs(soa, arg.va); 866 default: 867 return CheckNonHeapValue(fmt, arg); 868 } 869 } 870 871 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p) 872 REQUIRES_SHARED(Locks::mutator_lock_) { 873 CHECK(args_p != nullptr); 874 VarArgs args(args_p->Clone()); 875 ArtMethod* m = CheckMethodID(args.GetMethodID()); 876 if (m == nullptr) { 877 return false; 878 } 879 uint32_t len = 0; 880 const char* shorty = m->GetShorty(&len); 881 // Skip the return type 882 CHECK_GE(len, 1u); 883 len--; 884 shorty++; 885 for (uint32_t i = 0; i < len; i++) { 886 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) { 887 return false; 888 } 889 } 890 return true; 891 } 892 893 bool CheckNonHeapValue(char fmt, JniValueType arg) { 894 switch (fmt) { 895 case 'p': // TODO: pointer - null or readable? 896 case 'v': // JavaVM* 897 case 'B': // jbyte 898 case 'C': // jchar 899 case 'D': // jdouble 900 case 'F': // jfloat 901 case 'I': // jint 902 case 'J': // jlong 903 case 'S': // jshort 904 break; // Ignored. 905 case 'b': // jboolean, why two? Fall-through. 906 case 'Z': 907 return CheckBoolean(arg.Z); 908 case 'u': // utf8 909 if ((flags_ & kFlag_Release) != 0) { 910 return CheckNonNull(arg.u); 911 } else { 912 bool nullable = ((flags_ & kFlag_NullableUtf) != 0); 913 return CheckUtfString(arg.u, nullable); 914 } 915 case 'w': // jobjectRefType 916 switch (arg.w) { 917 case JNIInvalidRefType: 918 case JNILocalRefType: 919 case JNIGlobalRefType: 920 case JNIWeakGlobalRefType: 921 break; 922 default: 923 AbortF("Unknown reference type"); 924 return false; 925 } 926 break; 927 case 'z': // jsize 928 return CheckLengthPositive(arg.z); 929 default: 930 AbortF("unknown format specifier: '%c'", fmt); 931 return false; 932 } 933 return true; 934 } 935 936 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg, 937 std::string* msg) 938 REQUIRES_SHARED(Locks::mutator_lock_) { 939 switch (fmt) { 940 case 'L': // jobject fall-through. 941 case 'a': // jarray fall-through. 942 case 's': // jstring fall-through. 943 case 't': // jthrowable fall-through. 944 if (arg.L == nullptr) { 945 *msg += "NULL"; 946 } else { 947 StringAppendF(msg, "%p", arg.L); 948 } 949 break; 950 case 'c': { // jclass 951 jclass jc = arg.c; 952 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc); 953 if (c == nullptr) { 954 *msg += "NULL"; 955 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) { 956 StringAppendF(msg, "INVALID POINTER:%p", jc); 957 } else if (!c->IsClass()) { 958 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf(); 959 } else { 960 *msg += c->PrettyClass(); 961 if (!entry) { 962 StringAppendF(msg, " (%p)", jc); 963 } 964 } 965 break; 966 } 967 case 'f': { // jfieldID 968 jfieldID fid = arg.f; 969 ArtField* f = jni::DecodeArtField(fid); 970 *msg += ArtField::PrettyField(f); 971 if (!entry) { 972 StringAppendF(msg, " (%p)", fid); 973 } 974 break; 975 } 976 case 'm': { // jmethodID 977 jmethodID mid = arg.m; 978 ArtMethod* m = jni::DecodeArtMethod(mid); 979 *msg += ArtMethod::PrettyMethod(m); 980 if (!entry) { 981 StringAppendF(msg, " (%p)", mid); 982 } 983 break; 984 } 985 case '.': { 986 const VarArgs* va = arg.va; 987 VarArgs args(va->Clone()); 988 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID()); 989 uint32_t len; 990 const char* shorty = m->GetShorty(&len); 991 CHECK_GE(len, 1u); 992 // Skip past return value. 993 len--; 994 shorty++; 995 // Remove the previous ', ' from the message. 996 msg->erase(msg->length() - 2); 997 for (uint32_t i = 0; i < len; i++) { 998 *msg += ", "; 999 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg); 1000 } 1001 break; 1002 } 1003 default: 1004 TraceNonHeapValue(fmt, arg, msg); 1005 break; 1006 } 1007 } 1008 1009 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) { 1010 switch (fmt) { 1011 case 'B': // jbyte 1012 if (arg.B >= 0 && arg.B < 10) { 1013 StringAppendF(msg, "%d", arg.B); 1014 } else { 1015 StringAppendF(msg, "%#x (%d)", arg.B, arg.B); 1016 } 1017 break; 1018 case 'C': // jchar 1019 if (arg.C < 0x7f && arg.C >= ' ') { 1020 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C); 1021 } else { 1022 StringAppendF(msg, "U+%x", arg.C); 1023 } 1024 break; 1025 case 'F': // jfloat 1026 StringAppendF(msg, "%g", arg.F); 1027 break; 1028 case 'D': // jdouble 1029 StringAppendF(msg, "%g", arg.D); 1030 break; 1031 case 'S': // jshort 1032 StringAppendF(msg, "%d", arg.S); 1033 break; 1034 case 'i': // jint - fall-through. 1035 case 'I': // jint 1036 StringAppendF(msg, "%d", arg.I); 1037 break; 1038 case 'J': // jlong 1039 StringAppendF(msg, "%" PRId64, arg.J); 1040 break; 1041 case 'Z': // jboolean 1042 case 'b': // jboolean (JNI-style) 1043 *msg += arg.b == JNI_TRUE ? "true" : "false"; 1044 break; 1045 case 'V': // void 1046 DCHECK(arg.V == nullptr); 1047 *msg += "void"; 1048 break; 1049 case 'v': // JavaVM* 1050 StringAppendF(msg, "(JavaVM*)%p", arg.v); 1051 break; 1052 case 'E': 1053 StringAppendF(msg, "(JNIEnv*)%p", arg.E); 1054 break; 1055 case 'z': // non-negative jsize 1056 // You might expect jsize to be size_t, but it's not; it's the same as jint. 1057 // We only treat this specially so we can do the non-negative check. 1058 // TODO: maybe this wasn't worth it? 1059 StringAppendF(msg, "%d", arg.z); 1060 break; 1061 case 'p': // void* ("pointer") 1062 if (arg.p == nullptr) { 1063 *msg += "NULL"; 1064 } else { 1065 StringAppendF(msg, "(void*) %p", arg.p); 1066 } 1067 break; 1068 case 'r': { // jint (release mode) 1069 jint releaseMode = arg.r; 1070 if (releaseMode == 0) { 1071 *msg += "0"; 1072 } else if (releaseMode == JNI_ABORT) { 1073 *msg += "JNI_ABORT"; 1074 } else if (releaseMode == JNI_COMMIT) { 1075 *msg += "JNI_COMMIT"; 1076 } else { 1077 StringAppendF(msg, "invalid release mode %d", releaseMode); 1078 } 1079 break; 1080 } 1081 case 'u': // const char* (Modified UTF-8) 1082 if (arg.u == nullptr) { 1083 *msg += "NULL"; 1084 } else { 1085 StringAppendF(msg, "\"%s\"", arg.u); 1086 } 1087 break; 1088 case 'w': // jobjectRefType 1089 switch (arg.w) { 1090 case JNIInvalidRefType: 1091 *msg += "invalid reference type"; 1092 break; 1093 case JNILocalRefType: 1094 *msg += "local ref type"; 1095 break; 1096 case JNIGlobalRefType: 1097 *msg += "global ref type"; 1098 break; 1099 case JNIWeakGlobalRefType: 1100 *msg += "weak global ref type"; 1101 break; 1102 default: 1103 *msg += "unknown ref type"; 1104 break; 1105 } 1106 break; 1107 default: 1108 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'"; 1109 } 1110 } 1111 /* 1112 * Verify that "array" is non-null and points to an Array object. 1113 * 1114 * Since we're dealing with objects, switch to "running" mode. 1115 */ 1116 bool CheckArray(ScopedObjectAccess& soa, jarray java_array) 1117 REQUIRES_SHARED(Locks::mutator_lock_) { 1118 if (UNLIKELY(java_array == nullptr)) { 1119 AbortF("jarray was NULL"); 1120 return false; 1121 } 1122 1123 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array); 1124 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) { 1125 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 1126 AbortF("jarray is an invalid %s: %p (%p)", 1127 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)), 1128 java_array, 1129 a.Ptr()); 1130 return false; 1131 } else if (!a->IsArrayInstance()) { 1132 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str()); 1133 return false; 1134 } 1135 return true; 1136 } 1137 1138 bool CheckBoolean(jboolean z) { 1139 if (z != JNI_TRUE && z != JNI_FALSE) { 1140 AbortF("unexpected jboolean value: %d", z); 1141 return false; 1142 } 1143 return true; 1144 } 1145 1146 bool CheckLengthPositive(jsize length) { 1147 if (length < 0) { 1148 AbortF("negative jsize: %d", length); 1149 return false; 1150 } 1151 return true; 1152 } 1153 1154 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) { 1155 if (fid == nullptr) { 1156 AbortF("jfieldID was NULL"); 1157 return nullptr; 1158 } 1159 ArtField* f = jni::DecodeArtField(fid); 1160 // TODO: Better check here. 1161 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) { 1162 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 1163 AbortF("invalid jfieldID: %p", fid); 1164 return nullptr; 1165 } 1166 return f; 1167 } 1168 1169 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) { 1170 if (mid == nullptr) { 1171 AbortF("jmethodID was NULL"); 1172 return nullptr; 1173 } 1174 ArtMethod* m = jni::DecodeArtMethod(mid); 1175 // TODO: Better check here. 1176 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) { 1177 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR)); 1178 AbortF("invalid jmethodID: %p", mid); 1179 return nullptr; 1180 } 1181 return m; 1182 } 1183 1184 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) { 1185 Thread* self = Thread::Current(); 1186 if (self == nullptr) { 1187 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid()); 1188 return false; 1189 } 1190 1191 // Get the current thread's JNIEnv by going through our TLS pointer. 1192 JNIEnvExt* threadEnv = self->GetJniEnv(); 1193 1194 // Verify that the current thread is (a) attached and (b) associated with 1195 // this particular instance of JNIEnv. 1196 if (env != threadEnv) { 1197 // Get the thread owning the JNIEnv that's being used. 1198 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self; 1199 AbortF("thread %s using JNIEnv* from thread %s", 1200 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str()); 1201 return false; 1202 } 1203 1204 // Verify that, if this thread previously made a critical "get" call, we 1205 // do the corresponding "release" call before we try anything else. 1206 switch (flags_ & kFlag_CritMask) { 1207 case kFlag_CritOkay: // okay to call this method 1208 break; 1209 case kFlag_CritBad: // not okay to call 1210 if (threadEnv->critical) { 1211 AbortF("thread %s using JNI after critical get", 1212 ToStr<Thread>(*self).c_str()); 1213 return false; 1214 } 1215 break; 1216 case kFlag_CritGet: // this is a "get" call 1217 // Don't check here; we allow nested gets. 1218 threadEnv->critical++; 1219 break; 1220 case kFlag_CritRelease: // this is a "release" call 1221 threadEnv->critical--; 1222 if (threadEnv->critical < 0) { 1223 AbortF("thread %s called too many critical releases", 1224 ToStr<Thread>(*self).c_str()); 1225 return false; 1226 } 1227 break; 1228 default: 1229 LOG(FATAL) << "Bad flags (internal error): " << flags_; 1230 } 1231 1232 // Verify that, if an exception has been raised, the native code doesn't 1233 // make any JNI calls other than the Exception* methods. 1234 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) { 1235 mirror::Throwable* exception = self->GetException(); 1236 AbortF("JNI %s called with pending exception %s", 1237 function_name_, 1238 exception->Dump().c_str()); 1239 return false; 1240 } 1241 return true; 1242 } 1243 1244 // Verifies that "bytes" points to valid Modified UTF-8 data. 1245 bool CheckUtfString(const char* bytes, bool nullable) { 1246 if (bytes == nullptr) { 1247 if (!nullable) { 1248 AbortF("non-nullable const char* was NULL"); 1249 return false; 1250 } 1251 return true; 1252 } 1253 1254 const char* errorKind = nullptr; 1255 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind); 1256 if (errorKind != nullptr) { 1257 // This is an expensive loop that will resize often, but this isn't supposed to hit in 1258 // practice anyways. 1259 std::ostringstream oss; 1260 oss << std::hex; 1261 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes); 1262 while (*tmp != 0) { 1263 if (tmp == utf8) { 1264 oss << "<"; 1265 } 1266 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp); 1267 if (tmp == utf8) { 1268 oss << '>'; 1269 } 1270 tmp++; 1271 if (*tmp != 0) { 1272 oss << ' '; 1273 } 1274 } 1275 1276 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n" 1277 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str()); 1278 return false; 1279 } 1280 return true; 1281 } 1282 1283 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF 1284 // sequences in place of encoded surrogate pairs. 1285 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) { 1286 while (*bytes != '\0') { 1287 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1288 // Switch on the high four bits. 1289 switch (*utf8 >> 4) { 1290 case 0x00: 1291 case 0x01: 1292 case 0x02: 1293 case 0x03: 1294 case 0x04: 1295 case 0x05: 1296 case 0x06: 1297 case 0x07: 1298 // Bit pattern 0xxx. No need for any extra bytes. 1299 break; 1300 case 0x08: 1301 case 0x09: 1302 case 0x0a: 1303 case 0x0b: 1304 // Bit patterns 10xx, which are illegal start bytes. 1305 *errorKind = "start"; 1306 return utf8; 1307 case 0x0f: 1308 // Bit pattern 1111, which might be the start of a 4 byte sequence. 1309 if ((*utf8 & 0x08) == 0) { 1310 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence. 1311 // We consume one continuation byte here, and fall through to consume two more. 1312 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1313 if ((*utf8 & 0xc0) != 0x80) { 1314 *errorKind = "continuation"; 1315 return utf8; 1316 } 1317 } else { 1318 *errorKind = "start"; 1319 return utf8; 1320 } 1321 1322 // Fall through to the cases below to consume two more continuation bytes. 1323 FALLTHROUGH_INTENDED; 1324 case 0x0e: 1325 // Bit pattern 1110, so there are two additional bytes. 1326 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1327 if ((*utf8 & 0xc0) != 0x80) { 1328 *errorKind = "continuation"; 1329 return utf8; 1330 } 1331 1332 // Fall through to consume one more continuation byte. 1333 FALLTHROUGH_INTENDED; 1334 case 0x0c: 1335 case 0x0d: 1336 // Bit pattern 110x, so there is one additional byte. 1337 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1338 if ((*utf8 & 0xc0) != 0x80) { 1339 *errorKind = "continuation"; 1340 return utf8; 1341 } 1342 break; 1343 } 1344 } 1345 return 0; 1346 } 1347 1348 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) { 1349 va_list args; 1350 va_start(args, fmt); 1351 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args); 1352 va_end(args); 1353 } 1354 1355 // The name of the JNI function being checked. 1356 const char* const function_name_; 1357 1358 const int flags_; 1359 int indent_; 1360 1361 const bool has_method_; 1362 1363 DISALLOW_COPY_AND_ASSIGN(ScopedCheck); 1364 }; 1365 1366 /* 1367 * =========================================================================== 1368 * Guarded arrays 1369 * =========================================================================== 1370 */ 1371 1372 /* this gets tucked in at the start of the buffer; struct size must be even */ 1373 class GuardedCopy { 1374 public: 1375 /* 1376 * Create an over-sized buffer to hold the contents of "buf". Copy it in, 1377 * filling in the area around it with guard data. 1378 */ 1379 static void* Create(void* original_buf, size_t len, bool mod_okay) { 1380 const size_t new_len = LengthIncludingRedZones(len); 1381 uint8_t* const new_buf = DebugAlloc(new_len); 1382 1383 // If modification is not expected, grab a checksum. 1384 uLong adler = 0; 1385 if (!mod_okay) { 1386 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len); 1387 } 1388 1389 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler); 1390 1391 // Fill begin region with canary pattern. 1392 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 1393 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 1394 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j]; 1395 if (kCanary[j] == '\0') { 1396 j = 0; 1397 } else { 1398 j++; 1399 } 1400 } 1401 1402 // Copy the data in; note "len" could be zero. 1403 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len); 1404 1405 // Fill end region with canary pattern. 1406 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 1407 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j]; 1408 if (kCanary[j] == '\0') { 1409 j = 0; 1410 } else { 1411 j++; 1412 } 1413 } 1414 1415 return const_cast<uint8_t*>(copy->BufferWithinRedZones()); 1416 } 1417 1418 /* 1419 * Create a guarded copy of a primitive array. Modifications to the copied 1420 * data are allowed. Returns a pointer to the copied data. 1421 */ 1422 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy, 1423 void* original_ptr) { 1424 ScopedObjectAccess soa(env); 1425 1426 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array); 1427 size_t component_size = a->GetClass()->GetComponentSize(); 1428 size_t byte_count = a->GetLength() * component_size; 1429 void* result = Create(original_ptr, byte_count, true); 1430 if (is_copy != nullptr) { 1431 *is_copy = JNI_TRUE; 1432 } 1433 return result; 1434 } 1435 1436 /* 1437 * Perform the array "release" operation, which may or may not copy data 1438 * back into the managed heap, and may or may not release the underlying storage. 1439 */ 1440 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, 1441 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf, 1442 int mode) { 1443 ScopedObjectAccess soa(env); 1444 if (!GuardedCopy::Check(function_name, embedded_buf, true)) { 1445 return nullptr; 1446 } 1447 GuardedCopy* const copy = FromEmbedded(embedded_buf); 1448 void* original_ptr = copy->original_ptr_; 1449 if (mode != JNI_ABORT) { 1450 memcpy(original_ptr, embedded_buf, copy->original_length_); 1451 } 1452 if (mode != JNI_COMMIT) { 1453 Destroy(embedded_buf); 1454 } 1455 return original_ptr; 1456 } 1457 1458 1459 /* 1460 * Free up the guard buffer, scrub it, and return the original pointer. 1461 */ 1462 static void* Destroy(void* embedded_buf) { 1463 GuardedCopy* copy = FromEmbedded(embedded_buf); 1464 void* original_ptr = const_cast<void*>(copy->original_ptr_); 1465 size_t len = LengthIncludingRedZones(copy->original_length_); 1466 DebugFree(copy, len); 1467 return original_ptr; 1468 } 1469 1470 /* 1471 * Verify the guard area and, if "modOkay" is false, that the data itself 1472 * has not been altered. 1473 * 1474 * The caller has already checked that "dataBuf" is non-null. 1475 */ 1476 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) { 1477 const GuardedCopy* copy = FromEmbedded(embedded_buf); 1478 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name); 1479 } 1480 1481 private: 1482 GuardedCopy(void* original_buf, size_t len, uLong adler) : 1483 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) { 1484 } 1485 1486 static uint8_t* DebugAlloc(size_t len) { 1487 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 1488 if (result == MAP_FAILED) { 1489 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed"; 1490 } 1491 return reinterpret_cast<uint8_t*>(result); 1492 } 1493 1494 static void DebugFree(void* buf, size_t len) { 1495 if (munmap(buf, len) != 0) { 1496 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed"; 1497 } 1498 } 1499 1500 static size_t LengthIncludingRedZones(size_t len) { 1501 return len + kRedZoneSize; 1502 } 1503 1504 // Get the GuardedCopy from the interior pointer. 1505 static GuardedCopy* FromEmbedded(void* embedded_buf) { 1506 return reinterpret_cast<GuardedCopy*>( 1507 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 1508 } 1509 1510 static const GuardedCopy* FromEmbedded(const void* embedded_buf) { 1511 return reinterpret_cast<const GuardedCopy*>( 1512 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 1513 } 1514 1515 static void AbortF(const char* jni_function_name, const char* fmt, ...) { 1516 va_list args; 1517 va_start(args, fmt); 1518 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args); 1519 va_end(args); 1520 } 1521 1522 bool CheckHeader(const char* function_name, bool mod_okay) const { 1523 static const uint32_t kMagicCmp = kGuardMagic; 1524 1525 // Before we do anything with "pExtra", check the magic number. We 1526 // do the check with memcmp rather than "==" in case the pointer is 1527 // unaligned. If it points to completely bogus memory we're going 1528 // to crash, but there's no easy way around that. 1529 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) { 1530 uint8_t buf[4]; 1531 memcpy(buf, &magic_, 4); 1532 AbortF(function_name, 1533 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?", 1534 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian. 1535 return false; 1536 } 1537 1538 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we 1539 // told the client that we made a copy, there's no reason they can't alter the buffer. 1540 if (!mod_okay) { 1541 uLong computed_adler = 1542 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_); 1543 if (computed_adler != adler_) { 1544 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p", 1545 computed_adler, adler_, this); 1546 return false; 1547 } 1548 } 1549 return true; 1550 } 1551 1552 bool CheckRedZones(const char* function_name) const { 1553 // Check the begin red zone. 1554 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 1555 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 1556 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) { 1557 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i); 1558 return false; 1559 } 1560 if (kCanary[j] == '\0') { 1561 j = 0; 1562 } else { 1563 j++; 1564 } 1565 } 1566 1567 // Check end region. 1568 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 1569 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) { 1570 size_t offset_from_buffer_start = 1571 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]); 1572 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this, 1573 offset_from_buffer_start); 1574 return false; 1575 } 1576 if (kCanary[j] == '\0') { 1577 j = 0; 1578 } else { 1579 j++; 1580 } 1581 } 1582 return true; 1583 } 1584 1585 // Location that canary value will be written before the guarded region. 1586 const char* StartRedZone() const { 1587 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 1588 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy)); 1589 } 1590 1591 // Return the interior embedded buffer. 1592 const uint8_t* BufferWithinRedZones() const { 1593 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2); 1594 return embedded_buf; 1595 } 1596 1597 // Location that canary value will be written after the guarded region. 1598 const char* EndRedZone() const { 1599 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 1600 size_t buf_len = LengthIncludingRedZones(original_length_); 1601 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2))); 1602 } 1603 1604 static constexpr size_t kRedZoneSize = 512; 1605 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2; 1606 1607 // Value written before and after the guarded array. 1608 static const char* const kCanary; 1609 1610 static constexpr uint32_t kGuardMagic = 0xffd5aa96; 1611 1612 const uint32_t magic_; 1613 const uLong adler_; 1614 void* const original_ptr_; 1615 const size_t original_length_; 1616 }; 1617 const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE"; 1618 1619 /* 1620 * =========================================================================== 1621 * JNI functions 1622 * =========================================================================== 1623 */ 1624 1625 class CheckJNI { 1626 public: 1627 static jint GetVersion(JNIEnv* env) { 1628 ScopedObjectAccess soa(env); 1629 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1630 JniValueType args[1] = {{.E = env }}; 1631 if (sc.Check(soa, true, "E", args)) { 1632 JniValueType result; 1633 result.I = baseEnv(env)->GetVersion(env); 1634 if (sc.Check(soa, false, "I", &result)) { 1635 return result.I; 1636 } 1637 } 1638 return JNI_ERR; 1639 } 1640 1641 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) { 1642 ScopedObjectAccess soa(env); 1643 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1644 JniValueType args[2] = {{.E = env }, {.p = vm}}; 1645 if (sc.Check(soa, true, "Ep", args)) { 1646 JniValueType result; 1647 result.i = baseEnv(env)->GetJavaVM(env, vm); 1648 if (sc.Check(soa, false, "i", &result)) { 1649 return result.i; 1650 } 1651 } 1652 return JNI_ERR; 1653 } 1654 1655 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) { 1656 ScopedObjectAccess soa(env); 1657 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1658 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}}; 1659 if (sc.Check(soa, true, "EcpI", args)) { 1660 JniValueType result; 1661 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods); 1662 if (sc.Check(soa, false, "i", &result)) { 1663 return result.i; 1664 } 1665 } 1666 return JNI_ERR; 1667 } 1668 1669 static jint UnregisterNatives(JNIEnv* env, jclass c) { 1670 ScopedObjectAccess soa(env); 1671 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1672 JniValueType args[2] = {{.E = env }, {.c = c}}; 1673 if (sc.Check(soa, true, "Ec", args)) { 1674 JniValueType result; 1675 result.i = baseEnv(env)->UnregisterNatives(env, c); 1676 if (sc.Check(soa, false, "i", &result)) { 1677 return result.i; 1678 } 1679 } 1680 return JNI_ERR; 1681 } 1682 1683 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) { 1684 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to 1685 // know the object is invalid. The spec says that passing invalid objects or even ones that 1686 // are deleted isn't supported. 1687 ScopedObjectAccess soa(env); 1688 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1689 JniValueType args[2] = {{.E = env }, {.L = obj}}; 1690 if (sc.Check(soa, true, "EL", args)) { 1691 JniValueType result; 1692 result.w = baseEnv(env)->GetObjectRefType(env, obj); 1693 if (sc.Check(soa, false, "w", &result)) { 1694 return result.w; 1695 } 1696 } 1697 return JNIInvalidRefType; 1698 } 1699 1700 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, 1701 jsize bufLen) { 1702 ScopedObjectAccess soa(env); 1703 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1704 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}}; 1705 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) { 1706 JniValueType result; 1707 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen); 1708 if (sc.Check(soa, false, "c", &result)) { 1709 return result.c; 1710 } 1711 } 1712 return nullptr; 1713 } 1714 1715 static jclass FindClass(JNIEnv* env, const char* name) { 1716 ScopedObjectAccess soa(env); 1717 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1718 JniValueType args[2] = {{.E = env}, {.u = name}}; 1719 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) { 1720 JniValueType result; 1721 result.c = baseEnv(env)->FindClass(env, name); 1722 if (sc.Check(soa, false, "c", &result)) { 1723 return result.c; 1724 } 1725 } 1726 return nullptr; 1727 } 1728 1729 static jclass GetSuperclass(JNIEnv* env, jclass c) { 1730 ScopedObjectAccess soa(env); 1731 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1732 JniValueType args[2] = {{.E = env}, {.c = c}}; 1733 if (sc.Check(soa, true, "Ec", args)) { 1734 JniValueType result; 1735 result.c = baseEnv(env)->GetSuperclass(env, c); 1736 if (sc.Check(soa, false, "c", &result)) { 1737 return result.c; 1738 } 1739 } 1740 return nullptr; 1741 } 1742 1743 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) { 1744 ScopedObjectAccess soa(env); 1745 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1746 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}}; 1747 if (sc.Check(soa, true, "Ecc", args)) { 1748 JniValueType result; 1749 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2); 1750 if (sc.Check(soa, false, "b", &result)) { 1751 return result.b; 1752 } 1753 } 1754 return JNI_FALSE; 1755 } 1756 1757 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) { 1758 ScopedObjectAccess soa(env); 1759 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1760 JniValueType args[2] = {{.E = env}, {.L = method}}; 1761 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) { 1762 JniValueType result; 1763 result.m = baseEnv(env)->FromReflectedMethod(env, method); 1764 if (sc.Check(soa, false, "m", &result)) { 1765 return result.m; 1766 } 1767 } 1768 return nullptr; 1769 } 1770 1771 static jfieldID FromReflectedField(JNIEnv* env, jobject field) { 1772 ScopedObjectAccess soa(env); 1773 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1774 JniValueType args[2] = {{.E = env}, {.L = field}}; 1775 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) { 1776 JniValueType result; 1777 result.f = baseEnv(env)->FromReflectedField(env, field); 1778 if (sc.Check(soa, false, "f", &result)) { 1779 return result.f; 1780 } 1781 } 1782 return nullptr; 1783 } 1784 1785 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) { 1786 ScopedObjectAccess soa(env); 1787 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1788 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}}; 1789 if (sc.Check(soa, true, "Ecmb", args)) { 1790 JniValueType result; 1791 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic); 1792 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 1793 DCHECK(sc.CheckReflectedMethod(soa, result.L)); 1794 return result.L; 1795 } 1796 } 1797 return nullptr; 1798 } 1799 1800 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) { 1801 ScopedObjectAccess soa(env); 1802 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1803 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}}; 1804 if (sc.Check(soa, true, "Ecfb", args)) { 1805 JniValueType result; 1806 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic); 1807 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 1808 DCHECK(sc.CheckReflectedField(soa, result.L)); 1809 return result.L; 1810 } 1811 } 1812 return nullptr; 1813 } 1814 1815 static jint Throw(JNIEnv* env, jthrowable obj) { 1816 ScopedObjectAccess soa(env); 1817 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1818 JniValueType args[2] = {{.E = env}, {.t = obj}}; 1819 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) { 1820 JniValueType result; 1821 result.i = baseEnv(env)->Throw(env, obj); 1822 if (sc.Check(soa, false, "i", &result)) { 1823 return result.i; 1824 } 1825 } 1826 return JNI_ERR; 1827 } 1828 1829 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) { 1830 ScopedObjectAccess soa(env); 1831 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 1832 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}}; 1833 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) { 1834 JniValueType result; 1835 result.i = baseEnv(env)->ThrowNew(env, c, message); 1836 if (sc.Check(soa, false, "i", &result)) { 1837 return result.i; 1838 } 1839 } 1840 return JNI_ERR; 1841 } 1842 1843 static jthrowable ExceptionOccurred(JNIEnv* env) { 1844 ScopedObjectAccess soa(env); 1845 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1846 JniValueType args[1] = {{.E = env}}; 1847 if (sc.Check(soa, true, "E", args)) { 1848 JniValueType result; 1849 result.t = baseEnv(env)->ExceptionOccurred(env); 1850 if (sc.Check(soa, false, "t", &result)) { 1851 return result.t; 1852 } 1853 } 1854 return nullptr; 1855 } 1856 1857 static void ExceptionDescribe(JNIEnv* env) { 1858 ScopedObjectAccess soa(env); 1859 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1860 JniValueType args[1] = {{.E = env}}; 1861 if (sc.Check(soa, true, "E", args)) { 1862 JniValueType result; 1863 baseEnv(env)->ExceptionDescribe(env); 1864 result.V = nullptr; 1865 sc.Check(soa, false, "V", &result); 1866 } 1867 } 1868 1869 static void ExceptionClear(JNIEnv* env) { 1870 ScopedObjectAccess soa(env); 1871 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1872 JniValueType args[1] = {{.E = env}}; 1873 if (sc.Check(soa, true, "E", args)) { 1874 JniValueType result; 1875 baseEnv(env)->ExceptionClear(env); 1876 result.V = nullptr; 1877 sc.Check(soa, false, "V", &result); 1878 } 1879 } 1880 1881 static jboolean ExceptionCheck(JNIEnv* env) { 1882 ScopedObjectAccess soa(env); 1883 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__); 1884 JniValueType args[1] = {{.E = env}}; 1885 if (sc.Check(soa, true, "E", args)) { 1886 JniValueType result; 1887 result.b = baseEnv(env)->ExceptionCheck(env); 1888 if (sc.Check(soa, false, "b", &result)) { 1889 return result.b; 1890 } 1891 } 1892 return JNI_FALSE; 1893 } 1894 1895 static void FatalError(JNIEnv* env, const char* msg) { 1896 // The JNI specification doesn't say it's okay to call FatalError with a pending exception, 1897 // but you're about to abort anyway, and it's quite likely that you have a pending exception, 1898 // and it's not unimaginable that you don't know that you do. So we allow it. 1899 ScopedObjectAccess soa(env); 1900 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__); 1901 JniValueType args[2] = {{.E = env}, {.u = msg}}; 1902 if (sc.Check(soa, true, "Eu", args)) { 1903 JniValueType result; 1904 baseEnv(env)->FatalError(env, msg); 1905 // Unreachable. 1906 result.V = nullptr; 1907 sc.Check(soa, false, "V", &result); 1908 } 1909 } 1910 1911 static jint PushLocalFrame(JNIEnv* env, jint capacity) { 1912 ScopedObjectAccess soa(env); 1913 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1914 JniValueType args[2] = {{.E = env}, {.I = capacity}}; 1915 if (sc.Check(soa, true, "EI", args)) { 1916 JniValueType result; 1917 result.i = baseEnv(env)->PushLocalFrame(env, capacity); 1918 if (sc.Check(soa, false, "i", &result)) { 1919 return result.i; 1920 } 1921 } 1922 return JNI_ERR; 1923 } 1924 1925 static jobject PopLocalFrame(JNIEnv* env, jobject res) { 1926 ScopedObjectAccess soa(env); 1927 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1928 JniValueType args[2] = {{.E = env}, {.L = res}}; 1929 if (sc.Check(soa, true, "EL", args)) { 1930 JniValueType result; 1931 result.L = baseEnv(env)->PopLocalFrame(env, res); 1932 sc.Check(soa, false, "L", &result); 1933 return result.L; 1934 } 1935 return nullptr; 1936 } 1937 1938 static jobject NewGlobalRef(JNIEnv* env, jobject obj) { 1939 return NewRef(__FUNCTION__, env, obj, kGlobal); 1940 } 1941 1942 static jobject NewLocalRef(JNIEnv* env, jobject obj) { 1943 return NewRef(__FUNCTION__, env, obj, kLocal); 1944 } 1945 1946 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { 1947 return NewRef(__FUNCTION__, env, obj, kWeakGlobal); 1948 } 1949 1950 static void DeleteGlobalRef(JNIEnv* env, jobject obj) { 1951 DeleteRef(__FUNCTION__, env, obj, kGlobal); 1952 } 1953 1954 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) { 1955 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal); 1956 } 1957 1958 static void DeleteLocalRef(JNIEnv* env, jobject obj) { 1959 DeleteRef(__FUNCTION__, env, obj, kLocal); 1960 } 1961 1962 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) { 1963 ScopedObjectAccess soa(env); 1964 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1965 JniValueType args[2] = {{.E = env}, {.I = capacity}}; 1966 if (sc.Check(soa, true, "EI", args)) { 1967 JniValueType result; 1968 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity); 1969 if (sc.Check(soa, false, "i", &result)) { 1970 return result.i; 1971 } 1972 } 1973 return JNI_ERR; 1974 } 1975 1976 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) { 1977 ScopedObjectAccess soa(env); 1978 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1979 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}}; 1980 if (sc.Check(soa, true, "ELL", args)) { 1981 JniValueType result; 1982 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2); 1983 if (sc.Check(soa, false, "b", &result)) { 1984 return result.b; 1985 } 1986 } 1987 return JNI_FALSE; 1988 } 1989 1990 static jobject AllocObject(JNIEnv* env, jclass c) { 1991 ScopedObjectAccess soa(env); 1992 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1993 JniValueType args[2] = {{.E = env}, {.c = c}}; 1994 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) { 1995 JniValueType result; 1996 result.L = baseEnv(env)->AllocObject(env, c); 1997 if (sc.Check(soa, false, "L", &result)) { 1998 return result.L; 1999 } 2000 } 2001 return nullptr; 2002 } 2003 2004 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 2005 ScopedObjectAccess soa(env); 2006 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2007 VarArgs rest(mid, vargs); 2008 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}}; 2009 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 2010 sc.CheckConstructor(mid)) { 2011 JniValueType result; 2012 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs); 2013 if (sc.Check(soa, false, "L", &result)) { 2014 return result.L; 2015 } 2016 } 2017 return nullptr; 2018 } 2019 2020 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) { 2021 va_list args; 2022 va_start(args, mid); 2023 jobject result = NewObjectV(env, c, mid, args); 2024 va_end(args); 2025 return result; 2026 } 2027 2028 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { 2029 ScopedObjectAccess soa(env); 2030 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2031 VarArgs rest(mid, vargs); 2032 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}}; 2033 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 2034 sc.CheckConstructor(mid)) { 2035 JniValueType result; 2036 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs); 2037 if (sc.Check(soa, false, "L", &result)) { 2038 return result.L; 2039 } 2040 } 2041 return nullptr; 2042 } 2043 2044 static jclass GetObjectClass(JNIEnv* env, jobject obj) { 2045 ScopedObjectAccess soa(env); 2046 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2047 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2048 if (sc.Check(soa, true, "EL", args)) { 2049 JniValueType result; 2050 result.c = baseEnv(env)->GetObjectClass(env, obj); 2051 if (sc.Check(soa, false, "c", &result)) { 2052 return result.c; 2053 } 2054 } 2055 return nullptr; 2056 } 2057 2058 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) { 2059 ScopedObjectAccess soa(env); 2060 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2061 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}}; 2062 if (sc.Check(soa, true, "ELc", args)) { 2063 JniValueType result; 2064 result.b = baseEnv(env)->IsInstanceOf(env, obj, c); 2065 if (sc.Check(soa, false, "b", &result)) { 2066 return result.b; 2067 } 2068 } 2069 return JNI_FALSE; 2070 } 2071 2072 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2073 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false); 2074 } 2075 2076 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2077 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true); 2078 } 2079 2080 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2081 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false); 2082 } 2083 2084 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2085 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true); 2086 } 2087 2088 #define FIELD_ACCESSORS(jtype, name, ptype, shorty) \ 2089 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \ 2090 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \ 2091 } \ 2092 \ 2093 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \ 2094 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \ 2095 } \ 2096 \ 2097 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \ 2098 JniValueType value; \ 2099 value.shorty = v; \ 2100 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \ 2101 } \ 2102 \ 2103 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \ 2104 JniValueType value; \ 2105 value.shorty = v; \ 2106 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \ 2107 } 2108 2109 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L) 2110 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z) 2111 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B) 2112 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C) 2113 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S) 2114 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I) 2115 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J) 2116 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F) 2117 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D) 2118 #undef FIELD_ACCESSORS 2119 2120 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { 2121 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2122 } 2123 2124 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 2125 jvalue* vargs) { 2126 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2127 } 2128 2129 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { 2130 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2131 } 2132 2133 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { 2134 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2135 } 2136 2137 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 2138 va_list vargs) { 2139 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2140 } 2141 2142 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 2143 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2144 } 2145 2146 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { 2147 va_list vargs; 2148 va_start(vargs, mid); 2149 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2150 va_end(vargs); 2151 } 2152 2153 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) { 2154 va_list vargs; 2155 va_start(vargs, mid); 2156 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2157 va_end(vargs); 2158 } 2159 2160 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) { 2161 va_list vargs; 2162 va_start(vargs, mid); 2163 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2164 va_end(vargs); 2165 } 2166 2167 #define CALL(rtype, name, ptype, shorty) \ 2168 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \ 2169 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2170 } \ 2171 \ 2172 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2173 jvalue* vargs) { \ 2174 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2175 } \ 2176 \ 2177 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \ 2178 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2179 } \ 2180 \ 2181 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \ 2182 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2183 } \ 2184 \ 2185 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2186 va_list vargs) { \ 2187 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2188 } \ 2189 \ 2190 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \ 2191 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2192 } \ 2193 \ 2194 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \ 2195 va_list vargs; \ 2196 va_start(vargs, mid); \ 2197 rtype result = \ 2198 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2199 va_end(vargs); \ 2200 return result; \ 2201 } \ 2202 \ 2203 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2204 ...) { \ 2205 va_list vargs; \ 2206 va_start(vargs, mid); \ 2207 rtype result = \ 2208 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2209 va_end(vargs); \ 2210 return result; \ 2211 } \ 2212 \ 2213 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \ 2214 va_list vargs; \ 2215 va_start(vargs, mid); \ 2216 rtype result = \ 2217 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2218 va_end(vargs); \ 2219 return result; \ 2220 } 2221 2222 CALL(jobject, Object, Primitive::kPrimNot, L) 2223 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z) 2224 CALL(jbyte, Byte, Primitive::kPrimByte, B) 2225 CALL(jchar, Char, Primitive::kPrimChar, C) 2226 CALL(jshort, Short, Primitive::kPrimShort, S) 2227 CALL(jint, Int, Primitive::kPrimInt, I) 2228 CALL(jlong, Long, Primitive::kPrimLong, J) 2229 CALL(jfloat, Float, Primitive::kPrimFloat, F) 2230 CALL(jdouble, Double, Primitive::kPrimDouble, D) 2231 #undef CALL 2232 2233 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) { 2234 ScopedObjectAccess soa(env); 2235 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2236 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}}; 2237 if (sc.Check(soa, true, "Epz", args)) { 2238 JniValueType result; 2239 result.s = baseEnv(env)->NewString(env, unicode_chars, len); 2240 if (sc.Check(soa, false, "s", &result)) { 2241 return result.s; 2242 } 2243 } 2244 return nullptr; 2245 } 2246 2247 static jstring NewStringUTF(JNIEnv* env, const char* chars) { 2248 ScopedObjectAccess soa(env); 2249 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 2250 JniValueType args[2] = {{.E = env}, {.u = chars}}; 2251 if (sc.Check(soa, true, "Eu", args)) { 2252 JniValueType result; 2253 // TODO: stale? show pointer and truncate string. 2254 result.s = baseEnv(env)->NewStringUTF(env, chars); 2255 if (sc.Check(soa, false, "s", &result)) { 2256 return result.s; 2257 } 2258 } 2259 return nullptr; 2260 } 2261 2262 static jsize GetStringLength(JNIEnv* env, jstring string) { 2263 ScopedObjectAccess soa(env); 2264 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2265 JniValueType args[2] = {{.E = env}, {.s = string}}; 2266 if (sc.Check(soa, true, "Es", args)) { 2267 JniValueType result; 2268 result.z = baseEnv(env)->GetStringLength(env, string); 2269 if (sc.Check(soa, false, "z", &result)) { 2270 return result.z; 2271 } 2272 } 2273 return JNI_ERR; 2274 } 2275 2276 static jsize GetStringUTFLength(JNIEnv* env, jstring string) { 2277 ScopedObjectAccess soa(env); 2278 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2279 JniValueType args[2] = {{.E = env}, {.s = string}}; 2280 if (sc.Check(soa, true, "Es", args)) { 2281 JniValueType result; 2282 result.z = baseEnv(env)->GetStringUTFLength(env, string); 2283 if (sc.Check(soa, false, "z", &result)) { 2284 return result.z; 2285 } 2286 } 2287 return JNI_ERR; 2288 } 2289 2290 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) { 2291 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 2292 is_copy, false, false)); 2293 } 2294 2295 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) { 2296 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string, 2297 is_copy, true, false)); 2298 } 2299 2300 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) { 2301 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 2302 is_copy, false, true)); 2303 } 2304 2305 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) { 2306 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false); 2307 } 2308 2309 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) { 2310 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false); 2311 } 2312 2313 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) { 2314 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true); 2315 } 2316 2317 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) { 2318 ScopedObjectAccess soa(env); 2319 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2320 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 2321 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 2322 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 2323 if (sc.Check(soa, true, "EsIIp", args)) { 2324 baseEnv(env)->GetStringRegion(env, string, start, len, buf); 2325 JniValueType result; 2326 result.V = nullptr; 2327 sc.Check(soa, false, "V", &result); 2328 } 2329 } 2330 2331 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) { 2332 ScopedObjectAccess soa(env); 2333 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2334 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 2335 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 2336 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 2337 if (sc.Check(soa, true, "EsIIp", args)) { 2338 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf); 2339 JniValueType result; 2340 result.V = nullptr; 2341 sc.Check(soa, false, "V", &result); 2342 } 2343 } 2344 2345 static jsize GetArrayLength(JNIEnv* env, jarray array) { 2346 ScopedObjectAccess soa(env); 2347 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2348 JniValueType args[2] = {{.E = env}, {.a = array}}; 2349 if (sc.Check(soa, true, "Ea", args)) { 2350 JniValueType result; 2351 result.z = baseEnv(env)->GetArrayLength(env, array); 2352 if (sc.Check(soa, false, "z", &result)) { 2353 return result.z; 2354 } 2355 } 2356 return JNI_ERR; 2357 } 2358 2359 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class, 2360 jobject initial_element) { 2361 ScopedObjectAccess soa(env); 2362 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2363 JniValueType args[4] = 2364 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}}; 2365 if (sc.Check(soa, true, "EzcL", args)) { 2366 JniValueType result; 2367 // Note: assignability tests of initial_element are done in the base implementation. 2368 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element); 2369 if (sc.Check(soa, false, "a", &result)) { 2370 return down_cast<jobjectArray>(result.a); 2371 } 2372 } 2373 return nullptr; 2374 } 2375 2376 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) { 2377 ScopedObjectAccess soa(env); 2378 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2379 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}}; 2380 if (sc.Check(soa, true, "Eaz", args)) { 2381 JniValueType result; 2382 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index); 2383 if (sc.Check(soa, false, "L", &result)) { 2384 return result.L; 2385 } 2386 } 2387 return nullptr; 2388 } 2389 2390 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) { 2391 ScopedObjectAccess soa(env); 2392 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2393 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}}; 2394 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in 2395 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result 2396 // in ArrayStoreExceptions. 2397 if (sc.Check(soa, true, "EaIL", args)) { 2398 baseEnv(env)->SetObjectArrayElement(env, array, index, value); 2399 JniValueType result; 2400 result.V = nullptr; 2401 sc.Check(soa, false, "V", &result); 2402 } 2403 } 2404 2405 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) { 2406 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2407 Primitive::kPrimBoolean)); 2408 } 2409 2410 static jbyteArray NewByteArray(JNIEnv* env, jsize length) { 2411 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2412 Primitive::kPrimByte)); 2413 } 2414 2415 static jcharArray NewCharArray(JNIEnv* env, jsize length) { 2416 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2417 Primitive::kPrimChar)); 2418 } 2419 2420 static jshortArray NewShortArray(JNIEnv* env, jsize length) { 2421 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2422 Primitive::kPrimShort)); 2423 } 2424 2425 static jintArray NewIntArray(JNIEnv* env, jsize length) { 2426 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt)); 2427 } 2428 2429 static jlongArray NewLongArray(JNIEnv* env, jsize length) { 2430 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2431 Primitive::kPrimLong)); 2432 } 2433 2434 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) { 2435 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2436 Primitive::kPrimFloat)); 2437 } 2438 2439 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) { 2440 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2441 Primitive::kPrimDouble)); 2442 } 2443 2444 // NOLINT added to avoid wrong warning/fix from clang-tidy. 2445 #define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \ 2446 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \ 2447 return reinterpret_cast<ctype*>( /* NOLINT */ \ 2448 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \ 2449 } \ 2450 \ 2451 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \ 2452 jint mode) { \ 2453 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \ 2454 } \ 2455 \ 2456 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 2457 ctype* buf) { /* NOLINT */ \ 2458 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 2459 } \ 2460 \ 2461 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 2462 const ctype* buf) { \ 2463 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 2464 } 2465 2466 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean) 2467 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte) 2468 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar) 2469 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort) 2470 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt) 2471 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong) 2472 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat) 2473 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble) 2474 #undef PRIMITIVE_ARRAY_FUNCTIONS 2475 2476 static jint MonitorEnter(JNIEnv* env, jobject obj) { 2477 ScopedObjectAccess soa(env); 2478 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2479 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2480 if (sc.Check(soa, true, "EL", args)) { 2481 if (obj != nullptr) { 2482 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj); 2483 } 2484 JniValueType result; 2485 result.i = baseEnv(env)->MonitorEnter(env, obj); 2486 if (sc.Check(soa, false, "i", &result)) { 2487 return result.i; 2488 } 2489 } 2490 return JNI_ERR; 2491 } 2492 2493 static jint MonitorExit(JNIEnv* env, jobject obj) { 2494 ScopedObjectAccess soa(env); 2495 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 2496 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2497 if (sc.Check(soa, true, "EL", args)) { 2498 if (obj != nullptr) { 2499 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj); 2500 } 2501 JniValueType result; 2502 result.i = baseEnv(env)->MonitorExit(env, obj); 2503 if (sc.Check(soa, false, "i", &result)) { 2504 return result.i; 2505 } 2506 } 2507 return JNI_ERR; 2508 } 2509 2510 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) { 2511 ScopedObjectAccess soa(env); 2512 ScopedCheck sc(kFlag_CritGet, __FUNCTION__); 2513 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 2514 if (sc.Check(soa, true, "Eap", args)) { 2515 JniValueType result; 2516 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy); 2517 if (ptr != nullptr && soa.ForceCopy()) { 2518 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr); 2519 } 2520 result.p = ptr; 2521 if (sc.Check(soa, false, "p", &result)) { 2522 return const_cast<void*>(result.p); 2523 } 2524 } 2525 return nullptr; 2526 } 2527 2528 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) { 2529 ScopedObjectAccess soa(env); 2530 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__); 2531 sc.CheckNonNull(carray); 2532 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}}; 2533 if (sc.Check(soa, true, "Eapr", args)) { 2534 if (soa.ForceCopy()) { 2535 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode); 2536 } 2537 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode); 2538 JniValueType result; 2539 result.V = nullptr; 2540 sc.Check(soa, false, "V", &result); 2541 } 2542 } 2543 2544 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) { 2545 ScopedObjectAccess soa(env); 2546 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2547 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}}; 2548 if (sc.Check(soa, true, "EpJ", args)) { 2549 JniValueType result; 2550 // Note: the validity of address and capacity are checked in the base implementation. 2551 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity); 2552 if (sc.Check(soa, false, "L", &result)) { 2553 return result.L; 2554 } 2555 } 2556 return nullptr; 2557 } 2558 2559 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) { 2560 ScopedObjectAccess soa(env); 2561 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2562 JniValueType args[2] = {{.E = env}, {.L = buf}}; 2563 if (sc.Check(soa, true, "EL", args)) { 2564 JniValueType result; 2565 // Note: this is implemented in the base environment by a GetLongField which will sanity 2566 // check the type of buf in GetLongField above. 2567 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf); 2568 if (sc.Check(soa, false, "p", &result)) { 2569 return const_cast<void*>(result.p); 2570 } 2571 } 2572 return nullptr; 2573 } 2574 2575 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) { 2576 ScopedObjectAccess soa(env); 2577 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2578 JniValueType args[2] = {{.E = env}, {.L = buf}}; 2579 if (sc.Check(soa, true, "EL", args)) { 2580 JniValueType result; 2581 // Note: this is implemented in the base environment by a GetIntField which will sanity 2582 // check the type of buf in GetIntField above. 2583 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf); 2584 if (sc.Check(soa, false, "J", &result)) { 2585 return result.J; 2586 } 2587 } 2588 return JNI_ERR; 2589 } 2590 2591 private: 2592 static JavaVMExt* GetJavaVMExt(JNIEnv* env) { 2593 return reinterpret_cast<JNIEnvExt*>(env)->vm; 2594 } 2595 2596 static const JNINativeInterface* baseEnv(JNIEnv* env) { 2597 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions; 2598 } 2599 2600 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 2601 ScopedObjectAccess soa(env); 2602 ScopedCheck sc(kFlag_Default, function_name); 2603 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2604 if (sc.Check(soa, true, "EL", args)) { 2605 JniValueType result; 2606 switch (kind) { 2607 case kGlobal: 2608 result.L = baseEnv(env)->NewGlobalRef(env, obj); 2609 break; 2610 case kLocal: 2611 result.L = baseEnv(env)->NewLocalRef(env, obj); 2612 break; 2613 case kWeakGlobal: 2614 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj); 2615 break; 2616 default: 2617 LOG(FATAL) << "Unexpected reference kind: " << kind; 2618 } 2619 if (sc.Check(soa, false, "L", &result)) { 2620 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE); 2621 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L)); 2622 return result.L; 2623 } 2624 } 2625 return nullptr; 2626 } 2627 2628 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 2629 ScopedObjectAccess soa(env); 2630 ScopedCheck sc(kFlag_ExcepOkay, function_name); 2631 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2632 sc.Check(soa, true, "EL", args); 2633 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) { 2634 JniValueType result; 2635 switch (kind) { 2636 case kGlobal: 2637 baseEnv(env)->DeleteGlobalRef(env, obj); 2638 break; 2639 case kLocal: 2640 baseEnv(env)->DeleteLocalRef(env, obj); 2641 break; 2642 case kWeakGlobal: 2643 baseEnv(env)->DeleteWeakGlobalRef(env, obj); 2644 break; 2645 default: 2646 LOG(FATAL) << "Unexpected reference kind: " << kind; 2647 } 2648 result.V = nullptr; 2649 sc.Check(soa, false, "V", &result); 2650 } 2651 } 2652 2653 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c, 2654 const char* name, const char* sig, bool is_static) { 2655 ScopedObjectAccess soa(env); 2656 ScopedCheck sc(kFlag_Default, function_name); 2657 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 2658 if (sc.Check(soa, true, "Ecuu", args)) { 2659 JniValueType result; 2660 if (is_static) { 2661 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig); 2662 } else { 2663 result.m = baseEnv(env)->GetMethodID(env, c, name, sig); 2664 } 2665 if (sc.Check(soa, false, "m", &result)) { 2666 return result.m; 2667 } 2668 } 2669 return nullptr; 2670 } 2671 2672 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c, 2673 const char* name, const char* sig, bool is_static) { 2674 ScopedObjectAccess soa(env); 2675 ScopedCheck sc(kFlag_Default, function_name); 2676 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 2677 if (sc.Check(soa, true, "Ecuu", args)) { 2678 JniValueType result; 2679 if (is_static) { 2680 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig); 2681 } else { 2682 result.f = baseEnv(env)->GetFieldID(env, c, name, sig); 2683 } 2684 if (sc.Check(soa, false, "f", &result)) { 2685 return result.f; 2686 } 2687 } 2688 return nullptr; 2689 } 2690 2691 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 2692 bool is_static, Primitive::Type type) { 2693 ScopedObjectAccess soa(env); 2694 ScopedCheck sc(kFlag_Default, function_name); 2695 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}}; 2696 JniValueType result; 2697 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) && 2698 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 2699 const char* result_check = nullptr; 2700 switch (type) { 2701 case Primitive::kPrimNot: 2702 if (is_static) { 2703 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid); 2704 } else { 2705 result.L = baseEnv(env)->GetObjectField(env, obj, fid); 2706 } 2707 result_check = "L"; 2708 break; 2709 case Primitive::kPrimBoolean: 2710 if (is_static) { 2711 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid); 2712 } else { 2713 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid); 2714 } 2715 result_check = "Z"; 2716 break; 2717 case Primitive::kPrimByte: 2718 if (is_static) { 2719 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid); 2720 } else { 2721 result.B = baseEnv(env)->GetByteField(env, obj, fid); 2722 } 2723 result_check = "B"; 2724 break; 2725 case Primitive::kPrimChar: 2726 if (is_static) { 2727 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid); 2728 } else { 2729 result.C = baseEnv(env)->GetCharField(env, obj, fid); 2730 } 2731 result_check = "C"; 2732 break; 2733 case Primitive::kPrimShort: 2734 if (is_static) { 2735 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid); 2736 } else { 2737 result.S = baseEnv(env)->GetShortField(env, obj, fid); 2738 } 2739 result_check = "S"; 2740 break; 2741 case Primitive::kPrimInt: 2742 if (is_static) { 2743 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid); 2744 } else { 2745 result.I = baseEnv(env)->GetIntField(env, obj, fid); 2746 } 2747 result_check = "I"; 2748 break; 2749 case Primitive::kPrimLong: 2750 if (is_static) { 2751 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid); 2752 } else { 2753 result.J = baseEnv(env)->GetLongField(env, obj, fid); 2754 } 2755 result_check = "J"; 2756 break; 2757 case Primitive::kPrimFloat: 2758 if (is_static) { 2759 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid); 2760 } else { 2761 result.F = baseEnv(env)->GetFloatField(env, obj, fid); 2762 } 2763 result_check = "F"; 2764 break; 2765 case Primitive::kPrimDouble: 2766 if (is_static) { 2767 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid); 2768 } else { 2769 result.D = baseEnv(env)->GetDoubleField(env, obj, fid); 2770 } 2771 result_check = "D"; 2772 break; 2773 case Primitive::kPrimVoid: 2774 LOG(FATAL) << "Unexpected type: " << type; 2775 break; 2776 } 2777 if (sc.Check(soa, false, result_check, &result)) { 2778 return result; 2779 } 2780 } 2781 result.J = 0; 2782 return result; 2783 } 2784 2785 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 2786 bool is_static, Primitive::Type type, JniValueType value) { 2787 ScopedObjectAccess soa(env); 2788 ScopedCheck sc(kFlag_Default, function_name); 2789 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value}; 2790 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f', 2791 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'}; 2792 if (sc.Check(soa, true, sig, args) && 2793 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 2794 switch (type) { 2795 case Primitive::kPrimNot: 2796 if (is_static) { 2797 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L); 2798 } else { 2799 baseEnv(env)->SetObjectField(env, obj, fid, value.L); 2800 } 2801 break; 2802 case Primitive::kPrimBoolean: 2803 if (is_static) { 2804 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z); 2805 } else { 2806 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z); 2807 } 2808 break; 2809 case Primitive::kPrimByte: 2810 if (is_static) { 2811 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B); 2812 } else { 2813 baseEnv(env)->SetByteField(env, obj, fid, value.B); 2814 } 2815 break; 2816 case Primitive::kPrimChar: 2817 if (is_static) { 2818 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C); 2819 } else { 2820 baseEnv(env)->SetCharField(env, obj, fid, value.C); 2821 } 2822 break; 2823 case Primitive::kPrimShort: 2824 if (is_static) { 2825 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S); 2826 } else { 2827 baseEnv(env)->SetShortField(env, obj, fid, value.S); 2828 } 2829 break; 2830 case Primitive::kPrimInt: 2831 if (is_static) { 2832 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I); 2833 } else { 2834 baseEnv(env)->SetIntField(env, obj, fid, value.I); 2835 } 2836 break; 2837 case Primitive::kPrimLong: 2838 if (is_static) { 2839 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J); 2840 } else { 2841 baseEnv(env)->SetLongField(env, obj, fid, value.J); 2842 } 2843 break; 2844 case Primitive::kPrimFloat: 2845 if (is_static) { 2846 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F); 2847 } else { 2848 baseEnv(env)->SetFloatField(env, obj, fid, value.F); 2849 } 2850 break; 2851 case Primitive::kPrimDouble: 2852 if (is_static) { 2853 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D); 2854 } else { 2855 baseEnv(env)->SetDoubleField(env, obj, fid, value.D); 2856 } 2857 break; 2858 case Primitive::kPrimVoid: 2859 LOG(FATAL) << "Unexpected type: " << type; 2860 break; 2861 } 2862 JniValueType result; 2863 result.V = nullptr; 2864 sc.Check(soa, false, "V", &result); 2865 } 2866 } 2867 2868 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj, 2869 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs) 2870 REQUIRES_SHARED(Locks::mutator_lock_) { 2871 bool checked; 2872 switch (invoke) { 2873 case kVirtual: { 2874 DCHECK(c == nullptr); 2875 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}}; 2876 checked = sc.Check(soa, true, "ELm.", args); 2877 break; 2878 } 2879 case kDirect: { 2880 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}}; 2881 checked = sc.Check(soa, true, "ELcm.", args); 2882 break; 2883 } 2884 case kStatic: { 2885 DCHECK(obj == nullptr); 2886 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}}; 2887 checked = sc.Check(soa, true, "Ecm.", args); 2888 break; 2889 } 2890 default: 2891 LOG(FATAL) << "Unexpected invoke: " << invoke; 2892 checked = false; 2893 break; 2894 } 2895 return checked; 2896 } 2897 2898 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c, 2899 jmethodID mid, jvalue* vargs, Primitive::Type type, 2900 InvokeType invoke) { 2901 ScopedObjectAccess soa(env); 2902 ScopedCheck sc(kFlag_Default, function_name); 2903 JniValueType result; 2904 VarArgs rest(mid, vargs); 2905 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) && 2906 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 2907 const char* result_check; 2908 switch (type) { 2909 case Primitive::kPrimNot: 2910 result_check = "L"; 2911 switch (invoke) { 2912 case kVirtual: 2913 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs); 2914 break; 2915 case kDirect: 2916 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs); 2917 break; 2918 case kStatic: 2919 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs); 2920 break; 2921 default: 2922 break; 2923 } 2924 break; 2925 case Primitive::kPrimBoolean: 2926 result_check = "Z"; 2927 switch (invoke) { 2928 case kVirtual: 2929 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs); 2930 break; 2931 case kDirect: 2932 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs); 2933 break; 2934 case kStatic: 2935 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs); 2936 break; 2937 default: 2938 break; 2939 } 2940 break; 2941 case Primitive::kPrimByte: 2942 result_check = "B"; 2943 switch (invoke) { 2944 case kVirtual: 2945 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs); 2946 break; 2947 case kDirect: 2948 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs); 2949 break; 2950 case kStatic: 2951 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs); 2952 break; 2953 default: 2954 break; 2955 } 2956 break; 2957 case Primitive::kPrimChar: 2958 result_check = "C"; 2959 switch (invoke) { 2960 case kVirtual: 2961 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs); 2962 break; 2963 case kDirect: 2964 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs); 2965 break; 2966 case kStatic: 2967 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs); 2968 break; 2969 default: 2970 break; 2971 } 2972 break; 2973 case Primitive::kPrimShort: 2974 result_check = "S"; 2975 switch (invoke) { 2976 case kVirtual: 2977 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs); 2978 break; 2979 case kDirect: 2980 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs); 2981 break; 2982 case kStatic: 2983 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs); 2984 break; 2985 default: 2986 break; 2987 } 2988 break; 2989 case Primitive::kPrimInt: 2990 result_check = "I"; 2991 switch (invoke) { 2992 case kVirtual: 2993 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs); 2994 break; 2995 case kDirect: 2996 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs); 2997 break; 2998 case kStatic: 2999 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs); 3000 break; 3001 default: 3002 break; 3003 } 3004 break; 3005 case Primitive::kPrimLong: 3006 result_check = "J"; 3007 switch (invoke) { 3008 case kVirtual: 3009 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs); 3010 break; 3011 case kDirect: 3012 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs); 3013 break; 3014 case kStatic: 3015 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs); 3016 break; 3017 default: 3018 break; 3019 } 3020 break; 3021 case Primitive::kPrimFloat: 3022 result_check = "F"; 3023 switch (invoke) { 3024 case kVirtual: 3025 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs); 3026 break; 3027 case kDirect: 3028 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs); 3029 break; 3030 case kStatic: 3031 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs); 3032 break; 3033 default: 3034 break; 3035 } 3036 break; 3037 case Primitive::kPrimDouble: 3038 result_check = "D"; 3039 switch (invoke) { 3040 case kVirtual: 3041 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs); 3042 break; 3043 case kDirect: 3044 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs); 3045 break; 3046 case kStatic: 3047 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs); 3048 break; 3049 default: 3050 break; 3051 } 3052 break; 3053 case Primitive::kPrimVoid: 3054 result_check = "V"; 3055 result.V = nullptr; 3056 switch (invoke) { 3057 case kVirtual: 3058 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs); 3059 break; 3060 case kDirect: 3061 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs); 3062 break; 3063 case kStatic: 3064 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs); 3065 break; 3066 default: 3067 LOG(FATAL) << "Unexpected invoke: " << invoke; 3068 } 3069 break; 3070 default: 3071 LOG(FATAL) << "Unexpected return type: " << type; 3072 result_check = nullptr; 3073 } 3074 if (sc.Check(soa, false, result_check, &result)) { 3075 return result; 3076 } 3077 } 3078 result.J = 0; 3079 return result; 3080 } 3081 3082 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c, 3083 jmethodID mid, va_list vargs, Primitive::Type type, 3084 InvokeType invoke) { 3085 ScopedObjectAccess soa(env); 3086 ScopedCheck sc(kFlag_Default, function_name); 3087 JniValueType result; 3088 VarArgs rest(mid, vargs); 3089 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) && 3090 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 3091 const char* result_check; 3092 switch (type) { 3093 case Primitive::kPrimNot: 3094 result_check = "L"; 3095 switch (invoke) { 3096 case kVirtual: 3097 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs); 3098 break; 3099 case kDirect: 3100 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs); 3101 break; 3102 case kStatic: 3103 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs); 3104 break; 3105 default: 3106 LOG(FATAL) << "Unexpected invoke: " << invoke; 3107 } 3108 break; 3109 case Primitive::kPrimBoolean: 3110 result_check = "Z"; 3111 switch (invoke) { 3112 case kVirtual: 3113 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs); 3114 break; 3115 case kDirect: 3116 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs); 3117 break; 3118 case kStatic: 3119 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs); 3120 break; 3121 default: 3122 LOG(FATAL) << "Unexpected invoke: " << invoke; 3123 } 3124 break; 3125 case Primitive::kPrimByte: 3126 result_check = "B"; 3127 switch (invoke) { 3128 case kVirtual: 3129 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs); 3130 break; 3131 case kDirect: 3132 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs); 3133 break; 3134 case kStatic: 3135 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs); 3136 break; 3137 default: 3138 LOG(FATAL) << "Unexpected invoke: " << invoke; 3139 } 3140 break; 3141 case Primitive::kPrimChar: 3142 result_check = "C"; 3143 switch (invoke) { 3144 case kVirtual: 3145 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs); 3146 break; 3147 case kDirect: 3148 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs); 3149 break; 3150 case kStatic: 3151 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs); 3152 break; 3153 default: 3154 LOG(FATAL) << "Unexpected invoke: " << invoke; 3155 } 3156 break; 3157 case Primitive::kPrimShort: 3158 result_check = "S"; 3159 switch (invoke) { 3160 case kVirtual: 3161 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs); 3162 break; 3163 case kDirect: 3164 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs); 3165 break; 3166 case kStatic: 3167 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs); 3168 break; 3169 default: 3170 LOG(FATAL) << "Unexpected invoke: " << invoke; 3171 } 3172 break; 3173 case Primitive::kPrimInt: 3174 result_check = "I"; 3175 switch (invoke) { 3176 case kVirtual: 3177 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs); 3178 break; 3179 case kDirect: 3180 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs); 3181 break; 3182 case kStatic: 3183 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs); 3184 break; 3185 default: 3186 LOG(FATAL) << "Unexpected invoke: " << invoke; 3187 } 3188 break; 3189 case Primitive::kPrimLong: 3190 result_check = "J"; 3191 switch (invoke) { 3192 case kVirtual: 3193 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs); 3194 break; 3195 case kDirect: 3196 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs); 3197 break; 3198 case kStatic: 3199 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs); 3200 break; 3201 default: 3202 LOG(FATAL) << "Unexpected invoke: " << invoke; 3203 } 3204 break; 3205 case Primitive::kPrimFloat: 3206 result_check = "F"; 3207 switch (invoke) { 3208 case kVirtual: 3209 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs); 3210 break; 3211 case kDirect: 3212 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs); 3213 break; 3214 case kStatic: 3215 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs); 3216 break; 3217 default: 3218 LOG(FATAL) << "Unexpected invoke: " << invoke; 3219 } 3220 break; 3221 case Primitive::kPrimDouble: 3222 result_check = "D"; 3223 switch (invoke) { 3224 case kVirtual: 3225 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs); 3226 break; 3227 case kDirect: 3228 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs); 3229 break; 3230 case kStatic: 3231 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs); 3232 break; 3233 default: 3234 LOG(FATAL) << "Unexpected invoke: " << invoke; 3235 } 3236 break; 3237 case Primitive::kPrimVoid: 3238 result_check = "V"; 3239 result.V = nullptr; 3240 switch (invoke) { 3241 case kVirtual: 3242 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs); 3243 break; 3244 case kDirect: 3245 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs); 3246 break; 3247 case kStatic: 3248 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs); 3249 break; 3250 default: 3251 LOG(FATAL) << "Unexpected invoke: " << invoke; 3252 } 3253 break; 3254 default: 3255 LOG(FATAL) << "Unexpected return type: " << type; 3256 result_check = nullptr; 3257 } 3258 if (sc.Check(soa, false, result_check, &result)) { 3259 return result; 3260 } 3261 } 3262 result.J = 0; 3263 return result; 3264 } 3265 3266 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 3267 jboolean* is_copy, bool utf, bool critical) { 3268 ScopedObjectAccess soa(env); 3269 int flags = critical ? kFlag_CritGet : kFlag_CritOkay; 3270 ScopedCheck sc(flags, function_name); 3271 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}}; 3272 if (sc.Check(soa, true, "Esp", args)) { 3273 JniValueType result; 3274 void* ptr; 3275 if (utf) { 3276 CHECK(!critical); 3277 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy)); 3278 result.u = reinterpret_cast<char*>(ptr); 3279 } else { 3280 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) : 3281 baseEnv(env)->GetStringChars(env, string, is_copy)); 3282 result.p = ptr; 3283 } 3284 // TODO: could we be smarter about not copying when local_is_copy? 3285 if (ptr != nullptr && soa.ForceCopy()) { 3286 if (utf) { 3287 size_t length_in_bytes = strlen(result.u) + 1; 3288 result.u = 3289 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false)); 3290 } else { 3291 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2; 3292 result.p = 3293 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false)); 3294 } 3295 if (is_copy != nullptr) { 3296 *is_copy = JNI_TRUE; 3297 } 3298 } 3299 if (sc.Check(soa, false, utf ? "u" : "p", &result)) { 3300 return utf ? result.u : result.p; 3301 } 3302 } 3303 return nullptr; 3304 } 3305 3306 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 3307 const void* chars, bool utf, bool critical) { 3308 ScopedObjectAccess soa(env); 3309 int flags = kFlag_ExcepOkay | kFlag_Release; 3310 if (critical) { 3311 flags |= kFlag_CritRelease; 3312 } 3313 ScopedCheck sc(flags, function_name); 3314 sc.CheckNonNull(chars); 3315 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false); 3316 if (force_copy_ok && soa.ForceCopy()) { 3317 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars))); 3318 } 3319 if (force_copy_ok) { 3320 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}}; 3321 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) { 3322 if (utf) { 3323 CHECK(!critical); 3324 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars)); 3325 } else { 3326 if (critical) { 3327 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars)); 3328 } else { 3329 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars)); 3330 } 3331 } 3332 JniValueType result; 3333 sc.Check(soa, false, "V", &result); 3334 } 3335 } 3336 } 3337 3338 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length, 3339 Primitive::Type type) { 3340 ScopedObjectAccess soa(env); 3341 ScopedCheck sc(kFlag_Default, function_name); 3342 JniValueType args[2] = {{.E = env}, {.z = length}}; 3343 if (sc.Check(soa, true, "Ez", args)) { 3344 JniValueType result; 3345 switch (type) { 3346 case Primitive::kPrimBoolean: 3347 result.a = baseEnv(env)->NewBooleanArray(env, length); 3348 break; 3349 case Primitive::kPrimByte: 3350 result.a = baseEnv(env)->NewByteArray(env, length); 3351 break; 3352 case Primitive::kPrimChar: 3353 result.a = baseEnv(env)->NewCharArray(env, length); 3354 break; 3355 case Primitive::kPrimShort: 3356 result.a = baseEnv(env)->NewShortArray(env, length); 3357 break; 3358 case Primitive::kPrimInt: 3359 result.a = baseEnv(env)->NewIntArray(env, length); 3360 break; 3361 case Primitive::kPrimLong: 3362 result.a = baseEnv(env)->NewLongArray(env, length); 3363 break; 3364 case Primitive::kPrimFloat: 3365 result.a = baseEnv(env)->NewFloatArray(env, length); 3366 break; 3367 case Primitive::kPrimDouble: 3368 result.a = baseEnv(env)->NewDoubleArray(env, length); 3369 break; 3370 default: 3371 LOG(FATAL) << "Unexpected primitive type: " << type; 3372 } 3373 if (sc.Check(soa, false, "a", &result)) { 3374 return result.a; 3375 } 3376 } 3377 return nullptr; 3378 } 3379 3380 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type, 3381 JNIEnv* env, jarray array, jboolean* is_copy) { 3382 ScopedObjectAccess soa(env); 3383 ScopedCheck sc(kFlag_Default, function_name); 3384 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 3385 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3386 JniValueType result; 3387 void* ptr = nullptr; 3388 switch (type) { 3389 case Primitive::kPrimBoolean: 3390 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array), 3391 is_copy); 3392 break; 3393 case Primitive::kPrimByte: 3394 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy); 3395 break; 3396 case Primitive::kPrimChar: 3397 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy); 3398 break; 3399 case Primitive::kPrimShort: 3400 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy); 3401 break; 3402 case Primitive::kPrimInt: 3403 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy); 3404 break; 3405 case Primitive::kPrimLong: 3406 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy); 3407 break; 3408 case Primitive::kPrimFloat: 3409 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy); 3410 break; 3411 case Primitive::kPrimDouble: 3412 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy); 3413 break; 3414 default: 3415 LOG(FATAL) << "Unexpected primitive type: " << type; 3416 } 3417 if (ptr != nullptr && soa.ForceCopy()) { 3418 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr); 3419 if (is_copy != nullptr) { 3420 *is_copy = JNI_TRUE; 3421 } 3422 } 3423 result.p = ptr; 3424 if (sc.Check(soa, false, "p", &result)) { 3425 return const_cast<void*>(result.p); 3426 } 3427 } 3428 return nullptr; 3429 } 3430 3431 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type, 3432 JNIEnv* env, jarray array, void* elems, jint mode) { 3433 ScopedObjectAccess soa(env); 3434 ScopedCheck sc(kFlag_ExcepOkay, function_name); 3435 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3436 if (soa.ForceCopy()) { 3437 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode); 3438 } 3439 if (!soa.ForceCopy() || elems != nullptr) { 3440 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}}; 3441 if (sc.Check(soa, true, "Eapr", args)) { 3442 switch (type) { 3443 case Primitive::kPrimBoolean: 3444 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array), 3445 reinterpret_cast<jboolean*>(elems), mode); 3446 break; 3447 case Primitive::kPrimByte: 3448 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array), 3449 reinterpret_cast<jbyte*>(elems), mode); 3450 break; 3451 case Primitive::kPrimChar: 3452 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array), 3453 reinterpret_cast<jchar*>(elems), mode); 3454 break; 3455 case Primitive::kPrimShort: 3456 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array), 3457 reinterpret_cast<jshort*>(elems), mode); 3458 break; 3459 case Primitive::kPrimInt: 3460 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array), 3461 reinterpret_cast<jint*>(elems), mode); 3462 break; 3463 case Primitive::kPrimLong: 3464 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array), 3465 reinterpret_cast<jlong*>(elems), mode); 3466 break; 3467 case Primitive::kPrimFloat: 3468 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array), 3469 reinterpret_cast<jfloat*>(elems), mode); 3470 break; 3471 case Primitive::kPrimDouble: 3472 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array), 3473 reinterpret_cast<jdouble*>(elems), mode); 3474 break; 3475 default: 3476 LOG(FATAL) << "Unexpected primitive type: " << type; 3477 } 3478 JniValueType result; 3479 result.V = nullptr; 3480 sc.Check(soa, false, "V", &result); 3481 } 3482 } 3483 } 3484 } 3485 3486 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 3487 jarray array, jsize start, jsize len, void* buf) { 3488 ScopedObjectAccess soa(env); 3489 ScopedCheck sc(kFlag_Default, function_name); 3490 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 3491 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 3492 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 3493 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3494 switch (type) { 3495 case Primitive::kPrimBoolean: 3496 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 3497 reinterpret_cast<jboolean*>(buf)); 3498 break; 3499 case Primitive::kPrimByte: 3500 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 3501 reinterpret_cast<jbyte*>(buf)); 3502 break; 3503 case Primitive::kPrimChar: 3504 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 3505 reinterpret_cast<jchar*>(buf)); 3506 break; 3507 case Primitive::kPrimShort: 3508 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 3509 reinterpret_cast<jshort*>(buf)); 3510 break; 3511 case Primitive::kPrimInt: 3512 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 3513 reinterpret_cast<jint*>(buf)); 3514 break; 3515 case Primitive::kPrimLong: 3516 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 3517 reinterpret_cast<jlong*>(buf)); 3518 break; 3519 case Primitive::kPrimFloat: 3520 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 3521 reinterpret_cast<jfloat*>(buf)); 3522 break; 3523 case Primitive::kPrimDouble: 3524 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 3525 reinterpret_cast<jdouble*>(buf)); 3526 break; 3527 default: 3528 LOG(FATAL) << "Unexpected primitive type: " << type; 3529 } 3530 JniValueType result; 3531 result.V = nullptr; 3532 sc.Check(soa, false, "V", &result); 3533 } 3534 } 3535 3536 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 3537 jarray array, jsize start, jsize len, const void* buf) { 3538 ScopedObjectAccess soa(env); 3539 ScopedCheck sc(kFlag_Default, function_name); 3540 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 3541 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 3542 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 3543 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3544 switch (type) { 3545 case Primitive::kPrimBoolean: 3546 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 3547 reinterpret_cast<const jboolean*>(buf)); 3548 break; 3549 case Primitive::kPrimByte: 3550 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 3551 reinterpret_cast<const jbyte*>(buf)); 3552 break; 3553 case Primitive::kPrimChar: 3554 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 3555 reinterpret_cast<const jchar*>(buf)); 3556 break; 3557 case Primitive::kPrimShort: 3558 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 3559 reinterpret_cast<const jshort*>(buf)); 3560 break; 3561 case Primitive::kPrimInt: 3562 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 3563 reinterpret_cast<const jint*>(buf)); 3564 break; 3565 case Primitive::kPrimLong: 3566 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 3567 reinterpret_cast<const jlong*>(buf)); 3568 break; 3569 case Primitive::kPrimFloat: 3570 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 3571 reinterpret_cast<const jfloat*>(buf)); 3572 break; 3573 case Primitive::kPrimDouble: 3574 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 3575 reinterpret_cast<const jdouble*>(buf)); 3576 break; 3577 default: 3578 LOG(FATAL) << "Unexpected primitive type: " << type; 3579 } 3580 JniValueType result; 3581 result.V = nullptr; 3582 sc.Check(soa, false, "V", &result); 3583 } 3584 } 3585 }; 3586 3587 const JNINativeInterface gCheckNativeInterface = { 3588 nullptr, // reserved0. 3589 nullptr, // reserved1. 3590 nullptr, // reserved2. 3591 nullptr, // reserved3. 3592 CheckJNI::GetVersion, 3593 CheckJNI::DefineClass, 3594 CheckJNI::FindClass, 3595 CheckJNI::FromReflectedMethod, 3596 CheckJNI::FromReflectedField, 3597 CheckJNI::ToReflectedMethod, 3598 CheckJNI::GetSuperclass, 3599 CheckJNI::IsAssignableFrom, 3600 CheckJNI::ToReflectedField, 3601 CheckJNI::Throw, 3602 CheckJNI::ThrowNew, 3603 CheckJNI::ExceptionOccurred, 3604 CheckJNI::ExceptionDescribe, 3605 CheckJNI::ExceptionClear, 3606 CheckJNI::FatalError, 3607 CheckJNI::PushLocalFrame, 3608 CheckJNI::PopLocalFrame, 3609 CheckJNI::NewGlobalRef, 3610 CheckJNI::DeleteGlobalRef, 3611 CheckJNI::DeleteLocalRef, 3612 CheckJNI::IsSameObject, 3613 CheckJNI::NewLocalRef, 3614 CheckJNI::EnsureLocalCapacity, 3615 CheckJNI::AllocObject, 3616 CheckJNI::NewObject, 3617 CheckJNI::NewObjectV, 3618 CheckJNI::NewObjectA, 3619 CheckJNI::GetObjectClass, 3620 CheckJNI::IsInstanceOf, 3621 CheckJNI::GetMethodID, 3622 CheckJNI::CallObjectMethod, 3623 CheckJNI::CallObjectMethodV, 3624 CheckJNI::CallObjectMethodA, 3625 CheckJNI::CallBooleanMethod, 3626 CheckJNI::CallBooleanMethodV, 3627 CheckJNI::CallBooleanMethodA, 3628 CheckJNI::CallByteMethod, 3629 CheckJNI::CallByteMethodV, 3630 CheckJNI::CallByteMethodA, 3631 CheckJNI::CallCharMethod, 3632 CheckJNI::CallCharMethodV, 3633 CheckJNI::CallCharMethodA, 3634 CheckJNI::CallShortMethod, 3635 CheckJNI::CallShortMethodV, 3636 CheckJNI::CallShortMethodA, 3637 CheckJNI::CallIntMethod, 3638 CheckJNI::CallIntMethodV, 3639 CheckJNI::CallIntMethodA, 3640 CheckJNI::CallLongMethod, 3641 CheckJNI::CallLongMethodV, 3642 CheckJNI::CallLongMethodA, 3643 CheckJNI::CallFloatMethod, 3644 CheckJNI::CallFloatMethodV, 3645 CheckJNI::CallFloatMethodA, 3646 CheckJNI::CallDoubleMethod, 3647 CheckJNI::CallDoubleMethodV, 3648 CheckJNI::CallDoubleMethodA, 3649 CheckJNI::CallVoidMethod, 3650 CheckJNI::CallVoidMethodV, 3651 CheckJNI::CallVoidMethodA, 3652 CheckJNI::CallNonvirtualObjectMethod, 3653 CheckJNI::CallNonvirtualObjectMethodV, 3654 CheckJNI::CallNonvirtualObjectMethodA, 3655 CheckJNI::CallNonvirtualBooleanMethod, 3656 CheckJNI::CallNonvirtualBooleanMethodV, 3657 CheckJNI::CallNonvirtualBooleanMethodA, 3658 CheckJNI::CallNonvirtualByteMethod, 3659 CheckJNI::CallNonvirtualByteMethodV, 3660 CheckJNI::CallNonvirtualByteMethodA, 3661 CheckJNI::CallNonvirtualCharMethod, 3662 CheckJNI::CallNonvirtualCharMethodV, 3663 CheckJNI::CallNonvirtualCharMethodA, 3664 CheckJNI::CallNonvirtualShortMethod, 3665 CheckJNI::CallNonvirtualShortMethodV, 3666 CheckJNI::CallNonvirtualShortMethodA, 3667 CheckJNI::CallNonvirtualIntMethod, 3668 CheckJNI::CallNonvirtualIntMethodV, 3669 CheckJNI::CallNonvirtualIntMethodA, 3670 CheckJNI::CallNonvirtualLongMethod, 3671 CheckJNI::CallNonvirtualLongMethodV, 3672 CheckJNI::CallNonvirtualLongMethodA, 3673 CheckJNI::CallNonvirtualFloatMethod, 3674 CheckJNI::CallNonvirtualFloatMethodV, 3675 CheckJNI::CallNonvirtualFloatMethodA, 3676 CheckJNI::CallNonvirtualDoubleMethod, 3677 CheckJNI::CallNonvirtualDoubleMethodV, 3678 CheckJNI::CallNonvirtualDoubleMethodA, 3679 CheckJNI::CallNonvirtualVoidMethod, 3680 CheckJNI::CallNonvirtualVoidMethodV, 3681 CheckJNI::CallNonvirtualVoidMethodA, 3682 CheckJNI::GetFieldID, 3683 CheckJNI::GetObjectField, 3684 CheckJNI::GetBooleanField, 3685 CheckJNI::GetByteField, 3686 CheckJNI::GetCharField, 3687 CheckJNI::GetShortField, 3688 CheckJNI::GetIntField, 3689 CheckJNI::GetLongField, 3690 CheckJNI::GetFloatField, 3691 CheckJNI::GetDoubleField, 3692 CheckJNI::SetObjectField, 3693 CheckJNI::SetBooleanField, 3694 CheckJNI::SetByteField, 3695 CheckJNI::SetCharField, 3696 CheckJNI::SetShortField, 3697 CheckJNI::SetIntField, 3698 CheckJNI::SetLongField, 3699 CheckJNI::SetFloatField, 3700 CheckJNI::SetDoubleField, 3701 CheckJNI::GetStaticMethodID, 3702 CheckJNI::CallStaticObjectMethod, 3703 CheckJNI::CallStaticObjectMethodV, 3704 CheckJNI::CallStaticObjectMethodA, 3705 CheckJNI::CallStaticBooleanMethod, 3706 CheckJNI::CallStaticBooleanMethodV, 3707 CheckJNI::CallStaticBooleanMethodA, 3708 CheckJNI::CallStaticByteMethod, 3709 CheckJNI::CallStaticByteMethodV, 3710 CheckJNI::CallStaticByteMethodA, 3711 CheckJNI::CallStaticCharMethod, 3712 CheckJNI::CallStaticCharMethodV, 3713 CheckJNI::CallStaticCharMethodA, 3714 CheckJNI::CallStaticShortMethod, 3715 CheckJNI::CallStaticShortMethodV, 3716 CheckJNI::CallStaticShortMethodA, 3717 CheckJNI::CallStaticIntMethod, 3718 CheckJNI::CallStaticIntMethodV, 3719 CheckJNI::CallStaticIntMethodA, 3720 CheckJNI::CallStaticLongMethod, 3721 CheckJNI::CallStaticLongMethodV, 3722 CheckJNI::CallStaticLongMethodA, 3723 CheckJNI::CallStaticFloatMethod, 3724 CheckJNI::CallStaticFloatMethodV, 3725 CheckJNI::CallStaticFloatMethodA, 3726 CheckJNI::CallStaticDoubleMethod, 3727 CheckJNI::CallStaticDoubleMethodV, 3728 CheckJNI::CallStaticDoubleMethodA, 3729 CheckJNI::CallStaticVoidMethod, 3730 CheckJNI::CallStaticVoidMethodV, 3731 CheckJNI::CallStaticVoidMethodA, 3732 CheckJNI::GetStaticFieldID, 3733 CheckJNI::GetStaticObjectField, 3734 CheckJNI::GetStaticBooleanField, 3735 CheckJNI::GetStaticByteField, 3736 CheckJNI::GetStaticCharField, 3737 CheckJNI::GetStaticShortField, 3738 CheckJNI::GetStaticIntField, 3739 CheckJNI::GetStaticLongField, 3740 CheckJNI::GetStaticFloatField, 3741 CheckJNI::GetStaticDoubleField, 3742 CheckJNI::SetStaticObjectField, 3743 CheckJNI::SetStaticBooleanField, 3744 CheckJNI::SetStaticByteField, 3745 CheckJNI::SetStaticCharField, 3746 CheckJNI::SetStaticShortField, 3747 CheckJNI::SetStaticIntField, 3748 CheckJNI::SetStaticLongField, 3749 CheckJNI::SetStaticFloatField, 3750 CheckJNI::SetStaticDoubleField, 3751 CheckJNI::NewString, 3752 CheckJNI::GetStringLength, 3753 CheckJNI::GetStringChars, 3754 CheckJNI::ReleaseStringChars, 3755 CheckJNI::NewStringUTF, 3756 CheckJNI::GetStringUTFLength, 3757 CheckJNI::GetStringUTFChars, 3758 CheckJNI::ReleaseStringUTFChars, 3759 CheckJNI::GetArrayLength, 3760 CheckJNI::NewObjectArray, 3761 CheckJNI::GetObjectArrayElement, 3762 CheckJNI::SetObjectArrayElement, 3763 CheckJNI::NewBooleanArray, 3764 CheckJNI::NewByteArray, 3765 CheckJNI::NewCharArray, 3766 CheckJNI::NewShortArray, 3767 CheckJNI::NewIntArray, 3768 CheckJNI::NewLongArray, 3769 CheckJNI::NewFloatArray, 3770 CheckJNI::NewDoubleArray, 3771 CheckJNI::GetBooleanArrayElements, 3772 CheckJNI::GetByteArrayElements, 3773 CheckJNI::GetCharArrayElements, 3774 CheckJNI::GetShortArrayElements, 3775 CheckJNI::GetIntArrayElements, 3776 CheckJNI::GetLongArrayElements, 3777 CheckJNI::GetFloatArrayElements, 3778 CheckJNI::GetDoubleArrayElements, 3779 CheckJNI::ReleaseBooleanArrayElements, 3780 CheckJNI::ReleaseByteArrayElements, 3781 CheckJNI::ReleaseCharArrayElements, 3782 CheckJNI::ReleaseShortArrayElements, 3783 CheckJNI::ReleaseIntArrayElements, 3784 CheckJNI::ReleaseLongArrayElements, 3785 CheckJNI::ReleaseFloatArrayElements, 3786 CheckJNI::ReleaseDoubleArrayElements, 3787 CheckJNI::GetBooleanArrayRegion, 3788 CheckJNI::GetByteArrayRegion, 3789 CheckJNI::GetCharArrayRegion, 3790 CheckJNI::GetShortArrayRegion, 3791 CheckJNI::GetIntArrayRegion, 3792 CheckJNI::GetLongArrayRegion, 3793 CheckJNI::GetFloatArrayRegion, 3794 CheckJNI::GetDoubleArrayRegion, 3795 CheckJNI::SetBooleanArrayRegion, 3796 CheckJNI::SetByteArrayRegion, 3797 CheckJNI::SetCharArrayRegion, 3798 CheckJNI::SetShortArrayRegion, 3799 CheckJNI::SetIntArrayRegion, 3800 CheckJNI::SetLongArrayRegion, 3801 CheckJNI::SetFloatArrayRegion, 3802 CheckJNI::SetDoubleArrayRegion, 3803 CheckJNI::RegisterNatives, 3804 CheckJNI::UnregisterNatives, 3805 CheckJNI::MonitorEnter, 3806 CheckJNI::MonitorExit, 3807 CheckJNI::GetJavaVM, 3808 CheckJNI::GetStringRegion, 3809 CheckJNI::GetStringUTFRegion, 3810 CheckJNI::GetPrimitiveArrayCritical, 3811 CheckJNI::ReleasePrimitiveArrayCritical, 3812 CheckJNI::GetStringCritical, 3813 CheckJNI::ReleaseStringCritical, 3814 CheckJNI::NewWeakGlobalRef, 3815 CheckJNI::DeleteWeakGlobalRef, 3816 CheckJNI::ExceptionCheck, 3817 CheckJNI::NewDirectByteBuffer, 3818 CheckJNI::GetDirectBufferAddress, 3819 CheckJNI::GetDirectBufferCapacity, 3820 CheckJNI::GetObjectRefType, 3821 }; 3822 3823 const JNINativeInterface* GetCheckJniNativeInterface() { 3824 return &gCheckNativeInterface; 3825 } 3826 3827 class CheckJII { 3828 public: 3829 static jint DestroyJavaVM(JavaVM* vm) { 3830 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false); 3831 JniValueType args[1] = {{.v = vm}}; 3832 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 3833 JniValueType result; 3834 result.i = BaseVm(vm)->DestroyJavaVM(vm); 3835 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime, 3836 // which will delete the JavaVMExt. 3837 sc.CheckNonHeap(nullptr, false, "i", &result); 3838 return result.i; 3839 } 3840 3841 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 3842 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3843 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 3844 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 3845 JniValueType result; 3846 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args); 3847 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3848 return result.i; 3849 } 3850 3851 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 3852 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3853 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 3854 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 3855 JniValueType result; 3856 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args); 3857 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3858 return result.i; 3859 } 3860 3861 static jint DetachCurrentThread(JavaVM* vm) { 3862 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3863 JniValueType args[1] = {{.v = vm}}; 3864 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 3865 JniValueType result; 3866 result.i = BaseVm(vm)->DetachCurrentThread(vm); 3867 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3868 return result.i; 3869 } 3870 3871 static jint GetEnv(JavaVM* vm, void** p_env, jint version) { 3872 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3873 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}}; 3874 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args); 3875 JniValueType result; 3876 result.i = BaseVm(vm)->GetEnv(vm, p_env, version); 3877 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3878 return result.i; 3879 } 3880 3881 private: 3882 static const JNIInvokeInterface* BaseVm(JavaVM* vm) { 3883 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions(); 3884 } 3885 }; 3886 3887 const JNIInvokeInterface gCheckInvokeInterface = { 3888 nullptr, // reserved0 3889 nullptr, // reserved1 3890 nullptr, // reserved2 3891 CheckJII::DestroyJavaVM, 3892 CheckJII::AttachCurrentThread, 3893 CheckJII::DetachCurrentThread, 3894 CheckJII::GetEnv, 3895 CheckJII::AttachCurrentThreadAsDaemon 3896 }; 3897 3898 const JNIInvokeInterface* GetCheckJniInvokeInterface() { 3899 return &gCheckInvokeInterface; 3900 } 3901 3902 } // namespace art 3903