1/* 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// cssmalloc - memory allocation in the CDSA world. 27// 28// Don't eat heavily before inspecting this code. 29// 30#include <security_utilities/alloc.h> 31#include <security_utilities/memutils.h> 32#include <security_utilities/globalizer.h> 33#include <stdlib.h> 34#include <errno.h> 35 36using LowLevelMemoryUtilities::alignof; 37using LowLevelMemoryUtilities::increment; 38using LowLevelMemoryUtilities::alignUp; 39 40extern "C" size_t malloc_size(void *); 41 42 43// 44// Features of the Allocator root class 45// 46bool Allocator::operator == (const Allocator &alloc) const throw() 47{ 48 return this == &alloc; 49} 50 51Allocator::~Allocator() 52{ 53} 54 55 56// 57// Standard Allocator variants. 58// Note that all calls to Allocator::standard(xxx) with the same xxx argument 59// must produce compatible allocators (i.e. they must be work on a common memory 60// pool). This is trivially achieved here by using singletons. 61// 62struct DefaultAllocator : public Allocator { 63 void *malloc(size_t size) throw(std::bad_alloc); 64 void free(void *addr) throw(); 65 void *realloc(void *addr, size_t size) throw(std::bad_alloc); 66}; 67 68struct SensitiveAllocator : public DefaultAllocator { 69 void free(void *addr) throw(); 70 void *realloc(void *addr, size_t size) throw(std::bad_alloc); 71}; 72 73struct DefaultAllocators { 74 DefaultAllocator standard; 75 SensitiveAllocator sensitive; 76}; 77 78static ModuleNexus<DefaultAllocators> defaultAllocators; 79 80 81Allocator &Allocator::standard(UInt32 request) 82{ 83 switch (request) { 84 case normal: 85 return defaultAllocators().standard; 86 case sensitive: 87 return defaultAllocators().sensitive; 88 default: 89 UnixError::throwMe(ENOMEM); 90 } 91} 92 93void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc) 94{ 95 if (void *result = ::malloc(size)) 96 return result; 97 throw std::bad_alloc(); 98} 99 100void DefaultAllocator::free(void *addr) throw() 101{ 102 ::free(addr); 103} 104 105void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) 106{ 107 if (void *result = ::realloc(addr, newSize)) 108 return result; 109 throw std::bad_alloc(); 110} 111 112void SensitiveAllocator::free(void *addr) throw() 113{ 114 memset(addr, 0, malloc_size(addr)); 115 DefaultAllocator::free(addr); 116} 117 118void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) 119{ 120 size_t oldSize = malloc_size(addr); 121 if (newSize < oldSize) 122 memset(increment(addr, newSize), 0, oldSize - newSize); 123 return DefaultAllocator::realloc(addr, newSize); 124} 125 126 127// 128// Memory allocators for CssmHeap objects. 129// This implementation stores a pointer to the allocator used into memory 130// *after* the object's proper storage block. This allows the usual free() 131// functions to safely free our (hidden) pointer without knowing about it. 132// An allocator argument of NULL is interpreted as the standard allocator. 133// 134void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc) 135{ 136 if (alloc == NULL) 137 alloc = &Allocator::standard(); 138 size = alignUp(size, alignof<Allocator *>()); 139 size_t totalSize = size + sizeof(Allocator *); 140 void *addr = alloc->malloc(totalSize); 141 *(Allocator **)increment(addr, size) = alloc; 142 return addr; 143} 144 145void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw() 146{ 147 alloc->free(addr); // as per C++ std, called (only) if construction fails 148} 149 150void CssmHeap::operator delete (void *addr, size_t size) throw() 151{ 152 void *end = increment(addr, alignUp(size, alignof<Allocator *>())); 153 (*(Allocator **)end)->free(addr); 154} 155 156 157// 158// CssmVector 159// 160