ART: Disallow unresolved return types after Q
For apps targeting future releases, do not allow type mismatches
involving unresolved types. The behavior complicates the verifier
and the runtime and does not conform to regular expected behavior.
Historically this has been done for app compatibility when non-native
multidex was a thing. In that situation, even at runtime when an "early"
class is being verified a type might not be available because it is
supplied by a later injected dex file.
Classloader manipulations in this way are no longer supported. Classes
have to be available at verification time to not fail the class.
Bug: 121245951
Test: m test-art-host
Change-Id: I9608c79183be7b85b76892498d6a7007a29f2434
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index fc3005d..56b84a0 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -502,6 +502,7 @@
return false; // Pending exception.
}
if (!obj_result->VerifierInstanceOf(return_type)) {
+ CHECK_LE(Runtime::Current()->GetTargetSdkVersion(), 29u);
// This should never happen.
std::string temp1, temp2;
self->ThrowNewExceptionF("Ljava/lang/InternalError;",
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index a1f9a2a..c4be933 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2209,8 +2209,8 @@
<< reg_type;
} else if (!return_type.IsAssignableFrom(reg_type, this)) {
if (reg_type.IsUnresolvedTypes() || return_type.IsUnresolvedTypes()) {
- Fail(VERIFY_ERROR_NO_CLASS) << " can't resolve returned type '" << return_type
- << "' or '" << reg_type << "'";
+ Fail(api_level_ > 29u ? VERIFY_ERROR_BAD_CLASS_SOFT : VERIFY_ERROR_NO_CLASS)
+ << " can't resolve returned type '" << return_type << "' or '" << reg_type << "'";
} else {
bool soft_error = false;
// Check whether arrays are involved. They will show a valid class status, even