ART: Add guards to the dex cache and its shortcuts
Do not return fields, methods or classes if the (declaring) class is
erroneous.
Bug: 16692788
Change-Id: If43c2414ad0eb22db5eba7cf66396c7f16c26597
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 73de683..0dd1588 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -19,6 +19,8 @@
#include "art_method.h"
+#include "art_field.h"
+#include "class.h"
#include "class_linker.h"
#include "dex_cache.h"
#include "dex_file.h"
@@ -87,11 +89,60 @@
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
}
+inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index) {
+ ArtMethod* method = GetDexCacheResolvedMethods()->Get(method_index);
+ if (method != nullptr && !method->GetDeclaringClass()->IsErroneous()) {
+ return method;
+ } else {
+ return nullptr;
+ }
+}
+
+inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
+ GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
+}
+
+inline bool ArtMethod::HasDexCacheResolvedMethods() {
+ return GetDexCacheResolvedMethods() != nullptr;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
+ return GetDexCacheResolvedMethods() == other_cache;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
+ return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
+}
+
+
inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
return GetFieldObject<ObjectArray<Class>>(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_));
}
+template <bool kWithCheck>
+inline Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
+ Class* klass;
+ if (kWithCheck) {
+ klass = GetDexCacheResolvedTypes()->Get(type_index);
+ } else {
+ klass = GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
+ }
+ return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
+}
+
+inline bool ArtMethod::HasDexCacheResolvedTypes() {
+ return GetDexCacheResolvedTypes() != nullptr;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
+ return GetDexCacheResolvedTypes() == other_cache;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
+ return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
+}
+
inline uint32_t ArtMethod::GetCodeSize() {
DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode());
@@ -396,7 +447,7 @@
inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
- return method->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr;
+ return method->GetDexCacheResolvedType(type_idx) != nullptr;
}
inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 01e6149..4ebceff 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -216,13 +216,25 @@
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
}
- ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedMethods(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template <bool kWithCheck = true>
+ Class* GetDexCacheResolvedType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedTypes(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ bool HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Find the method that this method overrides
ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -518,6 +530,10 @@
static GcRoot<Class> java_lang_reflect_ArtMethod_;
private:
+ ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
friend struct art::ArtMethodOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(ArtMethod);
};
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 2c5fbcd..3c947ab 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -17,7 +17,9 @@
#ifndef ART_RUNTIME_MIRROR_DEX_CACHE_H_
#define ART_RUNTIME_MIRROR_DEX_CACHE_H_
+#include "art_field.h"
#include "art_method.h"
+#include "class.h"
#include "object.h"
#include "object_array.h"
@@ -30,9 +32,6 @@
namespace mirror {
-class ArtField;
-class ArtMethod;
-class Class;
class String;
// C++ mirror of java.lang.DexCache.
@@ -115,7 +114,12 @@
ArtField* GetResolvedField(uint32_t field_idx) ALWAYS_INLINE
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetResolvedFields()->Get(field_idx);
+ ArtField* field = GetResolvedFields()->Get(field_idx);
+ if (UNLIKELY(field == nullptr || field->GetDeclaringClass()->IsErroneous())) {
+ return nullptr;
+ } else {
+ return field;
+ }
}
void SetResolvedField(uint32_t field_idx, ArtField* resolved) ALWAYS_INLINE