1 // Copyright (c) 2007, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // --- 31 // Author: Fred Akalin 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <vector> 36 #include "gperftools/malloc_extension.h" 37 #include "base/logging.h" 38 39 using std::vector; 40 41 vector<void (*)()> g_testlist; // the tests to run 42 43 #define TEST(a, b) \ 44 struct Test_##a##_##b { \ 45 Test_##a##_##b() { g_testlist.push_back(&Run); } \ 46 static void Run(); \ 47 }; \ 48 static Test_##a##_##b g_test_##a##_##b; \ 49 void Test_##a##_##b::Run() 50 51 52 static int RUN_ALL_TESTS() { 53 vector<void (*)()>::const_iterator it; 54 for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { 55 (*it)(); // The test will error-exit if there's a problem. 56 } 57 fprintf(stderr, "\nPassed %d tests\n\nPASS\n", 58 static_cast<int>(g_testlist.size())); 59 return 0; 60 } 61 62 // The death tests are meant to be run from a shell-script driver, which 63 // passes in an integer saying which death test to run. We store that 64 // test-to-run here, and in the macro use a counter to see when we get 65 // to that test, so we can run it. 66 static int test_to_run = 0; // set in main() based on argv 67 static int test_counter = 0; // incremented every time the macro is called 68 #define IF_DEBUG_EXPECT_DEATH(statement, regex) do { \ 69 if (test_counter++ == test_to_run) { \ 70 fprintf(stderr, "Expected regex:%s\n", regex); \ 71 statement; \ 72 } \ 73 } while (false) 74 75 // This flag won't be compiled in in opt mode. 76 DECLARE_int32(max_free_queue_size); 77 78 // Test match as well as mismatch rules. But do not test on OS X; on 79 // OS X the OS converts new/new[] to malloc before it gets to us, so 80 // we are unable to catch these mismatch errors. 81 #ifndef __APPLE__ 82 TEST(DebugAllocationTest, DeallocMismatch) { 83 // malloc can be matched only by free 84 // new can be matched only by delete and delete(nothrow) 85 // new[] can be matched only by delete[] and delete[](nothrow) 86 // new(nothrow) can be matched only by delete and delete(nothrow) 87 // new(nothrow)[] can be matched only by delete[] and delete[](nothrow) 88 89 // Allocate with malloc. 90 { 91 int* x = static_cast<int*>(malloc(sizeof(*x))); 92 IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete"); 93 IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]"); 94 // Should work fine. 95 free(x); 96 } 97 98 // Allocate with new. 99 { 100 int* x = new int; 101 int* y = new int; 102 IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); 103 IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]"); 104 delete x; 105 ::operator delete(y, std::nothrow); 106 } 107 108 // Allocate with new[]. 109 { 110 int* x = new int[1]; 111 int* y = new int[1]; 112 IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); 113 IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete"); 114 delete [] x; 115 ::operator delete[](y, std::nothrow); 116 } 117 118 // Allocate with new(nothrow). 119 { 120 int* x = new(std::nothrow) int; 121 int* y = new(std::nothrow) int; 122 IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); 123 IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]"); 124 delete x; 125 ::operator delete(y, std::nothrow); 126 } 127 128 // Allocate with new(nothrow)[]. 129 { 130 int* x = new(std::nothrow) int[1]; 131 int* y = new(std::nothrow) int[1]; 132 IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free"); 133 IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete"); 134 delete [] x; 135 ::operator delete[](y, std::nothrow); 136 } 137 } 138 #endif // #ifdef OS_MACOSX 139 140 TEST(DebugAllocationTest, DoubleFree) { 141 int* pint = new int; 142 delete pint; 143 IF_DEBUG_EXPECT_DEATH(delete pint, "has been already deallocated"); 144 } 145 146 TEST(DebugAllocationTest, StompBefore) { 147 int* pint = new int; 148 #ifndef NDEBUG // don't stomp memory if we're not in a position to detect it 149 pint[-1] = 5; 150 IF_DEBUG_EXPECT_DEATH(delete pint, "a word before object"); 151 #endif 152 } 153 154 TEST(DebugAllocationTest, StompAfter) { 155 int* pint = new int; 156 #ifndef NDEBUG // don't stomp memory if we're not in a position to detect it 157 pint[1] = 5; 158 IF_DEBUG_EXPECT_DEATH(delete pint, "a word after object"); 159 #endif 160 } 161 162 TEST(DebugAllocationTest, FreeQueueTest) { 163 // Verify that the allocator doesn't return blocks that were recently freed. 164 int* x = new int; 165 int* old_x = x; 166 delete x; 167 x = new int; 168 #if 1 169 // This check should not be read as a universal guarantee of behavior. If 170 // other threads are executing, it would be theoretically possible for this 171 // check to fail despite the efforts of debugallocation.cc to the contrary. 172 // It should always hold under the controlled conditions of this unittest, 173 // however. 174 EXPECT_NE(x, old_x); // Allocator shouldn't return recently freed blocks 175 #else 176 // The below check passes, but since it isn't *required* to pass, I've left 177 // it commented out. 178 // EXPECT_EQ(x, old_x); 179 #endif 180 old_x = NULL; // avoid breaking opt build with an unused variable warning. 181 delete x; 182 } 183 184 TEST(DebugAllocationTest, DanglingPointerWriteTest) { 185 // This test can only be run if debugging. 186 // 187 // If not debugging, the 'new' following the dangling write might not be 188 // safe. When debugging, we expect the (trashed) deleted block to be on the 189 // list of recently-freed blocks, so the following 'new' will be safe. 190 #if 1 191 int* x = new int; 192 delete x; 193 int poisoned_x_value = *x; 194 *x = 1; // a dangling write. 195 196 char* s = new char[FLAGS_max_free_queue_size]; 197 // When we delete s, we push the storage that was previously allocated to x 198 // off the end of the free queue. At that point, the write to that memory 199 // will be detected. 200 IF_DEBUG_EXPECT_DEATH(delete [] s, "Memory was written to after being freed."); 201 202 // restore the poisoned value of x so that we can delete s without causing a 203 // crash. 204 *x = poisoned_x_value; 205 delete [] s; 206 #endif 207 } 208 209 TEST(DebugAllocationTest, DanglingWriteAtExitTest) { 210 int *x = new int; 211 delete x; 212 int old_x_value = *x; 213 *x = 1; 214 // verify that dangling writes are caught at program termination if the 215 // corrupted block never got pushed off of the end of the free queue. 216 IF_DEBUG_EXPECT_DEATH(exit(0), "Memory was written to after being freed."); 217 *x = old_x_value; // restore x so that the test can exit successfully. 218 } 219 220 TEST(DebugAllocationTest, StackTraceWithDanglingWriteAtExitTest) { 221 int *x = new int; 222 delete x; 223 int old_x_value = *x; 224 *x = 1; 225 // verify that we also get a stack trace when we have a dangling write. 226 // The " @ " is part of the stack trace output. 227 IF_DEBUG_EXPECT_DEATH(exit(0), " @ .*main"); 228 *x = old_x_value; // restore x so that the test can exit successfully. 229 } 230 231 static size_t CurrentlyAllocatedBytes() { 232 size_t value; 233 CHECK(MallocExtension::instance()->GetNumericProperty( 234 "generic.current_allocated_bytes", &value)); 235 return value; 236 } 237 238 TEST(DebugAllocationTest, CurrentlyAllocated) { 239 // Clear the free queue 240 #if 1 241 FLAGS_max_free_queue_size = 0; 242 // Force a round-trip through the queue management code so that the 243 // new size is seen and the queue of recently-freed blocks is flushed. 244 free(malloc(1)); 245 FLAGS_max_free_queue_size = 1048576; 246 #endif 247 248 // Free something and check that it disappears from allocated bytes 249 // immediately. 250 char* p = new char[1000]; 251 size_t after_malloc = CurrentlyAllocatedBytes(); 252 delete[] p; 253 size_t after_free = CurrentlyAllocatedBytes(); 254 EXPECT_LE(after_free, after_malloc - 1000); 255 } 256 257 TEST(DebugAllocationTest, GetAllocatedSizeTest) { 258 #if 1 259 // When debug_allocation is in effect, GetAllocatedSize should return 260 // exactly requested size, since debug_allocation doesn't allow users 261 // to write more than that. 262 for (int i = 0; i < 10; ++i) { 263 void *p = malloc(i); 264 EXPECT_EQ(i, MallocExtension::instance()->GetAllocatedSize(p)); 265 free(p); 266 } 267 #endif 268 void* a = malloc(1000); 269 EXPECT_GE(MallocExtension::instance()->GetAllocatedSize(a), 1000); 270 // This is just a sanity check. If we allocated too much, alloc is broken 271 EXPECT_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000); 272 EXPECT_GE(MallocExtension::instance()->GetEstimatedAllocatedSize(1000), 1000); 273 free(a); 274 } 275 276 TEST(DebugAllocationTest, HugeAlloc) { 277 // This must not be a const variable so it doesn't form an 278 // integral-constant-expression which can be *statically* rejected by the 279 // compiler as too large for the allocation. 280 size_t kTooBig = ~static_cast<size_t>(0); 281 void* a = NULL; 282 283 #ifndef NDEBUG 284 285 a = malloc(kTooBig); 286 EXPECT_EQ(NULL, a); 287 288 // kAlsoTooBig is small enough not to get caught by debugallocation's check, 289 // but will still fall through to tcmalloc's check. This must also be 290 // a non-const variable. See kTooBig for more details. 291 size_t kAlsoTooBig = kTooBig - 1024; 292 293 a = malloc(kAlsoTooBig); 294 EXPECT_EQ(NULL, a); 295 #endif 296 } 297 298 int main(int argc, char** argv) { 299 // If you run without args, we run the non-death parts of the test. 300 // Otherwise, argv[1] should be a number saying which death-test 301 // to run. We will output a regexp we expect the death-message 302 // to include, and then run the given death test (which hopefully 303 // will produce that error message). If argv[1] > the number of 304 // death tests, we will run only the non-death parts. One way to 305 // tell when you are done with all tests is when no 'expected 306 // regexp' message is printed for a given argv[1]. 307 if (argc < 2) { 308 test_to_run = -1; // will never match 309 } else { 310 test_to_run = atoi(argv[1]); 311 } 312 return RUN_ALL_TESTS(); 313 } 314