• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <sys/mman.h>
18 #include <unistd.h>
19 
20 #include "HeapWalker.h"
21 
22 #include <ScopedDisableMalloc.h>
23 #include <gtest/gtest.h>
24 #include "Allocator.h"
25 
26 namespace android {
27 
28 class HeapWalkerTest : public ::testing::Test {
29  public:
HeapWalkerTest()30   HeapWalkerTest() : disable_malloc_(), heap_() {}
31 
TearDown()32   void TearDown() {
33     ASSERT_TRUE(heap_.empty());
34     if (!HasFailure()) {
35       ASSERT_FALSE(disable_malloc_.timed_out());
36     }
37   }
38 
39  protected:
40   ScopedDisableMallocTimeout disable_malloc_;
41   Heap heap_;
42 };
43 
TEST_F(HeapWalkerTest,allocation)44 TEST_F(HeapWalkerTest, allocation) {
45   HeapWalker heap_walker(heap_);
46   ASSERT_TRUE(heap_walker.Allocation(3, 4));
47   ASSERT_TRUE(heap_walker.Allocation(2, 3));
48   ASSERT_TRUE(heap_walker.Allocation(4, 5));
49   ASSERT_TRUE(heap_walker.Allocation(6, 7));
50   ASSERT_TRUE(heap_walker.Allocation(0, 1));
51 }
52 
TEST_F(HeapWalkerTest,overlap)53 TEST_F(HeapWalkerTest, overlap) {
54   HeapWalker heap_walker(heap_);
55   ASSERT_TRUE(heap_walker.Allocation(2, 3));
56   ASSERT_TRUE(heap_walker.Allocation(3, 4));
57   ASSERT_FALSE(heap_walker.Allocation(2, 3));
58   ASSERT_FALSE(heap_walker.Allocation(1, 3));
59   ASSERT_FALSE(heap_walker.Allocation(1, 4));
60   ASSERT_FALSE(heap_walker.Allocation(1, 5));
61   ASSERT_FALSE(heap_walker.Allocation(3, 4));
62   ASSERT_FALSE(heap_walker.Allocation(3, 5));
63   ASSERT_TRUE(heap_walker.Allocation(4, 5));
64   ASSERT_TRUE(heap_walker.Allocation(1, 2));
65 }
66 
TEST_F(HeapWalkerTest,zero)67 TEST_F(HeapWalkerTest, zero) {
68   HeapWalker heap_walker(heap_);
69   ASSERT_TRUE(heap_walker.Allocation(2, 2));
70   ASSERT_FALSE(heap_walker.Allocation(2, 2));
71   ASSERT_TRUE(heap_walker.Allocation(3, 3));
72   ASSERT_TRUE(heap_walker.Allocation(1, 1));
73   ASSERT_FALSE(heap_walker.Allocation(2, 3));
74 }
75 
TEST_F(HeapWalkerTest,mapping)76 TEST_F(HeapWalkerTest, mapping) {
77   HeapWalker heap_walker(heap_);
78   heap_walker.Mapping(2, 3);
79   heap_walker.Mapping(4, 5);
80   ASSERT_TRUE(heap_walker.Allocation(2, 3));
81   ASSERT_TRUE(heap_walker.Allocation(4, 5));
82   // space between mappings is not checked, but could be in the future
83   ASSERT_TRUE(heap_walker.Allocation(3, 4));
84 
85   // re-enable malloc, ASSERT_DEATH may allocate
86   disable_malloc_.Enable();
87   ASSERT_DEATH({ heap_walker.Allocation(1, 2); }, "0x1-0x2.*outside.*0x2-0x5");
88   ASSERT_DEATH({ heap_walker.Allocation(1, 3); }, "0x1-0x3.*outside.*0x2-0x5");
89   ASSERT_DEATH({ heap_walker.Allocation(4, 6); }, "0x4-0x6.*outside.*0x2-0x5");
90   ASSERT_DEATH({ heap_walker.Allocation(5, 6); }, "0x5-0x6.*outside.*0x2-0x5");
91   ASSERT_DEATH({ heap_walker.Allocation(1, 6); }, "0x1-0x6.*outside.*0x2-0x5");
92 }
93 
94 #define buffer_begin(buffer) reinterpret_cast<uintptr_t>(buffer)
95 #define buffer_end(buffer) (reinterpret_cast<uintptr_t>(buffer) + sizeof(buffer))
96 
TEST_F(HeapWalkerTest,leak)97 TEST_F(HeapWalkerTest, leak) {
98   void* buffer1[16]{};
99   char buffer2[16]{};
100   buffer1[0] = &buffer2[0] - sizeof(void*);
101   buffer1[1] = &buffer2[15] + sizeof(void*);
102 
103   HeapWalker heap_walker(heap_);
104   heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
105 
106   ASSERT_EQ(true, heap_walker.DetectLeaks());
107 
108   allocator::vector<Range> leaked(heap_);
109   size_t num_leaks = 0;
110   size_t leaked_bytes = 0;
111   ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
112 
113   EXPECT_EQ(1U, num_leaks);
114   EXPECT_EQ(16U, leaked_bytes);
115   ASSERT_EQ(1U, leaked.size());
116   EXPECT_EQ(buffer_begin(buffer2), leaked[0].begin);
117   EXPECT_EQ(buffer_end(buffer2), leaked[0].end);
118 }
119 
TEST_F(HeapWalkerTest,live)120 TEST_F(HeapWalkerTest, live) {
121   const int from_buffer_entries = 4;
122   const int to_buffer_bytes = 16;
123 
124   for (int i = 0; i < from_buffer_entries; i++) {
125     for (int j = 0; j < to_buffer_bytes; j++) {
126       void* buffer1[from_buffer_entries]{};
127       char buffer2[to_buffer_bytes]{};
128       buffer1[i] = &buffer2[j];
129 
130       HeapWalker heap_walker(heap_);
131       heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
132       heap_walker.Root(buffer_begin(buffer1), buffer_end(buffer1));
133 
134       ASSERT_EQ(true, heap_walker.DetectLeaks());
135 
136       allocator::vector<Range> leaked(heap_);
137       size_t num_leaks = SIZE_MAX;
138       size_t leaked_bytes = SIZE_MAX;
139       ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
140 
141       EXPECT_EQ(0U, num_leaks);
142       EXPECT_EQ(0U, leaked_bytes);
143       EXPECT_EQ(0U, leaked.size());
144     }
145   }
146 }
147 
TEST_F(HeapWalkerTest,unaligned)148 TEST_F(HeapWalkerTest, unaligned) {
149   const int from_buffer_entries = 4;
150   const int to_buffer_bytes = 16;
151   void* buffer1[from_buffer_entries]{};
152   char buffer2[to_buffer_bytes]{};
153 
154   buffer1[1] = &buffer2;
155 
156   for (unsigned int i = 0; i < sizeof(uintptr_t); i++) {
157     for (unsigned int j = 0; j < sizeof(uintptr_t); j++) {
158       HeapWalker heap_walker(heap_);
159       heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
160       heap_walker.Root(buffer_begin(buffer1) + i, buffer_end(buffer1) - j);
161 
162       ASSERT_EQ(true, heap_walker.DetectLeaks());
163 
164       allocator::vector<Range> leaked(heap_);
165       size_t num_leaks = SIZE_MAX;
166       size_t leaked_bytes = SIZE_MAX;
167       ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
168 
169       EXPECT_EQ(0U, num_leaks);
170       EXPECT_EQ(0U, leaked_bytes);
171       EXPECT_EQ(0U, leaked.size());
172     }
173   }
174 }
175 
TEST_F(HeapWalkerTest,cycle)176 TEST_F(HeapWalkerTest, cycle) {
177   void* buffer1;
178   void* buffer2;
179 
180   buffer1 = &buffer2;
181   buffer2 = &buffer1;
182 
183   HeapWalker heap_walker(heap_);
184   heap_walker.Allocation(buffer_begin(buffer1), buffer_end(buffer1));
185   heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
186 
187   ASSERT_EQ(true, heap_walker.DetectLeaks());
188 
189   allocator::vector<Range> leaked(heap_);
190   size_t num_leaks = 0;
191   size_t leaked_bytes = 0;
192   ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
193 
194   EXPECT_EQ(2U, num_leaks);
195   EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
196   ASSERT_EQ(2U, leaked.size());
197 }
198 
TEST_F(HeapWalkerTest,segv)199 TEST_F(HeapWalkerTest, segv) {
200   const size_t page_size = sysconf(_SC_PAGE_SIZE);
201   void* buffer1 = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
202   ASSERT_NE(buffer1, nullptr);
203   void* buffer2;
204 
205   buffer2 = &buffer1;
206 
207   HeapWalker heap_walker(heap_);
208   heap_walker.Allocation(buffer_begin(buffer1), buffer_begin(buffer1) + page_size);
209   heap_walker.Root(buffer_begin(buffer2), buffer_end(buffer2));
210 
211   ASSERT_EQ(true, heap_walker.DetectLeaks());
212 
213   allocator::vector<Range> leaked(heap_);
214   size_t num_leaks = 0;
215   size_t leaked_bytes = 0;
216   ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
217 
218   EXPECT_EQ(0U, num_leaks);
219   EXPECT_EQ(0U, leaked_bytes);
220   ASSERT_EQ(0U, leaked.size());
221 }
222 
223 }  // namespace android
224