diff options
author | kaiwang@chromium.org <kaiwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-24 11:13:23 +0000 |
---|---|---|
committer | kaiwang@chromium.org <kaiwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-24 11:13:23 +0000 |
commit | a849dc1cd365ac9f21233b9950bb39860c39a867 (patch) | |
tree | 6af6115f10d1fd5ab950f06859d3f9a1da5a22fd /third_party | |
parent | 09096e0aa7bd96a31389825152d9547c56459273 (diff) | |
download | chromium_src-a849dc1cd365ac9f21233b9950bb39860c39a867.zip chromium_src-a849dc1cd365ac9f21233b9950bb39860c39a867.tar.gz chromium_src-a849dc1cd365ac9f21233b9950bb39860c39a867.tar.bz2 |
1. Enable large object pointer offset check in release build.
Following code will now cause a check error:
char* p = reinterpret_cast<char*>(malloc(kMaxSize + 1));
free(p + 1);
2. Remove a duplicated error reporting function "DieFromBadFreePointer", can
use "InvalidGetAllocatedSize".
Review URL: https://chromiumcodereview.appspot.com/10391178
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138775 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/tcmalloc/chromium/src/internal_logging.h | 9 | ||||
-rw-r--r-- | third_party/tcmalloc/chromium/src/tcmalloc.cc | 47 |
2 files changed, 31 insertions, 25 deletions
diff --git a/third_party/tcmalloc/chromium/src/internal_logging.h b/third_party/tcmalloc/chromium/src/internal_logging.h index 0267034..55e1808 100644 --- a/third_party/tcmalloc/chromium/src/internal_logging.h +++ b/third_party/tcmalloc/chromium/src/internal_logging.h @@ -113,12 +113,21 @@ do { \ } \ } while (0) +#define CHECK_CONDITION_PRINT(cond, str) \ +do { \ + if (!(cond)) { \ + ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, str); \ + } \ +} while (0) + // Our own version of assert() so we can avoid hanging by trying to do // all kinds of goofy printing while holding the malloc lock. #ifndef NDEBUG #define ASSERT(cond) CHECK_CONDITION(cond) +#define ASSERT_PRINT(cond, str) CHECK_CONDITION_PRINT(cond, str) #else #define ASSERT(cond) ((void) 0) +#define ASSERT_PRINT(cond, str) ((void) 0) #endif // Print into buffer diff --git a/third_party/tcmalloc/chromium/src/tcmalloc.cc b/third_party/tcmalloc/chromium/src/tcmalloc.cc index a87a4df..219a370 100644 --- a/third_party/tcmalloc/chromium/src/tcmalloc.cc +++ b/third_party/tcmalloc/chromium/src/tcmalloc.cc @@ -178,13 +178,13 @@ using tcmalloc::StackTrace; using tcmalloc::Static; using tcmalloc::ThreadCache; -// ---- Double free debug declarations +// ---- Functions doing validation with an extra mark. static size_t ExcludeSpaceForMark(size_t size); static void AddRoomForMark(size_t* size); static void ExcludeMarkFromSize(size_t* new_size); static void MarkAllocatedRegion(void* ptr); static void ValidateAllocatedRegion(void* ptr, size_t cl); -// ---- End Double free debug declarations +// ---- End validation functions. DECLARE_int64(tcmalloc_sample_parameter); DECLARE_double(tcmalloc_release_rate); @@ -950,7 +950,7 @@ static inline bool CheckCachedSizeClass(void *ptr) { cached_value == Static::pageheap()->GetDescriptor(p)->sizeclass; } -static inline void* CheckedMallocResult(void *result) { +static inline void* CheckMallocResult(void *result) { ASSERT(result == NULL || CheckCachedSizeClass(result)); MarkAllocatedRegion(result); return result; @@ -959,7 +959,7 @@ static inline void* CheckedMallocResult(void *result) { static inline void* SpanToMallocResult(Span *span) { Static::pageheap()->CacheSizeClass(span->start, 0); return - CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift)); + CheckMallocResult(reinterpret_cast<void*>(span->start << kPageShift)); } static void* DoSampledAllocation(size_t size) { @@ -1096,7 +1096,7 @@ inline void* do_malloc(size_t size) { } else { // The common case, and also the simplest. This just pops the // size-appropriate freelist, after replenishing it if it's empty. - ret = CheckedMallocResult(heap->Allocate(size, cl)); + ret = CheckMallocResult(heap->Allocate(size, cl)); } } else { ret = do_malloc_pages(heap, size); @@ -1156,7 +1156,15 @@ inline void do_free_with_callback(void* ptr, void (*invalid_free_fn)(void*)) { cl = span->sizeclass; Static::pageheap()->CacheSizeClass(p, cl); } + if (cl == 0) { + // Check to see if the object is in use. + CHECK_CONDITION_PRINT(span->location == Span::IN_USE, + "Object was not in-use"); + CHECK_CONDITION_PRINT( + span->start << kPageShift == reinterpret_cast<uintptr_t>(ptr), + "Pointer is not pointing to the start of a span"); + } ValidateAllocatedRegion(ptr, cl); if (cl != 0) { @@ -1276,7 +1284,7 @@ inline void* do_realloc(void* old_ptr, size_t new_size) { void* do_memalign(size_t align, size_t size) { ASSERT((align & (align - 1)) == 0); ASSERT(align > 0); - // Marked in CheckMallocResult(), which is also inside SpanToMallocResult(). + // Marked in CheckMallocResult(), which is also inside SpanToMallocResult(). AddRoomForMark(&size); if (size + align < size) return NULL; // Overflow @@ -1307,7 +1315,7 @@ void* do_memalign(size_t align, size_t size) { if (cl < kNumClasses) { ThreadCache* heap = ThreadCache::GetCache(); size = Static::sizemap()->class_to_size(cl); - return CheckedMallocResult(heap->Allocate(size, cl)); + return CheckMallocResult(heap->Allocate(size, cl)); } } @@ -1698,7 +1706,7 @@ extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW { #endif // TCMALLOC_USING_DEBUGALLOCATION -// ---Double free() debugging implementation ----------------------------------- +// --- Validation implementation with an extra mark ---------------------------- // We will put a mark at the extreme end of each allocation block. We make // sure that we always allocate enough "extra memory" that we can fit in the // mark, and still provide the requested usable region. If ever that mark is @@ -1741,22 +1749,11 @@ static void ValidateAllocatedRegion(void* ptr, size_t cl) {} #else // TCMALLOC_VALIDATION static void DieFromDoubleFree() { - char* p = NULL; - p++; - *p += 1; // Segv. -} - -static size_t DieFromBadFreePointer(const void* unused) { - char* p = NULL; - p += 2; - *p += 2; // Segv. - return 0; + Log(kCrash, __FILE__, __LINE__, "Attempt to double free"); } static void DieFromMemoryCorruption() { - char* p = NULL; - p += 3; - *p += 3; // Segv. + Log(kCrash, __FILE__, __LINE__, "Memory corrupted"); } // We can either do byte marking, or whole word marking based on the following @@ -1770,7 +1767,7 @@ static void DieFromMemoryCorruption() { typedef char MarkType; // char saves memory... int is more complete. static const MarkType kAllocationMarkMask = static_cast<MarkType>(0x36); -#else +#else typedef int MarkType; // char saves memory... int is more complete. static const MarkType kAllocationMarkMask = static_cast<MarkType>(0xE1AB9536); @@ -1793,9 +1790,9 @@ inline static size_t ExcludeSpaceForMark(size_t size) { } inline static MarkType* GetMarkLocation(void* ptr) { - size_t class_size = GetSizeWithCallback(ptr, DieFromBadFreePointer); - ASSERT(class_size % sizeof(kAllocationMarkMask) == 0); - size_t last_index = (class_size / sizeof(kAllocationMarkMask)) - 1; + size_t size = GetSizeWithCallback(ptr, &InvalidGetAllocatedSize); + ASSERT(size % sizeof(kAllocationMarkMask) == 0); + size_t last_index = (size / sizeof(kAllocationMarkMask)) - 1; return static_cast<MarkType*>(ptr) + last_index; } |