1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define _CRT_SECURE_NO_WARNINGS
6
7#include "base/process/memory.h"
8
9#include <limits>
10
11#include "base/compiler_specific.h"
12#include "base/debug/alias.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15#if defined(OS_WIN)
16#include <windows.h>
17#endif
18#if defined(OS_POSIX)
19#include <errno.h>
20#endif
21#if defined(OS_MACOSX)
22#include <malloc/malloc.h>
23#include "base/process/memory_unittest_mac.h"
24#endif
25#if defined(OS_LINUX)
26#include <glib.h>
27#include <malloc.h>
28#endif
29
30#if defined(OS_WIN)
31// HeapQueryInformation function pointer.
32typedef BOOL (WINAPI* HeapQueryFn)  \
33    (HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
34
35const int kConstantInModule = 42;
36
37TEST(ProcessMemoryTest, GetModuleFromAddress) {
38  // Since the unit tests are their own EXE, this should be
39  // equivalent to the EXE's HINSTANCE.
40  //
41  // kConstantInModule is a constant in this file and
42  // therefore within the unit test EXE.
43  EXPECT_EQ(::GetModuleHandle(NULL),
44            base::GetModuleFromAddress(
45                const_cast<int*>(&kConstantInModule)));
46
47  // Any address within the kernel32 module should return
48  // kernel32's HMODULE.  Our only assumption here is that
49  // kernel32 is larger than 4 bytes.
50  HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll");
51  HMODULE kernel32_from_address =
52      base::GetModuleFromAddress(reinterpret_cast<DWORD*>(kernel32) + 1);
53  EXPECT_EQ(kernel32, kernel32_from_address);
54}
55
56TEST(ProcessMemoryTest, EnableLFH) {
57  ASSERT_TRUE(base::EnableLowFragmentationHeap());
58  if (IsDebuggerPresent()) {
59    // Under these conditions, LFH can't be enabled. There's no point to test
60    // anything.
61    const char* no_debug_env = getenv("_NO_DEBUG_HEAP");
62    if (!no_debug_env || strcmp(no_debug_env, "1"))
63      return;
64  }
65  HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
66  ASSERT_TRUE(kernel32 != NULL);
67  HeapQueryFn heap_query = reinterpret_cast<HeapQueryFn>(GetProcAddress(
68      kernel32,
69      "HeapQueryInformation"));
70
71  // On Windows 2000, the function is not exported. This is not a reason to
72  // fail but we won't be able to retrieves information about the heap, so we
73  // should stop here.
74  if (heap_query == NULL)
75    return;
76
77  HANDLE heaps[1024] = { 0 };
78  unsigned number_heaps = GetProcessHeaps(1024, heaps);
79  EXPECT_GT(number_heaps, 0u);
80  for (unsigned i = 0; i < number_heaps; ++i) {
81    ULONG flag = 0;
82    SIZE_T length;
83    ASSERT_NE(0, heap_query(heaps[i],
84                            HeapCompatibilityInformation,
85                            &flag,
86                            sizeof(flag),
87                            &length));
88    // If flag is 0, the heap is a standard heap that does not support
89    // look-asides. If flag is 1, the heap supports look-asides. If flag is 2,
90    // the heap is a low-fragmentation heap (LFH). Note that look-asides are not
91    // supported on the LFH.
92
93    // We don't have any documented way of querying the HEAP_NO_SERIALIZE flag.
94    EXPECT_LE(flag, 2u);
95    EXPECT_NE(flag, 1u);
96  }
97}
98#endif  // defined(OS_WIN)
99
100#if defined(OS_MACOSX)
101
102// For the following Mac tests:
103// Note that base::EnableTerminationOnHeapCorruption() is called as part of
104// test suite setup and does not need to be done again, else mach_override
105// will fail.
106
107#if !defined(ADDRESS_SANITIZER)
108// The following code tests the system implementation of malloc() thus no need
109// to test it under AddressSanitizer.
110TEST(ProcessMemoryTest, MacMallocFailureDoesNotTerminate) {
111  // Test that ENOMEM doesn't crash via CrMallocErrorBreak two ways: the exit
112  // code and lack of the error string. The number of bytes is one less than
113  // MALLOC_ABSOLUTE_MAX_SIZE, more than which the system early-returns NULL and
114  // does not call through malloc_error_break(). See the comment at
115  // EnableTerminationOnOutOfMemory() for more information.
116  void* buf = NULL;
117  ASSERT_EXIT(
118      {
119        base::EnableTerminationOnOutOfMemory();
120
121        buf = malloc(std::numeric_limits<size_t>::max() - (2 * PAGE_SIZE) - 1);
122      },
123      testing::KilledBySignal(SIGTRAP),
124      "\\*\\*\\* error: can't allocate region.*"
125          "(Terminating process due to a potential for future heap "
126          "corruption){0}");
127
128  base::debug::Alias(buf);
129}
130#endif  // !defined(ADDRESS_SANITIZER)
131
132TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
133  // Assert that freeing an unallocated pointer will crash the process.
134  char buf[9];
135  asm("" : "=r" (buf));  // Prevent clang from being too smart.
136#if ARCH_CPU_64_BITS
137  // On 64 bit Macs, the malloc system automatically abort()s on heap corruption
138  // but does not output anything.
139  ASSERT_DEATH(free(buf), "");
140#elif defined(ADDRESS_SANITIZER)
141  // AddressSanitizer replaces malloc() and prints a different error message on
142  // heap corruption.
143  ASSERT_DEATH(free(buf), "attempting free on address which "
144      "was not malloc\\(\\)-ed");
145#else
146  ASSERT_DEATH(free(buf), "being freed.*"
147      "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*"
148      "Terminating process due to a potential for future heap corruption");
149#endif  // ARCH_CPU_64_BITS || defined(ADDRESS_SANITIZER)
150}
151
152#endif  // defined(OS_MACOSX)
153
154// Android doesn't implement set_new_handler, so we can't use the
155// OutOfMemoryTest cases.
156// OpenBSD does not support these tests either.
157// AddressSanitizer and ThreadSanitizer define the malloc()/free()/etc.
158// functions so that they don't crash if the program is out of memory, so the
159// OOM tests aren't supposed to work.
160// TODO(vandebo) make this work on Windows too.
161#if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
162    !defined(OS_WIN) && \
163    !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
164
165#if defined(USE_TCMALLOC)
166extern "C" {
167int tc_set_new_mode(int mode);
168}
169#endif  // defined(USE_TCMALLOC)
170
171class OutOfMemoryDeathTest : public testing::Test {
172 public:
173  OutOfMemoryDeathTest()
174      : value_(NULL),
175        // Make test size as large as possible minus a few pages so
176        // that alignment or other rounding doesn't make it wrap.
177        test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024),
178        signed_test_size_(std::numeric_limits<ssize_t>::max()) {
179  }
180
181#if defined(USE_TCMALLOC)
182  virtual void SetUp() OVERRIDE {
183    tc_set_new_mode(1);
184  }
185
186  virtual void TearDown() OVERRIDE {
187    tc_set_new_mode(0);
188  }
189#endif  // defined(USE_TCMALLOC)
190
191  void SetUpInDeathAssert() {
192    // Must call EnableTerminationOnOutOfMemory() because that is called from
193    // chrome's main function and therefore hasn't been called yet.
194    // Since this call may result in another thread being created and death
195    // tests shouldn't be started in a multithread environment, this call
196    // should be done inside of the ASSERT_DEATH.
197    base::EnableTerminationOnOutOfMemory();
198  }
199
200  void* value_;
201  size_t test_size_;
202  ssize_t signed_test_size_;
203};
204
205TEST_F(OutOfMemoryDeathTest, New) {
206  ASSERT_DEATH({
207      SetUpInDeathAssert();
208      value_ = operator new(test_size_);
209    }, "");
210}
211
212TEST_F(OutOfMemoryDeathTest, NewArray) {
213  ASSERT_DEATH({
214      SetUpInDeathAssert();
215      value_ = new char[test_size_];
216    }, "");
217}
218
219TEST_F(OutOfMemoryDeathTest, Malloc) {
220  ASSERT_DEATH({
221      SetUpInDeathAssert();
222      value_ = malloc(test_size_);
223    }, "");
224}
225
226TEST_F(OutOfMemoryDeathTest, Realloc) {
227  ASSERT_DEATH({
228      SetUpInDeathAssert();
229      value_ = realloc(NULL, test_size_);
230    }, "");
231}
232
233TEST_F(OutOfMemoryDeathTest, Calloc) {
234  ASSERT_DEATH({
235      SetUpInDeathAssert();
236      value_ = calloc(1024, test_size_ / 1024L);
237    }, "");
238}
239
240TEST_F(OutOfMemoryDeathTest, Valloc) {
241  ASSERT_DEATH({
242      SetUpInDeathAssert();
243      value_ = valloc(test_size_);
244    }, "");
245}
246
247#if defined(OS_LINUX)
248TEST_F(OutOfMemoryDeathTest, Pvalloc) {
249  ASSERT_DEATH({
250      SetUpInDeathAssert();
251      value_ = pvalloc(test_size_);
252    }, "");
253}
254
255TEST_F(OutOfMemoryDeathTest, Memalign) {
256  ASSERT_DEATH({
257      SetUpInDeathAssert();
258      value_ = memalign(4, test_size_);
259    }, "");
260}
261
262TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) {
263  // g_try_malloc is documented to return NULL on failure. (g_malloc is the
264  // 'safe' default that crashes if allocation fails). However, since we have
265  // hopefully overridden malloc, even g_try_malloc should fail. This tests
266  // that the run-time symbol resolution is overriding malloc for shared
267  // libraries as well as for our code.
268  ASSERT_DEATH({
269      SetUpInDeathAssert();
270      value_ = g_try_malloc(test_size_);
271    }, "");
272}
273#endif  // OS_LINUX
274
275// Android doesn't implement posix_memalign().
276#if defined(OS_POSIX) && !defined(OS_ANDROID)
277TEST_F(OutOfMemoryDeathTest, Posix_memalign) {
278  // Grab the return value of posix_memalign to silence a compiler warning
279  // about unused return values. We don't actually care about the return
280  // value, since we're asserting death.
281  ASSERT_DEATH({
282      SetUpInDeathAssert();
283      EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_));
284    }, "");
285}
286#endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
287
288#if defined(OS_MACOSX)
289
290// Purgeable zone tests
291
292TEST_F(OutOfMemoryDeathTest, MallocPurgeable) {
293  malloc_zone_t* zone = malloc_default_purgeable_zone();
294  ASSERT_DEATH({
295      SetUpInDeathAssert();
296      value_ = malloc_zone_malloc(zone, test_size_);
297    }, "");
298}
299
300TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) {
301  malloc_zone_t* zone = malloc_default_purgeable_zone();
302  ASSERT_DEATH({
303      SetUpInDeathAssert();
304      value_ = malloc_zone_realloc(zone, NULL, test_size_);
305    }, "");
306}
307
308TEST_F(OutOfMemoryDeathTest, CallocPurgeable) {
309  malloc_zone_t* zone = malloc_default_purgeable_zone();
310  ASSERT_DEATH({
311      SetUpInDeathAssert();
312      value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L);
313    }, "");
314}
315
316TEST_F(OutOfMemoryDeathTest, VallocPurgeable) {
317  malloc_zone_t* zone = malloc_default_purgeable_zone();
318  ASSERT_DEATH({
319      SetUpInDeathAssert();
320      value_ = malloc_zone_valloc(zone, test_size_);
321    }, "");
322}
323
324TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) {
325  malloc_zone_t* zone = malloc_default_purgeable_zone();
326  ASSERT_DEATH({
327      SetUpInDeathAssert();
328      value_ = malloc_zone_memalign(zone, 8, test_size_);
329    }, "");
330}
331
332// Since these allocation functions take a signed size, it's possible that
333// calling them just once won't be enough to exhaust memory. In the 32-bit
334// environment, it's likely that these allocation attempts will fail because
335// not enough contiguous address space is available. In the 64-bit environment,
336// it's likely that they'll fail because they would require a preposterous
337// amount of (virtual) memory.
338
339TEST_F(OutOfMemoryDeathTest, CFAllocatorSystemDefault) {
340  ASSERT_DEATH({
341      SetUpInDeathAssert();
342      while ((value_ =
343              base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {}
344    }, "");
345}
346
347TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) {
348  ASSERT_DEATH({
349      SetUpInDeathAssert();
350      while ((value_ =
351              base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {}
352    }, "");
353}
354
355TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) {
356  ASSERT_DEATH({
357      SetUpInDeathAssert();
358      while ((value_ =
359              base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {}
360    }, "");
361}
362
363#if !defined(ARCH_CPU_64_BITS)
364
365// See process_util_unittest_mac.mm for an explanation of why this test isn't
366// run in the 64-bit environment.
367
368TEST_F(OutOfMemoryDeathTest, PsychoticallyBigObjCObject) {
369  ASSERT_DEATH({
370      SetUpInDeathAssert();
371      while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {}
372    }, "");
373}
374
375#endif  // !ARCH_CPU_64_BITS
376#endif  // OS_MACOSX
377
378#endif  // !defined(OS_ANDROID) && !defined(OS_OPENBSD) &&
379        // !defined(OS_WIN) && !defined(ADDRESS_SANITIZER)
380