diff options
| author | 2016-12-15 14:21:04 -0800 | |
|---|---|---|
| committer | 2016-12-15 14:34:25 -0800 | |
| commit | 1e4841e9fc77e34acb1823ad0f98a4828f2f2fb1 (patch) | |
| tree | ef632a2ba72def6d5dbc01592a0d1d8411e021f5 | |
| parent | 9538f9e2a5d03f1b1bc07ebfbd93b61dcf8ad604 (diff) | |
Fill in empty iftable early
Previously it would not get filled in and remain null for some
erroneous classes. This caused crashes for things like
GetIfTableCount.
Added regression test (sample failure):
class_linker_test F 12-15 14:20:09 28771 28771 class-inl.h:532] Check failed: ret != nullptr java.lang.Class<Erroneous>
Bug: 33650297
Bug: 33642884
Test: test-art-host
Change-Id: I506210bad17d6d2c58ca7870165f8a4a514f64fe
| -rw-r--r-- | build/Android.gtest.mk | 4 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 2 | ||||
| -rw-r--r-- | runtime/class_linker_test.cc | 18 | ||||
| -rw-r--r-- | test/ErroneousA/ErroneousA.java | 17 | ||||
| -rw-r--r-- | test/ErroneousB/ErroneousB.java | 20 |
5 files changed, 60 insertions, 1 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index d59d8f690c..bd7f900965 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -26,6 +26,8 @@ GTEST_DEX_DIRECTORIES := \ AbstractMethod \ AllFields \ DexToDexDecompiler \ + ErroneousA \ + ErroneousB \ ExceptionHandle \ GetMethodSignature \ ImageLayoutA \ @@ -85,7 +87,7 @@ $(ART_TEST_TARGET_GTEST_VerifierDeps_DEX): $(ART_TEST_GTEST_VerifierDeps_SRC) $( ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary Nested ART_GTEST_atomic_method_ref_map_test_DEX_DEPS := Interfaces -ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MethodTypes MultiDex MyClass Nested Statics StaticsFromCode +ART_GTEST_class_linker_test_DEX_DEPS := ErroneousA ErroneousB Interfaces MethodTypes MultiDex MyClass Nested Statics StaticsFromCode ART_GTEST_class_table_test_DEX_DEPS := XandY ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods ProfileTestMultiDex ART_GTEST_dex_cache_test_DEX_DEPS := Main Packages MethodTypes diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 6565f6bf42..a66479b3c4 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2663,6 +2663,8 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, ObjectLock<mirror::Class> lock(self, klass); klass->SetClinitThreadId(self->GetTid()); + // Make sure we have a valid empty iftable even if there are errors. + klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable()); // Add the newly loaded class to the loaded classes table. ObjPtr<mirror::Class> existing = InsertClass(descriptor, klass.Get(), hash); diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 685677bd80..b83cf16f3d 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -1175,6 +1175,24 @@ TEST_F(ClassLinkerTest, ResolveVerifyAndClinit) { EXPECT_TRUE(init->IsInitialized()); } +TEST_F(ClassLinkerTest, ErroneousClass) { + ScopedObjectAccess soa(Thread::Current()); + jobject jclass_loader = LoadMultiDex("ErroneousA", "ErroneousB"); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader))); + hs.Self()->AssertNoPendingException(); + const char* descriptor = "LErroneous;"; + ObjPtr<mirror::Class> klass = class_linker_->FindClass(soa.Self(), descriptor, class_loader); + // Erronenous since we are extending final class. + hs.Self()->AssertPendingException(); + EXPECT_TRUE(klass == nullptr); + klass = class_linker_->LookupClass(soa.Self(), descriptor, class_loader.Get()); + EXPECT_FALSE(klass == nullptr); + EXPECT_TRUE(klass->IsErroneous()); + EXPECT_TRUE(klass->GetIfTable() != nullptr); +} + TEST_F(ClassLinkerTest, FinalizableBit) { ScopedObjectAccess soa(Thread::Current()); mirror::Class* c; diff --git a/test/ErroneousA/ErroneousA.java b/test/ErroneousA/ErroneousA.java new file mode 100644 index 0000000000..49da54452a --- /dev/null +++ b/test/ErroneousA/ErroneousA.java @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +final class FinalSuper {} diff --git a/test/ErroneousB/ErroneousB.java b/test/ErroneousB/ErroneousB.java new file mode 100644 index 0000000000..6c2902ab7d --- /dev/null +++ b/test/ErroneousB/ErroneousB.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Only final in first dex. +class FinalSuper {} + +class Erroneous extends FinalSuper {} |