Home | History | Annotate | Download | only in allocator
      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