diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-03 20:59:18 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-03 20:59:18 +0000 |
commit | f2950489c7c6e7b7fc2233e0cf47b8981e733011 (patch) | |
tree | 69bf8beaabe085b12b3577702d9331401e19290b /base | |
parent | e4b3aab4953bc9e487c223cad98d10b60228fd47 (diff) | |
download | chromium_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.mm | 54 | ||||
-rw-r--r-- | base/process_util_unittest.cc | 16 |
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) |