xref: /aosp_15_r20/art/runtime/gc/heap_verification_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "base/memory_tool.h"
20*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
22*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
24*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-alloc-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
27*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
28*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "verification-inl.h"
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
32*795d594fSAndroid Build Coastguard Worker namespace gc {
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker class VerificationTest : public CommonRuntimeTest {
35*795d594fSAndroid Build Coastguard Worker  protected:
VerificationTest()36*795d594fSAndroid Build Coastguard Worker   VerificationTest() {
37*795d594fSAndroid Build Coastguard Worker     use_boot_image_ = true;  // Make the Runtime creation cheaper.
38*795d594fSAndroid Build Coastguard Worker   }
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker   template <class T>
AllocObjectArray(Thread * self,size_t length)41*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
42*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
43*795d594fSAndroid Build Coastguard Worker     return mirror::ObjectArray<T>::Alloc(
44*795d594fSAndroid Build Coastguard Worker         self,
45*795d594fSAndroid Build Coastguard Worker         GetClassRoot<mirror::ObjectArray<mirror::Object>>(),
46*795d594fSAndroid Build Coastguard Worker         length);
47*795d594fSAndroid Build Coastguard Worker   }
48*795d594fSAndroid Build Coastguard Worker };
49*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,IsValidHeapObjectAddress)50*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, IsValidHeapObjectAddress) {
51*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
52*795d594fSAndroid Build Coastguard Worker   const Verification* const v = Runtime::Current()->GetHeap()->GetVerification();
53*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidHeapObjectAddress(reinterpret_cast<const void*>(1)));
54*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidHeapObjectAddress(reinterpret_cast<const void*>(4)));
55*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidHeapObjectAddress(nullptr));
56*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
57*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> string(
58*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test")));
59*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(v->IsValidHeapObjectAddress(string.Get()));
60*795d594fSAndroid Build Coastguard Worker   // Address in the heap that isn't aligned.
61*795d594fSAndroid Build Coastguard Worker   const void* unaligned_address =
62*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(string.Get()) + 1);
63*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(v->IsAddressInHeapSpace(unaligned_address));
64*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidHeapObjectAddress(unaligned_address));
65*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(v->IsValidHeapObjectAddress(string->GetClass()));
66*795d594fSAndroid Build Coastguard Worker   const uintptr_t uint_klass = reinterpret_cast<uintptr_t>(string->GetClass());
67*795d594fSAndroid Build Coastguard Worker   // Not actually a valid object but the verification can't know that. Guaranteed to be inside a
68*795d594fSAndroid Build Coastguard Worker   // heap space.
69*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(v->IsValidHeapObjectAddress(
70*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<const void*>(uint_klass + kObjectAlignment)));
71*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidHeapObjectAddress(
72*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<const void*>(&uint_klass)));
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,IsValidClassOrNotInHeap)75*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, IsValidClassOrNotInHeap) {
76*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
77*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
78*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> string(
79*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test")));
80*795d594fSAndroid Build Coastguard Worker   const Verification* const v = Runtime::Current()->GetHeap()->GetVerification();
81*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidClass(reinterpret_cast<mirror::Class*>(1)));
82*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidClass(reinterpret_cast<mirror::Class*>(4)));
83*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidClass(nullptr));
84*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(v->IsValidClass(string->GetClass()));
85*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidClass(reinterpret_cast<mirror::Class*>(string.Get())));
86*795d594fSAndroid Build Coastguard Worker }
87*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,IsValidClassInHeap)88*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, IsValidClassInHeap) {
89*795d594fSAndroid Build Coastguard Worker   // Now that the String class is allocated in the non-moving space when the
90*795d594fSAndroid Build Coastguard Worker   // runtime is running without a boot image (which is the case in this gtest),
91*795d594fSAndroid Build Coastguard Worker   // and we run with AddressSanizer, it is possible that the (presumably
92*795d594fSAndroid Build Coastguard Worker   // invalid) memory location `uint_klass - kObjectAlignment` tested below is
93*795d594fSAndroid Build Coastguard Worker   // poisoned when running with AddressSanizer. Disable this test in that case.
94*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_MEMORY_TOOL();
95*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
96*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
97*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> string(
98*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "test")));
99*795d594fSAndroid Build Coastguard Worker   const Verification* const v = Runtime::Current()->GetHeap()->GetVerification();
100*795d594fSAndroid Build Coastguard Worker   uintptr_t uint_klass = reinterpret_cast<uintptr_t>(string->GetClass());
101*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidClass(reinterpret_cast<mirror::Class*>(uint_klass - kObjectAlignment)));
102*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(v->IsValidClass(reinterpret_cast<mirror::Class*>(&uint_klass)));
103*795d594fSAndroid Build Coastguard Worker }
104*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,DumpInvalidObjectInfo)105*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, DumpInvalidObjectInfo) {
106*795d594fSAndroid Build Coastguard Worker   ScopedLogSeverity sls(LogSeverity::INFO);
107*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
108*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
109*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
110*795d594fSAndroid Build Coastguard Worker   const Verification* const v = runtime->GetHeap()->GetVerification();
111*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(1), "obj");
112*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(4), "obj");
113*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(nullptr, "obj");
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,DumpValidObjectInfo)116*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, DumpValidObjectInfo) {
117*795d594fSAndroid Build Coastguard Worker   // Now that the String class is allocated in the non-moving space when the
118*795d594fSAndroid Build Coastguard Worker   // runtime is running without a boot image (which is the case in this gtest),
119*795d594fSAndroid Build Coastguard Worker   // and we run with AddressSanizer, it is possible that the calls to
120*795d594fSAndroid Build Coastguard Worker   // Verification::DumpObjectInfo below involving the String class object
121*795d594fSAndroid Build Coastguard Worker   // (`string->GetClass()`, `uint_klass`, etc.) access poisoned memory when they
122*795d594fSAndroid Build Coastguard Worker   // call Verification::DumpRAMAroundAddress. Disable this test in that case.
123*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_MEMORY_TOOL();
124*795d594fSAndroid Build Coastguard Worker   ScopedLogSeverity sls(LogSeverity::INFO);
125*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
126*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
127*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
128*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> string(
129*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "obj")));
130*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ObjectArray<mirror::Object>> arr(
131*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(AllocObjectArray<mirror::Object>(soa.Self(), 256)));
132*795d594fSAndroid Build Coastguard Worker   const Verification* const v = runtime->GetHeap()->GetVerification();
133*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(string.Get(), "test");
134*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(string->GetClass(), "obj");
135*795d594fSAndroid Build Coastguard Worker   const uintptr_t uint_klass = reinterpret_cast<uintptr_t>(string->GetClass());
136*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(uint_klass - kObjectAlignment),
137*795d594fSAndroid Build Coastguard Worker                                  "obj");
138*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(reinterpret_cast<const void*>(&uint_klass), "obj");
139*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << v->DumpObjectInfo(arr.Get(), "arr");
140*795d594fSAndroid Build Coastguard Worker }
141*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,LogHeapCorruption)142*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, LogHeapCorruption) {
143*795d594fSAndroid Build Coastguard Worker   // Now that the String class is allocated in the non-moving space when the
144*795d594fSAndroid Build Coastguard Worker   // runtime is running without a boot image (which is the case in this gtest),
145*795d594fSAndroid Build Coastguard Worker   // and we run with AddressSanizer, it is possible that the call to
146*795d594fSAndroid Build Coastguard Worker   // Verification::LogHeapCorruption below involving the String class object
147*795d594fSAndroid Build Coastguard Worker   // (`string->GetClass()`) accesses poisoned memory when it calls
148*795d594fSAndroid Build Coastguard Worker   // Verification::DumpRAMAroundAddress. Disable this test in that case.
149*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_MEMORY_TOOL();
150*795d594fSAndroid Build Coastguard Worker   ScopedLogSeverity sls(LogSeverity::INFO);
151*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
152*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
153*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
154*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> string(
155*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "obj")));
156*795d594fSAndroid Build Coastguard Worker   using ObjArray = mirror::ObjectArray<mirror::Object>;
157*795d594fSAndroid Build Coastguard Worker   Handle<ObjArray> arr(
158*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(AllocObjectArray<mirror::Object>(soa.Self(), 256)));
159*795d594fSAndroid Build Coastguard Worker   const Verification* const v = runtime->GetHeap()->GetVerification();
160*795d594fSAndroid Build Coastguard Worker   arr->Set(0, string.Get());
161*795d594fSAndroid Build Coastguard Worker   // Test normal cases.
162*795d594fSAndroid Build Coastguard Worker   v->LogHeapCorruption(arr.Get(), ObjArray::DataOffset(kHeapReferenceSize), string.Get(), false);
163*795d594fSAndroid Build Coastguard Worker   v->LogHeapCorruption(string.Get(), mirror::Object::ClassOffset(), string->GetClass(), false);
164*795d594fSAndroid Build Coastguard Worker   // Test null holder cases.
165*795d594fSAndroid Build Coastguard Worker   v->LogHeapCorruption(nullptr, MemberOffset(0), string.Get(), false);
166*795d594fSAndroid Build Coastguard Worker   v->LogHeapCorruption(nullptr, MemberOffset(0), arr.Get(), false);
167*795d594fSAndroid Build Coastguard Worker }
168*795d594fSAndroid Build Coastguard Worker 
TEST_F(VerificationTest,FindPathFromRootSet)169*795d594fSAndroid Build Coastguard Worker TEST_F(VerificationTest, FindPathFromRootSet) {
170*795d594fSAndroid Build Coastguard Worker   ScopedLogSeverity sls(LogSeverity::INFO);
171*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
172*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
173*795d594fSAndroid Build Coastguard Worker   VariableSizedHandleScope hs(soa.Self());
174*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ObjectArray<mirror::Object>> arr(
175*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(AllocObjectArray<mirror::Object>(soa.Self(), 256)));
176*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> str = mirror::String::AllocFromModifiedUtf8(soa.Self(), "obj");
177*795d594fSAndroid Build Coastguard Worker   arr->Set(0, str);
178*795d594fSAndroid Build Coastguard Worker   const Verification* const v = runtime->GetHeap()->GetVerification();
179*795d594fSAndroid Build Coastguard Worker   std::string path = v->FirstPathFromRootSet(str);
180*795d594fSAndroid Build Coastguard Worker   EXPECT_GT(path.length(), 0u);
181*795d594fSAndroid Build Coastguard Worker   std::ostringstream oss;
182*795d594fSAndroid Build Coastguard Worker   oss << arr.Get();
183*795d594fSAndroid Build Coastguard Worker   EXPECT_NE(path.find(oss.str()), std::string::npos);
184*795d594fSAndroid Build Coastguard Worker   LOG(INFO) << path;
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker }  // namespace gc
188*795d594fSAndroid Build Coastguard Worker }  // namespace art
189