summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Almaz Mingaleev <mingaleev@google.com> 2024-08-29 12:57:14 +0000
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-09-24 10:15:56 +0000
commit63b8399f3f144769260d93a7a985233e5ac5b910 (patch)
tree2d46e0d91f2df79a80f9ed80cdcb49c08e7de9f6 /runtime/class_linker.cc
parent0b8cc45c57bd0d13901e2c1d15f74c8b562fb2d2 (diff)
Add more validation for const-method-handle.
Making it closer to JVMS 4.4.8 and 5.4.3.5. The RI rejects certain constructions at the class verification stage, hence there are separate classes for MethodHandle-s targeting <init> and <clinit> methods. In these cases The RI throws ClassFormatError during class load, but currently we do validations only when actual MethodHandle object is constructed, that's is the reason why test code has ICCE | CFE in catch blocks. That will be addressed in the upcoming CLs. This should not cause any compat issues as even if some of these MethodHandle were constructed successfully, their invocation leads to runtime crashes. Bug: 297147201 Test: ./art/test/testrunner/testrunner.py --host --64 --jvm -b Change-Id: I551b04e3c00ffc8bcdeac4760d9ac4b3bb7b2aff
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();