Index: base/allocator/tcmalloc_unittest.cc |
=================================================================== |
--- base/allocator/tcmalloc_unittest.cc (revision 0) |
+++ base/allocator/tcmalloc_unittest.cc (working copy) |
@@ -0,0 +1,81 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+#include <stdio.h> |
+#include "base/allocator/allocator_shim.h" |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+// TCMalloc header files |
+#include "common.h" // For TCMalloc constants like page size, etc. |
+ |
+using base::allocator::TCMallocDoMallocForTest; |
+using base::allocator::TCMallocDoFreeForTest; |
+using base::allocator::ExcludeSpaceForMarkForTest; |
+ |
+TEST(TCMallocFreeCheck, BadPointerInFirstPageOfTheLargeObject) { |
+ char* p = reinterpret_cast<char*>( |
+ TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1))); |
+ for (int offset = 1; offset < kPageSize ; offset <<= 1) { |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p + offset), |
+ "Pointer is not pointing to the start of a span"); |
+ } |
+} |
+ |
+TEST(TCMallocFreeCheck, BadPageAlignedPointerInsideLargeObject) { |
+ char* p = reinterpret_cast<char*>( |
+ TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1))); |
+ |
+ for (int offset = kPageSize; offset < kMaxSize; offset += kPageSize) { |
+ // Only the first and last page of a span are in heap map. So for others |
+ // tcmalloc will give a general error of invalid pointer. |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p + offset), |
+ "Attempt to free invalid pointer"); |
+ } |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p + kMaxSize), |
+ "Pointer is not pointing to the start of a span"); |
+} |
+ |
+TEST(TCMallocFreeCheck, DoubleFreeLargeObject) { |
+ char* p = reinterpret_cast<char*>( |
+ TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1))); |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), |
+ "Object was not in-use"); |
+} |
+ |
+ |
+#ifdef NDEBUG |
+TEST(TCMallocFreeCheck, DoubleFreeSmallObject) { |
+ for (size_t size = 1; |
+ size <= ExcludeSpaceForMarkForTest(kMaxSize); |
+ size <<= 1) { |
+ char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size)); |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), |
+ "Circular loop in list detected"); |
+ } |
+} |
+#else |
+TEST(TCMallocFreeCheck, DoubleFreeSmallObject) { |
+ size_t size = 1; |
+ |
+ // When the object is small, tcmalloc validation can not distinguish normal |
+ // memory corruption or double free, because there's not enough space in |
+ // freed objects to keep the mark. |
+ for (; size <= ExcludeSpaceForMarkForTest(kMinClassSize); size <<= 1) { |
+ char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size)); |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), |
+ "Memory corrupted"); |
+ } |
+ |
+ for (; size <= ExcludeSpaceForMarkForTest(kMaxSize); size <<= 1) { |
+ char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size)); |
+ ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), |
+ "Attempt to double free"); |
+ } |
+} |
+#endif |
+ |
+int main(int argc, char **argv) { |
+ testing::InitGoogleTest(&argc, argv); |
+ return RUN_ALL_TESTS(); |
+} |