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.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 SHARED_REQUIRES(Locks::mutator_lock_) { 272 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(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 SHARED_REQUIRES(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 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 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 SHARED_REQUIRES(Locks::mutator_lock_) { 363 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 (f->GetDeclaringClass() != c) { 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 SHARED_REQUIRES(Locks::mutator_lock_) { 386 ArtMethod* m = CheckMethodID(soa, mid); 387 if (m == nullptr) { 388 return false; 389 } 390 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 SHARED_REQUIRES(Locks::mutator_lock_) { 407 ArtMethod* m = CheckMethodID(soa, mid); 408 if (m == nullptr) { 409 return false; 410 } 411 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 SHARED_REQUIRES(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 SHARED_REQUIRES(Locks::mutator_lock_) { 560 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 SHARED_REQUIRES(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 SHARED_REQUIRES(Locks::mutator_lock_) { 592 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 SHARED_REQUIRES(Locks::mutator_lock_) { 608 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); 612 return false; 613 } 614 return true; 615 } 616 617 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc) 618 SHARED_REQUIRES(Locks::mutator_lock_) { 619 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); 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 SHARED_REQUIRES(Locks::mutator_lock_) { 650 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); 653 return false; 654 } 655 return true; 656 } 657 658 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type) 659 SHARED_REQUIRES(Locks::mutator_lock_) { 660 if (!CheckArray(soa, array)) { 661 return false; 662 } 663 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 SHARED_REQUIRES(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 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 mirror::Class* c = o->AsClass(); 702 if (field->GetDeclaringClass() != c) { 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 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 SHARED_REQUIRES(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 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); 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); 781 return false; 782 } 783 } 784 785 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) { 786 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 787 AbortF("%s is an invalid %s: %p (%p)", 788 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), 789 java_object, obj); 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 SHARED_REQUIRES(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 SHARED_REQUIRES(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 SHARED_REQUIRES(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 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 SHARED_REQUIRES(Locks::mutator_lock_) { 1105 if (UNLIKELY(java_array == nullptr)) { 1106 AbortF("jarray was NULL"); 1107 return false; 1108 } 1109 1110 mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 1111 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) { 1112 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 1113 AbortF("jarray is an invalid %s: %p (%p)", 1114 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), 1115 java_array, a); 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 SHARED_REQUIRES(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(ERROR)); 1150 AbortF("invalid jfieldID: %p", fid); 1151 return nullptr; 1152 } 1153 return f; 1154 } 1155 1156 ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid) 1157 SHARED_REQUIRES(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(ERROR)); 1166 AbortF("invalid jmethodID: %p", mid); 1167 return nullptr; 1168 } 1169 return m; 1170 } 1171 1172 bool CheckThread(JNIEnv* env) SHARED_REQUIRES(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 *correct* 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 AbortF("thread %s using JNIEnv* from thread %s", 1186 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*self).c_str()); 1187 return false; 1188 } 1189 1190 // Verify that, if this thread previously made a critical "get" call, we 1191 // do the corresponding "release" call before we try anything else. 1192 switch (flags_ & kFlag_CritMask) { 1193 case kFlag_CritOkay: // okay to call this method 1194 break; 1195 case kFlag_CritBad: // not okay to call 1196 if (threadEnv->critical) { 1197 AbortF("thread %s using JNI after critical get", 1198 ToStr<Thread>(*self).c_str()); 1199 return false; 1200 } 1201 break; 1202 case kFlag_CritGet: // this is a "get" call 1203 // Don't check here; we allow nested gets. 1204 threadEnv->critical++; 1205 break; 1206 case kFlag_CritRelease: // this is a "release" call 1207 threadEnv->critical--; 1208 if (threadEnv->critical < 0) { 1209 AbortF("thread %s called too many critical releases", 1210 ToStr<Thread>(*self).c_str()); 1211 return false; 1212 } 1213 break; 1214 default: 1215 LOG(FATAL) << "Bad flags (internal error): " << flags_; 1216 } 1217 1218 // Verify that, if an exception has been raised, the native code doesn't 1219 // make any JNI calls other than the Exception* methods. 1220 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) { 1221 mirror::Throwable* exception = self->GetException(); 1222 AbortF("JNI %s called with pending exception %s", 1223 function_name_, 1224 exception->Dump().c_str()); 1225 return false; 1226 } 1227 return true; 1228 } 1229 1230 // Verifies that "bytes" points to valid Modified UTF-8 data. 1231 bool CheckUtfString(const char* bytes, bool nullable) { 1232 if (bytes == nullptr) { 1233 if (!nullable) { 1234 AbortF("non-nullable const char* was NULL"); 1235 return false; 1236 } 1237 return true; 1238 } 1239 1240 const char* errorKind = nullptr; 1241 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind); 1242 if (errorKind != nullptr) { 1243 // This is an expensive loop that will resize often, but this isn't supposed to hit in 1244 // practice anyways. 1245 std::ostringstream oss; 1246 oss << std::hex; 1247 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes); 1248 while (*tmp != 0) { 1249 if (tmp == utf8) { 1250 oss << "<"; 1251 } 1252 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp); 1253 if (tmp == utf8) { 1254 oss << '>'; 1255 } 1256 tmp++; 1257 if (*tmp != 0) { 1258 oss << ' '; 1259 } 1260 } 1261 1262 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n" 1263 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str()); 1264 return false; 1265 } 1266 return true; 1267 } 1268 1269 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF 1270 // sequences in place of encoded surrogate pairs. 1271 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) { 1272 while (*bytes != '\0') { 1273 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1274 // Switch on the high four bits. 1275 switch (*utf8 >> 4) { 1276 case 0x00: 1277 case 0x01: 1278 case 0x02: 1279 case 0x03: 1280 case 0x04: 1281 case 0x05: 1282 case 0x06: 1283 case 0x07: 1284 // Bit pattern 0xxx. No need for any extra bytes. 1285 break; 1286 case 0x08: 1287 case 0x09: 1288 case 0x0a: 1289 case 0x0b: 1290 // Bit patterns 10xx, which are illegal start bytes. 1291 *errorKind = "start"; 1292 return utf8; 1293 case 0x0f: 1294 // Bit pattern 1111, which might be the start of a 4 byte sequence. 1295 if ((*utf8 & 0x08) == 0) { 1296 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence. 1297 // We consume one continuation byte here, and fall through to consume two more. 1298 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1299 if ((*utf8 & 0xc0) != 0x80) { 1300 *errorKind = "continuation"; 1301 return utf8; 1302 } 1303 } else { 1304 *errorKind = "start"; 1305 return utf8; 1306 } 1307 1308 // Fall through to the cases below to consume two more continuation bytes. 1309 FALLTHROUGH_INTENDED; 1310 case 0x0e: 1311 // Bit pattern 1110, so there are two additional bytes. 1312 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1313 if ((*utf8 & 0xc0) != 0x80) { 1314 *errorKind = "continuation"; 1315 return utf8; 1316 } 1317 1318 // Fall through to consume one more continuation byte. 1319 FALLTHROUGH_INTENDED; 1320 case 0x0c: 1321 case 0x0d: 1322 // Bit pattern 110x, so there is one additional byte. 1323 utf8 = reinterpret_cast<const uint8_t*>(bytes++); 1324 if ((*utf8 & 0xc0) != 0x80) { 1325 *errorKind = "continuation"; 1326 return utf8; 1327 } 1328 break; 1329 } 1330 } 1331 return 0; 1332 } 1333 1334 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) { 1335 va_list args; 1336 va_start(args, fmt); 1337 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args); 1338 va_end(args); 1339 } 1340 1341 // The name of the JNI function being checked. 1342 const char* const function_name_; 1343 1344 const int flags_; 1345 int indent_; 1346 1347 const bool has_method_; 1348 1349 DISALLOW_COPY_AND_ASSIGN(ScopedCheck); 1350}; 1351 1352/* 1353 * =========================================================================== 1354 * Guarded arrays 1355 * =========================================================================== 1356 */ 1357 1358/* this gets tucked in at the start of the buffer; struct size must be even */ 1359class GuardedCopy { 1360 public: 1361 /* 1362 * Create an over-sized buffer to hold the contents of "buf". Copy it in, 1363 * filling in the area around it with guard data. 1364 */ 1365 static void* Create(void* original_buf, size_t len, bool mod_okay) { 1366 const size_t new_len = LengthIncludingRedZones(len); 1367 uint8_t* const new_buf = DebugAlloc(new_len); 1368 1369 // If modification is not expected, grab a checksum. 1370 uLong adler = 0; 1371 if (!mod_okay) { 1372 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len); 1373 } 1374 1375 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler); 1376 1377 // Fill begin region with canary pattern. 1378 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 1379 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 1380 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j]; 1381 if (kCanary[j] == '\0') { 1382 j = 0; 1383 } else { 1384 j++; 1385 } 1386 } 1387 1388 // Copy the data in; note "len" could be zero. 1389 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len); 1390 1391 // Fill end region with canary pattern. 1392 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 1393 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j]; 1394 if (kCanary[j] == '\0') { 1395 j = 0; 1396 } else { 1397 j++; 1398 } 1399 } 1400 1401 return const_cast<uint8_t*>(copy->BufferWithinRedZones()); 1402 } 1403 1404 /* 1405 * Create a guarded copy of a primitive array. Modifications to the copied 1406 * data are allowed. Returns a pointer to the copied data. 1407 */ 1408 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy, 1409 void* original_ptr) { 1410 ScopedObjectAccess soa(env); 1411 1412 mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 1413 size_t component_size = a->GetClass()->GetComponentSize(); 1414 size_t byte_count = a->GetLength() * component_size; 1415 void* result = Create(original_ptr, byte_count, true); 1416 if (is_copy != nullptr) { 1417 *is_copy = JNI_TRUE; 1418 } 1419 return result; 1420 } 1421 1422 /* 1423 * Perform the array "release" operation, which may or may not copy data 1424 * back into the managed heap, and may or may not release the underlying storage. 1425 */ 1426 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, 1427 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf, 1428 int mode) { 1429 ScopedObjectAccess soa(env); 1430 if (!GuardedCopy::Check(function_name, embedded_buf, true)) { 1431 return nullptr; 1432 } 1433 GuardedCopy* const copy = FromEmbedded(embedded_buf); 1434 void* original_ptr = copy->original_ptr_; 1435 if (mode != JNI_ABORT) { 1436 memcpy(original_ptr, embedded_buf, copy->original_length_); 1437 } 1438 if (mode != JNI_COMMIT) { 1439 Destroy(embedded_buf); 1440 } 1441 return original_ptr; 1442 } 1443 1444 1445 /* 1446 * Free up the guard buffer, scrub it, and return the original pointer. 1447 */ 1448 static void* Destroy(void* embedded_buf) { 1449 GuardedCopy* copy = FromEmbedded(embedded_buf); 1450 void* original_ptr = const_cast<void*>(copy->original_ptr_); 1451 size_t len = LengthIncludingRedZones(copy->original_length_); 1452 DebugFree(copy, len); 1453 return original_ptr; 1454 } 1455 1456 /* 1457 * Verify the guard area and, if "modOkay" is false, that the data itself 1458 * has not been altered. 1459 * 1460 * The caller has already checked that "dataBuf" is non-null. 1461 */ 1462 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) { 1463 const GuardedCopy* copy = FromEmbedded(embedded_buf); 1464 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name); 1465 } 1466 1467 private: 1468 GuardedCopy(void* original_buf, size_t len, uLong adler) : 1469 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) { 1470 } 1471 1472 static uint8_t* DebugAlloc(size_t len) { 1473 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 1474 if (result == MAP_FAILED) { 1475 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed"; 1476 } 1477 return reinterpret_cast<uint8_t*>(result); 1478 } 1479 1480 static void DebugFree(void* buf, size_t len) { 1481 if (munmap(buf, len) != 0) { 1482 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed"; 1483 } 1484 } 1485 1486 static size_t LengthIncludingRedZones(size_t len) { 1487 return len + kRedZoneSize; 1488 } 1489 1490 // Get the GuardedCopy from the interior pointer. 1491 static GuardedCopy* FromEmbedded(void* embedded_buf) { 1492 return reinterpret_cast<GuardedCopy*>( 1493 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 1494 } 1495 1496 static const GuardedCopy* FromEmbedded(const void* embedded_buf) { 1497 return reinterpret_cast<const GuardedCopy*>( 1498 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2)); 1499 } 1500 1501 static void AbortF(const char* jni_function_name, const char* fmt, ...) { 1502 va_list args; 1503 va_start(args, fmt); 1504 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args); 1505 va_end(args); 1506 } 1507 1508 bool CheckHeader(const char* function_name, bool mod_okay) const { 1509 static const uint32_t kMagicCmp = kGuardMagic; 1510 1511 // Before we do anything with "pExtra", check the magic number. We 1512 // do the check with memcmp rather than "==" in case the pointer is 1513 // unaligned. If it points to completely bogus memory we're going 1514 // to crash, but there's no easy way around that. 1515 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) { 1516 uint8_t buf[4]; 1517 memcpy(buf, &magic_, 4); 1518 AbortF(function_name, 1519 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?", 1520 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian. 1521 return false; 1522 } 1523 1524 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we 1525 // told the client that we made a copy, there's no reason they can't alter the buffer. 1526 if (!mod_okay) { 1527 uLong computed_adler = 1528 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_); 1529 if (computed_adler != adler_) { 1530 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p", 1531 computed_adler, adler_, this); 1532 return false; 1533 } 1534 } 1535 return true; 1536 } 1537 1538 bool CheckRedZones(const char* function_name) const { 1539 // Check the begin red zone. 1540 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy); 1541 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) { 1542 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) { 1543 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i); 1544 return false; 1545 } 1546 if (kCanary[j] == '\0') { 1547 j = 0; 1548 } else { 1549 j++; 1550 } 1551 } 1552 1553 // Check end region. 1554 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) { 1555 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) { 1556 size_t offset_from_buffer_start = 1557 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]); 1558 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this, 1559 offset_from_buffer_start); 1560 return false; 1561 } 1562 if (kCanary[j] == '\0') { 1563 j = 0; 1564 } else { 1565 j++; 1566 } 1567 } 1568 return true; 1569 } 1570 1571 // Location that canary value will be written before the guarded region. 1572 const char* StartRedZone() const { 1573 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 1574 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy)); 1575 } 1576 1577 // Return the interior embedded buffer. 1578 const uint8_t* BufferWithinRedZones() const { 1579 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2); 1580 return embedded_buf; 1581 } 1582 1583 // Location that canary value will be written after the guarded region. 1584 const char* EndRedZone() const { 1585 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this); 1586 size_t buf_len = LengthIncludingRedZones(original_length_); 1587 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2))); 1588 } 1589 1590 static constexpr size_t kRedZoneSize = 512; 1591 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2; 1592 1593 // Value written before and after the guarded array. 1594 static const char* const kCanary; 1595 1596 static constexpr uint32_t kGuardMagic = 0xffd5aa96; 1597 1598 const uint32_t magic_; 1599 const uLong adler_; 1600 void* const original_ptr_; 1601 const size_t original_length_; 1602}; 1603const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE"; 1604 1605/* 1606 * =========================================================================== 1607 * JNI functions 1608 * =========================================================================== 1609 */ 1610 1611class CheckJNI { 1612 public: 1613 static jint GetVersion(JNIEnv* env) { 1614 ScopedObjectAccess soa(env); 1615 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1616 JniValueType args[1] = {{.E = env }}; 1617 if (sc.Check(soa, true, "E", args)) { 1618 JniValueType result; 1619 result.I = baseEnv(env)->GetVersion(env); 1620 if (sc.Check(soa, false, "I", &result)) { 1621 return result.I; 1622 } 1623 } 1624 return JNI_ERR; 1625 } 1626 1627 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) { 1628 ScopedObjectAccess soa(env); 1629 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1630 JniValueType args[2] = {{.E = env }, {.p = vm}}; 1631 if (sc.Check(soa, true, "Ep", args)) { 1632 JniValueType result; 1633 result.i = baseEnv(env)->GetJavaVM(env, vm); 1634 if (sc.Check(soa, false, "i", &result)) { 1635 return result.i; 1636 } 1637 } 1638 return JNI_ERR; 1639 } 1640 1641 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) { 1642 ScopedObjectAccess soa(env); 1643 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1644 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}}; 1645 if (sc.Check(soa, true, "EcpI", args)) { 1646 JniValueType result; 1647 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods); 1648 if (sc.Check(soa, false, "i", &result)) { 1649 return result.i; 1650 } 1651 } 1652 return JNI_ERR; 1653 } 1654 1655 static jint UnregisterNatives(JNIEnv* env, jclass c) { 1656 ScopedObjectAccess soa(env); 1657 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1658 JniValueType args[2] = {{.E = env }, {.c = c}}; 1659 if (sc.Check(soa, true, "Ec", args)) { 1660 JniValueType result; 1661 result.i = baseEnv(env)->UnregisterNatives(env, c); 1662 if (sc.Check(soa, false, "i", &result)) { 1663 return result.i; 1664 } 1665 } 1666 return JNI_ERR; 1667 } 1668 1669 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) { 1670 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to 1671 // know the object is invalid. The spec says that passing invalid objects or even ones that 1672 // are deleted isn't supported. 1673 ScopedObjectAccess soa(env); 1674 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1675 JniValueType args[2] = {{.E = env }, {.L = obj}}; 1676 if (sc.Check(soa, true, "EL", args)) { 1677 JniValueType result; 1678 result.w = baseEnv(env)->GetObjectRefType(env, obj); 1679 if (sc.Check(soa, false, "w", &result)) { 1680 return result.w; 1681 } 1682 } 1683 return JNIInvalidRefType; 1684 } 1685 1686 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, 1687 jsize bufLen) { 1688 ScopedObjectAccess soa(env); 1689 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1690 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}}; 1691 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) { 1692 JniValueType result; 1693 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen); 1694 if (sc.Check(soa, false, "c", &result)) { 1695 return result.c; 1696 } 1697 } 1698 return nullptr; 1699 } 1700 1701 static jclass FindClass(JNIEnv* env, const char* name) { 1702 ScopedObjectAccess soa(env); 1703 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1704 JniValueType args[2] = {{.E = env}, {.u = name}}; 1705 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) { 1706 JniValueType result; 1707 result.c = baseEnv(env)->FindClass(env, name); 1708 if (sc.Check(soa, false, "c", &result)) { 1709 return result.c; 1710 } 1711 } 1712 return nullptr; 1713 } 1714 1715 static jclass GetSuperclass(JNIEnv* env, jclass c) { 1716 ScopedObjectAccess soa(env); 1717 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1718 JniValueType args[2] = {{.E = env}, {.c = c}}; 1719 if (sc.Check(soa, true, "Ec", args)) { 1720 JniValueType result; 1721 result.c = baseEnv(env)->GetSuperclass(env, c); 1722 if (sc.Check(soa, false, "c", &result)) { 1723 return result.c; 1724 } 1725 } 1726 return nullptr; 1727 } 1728 1729 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) { 1730 ScopedObjectAccess soa(env); 1731 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1732 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}}; 1733 if (sc.Check(soa, true, "Ecc", args)) { 1734 JniValueType result; 1735 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2); 1736 if (sc.Check(soa, false, "b", &result)) { 1737 return result.b; 1738 } 1739 } 1740 return JNI_FALSE; 1741 } 1742 1743 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) { 1744 ScopedObjectAccess soa(env); 1745 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1746 JniValueType args[2] = {{.E = env}, {.L = method}}; 1747 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) { 1748 JniValueType result; 1749 result.m = baseEnv(env)->FromReflectedMethod(env, method); 1750 if (sc.Check(soa, false, "m", &result)) { 1751 return result.m; 1752 } 1753 } 1754 return nullptr; 1755 } 1756 1757 static jfieldID FromReflectedField(JNIEnv* env, jobject field) { 1758 ScopedObjectAccess soa(env); 1759 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1760 JniValueType args[2] = {{.E = env}, {.L = field}}; 1761 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) { 1762 JniValueType result; 1763 result.f = baseEnv(env)->FromReflectedField(env, field); 1764 if (sc.Check(soa, false, "f", &result)) { 1765 return result.f; 1766 } 1767 } 1768 return nullptr; 1769 } 1770 1771 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) { 1772 ScopedObjectAccess soa(env); 1773 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1774 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}}; 1775 if (sc.Check(soa, true, "Ecmb", args)) { 1776 JniValueType result; 1777 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic); 1778 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 1779 DCHECK(sc.CheckReflectedMethod(soa, result.L)); 1780 return result.L; 1781 } 1782 } 1783 return nullptr; 1784 } 1785 1786 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) { 1787 ScopedObjectAccess soa(env); 1788 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1789 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}}; 1790 if (sc.Check(soa, true, "Ecfb", args)) { 1791 JniValueType result; 1792 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic); 1793 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) { 1794 DCHECK(sc.CheckReflectedField(soa, result.L)); 1795 return result.L; 1796 } 1797 } 1798 return nullptr; 1799 } 1800 1801 static jint Throw(JNIEnv* env, jthrowable obj) { 1802 ScopedObjectAccess soa(env); 1803 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1804 JniValueType args[2] = {{.E = env}, {.t = obj}}; 1805 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) { 1806 JniValueType result; 1807 result.i = baseEnv(env)->Throw(env, obj); 1808 if (sc.Check(soa, false, "i", &result)) { 1809 return result.i; 1810 } 1811 } 1812 return JNI_ERR; 1813 } 1814 1815 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) { 1816 ScopedObjectAccess soa(env); 1817 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 1818 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}}; 1819 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) { 1820 JniValueType result; 1821 result.i = baseEnv(env)->ThrowNew(env, c, message); 1822 if (sc.Check(soa, false, "i", &result)) { 1823 return result.i; 1824 } 1825 } 1826 return JNI_ERR; 1827 } 1828 1829 static jthrowable ExceptionOccurred(JNIEnv* env) { 1830 ScopedObjectAccess soa(env); 1831 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1832 JniValueType args[1] = {{.E = env}}; 1833 if (sc.Check(soa, true, "E", args)) { 1834 JniValueType result; 1835 result.t = baseEnv(env)->ExceptionOccurred(env); 1836 if (sc.Check(soa, false, "t", &result)) { 1837 return result.t; 1838 } 1839 } 1840 return nullptr; 1841 } 1842 1843 static void ExceptionDescribe(JNIEnv* env) { 1844 ScopedObjectAccess soa(env); 1845 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1846 JniValueType args[1] = {{.E = env}}; 1847 if (sc.Check(soa, true, "E", args)) { 1848 JniValueType result; 1849 baseEnv(env)->ExceptionDescribe(env); 1850 result.V = nullptr; 1851 sc.Check(soa, false, "V", &result); 1852 } 1853 } 1854 1855 static void ExceptionClear(JNIEnv* env) { 1856 ScopedObjectAccess soa(env); 1857 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1858 JniValueType args[1] = {{.E = env}}; 1859 if (sc.Check(soa, true, "E", args)) { 1860 JniValueType result; 1861 baseEnv(env)->ExceptionClear(env); 1862 result.V = nullptr; 1863 sc.Check(soa, false, "V", &result); 1864 } 1865 } 1866 1867 static jboolean ExceptionCheck(JNIEnv* env) { 1868 ScopedObjectAccess soa(env); 1869 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__); 1870 JniValueType args[1] = {{.E = env}}; 1871 if (sc.Check(soa, true, "E", args)) { 1872 JniValueType result; 1873 result.b = baseEnv(env)->ExceptionCheck(env); 1874 if (sc.Check(soa, false, "b", &result)) { 1875 return result.b; 1876 } 1877 } 1878 return JNI_FALSE; 1879 } 1880 1881 static void FatalError(JNIEnv* env, const char* msg) { 1882 // The JNI specification doesn't say it's okay to call FatalError with a pending exception, 1883 // but you're about to abort anyway, and it's quite likely that you have a pending exception, 1884 // and it's not unimaginable that you don't know that you do. So we allow it. 1885 ScopedObjectAccess soa(env); 1886 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__); 1887 JniValueType args[2] = {{.E = env}, {.u = msg}}; 1888 if (sc.Check(soa, true, "Eu", args)) { 1889 JniValueType result; 1890 baseEnv(env)->FatalError(env, msg); 1891 // Unreachable. 1892 result.V = nullptr; 1893 sc.Check(soa, false, "V", &result); 1894 } 1895 } 1896 1897 static jint PushLocalFrame(JNIEnv* env, jint capacity) { 1898 ScopedObjectAccess soa(env); 1899 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1900 JniValueType args[2] = {{.E = env}, {.I = capacity}}; 1901 if (sc.Check(soa, true, "EI", args)) { 1902 JniValueType result; 1903 result.i = baseEnv(env)->PushLocalFrame(env, capacity); 1904 if (sc.Check(soa, false, "i", &result)) { 1905 return result.i; 1906 } 1907 } 1908 return JNI_ERR; 1909 } 1910 1911 static jobject PopLocalFrame(JNIEnv* env, jobject res) { 1912 ScopedObjectAccess soa(env); 1913 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 1914 JniValueType args[2] = {{.E = env}, {.L = res}}; 1915 if (sc.Check(soa, true, "EL", args)) { 1916 JniValueType result; 1917 result.L = baseEnv(env)->PopLocalFrame(env, res); 1918 sc.Check(soa, false, "L", &result); 1919 return result.L; 1920 } 1921 return nullptr; 1922 } 1923 1924 static jobject NewGlobalRef(JNIEnv* env, jobject obj) { 1925 return NewRef(__FUNCTION__, env, obj, kGlobal); 1926 } 1927 1928 static jobject NewLocalRef(JNIEnv* env, jobject obj) { 1929 return NewRef(__FUNCTION__, env, obj, kLocal); 1930 } 1931 1932 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { 1933 return NewRef(__FUNCTION__, env, obj, kWeakGlobal); 1934 } 1935 1936 static void DeleteGlobalRef(JNIEnv* env, jobject obj) { 1937 DeleteRef(__FUNCTION__, env, obj, kGlobal); 1938 } 1939 1940 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) { 1941 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal); 1942 } 1943 1944 static void DeleteLocalRef(JNIEnv* env, jobject obj) { 1945 DeleteRef(__FUNCTION__, env, obj, kLocal); 1946 } 1947 1948 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) { 1949 ScopedObjectAccess soa(env); 1950 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1951 JniValueType args[2] = {{.E = env}, {.I = capacity}}; 1952 if (sc.Check(soa, true, "EI", args)) { 1953 JniValueType result; 1954 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity); 1955 if (sc.Check(soa, false, "i", &result)) { 1956 return result.i; 1957 } 1958 } 1959 return JNI_ERR; 1960 } 1961 1962 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) { 1963 ScopedObjectAccess soa(env); 1964 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1965 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}}; 1966 if (sc.Check(soa, true, "ELL", args)) { 1967 JniValueType result; 1968 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2); 1969 if (sc.Check(soa, false, "b", &result)) { 1970 return result.b; 1971 } 1972 } 1973 return JNI_FALSE; 1974 } 1975 1976 static jobject AllocObject(JNIEnv* env, jclass c) { 1977 ScopedObjectAccess soa(env); 1978 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1979 JniValueType args[2] = {{.E = env}, {.c = c}}; 1980 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) { 1981 JniValueType result; 1982 result.L = baseEnv(env)->AllocObject(env, c); 1983 if (sc.Check(soa, false, "L", &result)) { 1984 return result.L; 1985 } 1986 } 1987 return nullptr; 1988 } 1989 1990 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 1991 ScopedObjectAccess soa(env); 1992 ScopedCheck sc(kFlag_Default, __FUNCTION__); 1993 VarArgs rest(mid, vargs); 1994 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}}; 1995 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 1996 sc.CheckConstructor(soa, mid)) { 1997 JniValueType result; 1998 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs); 1999 if (sc.Check(soa, false, "L", &result)) { 2000 return result.L; 2001 } 2002 } 2003 return nullptr; 2004 } 2005 2006 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) { 2007 va_list args; 2008 va_start(args, mid); 2009 jobject result = NewObjectV(env, c, mid, args); 2010 va_end(args); 2011 return result; 2012 } 2013 2014 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { 2015 ScopedObjectAccess soa(env); 2016 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2017 VarArgs rest(mid, vargs); 2018 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}}; 2019 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) && 2020 sc.CheckConstructor(soa, mid)) { 2021 JniValueType result; 2022 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs); 2023 if (sc.Check(soa, false, "L", &result)) { 2024 return result.L; 2025 } 2026 } 2027 return nullptr; 2028 } 2029 2030 static jclass GetObjectClass(JNIEnv* env, jobject obj) { 2031 ScopedObjectAccess soa(env); 2032 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2033 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2034 if (sc.Check(soa, true, "EL", args)) { 2035 JniValueType result; 2036 result.c = baseEnv(env)->GetObjectClass(env, obj); 2037 if (sc.Check(soa, false, "c", &result)) { 2038 return result.c; 2039 } 2040 } 2041 return nullptr; 2042 } 2043 2044 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) { 2045 ScopedObjectAccess soa(env); 2046 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2047 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}}; 2048 if (sc.Check(soa, true, "ELc", args)) { 2049 JniValueType result; 2050 result.b = baseEnv(env)->IsInstanceOf(env, obj, c); 2051 if (sc.Check(soa, false, "b", &result)) { 2052 return result.b; 2053 } 2054 } 2055 return JNI_FALSE; 2056 } 2057 2058 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2059 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false); 2060 } 2061 2062 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2063 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true); 2064 } 2065 2066 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2067 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false); 2068 } 2069 2070 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 2071 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true); 2072 } 2073 2074#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \ 2075 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \ 2076 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \ 2077 } \ 2078 \ 2079 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \ 2080 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \ 2081 } \ 2082 \ 2083 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \ 2084 JniValueType value; \ 2085 value.shorty = v; \ 2086 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \ 2087 } \ 2088 \ 2089 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \ 2090 JniValueType value; \ 2091 value.shorty = v; \ 2092 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \ 2093 } 2094 2095 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L) 2096 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z) 2097 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B) 2098 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C) 2099 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S) 2100 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I) 2101 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J) 2102 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F) 2103 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D) 2104#undef FIELD_ACCESSORS 2105 2106 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { 2107 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2108 } 2109 2110 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 2111 jvalue* vargs) { 2112 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2113 } 2114 2115 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { 2116 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2117 } 2118 2119 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { 2120 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2121 } 2122 2123 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, 2124 va_list vargs) { 2125 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2126 } 2127 2128 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { 2129 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2130 } 2131 2132 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { 2133 va_list vargs; 2134 va_start(vargs, mid); 2135 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual); 2136 va_end(vargs); 2137 } 2138 2139 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) { 2140 va_list vargs; 2141 va_start(vargs, mid); 2142 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect); 2143 va_end(vargs); 2144 } 2145 2146 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) { 2147 va_list vargs; 2148 va_start(vargs, mid); 2149 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic); 2150 va_end(vargs); 2151 } 2152 2153#define CALL(rtype, name, ptype, shorty) \ 2154 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \ 2155 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2156 } \ 2157 \ 2158 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2159 jvalue* vargs) { \ 2160 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2161 } \ 2162 \ 2163 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \ 2164 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2165 } \ 2166 \ 2167 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \ 2168 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2169 } \ 2170 \ 2171 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2172 va_list vargs) { \ 2173 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2174 } \ 2175 \ 2176 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \ 2177 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2178 } \ 2179 \ 2180 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \ 2181 va_list vargs; \ 2182 va_start(vargs, mid); \ 2183 rtype result = \ 2184 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \ 2185 va_end(vargs); \ 2186 return result; \ 2187 } \ 2188 \ 2189 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \ 2190 ...) { \ 2191 va_list vargs; \ 2192 va_start(vargs, mid); \ 2193 rtype result = \ 2194 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \ 2195 va_end(vargs); \ 2196 return result; \ 2197 } \ 2198 \ 2199 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \ 2200 va_list vargs; \ 2201 va_start(vargs, mid); \ 2202 rtype result = \ 2203 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \ 2204 va_end(vargs); \ 2205 return result; \ 2206 } 2207 2208 CALL(jobject, Object, Primitive::kPrimNot, L) 2209 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z) 2210 CALL(jbyte, Byte, Primitive::kPrimByte, B) 2211 CALL(jchar, Char, Primitive::kPrimChar, C) 2212 CALL(jshort, Short, Primitive::kPrimShort, S) 2213 CALL(jint, Int, Primitive::kPrimInt, I) 2214 CALL(jlong, Long, Primitive::kPrimLong, J) 2215 CALL(jfloat, Float, Primitive::kPrimFloat, F) 2216 CALL(jdouble, Double, Primitive::kPrimDouble, D) 2217#undef CALL 2218 2219 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) { 2220 ScopedObjectAccess soa(env); 2221 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2222 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}}; 2223 if (sc.Check(soa, true, "Epz", args)) { 2224 JniValueType result; 2225 result.s = baseEnv(env)->NewString(env, unicode_chars, len); 2226 if (sc.Check(soa, false, "s", &result)) { 2227 return result.s; 2228 } 2229 } 2230 return nullptr; 2231 } 2232 2233 static jstring NewStringUTF(JNIEnv* env, const char* chars) { 2234 ScopedObjectAccess soa(env); 2235 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__); 2236 JniValueType args[2] = {{.E = env}, {.u = chars}}; 2237 if (sc.Check(soa, true, "Eu", args)) { 2238 JniValueType result; 2239 // TODO: stale? show pointer and truncate string. 2240 result.s = baseEnv(env)->NewStringUTF(env, chars); 2241 if (sc.Check(soa, false, "s", &result)) { 2242 return result.s; 2243 } 2244 } 2245 return nullptr; 2246 } 2247 2248 static jsize GetStringLength(JNIEnv* env, jstring string) { 2249 ScopedObjectAccess soa(env); 2250 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2251 JniValueType args[2] = {{.E = env}, {.s = string}}; 2252 if (sc.Check(soa, true, "Es", args)) { 2253 JniValueType result; 2254 result.z = baseEnv(env)->GetStringLength(env, string); 2255 if (sc.Check(soa, false, "z", &result)) { 2256 return result.z; 2257 } 2258 } 2259 return JNI_ERR; 2260 } 2261 2262 static jsize GetStringUTFLength(JNIEnv* env, jstring string) { 2263 ScopedObjectAccess soa(env); 2264 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2265 JniValueType args[2] = {{.E = env}, {.s = string}}; 2266 if (sc.Check(soa, true, "Es", args)) { 2267 JniValueType result; 2268 result.z = baseEnv(env)->GetStringUTFLength(env, string); 2269 if (sc.Check(soa, false, "z", &result)) { 2270 return result.z; 2271 } 2272 } 2273 return JNI_ERR; 2274 } 2275 2276 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) { 2277 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 2278 is_copy, false, false)); 2279 } 2280 2281 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) { 2282 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string, 2283 is_copy, true, false)); 2284 } 2285 2286 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) { 2287 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string, 2288 is_copy, false, true)); 2289 } 2290 2291 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) { 2292 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false); 2293 } 2294 2295 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) { 2296 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false); 2297 } 2298 2299 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) { 2300 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true); 2301 } 2302 2303 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) { 2304 ScopedObjectAccess soa(env); 2305 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2306 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 2307 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 2308 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 2309 if (sc.Check(soa, true, "EsIIp", args)) { 2310 baseEnv(env)->GetStringRegion(env, string, start, len, buf); 2311 JniValueType result; 2312 result.V = nullptr; 2313 sc.Check(soa, false, "V", &result); 2314 } 2315 } 2316 2317 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) { 2318 ScopedObjectAccess soa(env); 2319 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2320 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}}; 2321 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 2322 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 2323 if (sc.Check(soa, true, "EsIIp", args)) { 2324 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf); 2325 JniValueType result; 2326 result.V = nullptr; 2327 sc.Check(soa, false, "V", &result); 2328 } 2329 } 2330 2331 static jsize GetArrayLength(JNIEnv* env, jarray array) { 2332 ScopedObjectAccess soa(env); 2333 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__); 2334 JniValueType args[2] = {{.E = env}, {.a = array}}; 2335 if (sc.Check(soa, true, "Ea", args)) { 2336 JniValueType result; 2337 result.z = baseEnv(env)->GetArrayLength(env, array); 2338 if (sc.Check(soa, false, "z", &result)) { 2339 return result.z; 2340 } 2341 } 2342 return JNI_ERR; 2343 } 2344 2345 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class, 2346 jobject initial_element) { 2347 ScopedObjectAccess soa(env); 2348 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2349 JniValueType args[4] = 2350 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}}; 2351 if (sc.Check(soa, true, "EzcL", args)) { 2352 JniValueType result; 2353 // Note: assignability tests of initial_element are done in the base implementation. 2354 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element); 2355 if (sc.Check(soa, false, "a", &result)) { 2356 return down_cast<jobjectArray>(result.a); 2357 } 2358 } 2359 return nullptr; 2360 } 2361 2362 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) { 2363 ScopedObjectAccess soa(env); 2364 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2365 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}}; 2366 if (sc.Check(soa, true, "Eaz", args)) { 2367 JniValueType result; 2368 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index); 2369 if (sc.Check(soa, false, "L", &result)) { 2370 return result.L; 2371 } 2372 } 2373 return nullptr; 2374 } 2375 2376 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) { 2377 ScopedObjectAccess soa(env); 2378 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2379 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}}; 2380 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in 2381 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result 2382 // in ArrayStoreExceptions. 2383 if (sc.Check(soa, true, "EaIL", args)) { 2384 baseEnv(env)->SetObjectArrayElement(env, array, index, value); 2385 JniValueType result; 2386 result.V = nullptr; 2387 sc.Check(soa, false, "V", &result); 2388 } 2389 } 2390 2391 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) { 2392 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2393 Primitive::kPrimBoolean)); 2394 } 2395 2396 static jbyteArray NewByteArray(JNIEnv* env, jsize length) { 2397 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2398 Primitive::kPrimByte)); 2399 } 2400 2401 static jcharArray NewCharArray(JNIEnv* env, jsize length) { 2402 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2403 Primitive::kPrimChar)); 2404 } 2405 2406 static jshortArray NewShortArray(JNIEnv* env, jsize length) { 2407 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2408 Primitive::kPrimShort)); 2409 } 2410 2411 static jintArray NewIntArray(JNIEnv* env, jsize length) { 2412 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt)); 2413 } 2414 2415 static jlongArray NewLongArray(JNIEnv* env, jsize length) { 2416 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2417 Primitive::kPrimLong)); 2418 } 2419 2420 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) { 2421 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2422 Primitive::kPrimFloat)); 2423 } 2424 2425 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) { 2426 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length, 2427 Primitive::kPrimDouble)); 2428 } 2429 2430#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \ 2431 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { \ 2432 return reinterpret_cast<ctype*>( \ 2433 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \ 2434 } \ 2435 \ 2436 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, \ 2437 jint mode) { \ 2438 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \ 2439 } \ 2440 \ 2441 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 2442 ctype* buf) { \ 2443 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 2444 } \ 2445 \ 2446 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \ 2447 const ctype* buf) { \ 2448 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \ 2449 } 2450 2451 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean) 2452 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte) 2453 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar) 2454 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort) 2455 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt) 2456 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong) 2457 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat) 2458 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble) 2459#undef PRIMITIVE_ARRAY_FUNCTIONS 2460 2461 static jint MonitorEnter(JNIEnv* env, jobject obj) { 2462 ScopedObjectAccess soa(env); 2463 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2464 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2465 if (sc.Check(soa, true, "EL", args)) { 2466 if (obj != nullptr) { 2467 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj); 2468 } 2469 JniValueType result; 2470 result.i = baseEnv(env)->MonitorEnter(env, obj); 2471 if (sc.Check(soa, false, "i", &result)) { 2472 return result.i; 2473 } 2474 } 2475 return JNI_ERR; 2476 } 2477 2478 static jint MonitorExit(JNIEnv* env, jobject obj) { 2479 ScopedObjectAccess soa(env); 2480 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__); 2481 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2482 if (sc.Check(soa, true, "EL", args)) { 2483 if (obj != nullptr) { 2484 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj); 2485 } 2486 JniValueType result; 2487 result.i = baseEnv(env)->MonitorExit(env, obj); 2488 if (sc.Check(soa, false, "i", &result)) { 2489 return result.i; 2490 } 2491 } 2492 return JNI_ERR; 2493 } 2494 2495 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) { 2496 ScopedObjectAccess soa(env); 2497 ScopedCheck sc(kFlag_CritGet, __FUNCTION__); 2498 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 2499 if (sc.Check(soa, true, "Eap", args)) { 2500 JniValueType result; 2501 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy); 2502 if (ptr != nullptr && soa.ForceCopy()) { 2503 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr); 2504 } 2505 result.p = ptr; 2506 if (sc.Check(soa, false, "p", &result)) { 2507 return const_cast<void*>(result.p); 2508 } 2509 } 2510 return nullptr; 2511 } 2512 2513 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) { 2514 ScopedObjectAccess soa(env); 2515 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__); 2516 sc.CheckNonNull(carray); 2517 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}}; 2518 if (sc.Check(soa, true, "Eapr", args)) { 2519 if (soa.ForceCopy()) { 2520 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode); 2521 } 2522 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode); 2523 JniValueType result; 2524 result.V = nullptr; 2525 sc.Check(soa, false, "V", &result); 2526 } 2527 } 2528 2529 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) { 2530 ScopedObjectAccess soa(env); 2531 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2532 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}}; 2533 if (sc.Check(soa, true, "EpJ", args)) { 2534 JniValueType result; 2535 // Note: the validity of address and capacity are checked in the base implementation. 2536 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity); 2537 if (sc.Check(soa, false, "L", &result)) { 2538 return result.L; 2539 } 2540 } 2541 return nullptr; 2542 } 2543 2544 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) { 2545 ScopedObjectAccess soa(env); 2546 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2547 JniValueType args[2] = {{.E = env}, {.L = buf}}; 2548 if (sc.Check(soa, true, "EL", args)) { 2549 JniValueType result; 2550 // Note: this is implemented in the base environment by a GetLongField which will sanity 2551 // check the type of buf in GetLongField above. 2552 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf); 2553 if (sc.Check(soa, false, "p", &result)) { 2554 return const_cast<void*>(result.p); 2555 } 2556 } 2557 return nullptr; 2558 } 2559 2560 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) { 2561 ScopedObjectAccess soa(env); 2562 ScopedCheck sc(kFlag_Default, __FUNCTION__); 2563 JniValueType args[2] = {{.E = env}, {.L = buf}}; 2564 if (sc.Check(soa, true, "EL", args)) { 2565 JniValueType result; 2566 // Note: this is implemented in the base environment by a GetIntField which will sanity 2567 // check the type of buf in GetIntField above. 2568 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf); 2569 if (sc.Check(soa, false, "J", &result)) { 2570 return result.J; 2571 } 2572 } 2573 return JNI_ERR; 2574 } 2575 2576 private: 2577 static JavaVMExt* GetJavaVMExt(JNIEnv* env) { 2578 return reinterpret_cast<JNIEnvExt*>(env)->vm; 2579 } 2580 2581 static const JNINativeInterface* baseEnv(JNIEnv* env) { 2582 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions; 2583 } 2584 2585 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 2586 ScopedObjectAccess soa(env); 2587 ScopedCheck sc(kFlag_Default, function_name); 2588 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2589 if (sc.Check(soa, true, "EL", args)) { 2590 JniValueType result; 2591 switch (kind) { 2592 case kGlobal: 2593 result.L = baseEnv(env)->NewGlobalRef(env, obj); 2594 break; 2595 case kLocal: 2596 result.L = baseEnv(env)->NewLocalRef(env, obj); 2597 break; 2598 case kWeakGlobal: 2599 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj); 2600 break; 2601 default: 2602 LOG(FATAL) << "Unexpected reference kind: " << kind; 2603 } 2604 if (sc.Check(soa, false, "L", &result)) { 2605 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE); 2606 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L)); 2607 return result.L; 2608 } 2609 } 2610 return nullptr; 2611 } 2612 2613 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) { 2614 ScopedObjectAccess soa(env); 2615 ScopedCheck sc(kFlag_ExcepOkay, function_name); 2616 JniValueType args[2] = {{.E = env}, {.L = obj}}; 2617 sc.Check(soa, true, "EL", args); 2618 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) { 2619 JniValueType result; 2620 switch (kind) { 2621 case kGlobal: 2622 baseEnv(env)->DeleteGlobalRef(env, obj); 2623 break; 2624 case kLocal: 2625 baseEnv(env)->DeleteLocalRef(env, obj); 2626 break; 2627 case kWeakGlobal: 2628 baseEnv(env)->DeleteWeakGlobalRef(env, obj); 2629 break; 2630 default: 2631 LOG(FATAL) << "Unexpected reference kind: " << kind; 2632 } 2633 result.V = nullptr; 2634 sc.Check(soa, false, "V", &result); 2635 } 2636 } 2637 2638 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c, 2639 const char* name, const char* sig, bool is_static) { 2640 ScopedObjectAccess soa(env); 2641 ScopedCheck sc(kFlag_Default, function_name); 2642 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 2643 if (sc.Check(soa, true, "Ecuu", args)) { 2644 JniValueType result; 2645 if (is_static) { 2646 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig); 2647 } else { 2648 result.m = baseEnv(env)->GetMethodID(env, c, name, sig); 2649 } 2650 if (sc.Check(soa, false, "m", &result)) { 2651 return result.m; 2652 } 2653 } 2654 return nullptr; 2655 } 2656 2657 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c, 2658 const char* name, const char* sig, bool is_static) { 2659 ScopedObjectAccess soa(env); 2660 ScopedCheck sc(kFlag_Default, function_name); 2661 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}}; 2662 if (sc.Check(soa, true, "Ecuu", args)) { 2663 JniValueType result; 2664 if (is_static) { 2665 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig); 2666 } else { 2667 result.f = baseEnv(env)->GetFieldID(env, c, name, sig); 2668 } 2669 if (sc.Check(soa, false, "f", &result)) { 2670 return result.f; 2671 } 2672 } 2673 return nullptr; 2674 } 2675 2676 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 2677 bool is_static, Primitive::Type type) { 2678 ScopedObjectAccess soa(env); 2679 ScopedCheck sc(kFlag_Default, function_name); 2680 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}}; 2681 JniValueType result; 2682 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) && 2683 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 2684 const char* result_check = nullptr; 2685 switch (type) { 2686 case Primitive::kPrimNot: 2687 if (is_static) { 2688 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid); 2689 } else { 2690 result.L = baseEnv(env)->GetObjectField(env, obj, fid); 2691 } 2692 result_check = "L"; 2693 break; 2694 case Primitive::kPrimBoolean: 2695 if (is_static) { 2696 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid); 2697 } else { 2698 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid); 2699 } 2700 result_check = "Z"; 2701 break; 2702 case Primitive::kPrimByte: 2703 if (is_static) { 2704 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid); 2705 } else { 2706 result.B = baseEnv(env)->GetByteField(env, obj, fid); 2707 } 2708 result_check = "B"; 2709 break; 2710 case Primitive::kPrimChar: 2711 if (is_static) { 2712 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid); 2713 } else { 2714 result.C = baseEnv(env)->GetCharField(env, obj, fid); 2715 } 2716 result_check = "C"; 2717 break; 2718 case Primitive::kPrimShort: 2719 if (is_static) { 2720 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid); 2721 } else { 2722 result.S = baseEnv(env)->GetShortField(env, obj, fid); 2723 } 2724 result_check = "S"; 2725 break; 2726 case Primitive::kPrimInt: 2727 if (is_static) { 2728 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid); 2729 } else { 2730 result.I = baseEnv(env)->GetIntField(env, obj, fid); 2731 } 2732 result_check = "I"; 2733 break; 2734 case Primitive::kPrimLong: 2735 if (is_static) { 2736 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid); 2737 } else { 2738 result.J = baseEnv(env)->GetLongField(env, obj, fid); 2739 } 2740 result_check = "J"; 2741 break; 2742 case Primitive::kPrimFloat: 2743 if (is_static) { 2744 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid); 2745 } else { 2746 result.F = baseEnv(env)->GetFloatField(env, obj, fid); 2747 } 2748 result_check = "F"; 2749 break; 2750 case Primitive::kPrimDouble: 2751 if (is_static) { 2752 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid); 2753 } else { 2754 result.D = baseEnv(env)->GetDoubleField(env, obj, fid); 2755 } 2756 result_check = "D"; 2757 break; 2758 case Primitive::kPrimVoid: 2759 LOG(FATAL) << "Unexpected type: " << type; 2760 break; 2761 } 2762 if (sc.Check(soa, false, result_check, &result)) { 2763 return result; 2764 } 2765 } 2766 result.J = 0; 2767 return result; 2768 } 2769 2770 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid, 2771 bool is_static, Primitive::Type type, JniValueType value) { 2772 ScopedObjectAccess soa(env); 2773 ScopedCheck sc(kFlag_Default, function_name); 2774 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value}; 2775 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f', 2776 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'}; 2777 if (sc.Check(soa, true, sig, args) && 2778 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) { 2779 switch (type) { 2780 case Primitive::kPrimNot: 2781 if (is_static) { 2782 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L); 2783 } else { 2784 baseEnv(env)->SetObjectField(env, obj, fid, value.L); 2785 } 2786 break; 2787 case Primitive::kPrimBoolean: 2788 if (is_static) { 2789 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z); 2790 } else { 2791 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z); 2792 } 2793 break; 2794 case Primitive::kPrimByte: 2795 if (is_static) { 2796 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B); 2797 } else { 2798 baseEnv(env)->SetByteField(env, obj, fid, value.B); 2799 } 2800 break; 2801 case Primitive::kPrimChar: 2802 if (is_static) { 2803 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C); 2804 } else { 2805 baseEnv(env)->SetCharField(env, obj, fid, value.C); 2806 } 2807 break; 2808 case Primitive::kPrimShort: 2809 if (is_static) { 2810 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S); 2811 } else { 2812 baseEnv(env)->SetShortField(env, obj, fid, value.S); 2813 } 2814 break; 2815 case Primitive::kPrimInt: 2816 if (is_static) { 2817 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I); 2818 } else { 2819 baseEnv(env)->SetIntField(env, obj, fid, value.I); 2820 } 2821 break; 2822 case Primitive::kPrimLong: 2823 if (is_static) { 2824 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J); 2825 } else { 2826 baseEnv(env)->SetLongField(env, obj, fid, value.J); 2827 } 2828 break; 2829 case Primitive::kPrimFloat: 2830 if (is_static) { 2831 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F); 2832 } else { 2833 baseEnv(env)->SetFloatField(env, obj, fid, value.F); 2834 } 2835 break; 2836 case Primitive::kPrimDouble: 2837 if (is_static) { 2838 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D); 2839 } else { 2840 baseEnv(env)->SetDoubleField(env, obj, fid, value.D); 2841 } 2842 break; 2843 case Primitive::kPrimVoid: 2844 LOG(FATAL) << "Unexpected type: " << type; 2845 break; 2846 } 2847 JniValueType result; 2848 result.V = nullptr; 2849 sc.Check(soa, false, "V", &result); 2850 } 2851 } 2852 2853 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj, 2854 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs) 2855 SHARED_REQUIRES(Locks::mutator_lock_) { 2856 bool checked; 2857 switch (invoke) { 2858 case kVirtual: { 2859 DCHECK(c == nullptr); 2860 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}}; 2861 checked = sc.Check(soa, true, "ELm.", args); 2862 break; 2863 } 2864 case kDirect: { 2865 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}}; 2866 checked = sc.Check(soa, true, "ELcm.", args); 2867 break; 2868 } 2869 case kStatic: { 2870 DCHECK(obj == nullptr); 2871 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}}; 2872 checked = sc.Check(soa, true, "Ecm.", args); 2873 break; 2874 } 2875 default: 2876 LOG(FATAL) << "Unexpected invoke: " << invoke; 2877 checked = false; 2878 break; 2879 } 2880 return checked; 2881 } 2882 2883 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c, 2884 jmethodID mid, jvalue* vargs, Primitive::Type type, 2885 InvokeType invoke) { 2886 ScopedObjectAccess soa(env); 2887 ScopedCheck sc(kFlag_Default, function_name); 2888 JniValueType result; 2889 VarArgs rest(mid, vargs); 2890 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) && 2891 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 2892 const char* result_check; 2893 switch (type) { 2894 case Primitive::kPrimNot: 2895 result_check = "L"; 2896 switch (invoke) { 2897 case kVirtual: 2898 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs); 2899 break; 2900 case kDirect: 2901 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs); 2902 break; 2903 case kStatic: 2904 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs); 2905 break; 2906 default: 2907 break; 2908 } 2909 break; 2910 case Primitive::kPrimBoolean: 2911 result_check = "Z"; 2912 switch (invoke) { 2913 case kVirtual: 2914 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs); 2915 break; 2916 case kDirect: 2917 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs); 2918 break; 2919 case kStatic: 2920 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs); 2921 break; 2922 default: 2923 break; 2924 } 2925 break; 2926 case Primitive::kPrimByte: 2927 result_check = "B"; 2928 switch (invoke) { 2929 case kVirtual: 2930 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs); 2931 break; 2932 case kDirect: 2933 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs); 2934 break; 2935 case kStatic: 2936 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs); 2937 break; 2938 default: 2939 break; 2940 } 2941 break; 2942 case Primitive::kPrimChar: 2943 result_check = "C"; 2944 switch (invoke) { 2945 case kVirtual: 2946 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs); 2947 break; 2948 case kDirect: 2949 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs); 2950 break; 2951 case kStatic: 2952 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs); 2953 break; 2954 default: 2955 break; 2956 } 2957 break; 2958 case Primitive::kPrimShort: 2959 result_check = "S"; 2960 switch (invoke) { 2961 case kVirtual: 2962 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs); 2963 break; 2964 case kDirect: 2965 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs); 2966 break; 2967 case kStatic: 2968 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs); 2969 break; 2970 default: 2971 break; 2972 } 2973 break; 2974 case Primitive::kPrimInt: 2975 result_check = "I"; 2976 switch (invoke) { 2977 case kVirtual: 2978 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs); 2979 break; 2980 case kDirect: 2981 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs); 2982 break; 2983 case kStatic: 2984 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs); 2985 break; 2986 default: 2987 break; 2988 } 2989 break; 2990 case Primitive::kPrimLong: 2991 result_check = "J"; 2992 switch (invoke) { 2993 case kVirtual: 2994 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs); 2995 break; 2996 case kDirect: 2997 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs); 2998 break; 2999 case kStatic: 3000 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs); 3001 break; 3002 default: 3003 break; 3004 } 3005 break; 3006 case Primitive::kPrimFloat: 3007 result_check = "F"; 3008 switch (invoke) { 3009 case kVirtual: 3010 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs); 3011 break; 3012 case kDirect: 3013 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs); 3014 break; 3015 case kStatic: 3016 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs); 3017 break; 3018 default: 3019 break; 3020 } 3021 break; 3022 case Primitive::kPrimDouble: 3023 result_check = "D"; 3024 switch (invoke) { 3025 case kVirtual: 3026 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs); 3027 break; 3028 case kDirect: 3029 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs); 3030 break; 3031 case kStatic: 3032 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs); 3033 break; 3034 default: 3035 break; 3036 } 3037 break; 3038 case Primitive::kPrimVoid: 3039 result_check = "V"; 3040 result.V = nullptr; 3041 switch (invoke) { 3042 case kVirtual: 3043 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs); 3044 break; 3045 case kDirect: 3046 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs); 3047 break; 3048 case kStatic: 3049 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs); 3050 break; 3051 default: 3052 LOG(FATAL) << "Unexpected invoke: " << invoke; 3053 } 3054 break; 3055 default: 3056 LOG(FATAL) << "Unexpected return type: " << type; 3057 result_check = nullptr; 3058 } 3059 if (sc.Check(soa, false, result_check, &result)) { 3060 return result; 3061 } 3062 } 3063 result.J = 0; 3064 return result; 3065 } 3066 3067 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c, 3068 jmethodID mid, va_list vargs, Primitive::Type type, 3069 InvokeType invoke) { 3070 ScopedObjectAccess soa(env); 3071 ScopedCheck sc(kFlag_Default, function_name); 3072 JniValueType result; 3073 VarArgs rest(mid, vargs); 3074 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) && 3075 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) { 3076 const char* result_check; 3077 switch (type) { 3078 case Primitive::kPrimNot: 3079 result_check = "L"; 3080 switch (invoke) { 3081 case kVirtual: 3082 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs); 3083 break; 3084 case kDirect: 3085 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs); 3086 break; 3087 case kStatic: 3088 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs); 3089 break; 3090 default: 3091 LOG(FATAL) << "Unexpected invoke: " << invoke; 3092 } 3093 break; 3094 case Primitive::kPrimBoolean: 3095 result_check = "Z"; 3096 switch (invoke) { 3097 case kVirtual: 3098 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs); 3099 break; 3100 case kDirect: 3101 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs); 3102 break; 3103 case kStatic: 3104 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs); 3105 break; 3106 default: 3107 LOG(FATAL) << "Unexpected invoke: " << invoke; 3108 } 3109 break; 3110 case Primitive::kPrimByte: 3111 result_check = "B"; 3112 switch (invoke) { 3113 case kVirtual: 3114 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs); 3115 break; 3116 case kDirect: 3117 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs); 3118 break; 3119 case kStatic: 3120 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs); 3121 break; 3122 default: 3123 LOG(FATAL) << "Unexpected invoke: " << invoke; 3124 } 3125 break; 3126 case Primitive::kPrimChar: 3127 result_check = "C"; 3128 switch (invoke) { 3129 case kVirtual: 3130 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs); 3131 break; 3132 case kDirect: 3133 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs); 3134 break; 3135 case kStatic: 3136 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs); 3137 break; 3138 default: 3139 LOG(FATAL) << "Unexpected invoke: " << invoke; 3140 } 3141 break; 3142 case Primitive::kPrimShort: 3143 result_check = "S"; 3144 switch (invoke) { 3145 case kVirtual: 3146 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs); 3147 break; 3148 case kDirect: 3149 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs); 3150 break; 3151 case kStatic: 3152 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs); 3153 break; 3154 default: 3155 LOG(FATAL) << "Unexpected invoke: " << invoke; 3156 } 3157 break; 3158 case Primitive::kPrimInt: 3159 result_check = "I"; 3160 switch (invoke) { 3161 case kVirtual: 3162 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs); 3163 break; 3164 case kDirect: 3165 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs); 3166 break; 3167 case kStatic: 3168 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs); 3169 break; 3170 default: 3171 LOG(FATAL) << "Unexpected invoke: " << invoke; 3172 } 3173 break; 3174 case Primitive::kPrimLong: 3175 result_check = "J"; 3176 switch (invoke) { 3177 case kVirtual: 3178 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs); 3179 break; 3180 case kDirect: 3181 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs); 3182 break; 3183 case kStatic: 3184 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs); 3185 break; 3186 default: 3187 LOG(FATAL) << "Unexpected invoke: " << invoke; 3188 } 3189 break; 3190 case Primitive::kPrimFloat: 3191 result_check = "F"; 3192 switch (invoke) { 3193 case kVirtual: 3194 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs); 3195 break; 3196 case kDirect: 3197 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs); 3198 break; 3199 case kStatic: 3200 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs); 3201 break; 3202 default: 3203 LOG(FATAL) << "Unexpected invoke: " << invoke; 3204 } 3205 break; 3206 case Primitive::kPrimDouble: 3207 result_check = "D"; 3208 switch (invoke) { 3209 case kVirtual: 3210 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs); 3211 break; 3212 case kDirect: 3213 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs); 3214 break; 3215 case kStatic: 3216 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs); 3217 break; 3218 default: 3219 LOG(FATAL) << "Unexpected invoke: " << invoke; 3220 } 3221 break; 3222 case Primitive::kPrimVoid: 3223 result_check = "V"; 3224 result.V = nullptr; 3225 switch (invoke) { 3226 case kVirtual: 3227 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs); 3228 break; 3229 case kDirect: 3230 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs); 3231 break; 3232 case kStatic: 3233 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs); 3234 break; 3235 default: 3236 LOG(FATAL) << "Unexpected invoke: " << invoke; 3237 } 3238 break; 3239 default: 3240 LOG(FATAL) << "Unexpected return type: " << type; 3241 result_check = nullptr; 3242 } 3243 if (sc.Check(soa, false, result_check, &result)) { 3244 return result; 3245 } 3246 } 3247 result.J = 0; 3248 return result; 3249 } 3250 3251 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 3252 jboolean* is_copy, bool utf, bool critical) { 3253 ScopedObjectAccess soa(env); 3254 int flags = critical ? kFlag_CritGet : kFlag_CritOkay; 3255 ScopedCheck sc(flags, function_name); 3256 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}}; 3257 if (sc.Check(soa, true, "Esp", args)) { 3258 JniValueType result; 3259 void* ptr; 3260 if (utf) { 3261 CHECK(!critical); 3262 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy)); 3263 result.u = reinterpret_cast<char*>(ptr); 3264 } else { 3265 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) : 3266 baseEnv(env)->GetStringChars(env, string, is_copy)); 3267 result.p = ptr; 3268 } 3269 // TODO: could we be smarter about not copying when local_is_copy? 3270 if (ptr != nullptr && soa.ForceCopy()) { 3271 if (utf) { 3272 size_t length_in_bytes = strlen(result.u) + 1; 3273 result.u = 3274 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false)); 3275 } else { 3276 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2; 3277 result.p = 3278 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false)); 3279 } 3280 if (is_copy != nullptr) { 3281 *is_copy = JNI_TRUE; 3282 } 3283 } 3284 if (sc.Check(soa, false, utf ? "u" : "p", &result)) { 3285 return utf ? result.u : result.p; 3286 } 3287 } 3288 return nullptr; 3289 } 3290 3291 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string, 3292 const void* chars, bool utf, bool critical) { 3293 ScopedObjectAccess soa(env); 3294 int flags = kFlag_ExcepOkay | kFlag_Release; 3295 if (critical) { 3296 flags |= kFlag_CritRelease; 3297 } 3298 ScopedCheck sc(flags, function_name); 3299 sc.CheckNonNull(chars); 3300 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false); 3301 if (force_copy_ok && soa.ForceCopy()) { 3302 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars))); 3303 } 3304 if (force_copy_ok) { 3305 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}}; 3306 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) { 3307 if (utf) { 3308 CHECK(!critical); 3309 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars)); 3310 } else { 3311 if (critical) { 3312 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars)); 3313 } else { 3314 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars)); 3315 } 3316 } 3317 JniValueType result; 3318 sc.Check(soa, false, "V", &result); 3319 } 3320 } 3321 } 3322 3323 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length, 3324 Primitive::Type type) { 3325 ScopedObjectAccess soa(env); 3326 ScopedCheck sc(kFlag_Default, function_name); 3327 JniValueType args[2] = {{.E = env}, {.z = length}}; 3328 if (sc.Check(soa, true, "Ez", args)) { 3329 JniValueType result; 3330 switch (type) { 3331 case Primitive::kPrimBoolean: 3332 result.a = baseEnv(env)->NewBooleanArray(env, length); 3333 break; 3334 case Primitive::kPrimByte: 3335 result.a = baseEnv(env)->NewByteArray(env, length); 3336 break; 3337 case Primitive::kPrimChar: 3338 result.a = baseEnv(env)->NewCharArray(env, length); 3339 break; 3340 case Primitive::kPrimShort: 3341 result.a = baseEnv(env)->NewShortArray(env, length); 3342 break; 3343 case Primitive::kPrimInt: 3344 result.a = baseEnv(env)->NewIntArray(env, length); 3345 break; 3346 case Primitive::kPrimLong: 3347 result.a = baseEnv(env)->NewLongArray(env, length); 3348 break; 3349 case Primitive::kPrimFloat: 3350 result.a = baseEnv(env)->NewFloatArray(env, length); 3351 break; 3352 case Primitive::kPrimDouble: 3353 result.a = baseEnv(env)->NewDoubleArray(env, length); 3354 break; 3355 default: 3356 LOG(FATAL) << "Unexpected primitive type: " << type; 3357 } 3358 if (sc.Check(soa, false, "a", &result)) { 3359 return result.a; 3360 } 3361 } 3362 return nullptr; 3363 } 3364 3365 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type, 3366 JNIEnv* env, jarray array, jboolean* is_copy) { 3367 ScopedObjectAccess soa(env); 3368 ScopedCheck sc(kFlag_Default, function_name); 3369 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}}; 3370 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3371 JniValueType result; 3372 void* ptr = nullptr; 3373 switch (type) { 3374 case Primitive::kPrimBoolean: 3375 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array), 3376 is_copy); 3377 break; 3378 case Primitive::kPrimByte: 3379 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy); 3380 break; 3381 case Primitive::kPrimChar: 3382 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy); 3383 break; 3384 case Primitive::kPrimShort: 3385 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy); 3386 break; 3387 case Primitive::kPrimInt: 3388 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy); 3389 break; 3390 case Primitive::kPrimLong: 3391 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy); 3392 break; 3393 case Primitive::kPrimFloat: 3394 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy); 3395 break; 3396 case Primitive::kPrimDouble: 3397 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy); 3398 break; 3399 default: 3400 LOG(FATAL) << "Unexpected primitive type: " << type; 3401 } 3402 if (ptr != nullptr && soa.ForceCopy()) { 3403 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr); 3404 if (is_copy != nullptr) { 3405 *is_copy = JNI_TRUE; 3406 } 3407 } 3408 result.p = ptr; 3409 if (sc.Check(soa, false, "p", &result)) { 3410 return const_cast<void*>(result.p); 3411 } 3412 } 3413 return nullptr; 3414 } 3415 3416 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type, 3417 JNIEnv* env, jarray array, void* elems, jint mode) { 3418 ScopedObjectAccess soa(env); 3419 ScopedCheck sc(kFlag_ExcepOkay, function_name); 3420 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3421 if (soa.ForceCopy()) { 3422 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode); 3423 } 3424 if (!soa.ForceCopy() || elems != nullptr) { 3425 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}}; 3426 if (sc.Check(soa, true, "Eapr", args)) { 3427 switch (type) { 3428 case Primitive::kPrimBoolean: 3429 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array), 3430 reinterpret_cast<jboolean*>(elems), mode); 3431 break; 3432 case Primitive::kPrimByte: 3433 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array), 3434 reinterpret_cast<jbyte*>(elems), mode); 3435 break; 3436 case Primitive::kPrimChar: 3437 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array), 3438 reinterpret_cast<jchar*>(elems), mode); 3439 break; 3440 case Primitive::kPrimShort: 3441 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array), 3442 reinterpret_cast<jshort*>(elems), mode); 3443 break; 3444 case Primitive::kPrimInt: 3445 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array), 3446 reinterpret_cast<jint*>(elems), mode); 3447 break; 3448 case Primitive::kPrimLong: 3449 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array), 3450 reinterpret_cast<jlong*>(elems), mode); 3451 break; 3452 case Primitive::kPrimFloat: 3453 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array), 3454 reinterpret_cast<jfloat*>(elems), mode); 3455 break; 3456 case Primitive::kPrimDouble: 3457 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array), 3458 reinterpret_cast<jdouble*>(elems), mode); 3459 break; 3460 default: 3461 LOG(FATAL) << "Unexpected primitive type: " << type; 3462 } 3463 JniValueType result; 3464 result.V = nullptr; 3465 sc.Check(soa, false, "V", &result); 3466 } 3467 } 3468 } 3469 } 3470 3471 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 3472 jarray array, jsize start, jsize len, void* buf) { 3473 ScopedObjectAccess soa(env); 3474 ScopedCheck sc(kFlag_Default, function_name); 3475 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 3476 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 3477 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 3478 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3479 switch (type) { 3480 case Primitive::kPrimBoolean: 3481 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 3482 reinterpret_cast<jboolean*>(buf)); 3483 break; 3484 case Primitive::kPrimByte: 3485 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 3486 reinterpret_cast<jbyte*>(buf)); 3487 break; 3488 case Primitive::kPrimChar: 3489 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 3490 reinterpret_cast<jchar*>(buf)); 3491 break; 3492 case Primitive::kPrimShort: 3493 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 3494 reinterpret_cast<jshort*>(buf)); 3495 break; 3496 case Primitive::kPrimInt: 3497 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 3498 reinterpret_cast<jint*>(buf)); 3499 break; 3500 case Primitive::kPrimLong: 3501 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 3502 reinterpret_cast<jlong*>(buf)); 3503 break; 3504 case Primitive::kPrimFloat: 3505 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 3506 reinterpret_cast<jfloat*>(buf)); 3507 break; 3508 case Primitive::kPrimDouble: 3509 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 3510 reinterpret_cast<jdouble*>(buf)); 3511 break; 3512 default: 3513 LOG(FATAL) << "Unexpected primitive type: " << type; 3514 } 3515 JniValueType result; 3516 result.V = nullptr; 3517 sc.Check(soa, false, "V", &result); 3518 } 3519 } 3520 3521 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env, 3522 jarray array, jsize start, jsize len, const void* buf) { 3523 ScopedObjectAccess soa(env); 3524 ScopedCheck sc(kFlag_Default, function_name); 3525 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}}; 3526 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices 3527 // result in ArrayIndexOutOfBoundsExceptions in the base implementation. 3528 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) { 3529 switch (type) { 3530 case Primitive::kPrimBoolean: 3531 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len, 3532 reinterpret_cast<const jboolean*>(buf)); 3533 break; 3534 case Primitive::kPrimByte: 3535 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len, 3536 reinterpret_cast<const jbyte*>(buf)); 3537 break; 3538 case Primitive::kPrimChar: 3539 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len, 3540 reinterpret_cast<const jchar*>(buf)); 3541 break; 3542 case Primitive::kPrimShort: 3543 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len, 3544 reinterpret_cast<const jshort*>(buf)); 3545 break; 3546 case Primitive::kPrimInt: 3547 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len, 3548 reinterpret_cast<const jint*>(buf)); 3549 break; 3550 case Primitive::kPrimLong: 3551 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len, 3552 reinterpret_cast<const jlong*>(buf)); 3553 break; 3554 case Primitive::kPrimFloat: 3555 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len, 3556 reinterpret_cast<const jfloat*>(buf)); 3557 break; 3558 case Primitive::kPrimDouble: 3559 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len, 3560 reinterpret_cast<const jdouble*>(buf)); 3561 break; 3562 default: 3563 LOG(FATAL) << "Unexpected primitive type: " << type; 3564 } 3565 JniValueType result; 3566 result.V = nullptr; 3567 sc.Check(soa, false, "V", &result); 3568 } 3569 } 3570}; 3571 3572const JNINativeInterface gCheckNativeInterface = { 3573 nullptr, // reserved0. 3574 nullptr, // reserved1. 3575 nullptr, // reserved2. 3576 nullptr, // reserved3. 3577 CheckJNI::GetVersion, 3578 CheckJNI::DefineClass, 3579 CheckJNI::FindClass, 3580 CheckJNI::FromReflectedMethod, 3581 CheckJNI::FromReflectedField, 3582 CheckJNI::ToReflectedMethod, 3583 CheckJNI::GetSuperclass, 3584 CheckJNI::IsAssignableFrom, 3585 CheckJNI::ToReflectedField, 3586 CheckJNI::Throw, 3587 CheckJNI::ThrowNew, 3588 CheckJNI::ExceptionOccurred, 3589 CheckJNI::ExceptionDescribe, 3590 CheckJNI::ExceptionClear, 3591 CheckJNI::FatalError, 3592 CheckJNI::PushLocalFrame, 3593 CheckJNI::PopLocalFrame, 3594 CheckJNI::NewGlobalRef, 3595 CheckJNI::DeleteGlobalRef, 3596 CheckJNI::DeleteLocalRef, 3597 CheckJNI::IsSameObject, 3598 CheckJNI::NewLocalRef, 3599 CheckJNI::EnsureLocalCapacity, 3600 CheckJNI::AllocObject, 3601 CheckJNI::NewObject, 3602 CheckJNI::NewObjectV, 3603 CheckJNI::NewObjectA, 3604 CheckJNI::GetObjectClass, 3605 CheckJNI::IsInstanceOf, 3606 CheckJNI::GetMethodID, 3607 CheckJNI::CallObjectMethod, 3608 CheckJNI::CallObjectMethodV, 3609 CheckJNI::CallObjectMethodA, 3610 CheckJNI::CallBooleanMethod, 3611 CheckJNI::CallBooleanMethodV, 3612 CheckJNI::CallBooleanMethodA, 3613 CheckJNI::CallByteMethod, 3614 CheckJNI::CallByteMethodV, 3615 CheckJNI::CallByteMethodA, 3616 CheckJNI::CallCharMethod, 3617 CheckJNI::CallCharMethodV, 3618 CheckJNI::CallCharMethodA, 3619 CheckJNI::CallShortMethod, 3620 CheckJNI::CallShortMethodV, 3621 CheckJNI::CallShortMethodA, 3622 CheckJNI::CallIntMethod, 3623 CheckJNI::CallIntMethodV, 3624 CheckJNI::CallIntMethodA, 3625 CheckJNI::CallLongMethod, 3626 CheckJNI::CallLongMethodV, 3627 CheckJNI::CallLongMethodA, 3628 CheckJNI::CallFloatMethod, 3629 CheckJNI::CallFloatMethodV, 3630 CheckJNI::CallFloatMethodA, 3631 CheckJNI::CallDoubleMethod, 3632 CheckJNI::CallDoubleMethodV, 3633 CheckJNI::CallDoubleMethodA, 3634 CheckJNI::CallVoidMethod, 3635 CheckJNI::CallVoidMethodV, 3636 CheckJNI::CallVoidMethodA, 3637 CheckJNI::CallNonvirtualObjectMethod, 3638 CheckJNI::CallNonvirtualObjectMethodV, 3639 CheckJNI::CallNonvirtualObjectMethodA, 3640 CheckJNI::CallNonvirtualBooleanMethod, 3641 CheckJNI::CallNonvirtualBooleanMethodV, 3642 CheckJNI::CallNonvirtualBooleanMethodA, 3643 CheckJNI::CallNonvirtualByteMethod, 3644 CheckJNI::CallNonvirtualByteMethodV, 3645 CheckJNI::CallNonvirtualByteMethodA, 3646 CheckJNI::CallNonvirtualCharMethod, 3647 CheckJNI::CallNonvirtualCharMethodV, 3648 CheckJNI::CallNonvirtualCharMethodA, 3649 CheckJNI::CallNonvirtualShortMethod, 3650 CheckJNI::CallNonvirtualShortMethodV, 3651 CheckJNI::CallNonvirtualShortMethodA, 3652 CheckJNI::CallNonvirtualIntMethod, 3653 CheckJNI::CallNonvirtualIntMethodV, 3654 CheckJNI::CallNonvirtualIntMethodA, 3655 CheckJNI::CallNonvirtualLongMethod, 3656 CheckJNI::CallNonvirtualLongMethodV, 3657 CheckJNI::CallNonvirtualLongMethodA, 3658 CheckJNI::CallNonvirtualFloatMethod, 3659 CheckJNI::CallNonvirtualFloatMethodV, 3660 CheckJNI::CallNonvirtualFloatMethodA, 3661 CheckJNI::CallNonvirtualDoubleMethod, 3662 CheckJNI::CallNonvirtualDoubleMethodV, 3663 CheckJNI::CallNonvirtualDoubleMethodA, 3664 CheckJNI::CallNonvirtualVoidMethod, 3665 CheckJNI::CallNonvirtualVoidMethodV, 3666 CheckJNI::CallNonvirtualVoidMethodA, 3667 CheckJNI::GetFieldID, 3668 CheckJNI::GetObjectField, 3669 CheckJNI::GetBooleanField, 3670 CheckJNI::GetByteField, 3671 CheckJNI::GetCharField, 3672 CheckJNI::GetShortField, 3673 CheckJNI::GetIntField, 3674 CheckJNI::GetLongField, 3675 CheckJNI::GetFloatField, 3676 CheckJNI::GetDoubleField, 3677 CheckJNI::SetObjectField, 3678 CheckJNI::SetBooleanField, 3679 CheckJNI::SetByteField, 3680 CheckJNI::SetCharField, 3681 CheckJNI::SetShortField, 3682 CheckJNI::SetIntField, 3683 CheckJNI::SetLongField, 3684 CheckJNI::SetFloatField, 3685 CheckJNI::SetDoubleField, 3686 CheckJNI::GetStaticMethodID, 3687 CheckJNI::CallStaticObjectMethod, 3688 CheckJNI::CallStaticObjectMethodV, 3689 CheckJNI::CallStaticObjectMethodA, 3690 CheckJNI::CallStaticBooleanMethod, 3691 CheckJNI::CallStaticBooleanMethodV, 3692 CheckJNI::CallStaticBooleanMethodA, 3693 CheckJNI::CallStaticByteMethod, 3694 CheckJNI::CallStaticByteMethodV, 3695 CheckJNI::CallStaticByteMethodA, 3696 CheckJNI::CallStaticCharMethod, 3697 CheckJNI::CallStaticCharMethodV, 3698 CheckJNI::CallStaticCharMethodA, 3699 CheckJNI::CallStaticShortMethod, 3700 CheckJNI::CallStaticShortMethodV, 3701 CheckJNI::CallStaticShortMethodA, 3702 CheckJNI::CallStaticIntMethod, 3703 CheckJNI::CallStaticIntMethodV, 3704 CheckJNI::CallStaticIntMethodA, 3705 CheckJNI::CallStaticLongMethod, 3706 CheckJNI::CallStaticLongMethodV, 3707 CheckJNI::CallStaticLongMethodA, 3708 CheckJNI::CallStaticFloatMethod, 3709 CheckJNI::CallStaticFloatMethodV, 3710 CheckJNI::CallStaticFloatMethodA, 3711 CheckJNI::CallStaticDoubleMethod, 3712 CheckJNI::CallStaticDoubleMethodV, 3713 CheckJNI::CallStaticDoubleMethodA, 3714 CheckJNI::CallStaticVoidMethod, 3715 CheckJNI::CallStaticVoidMethodV, 3716 CheckJNI::CallStaticVoidMethodA, 3717 CheckJNI::GetStaticFieldID, 3718 CheckJNI::GetStaticObjectField, 3719 CheckJNI::GetStaticBooleanField, 3720 CheckJNI::GetStaticByteField, 3721 CheckJNI::GetStaticCharField, 3722 CheckJNI::GetStaticShortField, 3723 CheckJNI::GetStaticIntField, 3724 CheckJNI::GetStaticLongField, 3725 CheckJNI::GetStaticFloatField, 3726 CheckJNI::GetStaticDoubleField, 3727 CheckJNI::SetStaticObjectField, 3728 CheckJNI::SetStaticBooleanField, 3729 CheckJNI::SetStaticByteField, 3730 CheckJNI::SetStaticCharField, 3731 CheckJNI::SetStaticShortField, 3732 CheckJNI::SetStaticIntField, 3733 CheckJNI::SetStaticLongField, 3734 CheckJNI::SetStaticFloatField, 3735 CheckJNI::SetStaticDoubleField, 3736 CheckJNI::NewString, 3737 CheckJNI::GetStringLength, 3738 CheckJNI::GetStringChars, 3739 CheckJNI::ReleaseStringChars, 3740 CheckJNI::NewStringUTF, 3741 CheckJNI::GetStringUTFLength, 3742 CheckJNI::GetStringUTFChars, 3743 CheckJNI::ReleaseStringUTFChars, 3744 CheckJNI::GetArrayLength, 3745 CheckJNI::NewObjectArray, 3746 CheckJNI::GetObjectArrayElement, 3747 CheckJNI::SetObjectArrayElement, 3748 CheckJNI::NewBooleanArray, 3749 CheckJNI::NewByteArray, 3750 CheckJNI::NewCharArray, 3751 CheckJNI::NewShortArray, 3752 CheckJNI::NewIntArray, 3753 CheckJNI::NewLongArray, 3754 CheckJNI::NewFloatArray, 3755 CheckJNI::NewDoubleArray, 3756 CheckJNI::GetBooleanArrayElements, 3757 CheckJNI::GetByteArrayElements, 3758 CheckJNI::GetCharArrayElements, 3759 CheckJNI::GetShortArrayElements, 3760 CheckJNI::GetIntArrayElements, 3761 CheckJNI::GetLongArrayElements, 3762 CheckJNI::GetFloatArrayElements, 3763 CheckJNI::GetDoubleArrayElements, 3764 CheckJNI::ReleaseBooleanArrayElements, 3765 CheckJNI::ReleaseByteArrayElements, 3766 CheckJNI::ReleaseCharArrayElements, 3767 CheckJNI::ReleaseShortArrayElements, 3768 CheckJNI::ReleaseIntArrayElements, 3769 CheckJNI::ReleaseLongArrayElements, 3770 CheckJNI::ReleaseFloatArrayElements, 3771 CheckJNI::ReleaseDoubleArrayElements, 3772 CheckJNI::GetBooleanArrayRegion, 3773 CheckJNI::GetByteArrayRegion, 3774 CheckJNI::GetCharArrayRegion, 3775 CheckJNI::GetShortArrayRegion, 3776 CheckJNI::GetIntArrayRegion, 3777 CheckJNI::GetLongArrayRegion, 3778 CheckJNI::GetFloatArrayRegion, 3779 CheckJNI::GetDoubleArrayRegion, 3780 CheckJNI::SetBooleanArrayRegion, 3781 CheckJNI::SetByteArrayRegion, 3782 CheckJNI::SetCharArrayRegion, 3783 CheckJNI::SetShortArrayRegion, 3784 CheckJNI::SetIntArrayRegion, 3785 CheckJNI::SetLongArrayRegion, 3786 CheckJNI::SetFloatArrayRegion, 3787 CheckJNI::SetDoubleArrayRegion, 3788 CheckJNI::RegisterNatives, 3789 CheckJNI::UnregisterNatives, 3790 CheckJNI::MonitorEnter, 3791 CheckJNI::MonitorExit, 3792 CheckJNI::GetJavaVM, 3793 CheckJNI::GetStringRegion, 3794 CheckJNI::GetStringUTFRegion, 3795 CheckJNI::GetPrimitiveArrayCritical, 3796 CheckJNI::ReleasePrimitiveArrayCritical, 3797 CheckJNI::GetStringCritical, 3798 CheckJNI::ReleaseStringCritical, 3799 CheckJNI::NewWeakGlobalRef, 3800 CheckJNI::DeleteWeakGlobalRef, 3801 CheckJNI::ExceptionCheck, 3802 CheckJNI::NewDirectByteBuffer, 3803 CheckJNI::GetDirectBufferAddress, 3804 CheckJNI::GetDirectBufferCapacity, 3805 CheckJNI::GetObjectRefType, 3806}; 3807 3808const JNINativeInterface* GetCheckJniNativeInterface() { 3809 return &gCheckNativeInterface; 3810} 3811 3812class CheckJII { 3813 public: 3814 static jint DestroyJavaVM(JavaVM* vm) { 3815 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false); 3816 JniValueType args[1] = {{.v = vm}}; 3817 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 3818 JniValueType result; 3819 result.i = BaseVm(vm)->DestroyJavaVM(vm); 3820 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime, 3821 // which will delete the JavaVMExt. 3822 sc.CheckNonHeap(nullptr, false, "i", &result); 3823 return result.i; 3824 } 3825 3826 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 3827 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3828 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 3829 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 3830 JniValueType result; 3831 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args); 3832 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3833 return result.i; 3834 } 3835 3836 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 3837 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3838 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}}; 3839 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args); 3840 JniValueType result; 3841 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args); 3842 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3843 return result.i; 3844 } 3845 3846 static jint DetachCurrentThread(JavaVM* vm) { 3847 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3848 JniValueType args[1] = {{.v = vm}}; 3849 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args); 3850 JniValueType result; 3851 result.i = BaseVm(vm)->DetachCurrentThread(vm); 3852 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3853 return result.i; 3854 } 3855 3856 static jint GetEnv(JavaVM* vm, void** p_env, jint version) { 3857 ScopedCheck sc(kFlag_Invocation, __FUNCTION__); 3858 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}}; 3859 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args); 3860 JniValueType result; 3861 result.i = BaseVm(vm)->GetEnv(vm, p_env, version); 3862 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result); 3863 return result.i; 3864 } 3865 3866 private: 3867 static const JNIInvokeInterface* BaseVm(JavaVM* vm) { 3868 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions(); 3869 } 3870}; 3871 3872const JNIInvokeInterface gCheckInvokeInterface = { 3873 nullptr, // reserved0 3874 nullptr, // reserved1 3875 nullptr, // reserved2 3876 CheckJII::DestroyJavaVM, 3877 CheckJII::AttachCurrentThread, 3878 CheckJII::DetachCurrentThread, 3879 CheckJII::GetEnv, 3880 CheckJII::AttachCurrentThreadAsDaemon 3881}; 3882 3883const JNIInvokeInterface* GetCheckJniInvokeInterface() { 3884 return &gCheckInvokeInterface; 3885} 3886 3887} // namespace art 3888