1// Copyright (c) 2005, 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: Michael Chastain 32// 33// This is a unit test for large allocations in malloc and friends. 34// "Large" means "so large that they overflow the address space". 35// For 32 bits, this means allocations near 2^32 bytes and 2^31 bytes. 36// For 64 bits, this means allocations near 2^64 bytes and 2^63 bytes. 37 38#include <stddef.h> // for size_t, NULL 39#include <stdlib.h> // for malloc, free, realloc 40#include <stdio.h> 41#include <set> // for set, etc 42 43#include "base/logging.h" // for operator<<, CHECK, etc 44 45using std::set; 46 47// Alloc a size that should always fail. 48 49void TryAllocExpectFail(size_t size) { 50 void* p1 = malloc(size); 51 CHECK(p1 == NULL); 52 53 void* p2 = malloc(1); 54 CHECK(p2 != NULL); 55 56 void* p3 = realloc(p2, size); 57 CHECK(p3 == NULL); 58 59 free(p2); 60} 61 62// Alloc a size that might work and might fail. 63// If it does work, touch some pages. 64 65void TryAllocMightFail(size_t size) { 66 unsigned char* p = static_cast<unsigned char*>(malloc(size)); 67 if ( p != NULL ) { 68 unsigned char volatile* vp = p; // prevent optimizations 69 static const size_t kPoints = 1024; 70 71 for ( size_t i = 0; i < kPoints; ++i ) { 72 vp[i * (size / kPoints)] = static_cast<unsigned char>(i); 73 } 74 75 for ( size_t i = 0; i < kPoints; ++i ) { 76 CHECK(vp[i * (size / kPoints)] == static_cast<unsigned char>(i)); 77 } 78 79 vp[size-1] = 'M'; 80 CHECK(vp[size-1] == 'M'); 81 } 82 83 free(p); 84} 85 86int main (int argc, char** argv) { 87 // Allocate some 0-byte objects. They better be unique. 88 // 0 bytes is not large but it exercises some paths related to 89 // large-allocation code. 90 { 91 static const int kZeroTimes = 1024; 92 printf("Test malloc(0) x %d\n", kZeroTimes); 93 set<char*> p_set; 94 for ( int i = 0; i < kZeroTimes; ++i ) { 95 char* p = new char; 96 CHECK(p != NULL); 97 CHECK(p_set.find(p) == p_set.end()); 98 p_set.insert(p_set.end(), p); 99 } 100 // Just leak the memory. 101 } 102 103 // Grab some memory so that some later allocations are guaranteed to fail. 104 printf("Test small malloc\n"); 105 void* p_small = malloc(4*1048576); 106 CHECK(p_small != NULL); 107 108 // Test sizes up near the maximum size_t. 109 // These allocations test the wrap-around code. 110 printf("Test malloc(0 - N)\n"); 111 const size_t zero = 0; 112 static const size_t kMinusNTimes = 16384; 113 for ( size_t i = 1; i < kMinusNTimes; ++i ) { 114 TryAllocExpectFail(zero - i); 115 } 116 117 // Test sizes a bit smaller. 118 // The small malloc above guarantees that all these return NULL. 119 printf("Test malloc(0 - 1048576 - N)\n"); 120 static const size_t kMinusMBMinusNTimes = 16384; 121 for ( size_t i = 0; i < kMinusMBMinusNTimes; ++i) { 122 TryAllocExpectFail(zero - 1048576 - i); 123 } 124 125 // Test sizes at half of size_t. 126 // These might or might not fail to allocate. 127 printf("Test malloc(max/2 +- N)\n"); 128 static const size_t kHalfPlusMinusTimes = 64; 129 const size_t half = (zero - 2) / 2 + 1; 130 for ( size_t i = 0; i < kHalfPlusMinusTimes; ++i) { 131 TryAllocMightFail(half - i); 132 TryAllocMightFail(half + i); 133 } 134 135 printf("PASS\n"); 136 return 0; 137} 138