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