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.

(cherry pick commit a56ce5e267c9744ed99e40ae5cd9b527971e1d63)

Bug: 20557050

Change-Id: If672c0e67bc49e672e34d75ffbe29c65f5a423b9
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 9820db7..388921b 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -30,10 +30,11 @@
 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 @@
       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 @@
   }
   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 70311bb..933784e 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -54,7 +54,19 @@
 }
 
 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;
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index b471293..93d1f66 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -20,6 +20,7 @@
 #include "art_field-inl.h"
 #include "class_linker-inl.h"
 #include "common_compiler_test.h"
+#include "mirror/field-inl.h"
 #include "mirror/method.h"
 #include "scoped_thread_state_change.h"
 
@@ -191,4 +192,53 @@
   EXPECT_FALSE(field->IsPrimitiveType());
 }
 
+// Creates two proxy classes and check the art/mirror fields of their static fields.
+TEST_F(ProxyTest, CheckArtMirrorFieldsOfProxyStaticFields) {
+  ScopedObjectAccess soa(Thread::Current());
+  jobject jclass_loader = LoadDex("Interfaces");
+  StackHandleScope<7> hs(soa.Self());
+  Handle<mirror::ClassLoader> class_loader(
+      hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+
+  Handle<mirror::Class> proxyClass0;
+  Handle<mirror::Class> proxyClass1;
+  {
+    std::vector<mirror::Class*> interfaces;
+    proxyClass0 = hs.NewHandle(GenerateProxyClass(soa, jclass_loader, "$Proxy0", interfaces));
+    proxyClass1 = hs.NewHandle(GenerateProxyClass(soa, jclass_loader, "$Proxy1", interfaces));
+  }
+
+  ASSERT_TRUE(proxyClass0.Get() != nullptr);
+  ASSERT_TRUE(proxyClass0->IsProxyClass());
+  ASSERT_TRUE(proxyClass0->IsInitialized());
+  ASSERT_TRUE(proxyClass1.Get() != nullptr);
+  ASSERT_TRUE(proxyClass1->IsProxyClass());
+  ASSERT_TRUE(proxyClass1->IsInitialized());
+
+  ArtField* static_fields0 = proxyClass0->GetSFields();
+  ASSERT_TRUE(static_fields0 != nullptr);
+  ASSERT_EQ(2u, proxyClass0->NumStaticFields());
+  ArtField* static_fields1 = proxyClass1->GetSFields();
+  ASSERT_TRUE(static_fields1 != nullptr);
+  ASSERT_EQ(2u, proxyClass1->NumStaticFields());
+
+  EXPECT_EQ(static_fields0[0].GetDeclaringClass(), proxyClass0.Get());
+  EXPECT_EQ(static_fields0[1].GetDeclaringClass(), proxyClass0.Get());
+  EXPECT_EQ(static_fields1[0].GetDeclaringClass(), proxyClass1.Get());
+  EXPECT_EQ(static_fields1[1].GetDeclaringClass(), proxyClass1.Get());
+
+  Handle<mirror::Field> field00 =
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0[0], true));
+  Handle<mirror::Field> field01 =
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0[1], true));
+  Handle<mirror::Field> field10 =
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1[0], true));
+  Handle<mirror::Field> field11 =
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1[1], true));
+  EXPECT_EQ(field00->GetArtField(), &static_fields0[0]);
+  EXPECT_EQ(field01->GetArtField(), &static_fields0[1]);
+  EXPECT_EQ(field10->GetArtField(), &static_fields1[0]);
+  EXPECT_EQ(field11->GetArtField(), &static_fields1[1]);
+}
+
 }  // namespace art