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