diff options
| -rw-r--r-- | runtime/class_linker.cc | 8 | ||||
| -rw-r--r-- | runtime/class_linker.h | 2 | ||||
| -rw-r--r-- | runtime/class_linker_test.cc | 38 | ||||
| -rw-r--r-- | runtime/dex_file.h | 1 | ||||
| -rw-r--r-- | runtime/mirror/dex_cache.cc | 6 | ||||
| -rw-r--r-- | runtime/mirror/dex_cache.h | 7 | ||||
| -rw-r--r-- | tools/libcore_failures.txt | 1 |
7 files changed, 54 insertions, 9 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 894cf67ccb..bb709e8774 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2927,19 +2927,19 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, CHECK(dex_cache.Get() != nullptr) << dex_file.GetLocation(); // For app images, the dex cache location may be a suffix of the dex file location since the // dex file location is an absolute path. - const size_t dex_cache_length = dex_cache->GetLocation()->GetLength(); + const std::string dex_cache_location = dex_cache->GetLocation()->ToModifiedUtf8(); + const size_t dex_cache_length = dex_cache_location.length(); CHECK_GT(dex_cache_length, 0u) << dex_file.GetLocation(); std::string dex_file_location = dex_file.GetLocation(); CHECK_GE(dex_file_location.length(), dex_cache_length) - << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation(); + << dex_cache_location << " " << dex_file.GetLocation(); // Take suffix. const std::string dex_file_suffix = dex_file_location.substr( dex_file_location.length() - dex_cache_length, dex_cache_length); // Example dex_cache location is SettingsProvider.apk and // dex file location is /system/priv-app/SettingsProvider/SettingsProvider.apk - CHECK(dex_cache->GetLocation()->Equals(dex_file_suffix)) - << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation(); + CHECK_EQ(dex_cache_location, dex_file_suffix); // Clean up pass to remove null dex caches. // Null dex caches can occur due to class unloading and we are lazily removing null entries. JavaVMExt* const vm = self->GetJniEnv()->vm; diff --git a/runtime/class_linker.h b/runtime/class_linker.h index d503dd4704..4975c29742 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -1063,8 +1063,8 @@ class ClassLinker { friend class ImageWriter; // for GetClassRoots friend class JniCompilerTest; // for GetRuntimeQuickGenericJniStub friend class JniInternalTest; // for GetRuntimeQuickGenericJniStub + ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for DexLock, and RegisterDexFileLocked ART_FRIEND_TEST(mirror::DexCacheTest, Open); // for AllocDexCache - DISALLOW_COPY_AND_ASSIGN(ClassLinker); }; diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 471d7ca5e6..40dfda9316 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -1201,4 +1201,42 @@ TEST_F(ClassLinkerTest, IsBootStrapClassLoaded) { EXPECT_FALSE(statics.Get()->IsBootStrapClassLoaded()); } +// Regression test for b/26799552. +TEST_F(ClassLinkerTest, RegisterDexFileName) { + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<2> hs(soa.Self()); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + MutableHandle<mirror::DexCache> dex_cache(hs.NewHandle<mirror::DexCache>(nullptr)); + { + ReaderMutexLock mu(soa.Self(), *class_linker->DexLock()); + for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) { + dex_cache.Assign(down_cast<mirror::DexCache*>(soa.Self()->DecodeJObject(data.weak_root))); + if (dex_cache.Get() != nullptr) { + break; + } + } + ASSERT_TRUE(dex_cache.Get() != nullptr); + } + // Make a copy of the dex cache and change the name. + dex_cache.Assign(dex_cache->Clone(soa.Self())->AsDexCache()); + const uint16_t data[] = { 0x20AC, 0x20A1 }; + Handle<mirror::String> location(hs.NewHandle(mirror::String::AllocFromUtf16(soa.Self(), + arraysize(data), + data))); + dex_cache->SetLocation(location.Get()); + const DexFile* old_dex_file = dex_cache->GetDexFile(); + + DexFile* dex_file = new DexFile(old_dex_file->Begin(), + old_dex_file->Size(), + location->ToModifiedUtf8(), + 0u, + nullptr, + nullptr); + { + WriterMutexLock mu(soa.Self(), *class_linker->DexLock()); + // Check that inserting with a UTF16 name works. + class_linker->RegisterDexFileLocked(*dex_file, dex_cache); + } +} + } // namespace art diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 968b37ba86..200121e61f 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -1260,6 +1260,7 @@ class DexFile { mutable std::unique_ptr<TypeLookupTable> lookup_table_; friend class DexFileVerifierTest; + ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for constructor }; struct DexFileReference { diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index 7b058d0c92..692c6cb0c1 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -50,7 +50,7 @@ void DexCache::Init(const DexFile* dex_file, CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr); SetDexFile(dex_file); - SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location); + SetLocation(location); SetStrings(strings); SetResolvedTypes(resolved_types); SetResolvedMethods(resolved_methods); @@ -79,5 +79,9 @@ void DexCache::Fixup(ArtMethod* trampoline, size_t pointer_size) { } } +void DexCache::SetLocation(mirror::String* location) { + SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location); +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index 5ed061f6a4..0002076ce0 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -191,11 +191,12 @@ class MANAGED DexCache FINAL : public Object { return GetFieldPtr<const DexFile*>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_)); } - void SetDexFile(const DexFile* dex_file) SHARED_REQUIRES(Locks::mutator_lock_) - ALWAYS_INLINE { - return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file); + void SetDexFile(const DexFile* dex_file) SHARED_REQUIRES(Locks::mutator_lock_) { + SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file); } + void SetLocation(mirror::String* location) SHARED_REQUIRES(Locks::mutator_lock_); + // NOTE: Get/SetElementPtrSize() are intended for working with ArtMethod** and ArtField** // provided by GetResolvedMethods/Fields() and ArtMethod::GetDexCacheResolvedMethods(), // so they need to be public. diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt index 351e99e8d4..6d67f8477d 100644 --- a/tools/libcore_failures.txt +++ b/tools/libcore_failures.txt @@ -260,6 +260,7 @@ "dalvik.system.JniTest#testPassingShorts", "dalvik.system.JniTest#testPassingThis", "libcore.util.NativeAllocationRegistryTest#testBadSize", + "libcore.util.NativeAllocationRegistryTest#testEarlyFree", "libcore.util.NativeAllocationRegistryTest#testNativeAllocationAllocatorAndNoSharedRegistry", "libcore.util.NativeAllocationRegistryTest#testNativeAllocationAllocatorAndSharedRegistry", "libcore.util.NativeAllocationRegistryTest#testNativeAllocationNoAllocatorAndNoSharedRegistry", |