memory_win.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
1// Copyright (c) 2013 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#include "base/process/memory.h"
6
7#include <psapi.h>
8
9#include "base/logging.h"
10#include "base/memory/scoped_ptr.h"
11
12namespace base {
13
14namespace {
15
16void OnNoMemory() {
17  // Kill the process. This is important for security, since WebKit doesn't
18  // NULL-check many memory allocations. If a malloc fails, returns NULL, and
19  // the buffer is then used, it provides a handy mapping of memory starting at
20  // address 0 for an attacker to utilize.
21  __debugbreak();
22  _exit(1);
23}
24
25// HeapSetInformation function pointer.
26typedef BOOL (WINAPI* HeapSetFn)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
27
28}  // namespace
29
30bool EnableLowFragmentationHeap() {
31  HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
32  HeapSetFn heap_set = reinterpret_cast<HeapSetFn>(GetProcAddress(
33      kernel32,
34      "HeapSetInformation"));
35
36  // On Windows 2000, the function is not exported. This is not a reason to
37  // fail.
38  if (!heap_set)
39    return true;
40
41  unsigned number_heaps = GetProcessHeaps(0, NULL);
42  if (!number_heaps)
43    return false;
44
45  // Gives us some extra space in the array in case a thread is creating heaps
46  // at the same time we're querying them.
47  static const int MARGIN = 8;
48  scoped_ptr<HANDLE[]> heaps(new HANDLE[number_heaps + MARGIN]);
49  number_heaps = GetProcessHeaps(number_heaps + MARGIN, heaps.get());
50  if (!number_heaps)
51    return false;
52
53  for (unsigned i = 0; i < number_heaps; ++i) {
54    ULONG lfh_flag = 2;
55    // Don't bother with the result code. It may fails on heaps that have the
56    // HEAP_NO_SERIALIZE flag. This is expected and not a problem at all.
57    heap_set(heaps[i],
58             HeapCompatibilityInformation,
59             &lfh_flag,
60             sizeof(lfh_flag));
61  }
62  return true;
63}
64
65void EnableTerminationOnHeapCorruption() {
66  // Ignore the result code. Supported on XP SP3 and Vista.
67  HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
68}
69
70void EnableTerminationOnOutOfMemory() {
71  std::set_new_handler(&OnNoMemory);
72}
73
74HMODULE GetModuleFromAddress(void* address) {
75  HMODULE instance = NULL;
76  if (!::GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
77                            GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
78                            static_cast<char*>(address),
79                            &instance)) {
80    NOTREACHED();
81  }
82  return instance;
83}
84
85// TODO(b.kelemen): implement it with the required semantics. On Linux this is
86// implemented with a weak symbol that is overridden by tcmalloc. This is
87// neccessary because base cannot have a direct dependency on tcmalloc. Since
88// weak symbols are not supported on Windows this will involve some build time
89// magic, much like what is done for libcrt in order to override the allocation
90// functions.
91bool UncheckedMalloc(size_t size, void** result) {
92  *result = malloc(size);
93  return *result != NULL;
94}
95
96}  // namespace base
97