1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #include <stdio.h> 5 #include "base/allocator/allocator_shim.h" 6 7 #include "testing/gtest/include/gtest/gtest.h" 8 9 // TCMalloc header files 10 #include "common.h" // For TCMalloc constants like page size, etc. 11 12 using base::allocator::TCMallocDoMallocForTest; 13 using base::allocator::TCMallocDoFreeForTest; 14 using base::allocator::ExcludeSpaceForMarkForTest; 15 16 TEST(TCMallocFreeCheck, BadPointerInFirstPageOfTheLargeObject) { 17 char* p = reinterpret_cast<char*>( 18 TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1))); 19 for (int offset = 1; offset < kPageSize ; offset <<= 1) { 20 ASSERT_DEATH(TCMallocDoFreeForTest(p + offset), 21 "Pointer is not pointing to the start of a span"); 22 } 23 } 24 25 TEST(TCMallocFreeCheck, BadPageAlignedPointerInsideLargeObject) { 26 char* p = reinterpret_cast<char*>( 27 TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1))); 28 29 for (int offset = kPageSize; offset < kMaxSize; offset += kPageSize) { 30 // Only the first and last page of a span are in heap map. So for others 31 // tcmalloc will give a general error of invalid pointer. 32 ASSERT_DEATH(TCMallocDoFreeForTest(p + offset), 33 "Attempt to free invalid pointer"); 34 } 35 ASSERT_DEATH(TCMallocDoFreeForTest(p + kMaxSize), 36 "Pointer is not pointing to the start of a span"); 37 } 38 39 TEST(TCMallocFreeCheck, DoubleFreeLargeObject) { 40 char* p = reinterpret_cast<char*>( 41 TCMallocDoMallocForTest(ExcludeSpaceForMarkForTest(kMaxSize + 1))); 42 ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), 43 "Object was not in-use"); 44 } 45 46 47 #ifdef NDEBUG 48 TEST(TCMallocFreeCheck, DoubleFreeSmallObject) { 49 for (size_t size = 1; 50 size <= ExcludeSpaceForMarkForTest(kMaxSize); 51 size <<= 1) { 52 char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size)); 53 ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), 54 "Circular loop in list detected"); 55 } 56 } 57 #else 58 TEST(TCMallocFreeCheck, DoubleFreeSmallObject) { 59 size_t size = 1; 60 61 // When the object is small, tcmalloc validation can not distinguish normal 62 // memory corruption or double free, because there's not enough space in 63 // freed objects to keep the mark. 64 for (; size <= ExcludeSpaceForMarkForTest(kMinClassSize); size <<= 1) { 65 char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size)); 66 ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), 67 "Memory corrupted"); 68 } 69 70 for (; size <= ExcludeSpaceForMarkForTest(kMaxSize); size <<= 1) { 71 char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size)); 72 ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p), 73 "Attempt to double free"); 74 } 75 } 76 #endif 77 78 int main(int argc, char **argv) { 79 testing::InitGoogleTest(&argc, argv); 80 return RUN_ALL_TESTS(); 81 } 82