diff options
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 69 |
1 files changed, 45 insertions, 24 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 2d1bf6f780..c7fbf59420 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -66,12 +66,14 @@ #include "class_loader_utils.h" #include "class_root-inl.h" #include "class_table-inl.h" +#include "common_throws.h" #include "compiler_callbacks.h" #include "debug_print.h" #include "debugger.h" #include "dex/class_accessor-inl.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" +#include "dex/dex_file.h" #include "dex/dex_file_annotations.h" #include "dex/dex_file_exception_helpers.h" #include "dex/dex_file_loader.h" @@ -10338,6 +10340,12 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForField( ThrowIllegalAccessErrorField(referring_class, target_field); return nullptr; } + // TODO(b/364876321): ResolveField might return instance field when is_static is true and + // vice versa. + if (UNLIKELY(is_static != target_field->IsStatic())) { + ThrowIncompatibleClassChangeErrorField(target_field, is_static, referrer); + return nullptr; + } if (UNLIKELY(is_put && target_field->IsFinal())) { ThrowIllegalAccessErrorField(referring_class, target_field); return nullptr; @@ -10430,19 +10438,21 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForMethod( case DexFile::MethodHandleType::kInvokeStatic: { kind = mirror::MethodHandle::Kind::kInvokeStatic; receiver_count = 0; - target_method = ResolveMethod<ResolveMode::kNoChecks>(self, - method_handle.field_or_method_idx_, - referrer, - InvokeType::kStatic); + target_method = + ResolveMethod<ResolveMode::kCheckICCEAndIAE>(self, + method_handle.field_or_method_idx_, + referrer, + InvokeType::kStatic); break; } case DexFile::MethodHandleType::kInvokeInstance: { kind = mirror::MethodHandle::Kind::kInvokeVirtual; receiver_count = 1; - target_method = ResolveMethod<ResolveMode::kNoChecks>(self, - method_handle.field_or_method_idx_, - referrer, - InvokeType::kVirtual); + target_method = + ResolveMethod<ResolveMode::kCheckICCEAndIAE>(self, + method_handle.field_or_method_idx_, + referrer, + InvokeType::kVirtual); break; } case DexFile::MethodHandleType::kInvokeConstructor: { @@ -10450,10 +10460,11 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForMethod( // are special cased later in this method. kind = mirror::MethodHandle::Kind::kInvokeTransform; receiver_count = 0; - target_method = ResolveMethod<ResolveMode::kNoChecks>(self, - method_handle.field_or_method_idx_, - referrer, - InvokeType::kDirect); + target_method = + ResolveMethod<ResolveMode::kCheckICCEAndIAE>(self, + method_handle.field_or_method_idx_, + referrer, + InvokeType::kDirect); break; } case DexFile::MethodHandleType::kInvokeDirect: { @@ -10475,16 +10486,18 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForMethod( if (target_method->IsPrivate()) { kind = mirror::MethodHandle::Kind::kInvokeDirect; - target_method = ResolveMethod<ResolveMode::kNoChecks>(self, - method_handle.field_or_method_idx_, - referrer, - InvokeType::kDirect); + target_method = + ResolveMethod<ResolveMode::kCheckICCEAndIAE>(self, + method_handle.field_or_method_idx_, + referrer, + InvokeType::kDirect); } else { kind = mirror::MethodHandle::Kind::kInvokeSuper; - target_method = ResolveMethod<ResolveMode::kNoChecks>(self, - method_handle.field_or_method_idx_, - referrer, - InvokeType::kSuper); + target_method = + ResolveMethod<ResolveMode::kCheckICCEAndIAE>(self, + method_handle.field_or_method_idx_, + referrer, + InvokeType::kSuper); if (UNLIKELY(target_method == nullptr)) { break; } @@ -10500,10 +10513,11 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForMethod( case DexFile::MethodHandleType::kInvokeInterface: { kind = mirror::MethodHandle::Kind::kInvokeInterface; receiver_count = 1; - target_method = ResolveMethod<ResolveMode::kNoChecks>(self, - method_handle.field_or_method_idx_, - referrer, - InvokeType::kInterface); + target_method = + ResolveMethod<ResolveMode::kCheckICCEAndIAE>(self, + method_handle.field_or_method_idx_, + referrer, + InvokeType::kInterface); break; } } @@ -10513,6 +10527,13 @@ ObjPtr<mirror::MethodHandle> ClassLinker::ResolveMethodHandleForMethod( return nullptr; } + // According to JVMS 4.4.8 none of invoke* MethodHandle-s can target <clinit> methods. + if (UNLIKELY(target_method->IsClassInitializer())) { + ThrowClassFormatError(referrer->GetDeclaringClass(), + "Method handles can't target class initializer method"); + return nullptr; + } + ObjPtr<mirror::Class> target_class = target_method->GetDeclaringClass(); ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); uint32_t access_flags = target_method->GetAccessFlags(); |