summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authoravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-03 20:59:18 +0000
committeravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-03 20:59:18 +0000
commitf2950489c7c6e7b7fc2233e0cf47b8981e733011 (patch)
tree69bf8beaabe085b12b3577702d9331401e19290b /base
parente4b3aab4953bc9e487c223cad98d10b60228fd47 (diff)
downloadchromium_src-f2950489c7c6e7b7fc2233e0cf47b8981e733011.zip
chromium_src-f2950489c7c6e7b7fc2233e0cf47b8981e733011.tar.gz
chromium_src-f2950489c7c6e7b7fc2233e0cf47b8981e733011.tar.bz2
On 64 bit Macs, the malloc system automatically abort()s on heap corruption.
BUG=225806 TEST=ProcessUtilTest.MacTerminateOnHeapCorruption passes Review URL: https://chromiumcodereview.appspot.com/13567003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192147 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/process_util_mac.mm54
-rw-r--r--base/process_util_unittest.cc16
2 files changed, 52 insertions, 18 deletions
diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm
index 925f21e..b4ccd4a 100644
--- a/base/process_util_mac.mm
+++ b/base/process_util_mac.mm
@@ -6,14 +6,12 @@
#import <Cocoa/Cocoa.h>
#include <crt_externs.h>
-#include <dlfcn.h>
#include <errno.h>
#include <mach/mach.h>
#include <mach/mach_init.h>
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
#include <mach/task.h>
-#include <mach-o/nlist.h>
#include <malloc/malloc.h>
#import <objc/runtime.h>
#include <signal.h>
@@ -36,10 +34,16 @@
#include "base/posix/eintr_wrapper.h"
#include "base/string_util.h"
#include "base/sys_info.h"
-#include "base/threading/thread_local.h"
#include "third_party/apple_apsl/CFBase.h"
#include "third_party/apple_apsl/malloc.h"
+
+#if ARCH_CPU_32_BITS
+#include <dlfcn.h>
+#include <mach-o/nlist.h>
+
+#include "base/threading/thread_local.h"
#include "third_party/mach_override/mach_override.h"
+#endif // ARCH_CPU_32_BITS
namespace base {
@@ -486,6 +490,9 @@ size_t GetSystemCommitCharge() {
return (data.active_count * page_size) / 1024;
}
+// These are helpers for EnableTerminationOnHeapCorruption, which is a no-op
+// on 64 bit Macs.
+#if ARCH_CPU_32_BITS
namespace {
// Finds the library path for malloc() and thus the libC part of libSystem,
@@ -508,7 +515,6 @@ malloc_error_break_t g_original_malloc_error_break = NULL;
// as __private_extern__ and cannot be dlsym()ed. Instead, use nlist() to
// get it.
malloc_error_break_t LookUpMallocErrorBreak() {
-#if ARCH_CPU_32_BITS
const char* lib_c_path = LookUpLibCPath();
if (!lib_c_path)
return NULL;
@@ -538,9 +544,6 @@ malloc_error_break_t LookUpMallocErrorBreak() {
reference_addr += nl[0].n_value;
return reinterpret_cast<malloc_error_break_t>(reference_addr);
-#endif // ARCH_CPU_32_BITS
-
- return NULL;
}
// Simple scoper that saves the current value of errno, resets it to 0, and on
@@ -624,14 +627,14 @@ void CrMallocErrorBreak() {
}
} // namespace
+#endif // ARCH_CPU_32_BITS
void EnableTerminationOnHeapCorruption() {
-#ifdef ADDRESS_SANITIZER
- // Don't do anything special on heap corruption, because it should be handled
- // by AddressSanitizer.
+#if defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS
+ // AddressSanitizer handles heap corruption, and on 64 bit Macs, the malloc
+ // system automatically abort()s on heap corruption.
return;
-#endif
-
+#else
// Only override once, otherwise CrMallocErrorBreak() will recurse
// to itself.
if (g_original_malloc_error_break)
@@ -650,6 +653,7 @@ void EnableTerminationOnHeapCorruption() {
if (err != err_none)
DLOG(WARNING) << "Could not override malloc_error_break; error = " << err;
+#endif // defined(ADDRESS_SANITIZER) || ARCH_CPU_64_BITS
}
// ------------------------------------------------------------------------
@@ -748,7 +752,9 @@ memalign_type g_old_memalign_purgeable;
void* oom_killer_malloc(struct _malloc_zone_t* zone,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_malloc(zone, size);
if (!result && size)
debug::BreakDebugger();
@@ -758,7 +764,9 @@ void* oom_killer_malloc(struct _malloc_zone_t* zone,
void* oom_killer_calloc(struct _malloc_zone_t* zone,
size_t num_items,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_calloc(zone, num_items, size);
if (!result && num_items && size)
debug::BreakDebugger();
@@ -767,7 +775,9 @@ void* oom_killer_calloc(struct _malloc_zone_t* zone,
void* oom_killer_valloc(struct _malloc_zone_t* zone,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_valloc(zone, size);
if (!result && size)
debug::BreakDebugger();
@@ -776,14 +786,18 @@ void* oom_killer_valloc(struct _malloc_zone_t* zone,
void oom_killer_free(struct _malloc_zone_t* zone,
void* ptr) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
g_old_free(zone, ptr);
}
void* oom_killer_realloc(struct _malloc_zone_t* zone,
void* ptr,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_realloc(zone, ptr, size);
if (!result && size)
debug::BreakDebugger();
@@ -793,7 +807,9 @@ void* oom_killer_realloc(struct _malloc_zone_t* zone,
void* oom_killer_memalign(struct _malloc_zone_t* zone,
size_t alignment,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_memalign(zone, alignment, size);
// Only die if posix_memalign would have returned ENOMEM, since there are
// other reasons why NULL might be returned (see
@@ -807,7 +823,9 @@ void* oom_killer_memalign(struct _malloc_zone_t* zone,
void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_malloc_purgeable(zone, size);
if (!result && size)
debug::BreakDebugger();
@@ -817,7 +835,9 @@ void* oom_killer_malloc_purgeable(struct _malloc_zone_t* zone,
void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone,
size_t num_items,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_calloc_purgeable(zone, num_items, size);
if (!result && num_items && size)
debug::BreakDebugger();
@@ -826,7 +846,9 @@ void* oom_killer_calloc_purgeable(struct _malloc_zone_t* zone,
void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_valloc_purgeable(zone, size);
if (!result && size)
debug::BreakDebugger();
@@ -835,14 +857,18 @@ void* oom_killer_valloc_purgeable(struct _malloc_zone_t* zone,
void oom_killer_free_purgeable(struct _malloc_zone_t* zone,
void* ptr) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
g_old_free_purgeable(zone, ptr);
}
void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone,
void* ptr,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_realloc_purgeable(zone, ptr, size);
if (!result && size)
debug::BreakDebugger();
@@ -852,7 +878,9 @@ void* oom_killer_realloc_purgeable(struct _malloc_zone_t* zone,
void* oom_killer_memalign_purgeable(struct _malloc_zone_t* zone,
size_t alignment,
size_t size) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
+#endif // ARCH_CPU_32_BITS
void* result = g_old_memalign_purgeable(zone, alignment, size);
// Only die if posix_memalign would have returned ENOMEM, since there are
// other reasons why NULL might be returned (see
@@ -940,8 +968,10 @@ id oom_killer_allocWithZone(id self, SEL _cmd, NSZone* zone)
void* UncheckedMalloc(size_t size) {
if (g_old_malloc) {
+#if ARCH_CPU_32_BITS
ScopedClearErrno clear_errno;
ThreadLocalBooleanAutoReset flag(g_unchecked_malloc.Pointer(), true);
+#endif // ARCH_CPU_32_BITS
return g_old_malloc(malloc_default_zone(), size);
}
return malloc(size);
diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc
index be69b93..ef383b6 100644
--- a/base/process_util_unittest.cc
+++ b/base/process_util_unittest.cc
@@ -567,16 +567,20 @@ TEST_F(ProcessUtilTest, MacTerminateOnHeapCorruption) {
// Assert that freeing an unallocated pointer will crash the process.
char buf[3];
asm("" : "=r" (buf)); // Prevent clang from being too smart.
-#if !defined(ADDRESS_SANITIZER)
- ASSERT_DEATH(free(buf), "being freed.*"
- "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*"
- "Terminating process due to a potential for future heap corruption");
-#else
+#if ARCH_CPU_64_BITS
+ // On 64 bit Macs, the malloc system automatically abort()s on heap corruption
+ // but does not output anything.
+ ASSERT_DEATH(free(buf), "");
+#elif defined(ADDRESS_SANITIZER)
// AddressSanitizer replaces malloc() and prints a different error message on
// heap corruption.
ASSERT_DEATH(free(buf), "attempting free on address which "
"was not malloc\\(\\)-ed");
-#endif // !defined(ADDRESS_SANITIZER)
+#else
+ ASSERT_DEATH(free(buf), "being freed.*"
+ "\\*\\*\\* set a breakpoint in malloc_error_break to debug.*"
+ "Terminating process due to a potential for future heap corruption");
+#endif // ARCH_CPU_64_BITS || defined(ADDRESS_SANITIZER)
}
#endif // defined(OS_MACOSX)