1 /* 2 * Copyright (C) 2011 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 "reflection-inl.h" 18 19 #include "art_field-inl.h" 20 #include "art_method-inl.h" 21 #include "base/enums.h" 22 #include "class_linker.h" 23 #include "common_throws.h" 24 #include "dex_file-inl.h" 25 #include "indirect_reference_table-inl.h" 26 #include "java_vm_ext.h" 27 #include "jni_internal.h" 28 #include "mirror/class-inl.h" 29 #include "mirror/executable.h" 30 #include "mirror/object_array-inl.h" 31 #include "nativehelper/ScopedLocalRef.h" 32 #include "nth_caller_visitor.h" 33 #include "scoped_thread_state_change-inl.h" 34 #include "stack_reference.h" 35 #include "well_known_classes.h" 36 37 namespace art { 38 39 using android::base::StringPrintf; 40 41 class ArgArray { 42 public: 43 ArgArray(const char* shorty, uint32_t shorty_len) 44 : shorty_(shorty), shorty_len_(shorty_len), num_bytes_(0) { 45 size_t num_slots = shorty_len + 1; // +1 in case of receiver. 46 if (LIKELY((num_slots * 2) < kSmallArgArraySize)) { 47 // We can trivially use the small arg array. 48 arg_array_ = small_arg_array_; 49 } else { 50 // Analyze shorty to see if we need the large arg array. 51 for (size_t i = 1; i < shorty_len; ++i) { 52 char c = shorty[i]; 53 if (c == 'J' || c == 'D') { 54 num_slots++; 55 } 56 } 57 if (num_slots <= kSmallArgArraySize) { 58 arg_array_ = small_arg_array_; 59 } else { 60 large_arg_array_.reset(new uint32_t[num_slots]); 61 arg_array_ = large_arg_array_.get(); 62 } 63 } 64 } 65 66 uint32_t* GetArray() { 67 return arg_array_; 68 } 69 70 uint32_t GetNumBytes() { 71 return num_bytes_; 72 } 73 74 void Append(uint32_t value) { 75 arg_array_[num_bytes_ / 4] = value; 76 num_bytes_ += 4; 77 } 78 79 void Append(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) { 80 Append(StackReference<mirror::Object>::FromMirrorPtr(obj.Ptr()).AsVRegValue()); 81 } 82 83 void AppendWide(uint64_t value) { 84 arg_array_[num_bytes_ / 4] = value; 85 arg_array_[(num_bytes_ / 4) + 1] = value >> 32; 86 num_bytes_ += 8; 87 } 88 89 void AppendFloat(float value) { 90 jvalue jv; 91 jv.f = value; 92 Append(jv.i); 93 } 94 95 void AppendDouble(double value) { 96 jvalue jv; 97 jv.d = value; 98 AppendWide(jv.j); 99 } 100 101 void BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, 102 ObjPtr<mirror::Object> receiver, 103 va_list ap) 104 REQUIRES_SHARED(Locks::mutator_lock_) { 105 // Set receiver if non-null (method is not static) 106 if (receiver != nullptr) { 107 Append(receiver); 108 } 109 for (size_t i = 1; i < shorty_len_; ++i) { 110 switch (shorty_[i]) { 111 case 'Z': 112 case 'B': 113 case 'C': 114 case 'S': 115 case 'I': 116 Append(va_arg(ap, jint)); 117 break; 118 case 'F': 119 AppendFloat(va_arg(ap, jdouble)); 120 break; 121 case 'L': 122 Append(soa.Decode<mirror::Object>(va_arg(ap, jobject))); 123 break; 124 case 'D': 125 AppendDouble(va_arg(ap, jdouble)); 126 break; 127 case 'J': 128 AppendWide(va_arg(ap, jlong)); 129 break; 130 #ifndef NDEBUG 131 default: 132 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 133 #endif 134 } 135 } 136 } 137 138 void BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable& soa, 139 ObjPtr<mirror::Object> receiver, jvalue* args) 140 REQUIRES_SHARED(Locks::mutator_lock_) { 141 // Set receiver if non-null (method is not static) 142 if (receiver != nullptr) { 143 Append(receiver); 144 } 145 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) { 146 switch (shorty_[i]) { 147 case 'Z': 148 Append(args[args_offset].z); 149 break; 150 case 'B': 151 Append(args[args_offset].b); 152 break; 153 case 'C': 154 Append(args[args_offset].c); 155 break; 156 case 'S': 157 Append(args[args_offset].s); 158 break; 159 case 'I': 160 case 'F': 161 Append(args[args_offset].i); 162 break; 163 case 'L': 164 Append(soa.Decode<mirror::Object>(args[args_offset].l)); 165 break; 166 case 'D': 167 case 'J': 168 AppendWide(args[args_offset].j); 169 break; 170 #ifndef NDEBUG 171 default: 172 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 173 #endif 174 } 175 } 176 } 177 178 void BuildArgArrayFromFrame(ShadowFrame* shadow_frame, uint32_t arg_offset) 179 REQUIRES_SHARED(Locks::mutator_lock_) { 180 // Set receiver if non-null (method is not static) 181 size_t cur_arg = arg_offset; 182 if (!shadow_frame->GetMethod()->IsStatic()) { 183 Append(shadow_frame->GetVReg(cur_arg)); 184 cur_arg++; 185 } 186 for (size_t i = 1; i < shorty_len_; ++i) { 187 switch (shorty_[i]) { 188 case 'Z': 189 case 'B': 190 case 'C': 191 case 'S': 192 case 'I': 193 case 'F': 194 case 'L': 195 Append(shadow_frame->GetVReg(cur_arg)); 196 cur_arg++; 197 break; 198 case 'D': 199 case 'J': 200 AppendWide(shadow_frame->GetVRegLong(cur_arg)); 201 cur_arg++; 202 cur_arg++; 203 break; 204 #ifndef NDEBUG 205 default: 206 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 207 #endif 208 } 209 } 210 } 211 212 static void ThrowIllegalPrimitiveArgumentException(const char* expected, 213 const char* found_descriptor) 214 REQUIRES_SHARED(Locks::mutator_lock_) { 215 ThrowIllegalArgumentException( 216 StringPrintf("Invalid primitive conversion from %s to %s", expected, 217 PrettyDescriptor(found_descriptor).c_str()).c_str()); 218 } 219 220 bool BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver, 221 ObjPtr<mirror::ObjectArray<mirror::Object>> raw_args, 222 ArtMethod* m, 223 Thread* self) 224 REQUIRES_SHARED(Locks::mutator_lock_) { 225 const DexFile::TypeList* classes = m->GetParameterTypeList(); 226 // Set receiver if non-null (method is not static) 227 if (receiver != nullptr) { 228 Append(receiver); 229 } 230 StackHandleScope<2> hs(self); 231 MutableHandle<mirror::Object> arg(hs.NewHandle<mirror::Object>(nullptr)); 232 Handle<mirror::ObjectArray<mirror::Object>> args( 233 hs.NewHandle<mirror::ObjectArray<mirror::Object>>(raw_args)); 234 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) { 235 arg.Assign(args->Get(args_offset)); 236 if (((shorty_[i] == 'L') && (arg != nullptr)) || 237 ((arg == nullptr && shorty_[i] != 'L'))) { 238 // TODO: The method's parameter's type must have been previously resolved, yet 239 // we've seen cases where it's not b/34440020. 240 ObjPtr<mirror::Class> dst_class( 241 m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_, 242 true /* resolve */)); 243 if (dst_class.Ptr() == nullptr) { 244 CHECK(self->IsExceptionPending()); 245 return false; 246 } 247 if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) { 248 ThrowIllegalArgumentException( 249 StringPrintf("method %s argument %zd has type %s, got %s", 250 m->PrettyMethod(false).c_str(), 251 args_offset + 1, // Humans don't count from 0. 252 mirror::Class::PrettyDescriptor(dst_class).c_str(), 253 mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str()); 254 return false; 255 } 256 } 257 258 #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \ 259 if (LIKELY(arg != nullptr && \ 260 arg->GetClass()->DescriptorEquals(match_descriptor))) { \ 261 ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ 262 append(primitive_field-> get_fn(arg.Get())); 263 264 #define DO_ARG(match_descriptor, get_fn, append) \ 265 } else if (LIKELY(arg != nullptr && \ 266 arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ 267 ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ 268 append(primitive_field-> get_fn(arg.Get())); 269 270 #define DO_FAIL(expected) \ 271 } else { \ 272 if (arg->GetClass<>()->IsPrimitive()) { \ 273 std::string temp; \ 274 ThrowIllegalPrimitiveArgumentException(expected, \ 275 arg->GetClass<>()->GetDescriptor(&temp)); \ 276 } else { \ 277 ThrowIllegalArgumentException(\ 278 StringPrintf("method %s argument %zd has type %s, got %s", \ 279 ArtMethod::PrettyMethod(m, false).c_str(), \ 280 args_offset + 1, \ 281 expected, \ 282 mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str()); \ 283 } \ 284 return false; \ 285 } } 286 287 switch (shorty_[i]) { 288 case 'L': 289 Append(arg.Get()); 290 break; 291 case 'Z': 292 DO_FIRST_ARG("Ljava/lang/Boolean;", GetBoolean, Append) 293 DO_FAIL("boolean") 294 break; 295 case 'B': 296 DO_FIRST_ARG("Ljava/lang/Byte;", GetByte, Append) 297 DO_FAIL("byte") 298 break; 299 case 'C': 300 DO_FIRST_ARG("Ljava/lang/Character;", GetChar, Append) 301 DO_FAIL("char") 302 break; 303 case 'S': 304 DO_FIRST_ARG("Ljava/lang/Short;", GetShort, Append) 305 DO_ARG("Ljava/lang/Byte;", GetByte, Append) 306 DO_FAIL("short") 307 break; 308 case 'I': 309 DO_FIRST_ARG("Ljava/lang/Integer;", GetInt, Append) 310 DO_ARG("Ljava/lang/Character;", GetChar, Append) 311 DO_ARG("Ljava/lang/Short;", GetShort, Append) 312 DO_ARG("Ljava/lang/Byte;", GetByte, Append) 313 DO_FAIL("int") 314 break; 315 case 'J': 316 DO_FIRST_ARG("Ljava/lang/Long;", GetLong, AppendWide) 317 DO_ARG("Ljava/lang/Integer;", GetInt, AppendWide) 318 DO_ARG("Ljava/lang/Character;", GetChar, AppendWide) 319 DO_ARG("Ljava/lang/Short;", GetShort, AppendWide) 320 DO_ARG("Ljava/lang/Byte;", GetByte, AppendWide) 321 DO_FAIL("long") 322 break; 323 case 'F': 324 DO_FIRST_ARG("Ljava/lang/Float;", GetFloat, AppendFloat) 325 DO_ARG("Ljava/lang/Long;", GetLong, AppendFloat) 326 DO_ARG("Ljava/lang/Integer;", GetInt, AppendFloat) 327 DO_ARG("Ljava/lang/Character;", GetChar, AppendFloat) 328 DO_ARG("Ljava/lang/Short;", GetShort, AppendFloat) 329 DO_ARG("Ljava/lang/Byte;", GetByte, AppendFloat) 330 DO_FAIL("float") 331 break; 332 case 'D': 333 DO_FIRST_ARG("Ljava/lang/Double;", GetDouble, AppendDouble) 334 DO_ARG("Ljava/lang/Float;", GetFloat, AppendDouble) 335 DO_ARG("Ljava/lang/Long;", GetLong, AppendDouble) 336 DO_ARG("Ljava/lang/Integer;", GetInt, AppendDouble) 337 DO_ARG("Ljava/lang/Character;", GetChar, AppendDouble) 338 DO_ARG("Ljava/lang/Short;", GetShort, AppendDouble) 339 DO_ARG("Ljava/lang/Byte;", GetByte, AppendDouble) 340 DO_FAIL("double") 341 break; 342 #ifndef NDEBUG 343 default: 344 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 345 UNREACHABLE(); 346 #endif 347 } 348 #undef DO_FIRST_ARG 349 #undef DO_ARG 350 #undef DO_FAIL 351 } 352 return true; 353 } 354 355 private: 356 enum { kSmallArgArraySize = 16 }; 357 const char* const shorty_; 358 const uint32_t shorty_len_; 359 uint32_t num_bytes_; 360 uint32_t* arg_array_; 361 uint32_t small_arg_array_[kSmallArgArraySize]; 362 std::unique_ptr<uint32_t[]> large_arg_array_; 363 }; 364 365 static void CheckMethodArguments(JavaVMExt* vm, ArtMethod* m, uint32_t* args) 366 REQUIRES_SHARED(Locks::mutator_lock_) { 367 const DexFile::TypeList* params = m->GetParameterTypeList(); 368 if (params == nullptr) { 369 return; // No arguments so nothing to check. 370 } 371 uint32_t offset = 0; 372 uint32_t num_params = params->Size(); 373 size_t error_count = 0; 374 if (!m->IsStatic()) { 375 offset = 1; 376 } 377 // TODO: If args contain object references, it may cause problems. 378 Thread* const self = Thread::Current(); 379 for (uint32_t i = 0; i < num_params; i++) { 380 dex::TypeIndex type_idx = params->GetTypeItem(i).type_idx_; 381 ObjPtr<mirror::Class> param_type(m->GetClassFromTypeIndex(type_idx, true /* resolve */)); 382 if (param_type == nullptr) { 383 CHECK(self->IsExceptionPending()); 384 LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: " 385 << m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n" 386 << self->GetException()->Dump(); 387 self->ClearException(); 388 ++error_count; 389 } else if (!param_type->IsPrimitive()) { 390 // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension, 391 // this is a hard to fix problem since the args can contain Object*, we need to save and 392 // restore them by using a visitor similar to the ones used in the trampoline entrypoints. 393 ObjPtr<mirror::Object> argument = 394 (reinterpret_cast<StackReference<mirror::Object>*>(&args[i + offset]))->AsMirrorPtr(); 395 if (argument != nullptr && !argument->InstanceOf(param_type)) { 396 LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of " 397 << argument->PrettyTypeOf() << " as argument " << (i + 1) 398 << " to " << m->PrettyMethod(); 399 ++error_count; 400 } 401 } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) { 402 offset++; 403 } else { 404 int32_t arg = static_cast<int32_t>(args[i + offset]); 405 if (param_type->IsPrimitiveBoolean()) { 406 if (arg != JNI_TRUE && arg != JNI_FALSE) { 407 LOG(ERROR) << "JNI ERROR (app bug): expected jboolean (0/1) but got value of " 408 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod(); 409 ++error_count; 410 } 411 } else if (param_type->IsPrimitiveByte()) { 412 if (arg < -128 || arg > 127) { 413 LOG(ERROR) << "JNI ERROR (app bug): expected jbyte but got value of " 414 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod(); 415 ++error_count; 416 } 417 } else if (param_type->IsPrimitiveChar()) { 418 if (args[i + offset] > 0xFFFF) { 419 LOG(ERROR) << "JNI ERROR (app bug): expected jchar but got value of " 420 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod(); 421 ++error_count; 422 } 423 } else if (param_type->IsPrimitiveShort()) { 424 if (arg < -32768 || arg > 0x7FFF) { 425 LOG(ERROR) << "JNI ERROR (app bug): expected jshort but got value of " 426 << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod(); 427 ++error_count; 428 } 429 } 430 } 431 } 432 if (UNLIKELY(error_count > 0)) { 433 // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort 434 // with an argument. 435 vm->JniAbortF(nullptr, "bad arguments passed to %s (see above for details)", 436 m->PrettyMethod().c_str()); 437 } 438 } 439 440 static ArtMethod* FindVirtualMethod(ObjPtr<mirror::Object> receiver, ArtMethod* method) 441 REQUIRES_SHARED(Locks::mutator_lock_) { 442 return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, kRuntimePointerSize); 443 } 444 445 446 static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa, 447 ArtMethod* method, ArgArray* arg_array, JValue* result, 448 const char* shorty) 449 REQUIRES_SHARED(Locks::mutator_lock_) { 450 uint32_t* args = arg_array->GetArray(); 451 if (UNLIKELY(soa.Env()->check_jni)) { 452 CheckMethodArguments(soa.Vm(), method->GetInterfaceMethodIfProxy(kRuntimePointerSize), args); 453 } 454 method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty); 455 } 456 457 JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, 458 va_list args) 459 REQUIRES_SHARED(Locks::mutator_lock_) { 460 // We want to make sure that the stack is not within a small distance from the 461 // protected region in case we are calling into a leaf function whose stack 462 // check has been elided. 463 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 464 ThrowStackOverflowError(soa.Self()); 465 return JValue(); 466 } 467 468 ArtMethod* method = jni::DecodeArtMethod(mid); 469 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 470 if (is_string_init) { 471 // Replace calls to String.<init> with equivalent StringFactory call. 472 method = WellKnownClasses::StringInitToStringFactory(method); 473 } 474 ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj); 475 uint32_t shorty_len = 0; 476 const char* shorty = 477 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len); 478 JValue result; 479 ArgArray arg_array(shorty, shorty_len); 480 arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); 481 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 482 if (is_string_init) { 483 // For string init, remap original receiver to StringFactory result. 484 UpdateReference(soa.Self(), obj, result.GetL()); 485 } 486 return result; 487 } 488 489 JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, 490 jvalue* args) { 491 // We want to make sure that the stack is not within a small distance from the 492 // protected region in case we are calling into a leaf function whose stack 493 // check has been elided. 494 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 495 ThrowStackOverflowError(soa.Self()); 496 return JValue(); 497 } 498 499 ArtMethod* method = jni::DecodeArtMethod(mid); 500 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 501 if (is_string_init) { 502 // Replace calls to String.<init> with equivalent StringFactory call. 503 method = WellKnownClasses::StringInitToStringFactory(method); 504 } 505 ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj); 506 uint32_t shorty_len = 0; 507 const char* shorty = 508 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len); 509 JValue result; 510 ArgArray arg_array(shorty, shorty_len); 511 arg_array.BuildArgArrayFromJValues(soa, receiver, args); 512 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 513 if (is_string_init) { 514 // For string init, remap original receiver to StringFactory result. 515 UpdateReference(soa.Self(), obj, result.GetL()); 516 } 517 return result; 518 } 519 520 JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, 521 jobject obj, jmethodID mid, jvalue* args) { 522 // We want to make sure that the stack is not within a small distance from the 523 // protected region in case we are calling into a leaf function whose stack 524 // check has been elided. 525 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 526 ThrowStackOverflowError(soa.Self()); 527 return JValue(); 528 } 529 530 ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj); 531 ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid)); 532 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 533 if (is_string_init) { 534 // Replace calls to String.<init> with equivalent StringFactory call. 535 method = WellKnownClasses::StringInitToStringFactory(method); 536 receiver = nullptr; 537 } 538 uint32_t shorty_len = 0; 539 const char* shorty = 540 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len); 541 JValue result; 542 ArgArray arg_array(shorty, shorty_len); 543 arg_array.BuildArgArrayFromJValues(soa, receiver, args); 544 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 545 if (is_string_init) { 546 // For string init, remap original receiver to StringFactory result. 547 UpdateReference(soa.Self(), obj, result.GetL()); 548 } 549 return result; 550 } 551 552 JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, 553 jobject obj, jmethodID mid, va_list args) { 554 // We want to make sure that the stack is not within a small distance from the 555 // protected region in case we are calling into a leaf function whose stack 556 // check has been elided. 557 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 558 ThrowStackOverflowError(soa.Self()); 559 return JValue(); 560 } 561 562 ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj); 563 ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid)); 564 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 565 if (is_string_init) { 566 // Replace calls to String.<init> with equivalent StringFactory call. 567 method = WellKnownClasses::StringInitToStringFactory(method); 568 receiver = nullptr; 569 } 570 uint32_t shorty_len = 0; 571 const char* shorty = 572 method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len); 573 JValue result; 574 ArgArray arg_array(shorty, shorty_len); 575 arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); 576 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 577 if (is_string_init) { 578 // For string init, remap original receiver to StringFactory result. 579 UpdateReference(soa.Self(), obj, result.GetL()); 580 } 581 return result; 582 } 583 584 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod, 585 jobject javaReceiver, jobject javaArgs, size_t num_frames) { 586 // We want to make sure that the stack is not within a small distance from the 587 // protected region in case we are calling into a leaf function whose stack 588 // check has been elided. 589 if (UNLIKELY(__builtin_frame_address(0) < 590 soa.Self()->GetStackEndForInterpreter(true))) { 591 ThrowStackOverflowError(soa.Self()); 592 return nullptr; 593 } 594 595 ObjPtr<mirror::Executable> executable = soa.Decode<mirror::Executable>(javaMethod); 596 const bool accessible = executable->IsAccessible(); 597 ArtMethod* m = executable->GetArtMethod(); 598 599 ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass(); 600 if (UNLIKELY(!declaring_class->IsInitialized())) { 601 StackHandleScope<1> hs(soa.Self()); 602 HandleWrapperObjPtr<mirror::Class> h_class(hs.NewHandleWrapper(&declaring_class)); 603 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), h_class, true, true)) { 604 return nullptr; 605 } 606 } 607 608 ObjPtr<mirror::Object> receiver; 609 if (!m->IsStatic()) { 610 // Replace calls to String.<init> with equivalent StringFactory call. 611 if (declaring_class->IsStringClass() && m->IsConstructor()) { 612 m = WellKnownClasses::StringInitToStringFactory(m); 613 CHECK(javaReceiver == nullptr); 614 } else { 615 // Check that the receiver is non-null and an instance of the field's declaring class. 616 receiver = soa.Decode<mirror::Object>(javaReceiver); 617 if (!VerifyObjectIsClass(receiver, declaring_class)) { 618 return nullptr; 619 } 620 621 // Find the actual implementation of the virtual method. 622 m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, kRuntimePointerSize); 623 } 624 } 625 626 // Get our arrays of arguments and their types, and check they're the same size. 627 ObjPtr<mirror::ObjectArray<mirror::Object>> objects = 628 soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs); 629 auto* np_method = m->GetInterfaceMethodIfProxy(kRuntimePointerSize); 630 const DexFile::TypeList* classes = np_method->GetParameterTypeList(); 631 uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size(); 632 uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0; 633 if (arg_count != classes_size) { 634 ThrowIllegalArgumentException(StringPrintf("Wrong number of arguments; expected %d, got %d", 635 classes_size, arg_count).c_str()); 636 return nullptr; 637 } 638 639 // If method is not set to be accessible, verify it can be accessed by the caller. 640 ObjPtr<mirror::Class> calling_class; 641 if (!accessible && !VerifyAccess(soa.Self(), 642 receiver, 643 declaring_class, 644 m->GetAccessFlags(), 645 &calling_class, 646 num_frames)) { 647 ThrowIllegalAccessException( 648 StringPrintf("Class %s cannot access %s method %s of class %s", 649 calling_class == nullptr ? "null" : calling_class->PrettyClass().c_str(), 650 PrettyJavaAccessFlags(m->GetAccessFlags()).c_str(), 651 m->PrettyMethod().c_str(), 652 m->GetDeclaringClass() == nullptr ? "null" : 653 m->GetDeclaringClass()->PrettyClass().c_str()).c_str()); 654 return nullptr; 655 } 656 657 // Invoke the method. 658 JValue result; 659 uint32_t shorty_len = 0; 660 const char* shorty = np_method->GetShorty(&shorty_len); 661 ArgArray arg_array(shorty, shorty_len); 662 if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method, soa.Self())) { 663 CHECK(soa.Self()->IsExceptionPending()); 664 return nullptr; 665 } 666 667 InvokeWithArgArray(soa, m, &arg_array, &result, shorty); 668 669 // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early. 670 if (soa.Self()->IsExceptionPending()) { 671 // If we get another exception when we are trying to wrap, then just use that instead. 672 ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred()); 673 soa.Self()->ClearException(); 674 jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException"); 675 if (exception_class == nullptr) { 676 soa.Self()->AssertPendingException(); 677 return nullptr; 678 } 679 jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V"); 680 CHECK(mid != nullptr); 681 jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th.get()); 682 if (exception_instance == nullptr) { 683 soa.Self()->AssertPendingException(); 684 return nullptr; 685 } 686 soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance)); 687 return nullptr; 688 } 689 690 // Box if necessary and return. 691 return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result)); 692 } 693 694 ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value) { 695 if (src_class == Primitive::kPrimNot) { 696 return MakeObjPtr(value.GetL()); 697 } 698 if (src_class == Primitive::kPrimVoid) { 699 // There's no such thing as a void field, and void methods invoked via reflection return null. 700 return nullptr; 701 } 702 703 jmethodID m = nullptr; 704 const char* shorty; 705 switch (src_class) { 706 case Primitive::kPrimBoolean: 707 m = WellKnownClasses::java_lang_Boolean_valueOf; 708 shorty = "LZ"; 709 break; 710 case Primitive::kPrimByte: 711 m = WellKnownClasses::java_lang_Byte_valueOf; 712 shorty = "LB"; 713 break; 714 case Primitive::kPrimChar: 715 m = WellKnownClasses::java_lang_Character_valueOf; 716 shorty = "LC"; 717 break; 718 case Primitive::kPrimDouble: 719 m = WellKnownClasses::java_lang_Double_valueOf; 720 shorty = "LD"; 721 break; 722 case Primitive::kPrimFloat: 723 m = WellKnownClasses::java_lang_Float_valueOf; 724 shorty = "LF"; 725 break; 726 case Primitive::kPrimInt: 727 m = WellKnownClasses::java_lang_Integer_valueOf; 728 shorty = "LI"; 729 break; 730 case Primitive::kPrimLong: 731 m = WellKnownClasses::java_lang_Long_valueOf; 732 shorty = "LJ"; 733 break; 734 case Primitive::kPrimShort: 735 m = WellKnownClasses::java_lang_Short_valueOf; 736 shorty = "LS"; 737 break; 738 default: 739 LOG(FATAL) << static_cast<int>(src_class); 740 shorty = nullptr; 741 } 742 743 ScopedObjectAccessUnchecked soa(Thread::Current()); 744 DCHECK_EQ(soa.Self()->GetState(), kRunnable); 745 746 ArgArray arg_array(shorty, 2); 747 JValue result; 748 if (src_class == Primitive::kPrimDouble || src_class == Primitive::kPrimLong) { 749 arg_array.AppendWide(value.GetJ()); 750 } else { 751 arg_array.Append(value.GetI()); 752 } 753 754 jni::DecodeArtMethod(m)->Invoke(soa.Self(), 755 arg_array.GetArray(), 756 arg_array.GetNumBytes(), 757 &result, 758 shorty); 759 return result.GetL(); 760 } 761 762 static std::string UnboxingFailureKind(ArtField* f) 763 REQUIRES_SHARED(Locks::mutator_lock_) { 764 if (f != nullptr) { 765 return "field " + f->PrettyField(false); 766 } 767 return "result"; 768 } 769 770 static bool UnboxPrimitive(ObjPtr<mirror::Object> o, 771 ObjPtr<mirror::Class> dst_class, 772 ArtField* f, 773 JValue* unboxed_value) 774 REQUIRES_SHARED(Locks::mutator_lock_) { 775 bool unbox_for_result = (f == nullptr); 776 if (!dst_class->IsPrimitive()) { 777 if (UNLIKELY(o != nullptr && !o->InstanceOf(dst_class))) { 778 if (!unbox_for_result) { 779 ThrowIllegalArgumentException( 780 StringPrintf("%s has type %s, got %s", 781 UnboxingFailureKind(f).c_str(), 782 dst_class->PrettyDescriptor().c_str(), 783 o->PrettyTypeOf().c_str()).c_str()); 784 } else { 785 ThrowClassCastException( 786 StringPrintf("Couldn't convert result of type %s to %s", 787 o->PrettyTypeOf().c_str(), 788 dst_class->PrettyDescriptor().c_str()).c_str()); 789 } 790 return false; 791 } 792 unboxed_value->SetL(o); 793 return true; 794 } 795 if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) { 796 ThrowIllegalArgumentException(StringPrintf("Can't unbox %s to void", 797 UnboxingFailureKind(f).c_str()).c_str()); 798 return false; 799 } 800 if (UNLIKELY(o == nullptr)) { 801 if (!unbox_for_result) { 802 ThrowIllegalArgumentException( 803 StringPrintf("%s has type %s, got null", 804 UnboxingFailureKind(f).c_str(), 805 dst_class->PrettyDescriptor().c_str()).c_str()); 806 } else { 807 ThrowNullPointerException( 808 StringPrintf("Expected to unbox a '%s' primitive type but was returned null", 809 dst_class->PrettyDescriptor().c_str()).c_str()); 810 } 811 return false; 812 } 813 814 JValue boxed_value; 815 ObjPtr<mirror::Class> klass = o->GetClass(); 816 ObjPtr<mirror::Class> src_class = nullptr; 817 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 818 ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0); 819 if (klass->DescriptorEquals("Ljava/lang/Boolean;")) { 820 src_class = class_linker->FindPrimitiveClass('Z'); 821 boxed_value.SetZ(primitive_field->GetBoolean(o)); 822 } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) { 823 src_class = class_linker->FindPrimitiveClass('B'); 824 boxed_value.SetB(primitive_field->GetByte(o)); 825 } else if (klass->DescriptorEquals("Ljava/lang/Character;")) { 826 src_class = class_linker->FindPrimitiveClass('C'); 827 boxed_value.SetC(primitive_field->GetChar(o)); 828 } else if (klass->DescriptorEquals("Ljava/lang/Float;")) { 829 src_class = class_linker->FindPrimitiveClass('F'); 830 boxed_value.SetF(primitive_field->GetFloat(o)); 831 } else if (klass->DescriptorEquals("Ljava/lang/Double;")) { 832 src_class = class_linker->FindPrimitiveClass('D'); 833 boxed_value.SetD(primitive_field->GetDouble(o)); 834 } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) { 835 src_class = class_linker->FindPrimitiveClass('I'); 836 boxed_value.SetI(primitive_field->GetInt(o)); 837 } else if (klass->DescriptorEquals("Ljava/lang/Long;")) { 838 src_class = class_linker->FindPrimitiveClass('J'); 839 boxed_value.SetJ(primitive_field->GetLong(o)); 840 } else if (klass->DescriptorEquals("Ljava/lang/Short;")) { 841 src_class = class_linker->FindPrimitiveClass('S'); 842 boxed_value.SetS(primitive_field->GetShort(o)); 843 } else { 844 std::string temp; 845 ThrowIllegalArgumentException( 846 StringPrintf("%s has type %s, got %s", UnboxingFailureKind(f).c_str(), 847 dst_class->PrettyDescriptor().c_str(), 848 PrettyDescriptor(o->GetClass()->GetDescriptor(&temp)).c_str()).c_str()); 849 return false; 850 } 851 852 return ConvertPrimitiveValue(unbox_for_result, 853 src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(), 854 boxed_value, unboxed_value); 855 } 856 857 bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o, 858 ObjPtr<mirror::Class> dst_class, 859 ArtField* f, 860 JValue* unboxed_value) { 861 DCHECK(f != nullptr); 862 return UnboxPrimitive(o, dst_class, f, unboxed_value); 863 } 864 865 bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o, 866 ObjPtr<mirror::Class> dst_class, 867 JValue* unboxed_value) { 868 return UnboxPrimitive(o, dst_class, nullptr, unboxed_value); 869 } 870 871 ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames) { 872 NthCallerVisitor visitor(self, num_frames); 873 visitor.WalkStack(); 874 return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr; 875 } 876 877 bool VerifyAccess(Thread* self, 878 ObjPtr<mirror::Object> obj, 879 ObjPtr<mirror::Class> declaring_class, 880 uint32_t access_flags, 881 ObjPtr<mirror::Class>* calling_class, 882 size_t num_frames) { 883 if ((access_flags & kAccPublic) != 0) { 884 return true; 885 } 886 ObjPtr<mirror::Class> klass = GetCallingClass(self, num_frames); 887 if (UNLIKELY(klass == nullptr)) { 888 // The caller is an attached native thread. 889 return false; 890 } 891 *calling_class = klass; 892 return VerifyAccess(obj, declaring_class, access_flags, klass); 893 } 894 895 bool VerifyAccess(ObjPtr<mirror::Object> obj, 896 ObjPtr<mirror::Class> declaring_class, 897 uint32_t access_flags, 898 ObjPtr<mirror::Class> calling_class) { 899 if (calling_class == declaring_class) { 900 return true; 901 } 902 ScopedAssertNoThreadSuspension sants("verify-access"); 903 if ((access_flags & kAccPrivate) != 0) { 904 return false; 905 } 906 if ((access_flags & kAccProtected) != 0) { 907 if (obj != nullptr && !obj->InstanceOf(calling_class) && 908 !declaring_class->IsInSamePackage(calling_class)) { 909 return false; 910 } else if (declaring_class->IsAssignableFrom(calling_class)) { 911 return true; 912 } 913 } 914 return declaring_class->IsInSamePackage(calling_class); 915 } 916 917 void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) { 918 std::string expected_class_name(mirror::Class::PrettyDescriptor(c)); 919 std::string actual_class_name(mirror::Object::PrettyTypeOf(o)); 920 ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s", 921 expected_class_name.c_str(), 922 actual_class_name.c_str()).c_str()); 923 } 924 925 // This only works if there's one reference which points to the object in obj. 926 // Will need to be fixed if there's cases where it's not. 927 void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result) { 928 IndirectRef ref = reinterpret_cast<IndirectRef>(obj); 929 IndirectRefKind kind = IndirectReferenceTable::GetIndirectRefKind(ref); 930 if (kind == kLocal) { 931 self->GetJniEnv()->locals.Update(obj, result); 932 } else if (kind == kHandleScopeOrInvalid) { 933 LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid"; 934 } else if (kind == kGlobal) { 935 self->GetJniEnv()->vm->UpdateGlobal(self, ref, result); 936 } else { 937 DCHECK_EQ(kind, kWeakGlobal); 938 self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result); 939 } 940 } 941 942 } // namespace art 943