Fix verifier/linker IncompatibleClassChangeError with hidden API
The verifier and class linker will attempt to find a method with
the wrong type if it could not be found with the original type,
i.e an interface method on a regular class and vice versa.
This logic did not previously take hidden API restrictions into
account and would result in bogus error messages to the user or
debug crashes.
Bug: 64382372
Bug: 77464273
Test: art/test.py -r -t 674-hiddenapi
Change-Id: If8327a70dd73b90249da3d9e505f0c6f89838f8e
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 0e72f27..aa34427 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -27,6 +27,9 @@
static inline std::ostream& operator<<(std::ostream& os, AccessMethod value) {
switch (value) {
+ case kNone:
+ LOG(FATAL) << "Internal access to hidden API should not be logged";
+ UNREACHABLE();
case kReflection:
os << "reflection";
break;
@@ -116,6 +119,8 @@
template<typename T>
Action GetMemberActionImpl(T* member, Action action, AccessMethod access_method) {
+ DCHECK_NE(action, kAllow);
+
// Get the signature, we need it later.
MemberSignature member_signature(member);
@@ -135,10 +140,12 @@
}
}
- // Print a log message with information about this class member access.
- // We do this regardless of whether we block the access or not.
- member_signature.WarnAboutAccess(access_method,
- HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags()));
+ if (access_method != kNone) {
+ // Print a log message with information about this class member access.
+ // We do this regardless of whether we block the access or not.
+ member_signature.WarnAboutAccess(access_method,
+ HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags()));
+ }
if (action == kDeny) {
// Block access
@@ -148,16 +155,18 @@
// Allow access to this member but print a warning.
DCHECK(action == kAllowButWarn || action == kAllowButWarnAndToast);
- // Depending on a runtime flag, we might move the member into whitelist and
- // skip the warning the next time the member is accessed.
- if (runtime->ShouldDedupeHiddenApiWarnings()) {
- member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
- member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
- }
+ if (access_method != kNone) {
+ // Depending on a runtime flag, we might move the member into whitelist and
+ // skip the warning the next time the member is accessed.
+ if (runtime->ShouldDedupeHiddenApiWarnings()) {
+ member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
+ member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
+ }
- // If this action requires a UI warning, set the appropriate flag.
- if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
- runtime->SetPendingHiddenApiWarning(true);
+ // If this action requires a UI warning, set the appropriate flag.
+ if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
+ runtime->SetPendingHiddenApiWarning(true);
+ }
}
return action;