summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2016-12-15 14:21:04 -0800
committer Mathieu Chartier <mathieuc@google.com> 2016-12-15 14:34:25 -0800
commit1e4841e9fc77e34acb1823ad0f98a4828f2f2fb1 (patch)
treeef632a2ba72def6d5dbc01592a0d1d8411e021f5
parent9538f9e2a5d03f1b1bc07ebfbd93b61dcf8ad604 (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.mk4
-rw-r--r--runtime/class_linker.cc2
-rw-r--r--runtime/class_linker_test.cc18
-rw-r--r--test/ErroneousA/ErroneousA.java17
-rw-r--r--test/ErroneousB/ErroneousB.java20
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 {}