2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 // cssmalloc - memory allocation in the CDSA world.
22 // Don't eat heavily before inspecting this code.
24 #include <Security/cssmalloc.h>
25 #include <Security/memutils.h>
26 #include <Security/globalizer.h>
27 #include <Security/trackingallocator.h>
31 using LowLevelMemoryUtilities::alignof;
32 using LowLevelMemoryUtilities::increment
;
33 using LowLevelMemoryUtilities::alignUp
;
35 extern "C" size_t malloc_size(void *);
39 // Features of the CssmAllocator root class
41 bool CssmAllocator::operator == (const CssmAllocator
&alloc
) const throw()
43 return this == &alloc
;
46 CssmAllocator::~CssmAllocator()
52 // Standard CssmAllocator variants.
53 // Note that all calls to CssmAllocator::standard(xxx) with the same xxx argument
54 // must produce compatible allocators (i.e. they must be work on a common memory
55 // pool). This is trivially achieved here by using singletons.
57 struct DefaultCssmAllocator
: public CssmAllocator
{
58 void *malloc(size_t size
) throw(std::bad_alloc
);
59 void free(void *addr
) throw();
60 void *realloc(void *addr
, size_t size
) throw(std::bad_alloc
);
63 struct SensitiveCssmAllocator
: public DefaultCssmAllocator
{
64 void free(void *addr
) throw();
65 void *realloc(void *addr
, size_t size
) throw(std::bad_alloc
);
68 struct DefaultAllocators
{
69 DefaultCssmAllocator standard
;
70 SensitiveCssmAllocator sensitive
;
73 static ModuleNexus
<DefaultAllocators
> defaultAllocators
;
76 CssmAllocator
&CssmAllocator::standard(uint32 request
)
80 return defaultAllocators().standard
;
82 return defaultAllocators().sensitive
;
84 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR
);
88 void *DefaultCssmAllocator::malloc(size_t size
) throw(std::bad_alloc
)
90 if (void *result
= ::malloc(size
))
92 throw std::bad_alloc();
95 void DefaultCssmAllocator::free(void *addr
) throw()
100 void *DefaultCssmAllocator::realloc(void *addr
, size_t newSize
) throw(std::bad_alloc
)
102 if (void *result
= ::realloc(addr
, newSize
))
104 throw std::bad_alloc();
107 void SensitiveCssmAllocator::free(void *addr
) throw()
109 memset(addr
, 0, malloc_size(addr
));
110 DefaultCssmAllocator::free(addr
);
113 void *SensitiveCssmAllocator::realloc(void *addr
, size_t newSize
) throw(std::bad_alloc
)
115 size_t oldSize
= malloc_size(addr
);
116 if (newSize
< oldSize
)
117 memset(increment(addr
, newSize
), 0, oldSize
- newSize
);
118 return DefaultCssmAllocator::realloc(addr
, newSize
);
121 TrackingAllocator::~TrackingAllocator()
123 AllocSet::iterator first
= mAllocSet
.begin(), last
= mAllocSet
.end();
124 for (; first
!= last
; ++first
)
125 mAllocator
.free(*first
);
129 // CssmMemoryFunctionsAllocators
131 void *CssmMemoryFunctionsAllocator::malloc(size_t size
) throw(std::bad_alloc
)
132 { return functions
.malloc(size
); }
134 void CssmMemoryFunctionsAllocator::free(void *addr
) throw()
135 { return functions
.free(addr
); }
137 void *CssmMemoryFunctionsAllocator::realloc(void *addr
, size_t size
) throw(std::bad_alloc
)
138 { return functions
.realloc(addr
, size
); }
142 // CssmAllocatorMemoryFunctions
144 CssmAllocatorMemoryFunctions::CssmAllocatorMemoryFunctions(CssmAllocator
&alloc
)
147 malloc_func
= relayMalloc
;
148 free_func
= relayFree
;
149 realloc_func
= relayRealloc
;
150 calloc_func
= relayCalloc
;
153 void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size
, void *ref
) throw(std::bad_alloc
)
154 { return allocator(ref
).malloc(size
); }
156 void CssmAllocatorMemoryFunctions::relayFree(void *mem
, void *ref
) throw()
157 { allocator(ref
).free(mem
); }
159 void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem
, size_t size
, void *ref
) throw(std::bad_alloc
)
160 { return allocator(ref
).realloc(mem
, size
); }
162 void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count
, size_t size
, void *ref
) throw(std::bad_alloc
)
164 // CssmAllocator doesn't have a calloc() method
165 void *mem
= allocator(ref
).malloc(size
* count
);
166 memset(mem
, 0, size
* count
);
172 // Memory allocators for CssmHeap objects.
173 // This implementation stores a pointer to the allocator used into memory
174 // *after* the object's proper storage block. This allows the usual free()
175 // functions to safely free our (hidden) pointer without knowing about it.
176 // An allocator argument of NULL is interpreted as the standard allocator.
178 void *CssmHeap::operator new (size_t size
, CssmAllocator
*alloc
) throw(std::bad_alloc
)
181 alloc
= &CssmAllocator::standard();
182 size
= alignUp(size
, alignof<CssmAllocator
*>());
183 size_t totalSize
= size
+ sizeof(CssmAllocator
*);
184 void *addr
= alloc
->malloc(totalSize
);
185 *(CssmAllocator
**)increment(addr
, size
) = alloc
;
189 void CssmHeap::operator delete (void *addr
, size_t size
, CssmAllocator
*alloc
) throw()
191 alloc
->free(addr
); // as per C++ std, called (only) if construction fails
194 void CssmHeap::operator delete (void *addr
, size_t size
) throw()
196 void *end
= increment(addr
, alignUp(size
, alignof<CssmAllocator
*>()));
197 (*(CssmAllocator
**)end
)->free(addr
);