2  * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  26 // cssmalloc - memory allocation in the CDSA world. 
  28 // Don't eat heavily before inspecting this code. 
  30 #define __STDC_WANT_LIB_EXT1__ 1 
  33 #include <security_utilities/alloc.h> 
  34 #include <security_utilities/memutils.h> 
  35 #include <security_utilities/globalizer.h> 
  39 using LowLevelMemoryUtilities::alignof_template
; 
  40 using LowLevelMemoryUtilities::increment
; 
  41 using LowLevelMemoryUtilities::alignUp
; 
  43 extern "C" size_t malloc_size(void *); 
  47 // Features of the Allocator root class 
  49 bool Allocator::operator == (const Allocator 
&alloc
) const throw() 
  51         return this == &alloc
; 
  54 Allocator::~Allocator() 
  60 // Standard Allocator variants. 
  61 // Note that all calls to Allocator::standard(xxx) with the same xxx argument 
  62 // must produce compatible allocators (i.e. they must be work on a common memory 
  63 // pool). This is trivially achieved here by using singletons. 
  65 struct DefaultAllocator 
: public Allocator 
{ 
  66         void *malloc(size_t size
) throw(std::bad_alloc
); 
  67         void free(void *addr
) throw(); 
  68         void *realloc(void *addr
, size_t size
) throw(std::bad_alloc
); 
  71 struct SensitiveAllocator 
: public DefaultAllocator 
{ 
  72     void free(void *addr
) throw(); 
  73     void *realloc(void *addr
, size_t size
) throw(std::bad_alloc
); 
  76 struct DefaultAllocators 
{ 
  77     DefaultAllocator standard
; 
  78     SensitiveAllocator sensitive
; 
  81 static ModuleNexus
<DefaultAllocators
> defaultAllocators
; 
  84 Allocator 
&Allocator::standard(UInt32 request
) 
  88         return defaultAllocators().standard
; 
  90         return defaultAllocators().sensitive
; 
  92         UnixError::throwMe(ENOMEM
); 
  96 void *DefaultAllocator::malloc(size_t size
) throw(std::bad_alloc
) 
  98         if (void *result 
= ::malloc(size
)) 
 100         throw std::bad_alloc(); 
 103 void DefaultAllocator::free(void *addr
) throw() 
 108 void *DefaultAllocator::realloc(void *addr
, size_t newSize
) throw(std::bad_alloc
) 
 110         if (void *result 
= ::realloc(addr
, newSize
)) 
 112         throw std::bad_alloc(); 
 115 void SensitiveAllocator::free(void *addr
) throw() 
 117     memset(addr
, 0, malloc_size(addr
)); 
 118     DefaultAllocator::free(addr
); 
 121 void *SensitiveAllocator::realloc(void *addr
, size_t newSize
) throw(std::bad_alloc
) 
 123     size_t oldSize 
= malloc_size(addr
); 
 124     if (newSize 
< oldSize
) 
 125         memset(increment(addr
, newSize
), 0, oldSize 
- newSize
); 
 126     return DefaultAllocator::realloc(addr
, newSize
); 
 131 // Memory allocators for CssmHeap objects. 
 132 // This implementation stores a pointer to the allocator used into memory 
 133 // *after* the object's proper storage block. This allows the usual free() 
 134 // functions to safely free our (hidden) pointer without knowing about it. 
 135 // An allocator argument of NULL is interpreted as the standard allocator. 
 137 void *CssmHeap::operator new (size_t size
, Allocator 
*alloc
) throw(std::bad_alloc
) 
 140                 alloc 
= &Allocator::standard(); 
 141         size 
= alignUp(size
, alignof_template
<Allocator 
*>()); 
 142         size_t totalSize 
= size 
+ sizeof(Allocator 
*); 
 143         void *addr 
= alloc
->malloc(totalSize
); 
 144         *(Allocator 
**)increment(addr
, size
) = alloc
; 
 148 void CssmHeap::operator delete (void *addr
, size_t size
, Allocator 
*alloc
) throw() 
 150         alloc
->free(addr
);      // as per C++ std, called (only) if construction fails 
 153 void CssmHeap::operator delete (void *addr
, size_t size
) throw() 
 155         void *end 
= increment(addr
, alignUp(size
, alignof_template
<Allocator 
*>())); 
 156         (*(Allocator 
**)end
)->free(addr
);