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