summaryrefslogtreecommitdiffstats
path: root/runtime/mirror
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2015-05-20 15:51:29 -0700
committerHiroshi Yamauchi <yamauchi@google.com>2015-05-20 16:09:30 -0700
commita56ce5e267c9744ed99e40ae5cd9b527971e1d63 (patch)
tree4a916a7f4dc89d6444ade0d74cc64a3ad5126646 /runtime/mirror
parentce70082da8a4e63c280c2f049a67b38acc82ee1a (diff)
downloadart-a56ce5e267c9744ed99e40ae5cd9b527971e1d63.tar.gz
art-a56ce5e267c9744ed99e40ae5cd9b527971e1d63.tar.bz2
art-a56ce5e267c9744ed99e40ae5cd9b527971e1d63.zip
Fix a cts crash around proxy class fields.
org.apache.harmony.tests.java.io.SerializationStressTest4#test_writeObject_Proxy As the static fields of proxy classes share the dex file indices, they shouldn't be resolved in the dex cache or else Field::GetArtField() may return a wrong art field that belong to a different proxy class. Bug: 20557050 Change-Id: If672c0e67bc49e672e34d75ffbe29c65f5a423b9
Diffstat (limited to 'runtime/mirror')
-rw-r--r--runtime/mirror/field-inl.h26
-rw-r--r--runtime/mirror/field.cc14
2 files changed, 30 insertions, 10 deletions
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 9820db77b1..388921b44e 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -30,10 +30,11 @@ namespace mirror {
template <bool kTransactionActive>
inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field,
bool force_resolve) {
+ StackHandleScope<2> hs(self);
// Try to resolve type before allocating since this is a thread suspension point.
- mirror::Class* type = field->GetType<true>();
+ Handle<mirror::Class> type = hs.NewHandle(field->GetType<true>());
- if (type == nullptr) {
+ if (type.Get() == nullptr) {
if (force_resolve) {
if (kIsDebugBuild) {
self->AssertPendingException();
@@ -48,7 +49,6 @@ inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field,
self->ClearException();
}
}
- StackHandleScope<1> hs(self);
auto ret = hs.NewHandle(static_cast<Field*>(StaticClass()->AllocObject(self)));
if (ret.Get() == nullptr) {
if (kIsDebugBuild) {
@@ -58,14 +58,22 @@ inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field,
}
auto dex_field_index = field->GetDexFieldIndex();
auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, sizeof(void*));
- if (resolved_field != nullptr) {
- DCHECK_EQ(resolved_field, field);
+ if (field->GetDeclaringClass()->IsProxyClass()) {
+ DCHECK(field->IsStatic());
+ DCHECK_LT(dex_field_index, 2U);
+ // The two static fields (interfaces, throws) of all proxy classes
+ // share the same dex file indices 0 and 1. So, we can't resolve
+ // them in the dex cache.
} else {
- // We rely on the field being resolved so that we can back to the ArtField
- // (i.e. FromReflectedMethod).
- field->GetDexCache()->SetResolvedField(dex_field_index, field, sizeof(void*));
+ if (resolved_field != nullptr) {
+ DCHECK_EQ(resolved_field, field);
+ } else {
+ // We rely on the field being resolved so that we can back to the ArtField
+ // (i.e. FromReflectedMethod).
+ field->GetDexCache()->SetResolvedField(dex_field_index, field, sizeof(void*));
+ }
}
- ret->SetType<kTransactionActive>(type);
+ ret->SetType<kTransactionActive>(type.Get());
ret->SetDeclaringClass<kTransactionActive>(field->GetDeclaringClass());
ret->SetAccessFlags<kTransactionActive>(field->GetAccessFlags());
ret->SetDexFieldIndex<kTransactionActive>(dex_field_index);
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index 70311bb889..933784e7ff 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -54,7 +54,19 @@ void Field::VisitRoots(RootVisitor* visitor) {
}
ArtField* Field::GetArtField() {
- mirror::DexCache* const dex_cache = GetDeclaringClass()->GetDexCache();
+ mirror::Class* declaring_class = GetDeclaringClass();
+ if (UNLIKELY(declaring_class->IsProxyClass())) {
+ DCHECK(IsStatic());
+ DCHECK_EQ(declaring_class->NumStaticFields(), 2U);
+ // 0 == Class[] interfaces; 1 == Class[][] throws;
+ if (GetDexFieldIndex() == 0) {
+ return &declaring_class->GetSFields()[0];
+ } else {
+ DCHECK_EQ(GetDexFieldIndex(), 1U);
+ return &declaring_class->GetSFields()[1];
+ }
+ }
+ mirror::DexCache* const dex_cache = declaring_class->GetDexCache();
ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex(), sizeof(void*));
CHECK(art_field != nullptr);
return art_field;