Enabled access check for classes and methods in the verifier.

All checks should pass in frameworks. The only thing left in the
verifier is to tolerate classes/methods/fields that fail to resolve
initially.

Change-Id: I2afe0295bb16542259b2122a9056b3139d908871
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index ebb71b2..6ea276f 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -4366,7 +4366,6 @@
     return NULL;
   }
 
-#if 0
   /* Check if access is allowed. */
   if (!referrer->CanAccess(res_class)) {
     LOG(ERROR) << "VFY: illegal class access: "
@@ -4375,7 +4374,6 @@
     *failure = VERIFY_ERROR_ACCESS_CLASS;
     return NULL;
   }
-#endif
 
   return res_class;
 }
@@ -4414,9 +4412,8 @@
     }
   }
 
-#if 0
   /* Check if access is allowed. */
-  if (!referrer->CanAccess(res_method->GetDeclaringClass())) {
+  if (!referrer->CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
     LOG(ERROR) << "VFY: illegal method access (call "
                << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                << "." << res_method->GetName()->ToModifiedUtf8() << " "
@@ -4425,7 +4422,6 @@
     *failure = VERIFY_ERROR_ACCESS_METHOD;
     return NULL;
   }
-#endif
 
   return res_method;
 }
@@ -4467,7 +4463,7 @@
   }
 
   /* Check if access is allowed. */
-  if (!referrer->CanAccess(res_field->GetDeclaringClass())) {
+  if (!referrer->CanAccessMember(res_field->GetDeclaringClass(), res_field->GetAccessFlags())) {
     LOG(ERROR) << "VFY: access denied from "
                << referrer->GetDescriptor()->ToModifiedUtf8() << " to field "
                << res_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
diff --git a/src/object.cc b/src/object.cc
index 813abce..64607e8 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1030,10 +1030,10 @@
     return false;
   }
   // Arrays are in the same package when their element classes are.
-  if (klass1->IsArrayClass()) {
+  while (klass1->IsArrayClass()) {
     klass1 = klass1->GetComponentType();
   }
-  if (klass2->IsArrayClass()) {
+  while (klass2->IsArrayClass()) {
     klass2 = klass2->GetComponentType();
   }
   // Compare the package part of the descriptor string.
diff --git a/src/object.h b/src/object.h
index 2ee90fc..63a2b30 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1501,6 +1501,35 @@
     return that->IsPublic() || this->IsInSamePackage(that);
   }
 
+  // Validate method/field access.
+  bool CanAccessMember(const Class* access_to, uint32_t member_flags) const {
+    // quick accept for public access
+    if (member_flags & kAccPublic) {
+      return true;
+    }
+
+    // quick accept for access from same class
+    if (this == access_to) {
+      return true;
+    }
+
+    // quick reject for private access from another class
+    if (member_flags & kAccPrivate) {
+      return false;
+    }
+
+    // Semi-quick test for protected access from a sub-class, which may or
+    // may not be in the same package.
+    if (member_flags & kAccProtected) {
+      if (this->IsSubClass(access_to)) {
+        return true;
+      }
+    }
+
+    // Allow protected and private access from other classes in the same package.
+    return this->IsInSamePackage(access_to);
+  }
+
   bool IsSubClass(const Class* klass) const;
 
   bool IsAssignableFrom(const Class* src) const {