summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc69
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();