From 7e24b6ca2aa2c15a24504c02fad09f47e1ece8b5 Mon Sep 17 00:00:00 2001 From: Aliaksey Kandratsenka Date: Sun, 16 Feb 2014 17:04:26 -0800 Subject: added debugallocation check for offset_ corruption It was previously possible (although unlikely) for damaged offset_ field to lead FromRawPointer implementation into different MallocBlock. As is usual with any damage, it's best to catch errors at earliest possible time. --- src/debugallocation.cc | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/debugallocation.cc b/src/debugallocation.cc index eeb9f55..b7e72cf 100644 --- a/src/debugallocation.cc +++ b/src/debugallocation.cc @@ -735,14 +735,36 @@ class MallocBlock { " deallocated; or else a word before the object has been" " corrupted (memory stomping bug)", p); } - // If mb->offset_ is zero (common case), mb is the real header. If - // mb->offset_ is non-zero, this block was allocated by memalign, and - // mb->offset_ is the distance backwards to the real header from mb, - // which is a fake header. The following subtraction works for both zero - // and non-zero values. - return reinterpret_cast( - reinterpret_cast(mb) - mb->offset_); + // If mb->offset_ is zero (common case), mb is the real header. + // If mb->offset_ is non-zero, this block was allocated by debug + // memallign implementation, and mb->offset_ is the distance + // backwards to the real header from mb, which is a fake header. + if (mb->offset_ == 0) { + return mb; + } + + MallocBlock *main_block = reinterpret_cast( + reinterpret_cast(mb) - mb->offset_); + + if (main_block->offset_ != 0) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " Need 0 but got %x", + (unsigned)(main_block->offset_)); + } + if (main_block >= p) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " Detected main_block address overflow: %x", + (unsigned)(mb->offset_)); + } + if (main_block->size2_addr() < p) { + RAW_LOG(FATAL, "memory corruption bug: offset_ field is corrupted." + " It points below it's own main_block: %x", + (unsigned)(mb->offset_)); + } + + return main_block; } + static const MallocBlock* FromRawPointer(const void* p) { // const-safe version: we just cast about return FromRawPointer(const_cast(p)); @@ -1247,7 +1269,6 @@ extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW { char *old_end = old_begin + old->data_size(); ssize_t old_ssize = old_end - (char *)ptr; - // TODO: make FromRawPointer check for out-of-bounds offset values CHECK_CONDITION(old_ssize >= 0); size_t old_size = (size_t)old_ssize; @@ -1341,6 +1362,9 @@ static void *do_debug_memalign(size_t alignment, size_t size) { // p is now end of fake header (beginning of client area), // and orig_p is the end of the real header, so offset_ // is their difference. + // + // Note that other fields of fake_hdr are initialized with + // kMagicUninitializedByte fake_hdr->set_offset(reinterpret_cast(p) - orig_p); } return p; -- cgit v1.2.1