diff options
| -rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 5 | ||||
| -rw-r--r-- | runtime/mirror/class.cc | 14 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 7 | ||||
| -rw-r--r-- | runtime/native/java_lang_Class.cc | 13 | ||||
| -rw-r--r-- | test/2252-class-value-before-and-after-u/src-art/Main.java | 14 |
5 files changed, 42 insertions, 11 deletions
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 0d40e13f51..cafd7c456c 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -47,6 +47,7 @@ #include "mirror/array-alloc-inl.h" #include "mirror/array-inl.h" #include "mirror/class-alloc-inl.h" +#include "mirror/class.h" #include "mirror/executable-inl.h" #include "mirror/field.h" #include "mirror/method.h" @@ -138,6 +139,10 @@ static void UnstartedRuntimeFindClass(Thread* self, ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ObjPtr<mirror::Class> found = class_linker->FindClass(self, descriptor.c_str(), class_loader); + if (found != nullptr && !found->CheckIsVisibleWithTargetSdk(self)) { + CHECK(self->IsExceptionPending()); + return; + } if (found != nullptr && initialize_class) { StackHandleScope<1> hs(self); HandleWrapperObjPtr<mirror::Class> h_class = hs.NewHandleWrapper(&found); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 79676007c1..6458613c37 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -27,6 +27,7 @@ #include "art_method-inl.h" #include "base/enums.h" #include "base/logging.h" // For VLOG. +#include "base/sdk_version.h" #include "base/utils.h" #include "class-inl.h" #include "class_ext-inl.h" @@ -2128,6 +2129,19 @@ size_t Class::GetMethodIdOffset(ArtMethod* method, PointerSize pointer_size) { return res; } +bool Class::CheckIsVisibleWithTargetSdk(Thread* self) { + uint32_t targetSdkVersion = Runtime::Current()->GetTargetSdkVersion(); + if (IsSdkVersionSetAndAtMost(targetSdkVersion, SdkVersion::kT)) { + ObjPtr<mirror::Class> java_lang_ClassValue = + WellKnownClasses::ToClass(WellKnownClasses::java_lang_ClassValue); + if (this == java_lang_ClassValue.Ptr()) { + self->ThrowNewException("Ljava/lang/ClassNotFoundException;", "java.lang.ClassValue"); + return false; + } + } + return true; +} + ArtMethod* Class::FindAccessibleInterfaceMethod(ArtMethod* implementation_method, PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index ca13462da8..bd37534b6b 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1356,6 +1356,13 @@ class MANAGED Class final : public Object { size_t GetMethodIdOffset(ArtMethod* method, PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_); + // Returns whether the class should be visible to an app. + // Notorious example is java.lang.ClassValue, which was added in Android U and proguarding tools + // used that as justification to remove computeValue method implementation. Such an app running + // on U+ will fail with AbstractMethodError as computeValue is not implemented. + // See b/259501764. + bool CheckIsVisibleWithTargetSdk(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); + private: template <typename T, VerifyObjectFlags kVerifyFlags, typename Visitor> void FixupNativePointer( diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index c5fdda7ee8..593a454d37 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -21,7 +21,6 @@ #include "art_field-inl.h" #include "art_method-alloc-inl.h" #include "base/enums.h" -#include "base/sdk_version.h" #include "class_linker-inl.h" #include "class_root-inl.h" #include "common_throws.h" @@ -45,7 +44,6 @@ #include "mirror/proxy.h" #include "mirror/string-alloc-inl.h" #include "mirror/string-inl.h" -#include "mirror/string.h" #include "native_util.h" #include "nativehelper/jni_macros.h" #include "nativehelper/scoped_local_ref.h" @@ -140,14 +138,9 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean // So far ClassValue is the only class with such a problem and hence this // ad-hoc check. // See b/259501764. - uint32_t targetSdkVersion = Runtime::Current()->GetTargetSdkVersion(); - if (IsSdkVersionSetAndAtMost(targetSdkVersion, SdkVersion::kT)) { - ObjPtr<mirror::Class> java_lang_ClassValue = - WellKnownClasses::ToClass(WellKnownClasses::java_lang_ClassValue); - if (c.Get() == java_lang_ClassValue.Ptr()) { - soa.Self()->ThrowNewException("Ljava/lang/ClassNotFoundException;", "java.lang.ClassValue"); - return nullptr; - } + if (!c->CheckIsVisibleWithTargetSdk(soa.Self())) { + DCHECK(soa.Self()->IsExceptionPending()); + return nullptr; } return soa.AddLocalReference<jclass>(c.Get()); diff --git a/test/2252-class-value-before-and-after-u/src-art/Main.java b/test/2252-class-value-before-and-after-u/src-art/Main.java index 88746e1c76..53704d7e82 100644 --- a/test/2252-class-value-before-and-after-u/src-art/Main.java +++ b/test/2252-class-value-before-and-after-u/src-art/Main.java @@ -18,6 +18,14 @@ import dalvik.system.VMRuntime; public class Main { public static void main(String[] args) { + VMRuntime.getRuntime().setTargetSdkVersion(0); + try { + Class classValueClass = Class.forName("java.lang.ClassValue"); + } catch (ClassNotFoundException ignored) { + throw new Error( + "java.lang.ClassValue should be available when targetSdkLevel is not set"); + } + VMRuntime.getRuntime().setTargetSdkVersion(34); try { @@ -30,6 +38,10 @@ public class Main { try { Class classValueClass = Class.forName("java.lang.ClassValue"); throw new Error("Was able to find " + classValueClass + " on targetSdkLevel 33"); - } catch (ClassNotFoundException expected) {} + } catch (ClassNotFoundException expected) { + if (!expected.getMessage().contains("java.lang.ClassValue")) { + throw new Error("Thrown exception should contain class name, but was: " + expected); + } + } } } |