ART: Fix to ClassLinker::ResolveMethodHandleForField()
Adds check for constant method handles to not mutate final fields.
Test: art/test/run-test --host 979
Bug: 66890674
Change-Id: I21d55468c703093e9bc7807667257c07271883d3
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 72c110a..fd92c14 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -8236,29 +8236,34 @@
DexFile::MethodHandleType handle_type =
static_cast<DexFile::MethodHandleType>(method_handle.method_handle_type_);
mirror::MethodHandle::Kind kind;
+ bool is_put;
bool is_static;
int32_t num_params;
switch (handle_type) {
case DexFile::MethodHandleType::kStaticPut: {
kind = mirror::MethodHandle::Kind::kStaticPut;
+ is_put = true;
is_static = true;
num_params = 1;
break;
}
case DexFile::MethodHandleType::kStaticGet: {
kind = mirror::MethodHandle::Kind::kStaticGet;
+ is_put = false;
is_static = true;
num_params = 0;
break;
}
case DexFile::MethodHandleType::kInstancePut: {
kind = mirror::MethodHandle::Kind::kInstancePut;
+ is_put = true;
is_static = false;
num_params = 2;
break;
}
case DexFile::MethodHandleType::kInstanceGet: {
kind = mirror::MethodHandle::Kind::kInstanceGet;
+ is_put = false;
is_static = false;
num_params = 1;
break;
@@ -8280,6 +8285,10 @@
ThrowIllegalAccessErrorField(referring_class, target_field);
return nullptr;
}
+ if (UNLIKELY(is_put && target_field->IsFinal())) {
+ ThrowIllegalAccessErrorField(referring_class, target_field);
+ return nullptr;
+ }
} else {
DCHECK(Thread::Current()->IsExceptionPending());
return nullptr;