]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmalloc.cpp
Security-179.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmalloc.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // cssmalloc - memory allocation in the CDSA world.
21 //
22 // Don't eat heavily before inspecting this code.
23 //
24 #include <Security/cssmalloc.h>
25 #include <Security/memutils.h>
26 #include <Security/globalizer.h>
27 #include <Security/trackingallocator.h>
28 #include <stdlib.h>
29 #include <errno.h>
30
31 using LowLevelMemoryUtilities::alignof;
32 using LowLevelMemoryUtilities::increment;
33 using LowLevelMemoryUtilities::alignUp;
34
35 extern "C" size_t malloc_size(void *);
36
37
38 //
39 // Features of the CssmAllocator root class
40 //
41 bool CssmAllocator::operator == (const CssmAllocator &alloc) const throw()
42 {
43 return this == &alloc;
44 }
45
46 CssmAllocator::~CssmAllocator()
47 {
48 }
49
50
51 //
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.
56 //
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);
61 };
62
63 struct SensitiveCssmAllocator : public DefaultCssmAllocator {
64 void free(void *addr) throw();
65 void *realloc(void *addr, size_t size) throw(std::bad_alloc);
66 };
67
68 struct DefaultAllocators {
69 DefaultCssmAllocator standard;
70 SensitiveCssmAllocator sensitive;
71 };
72
73 static ModuleNexus<DefaultAllocators> defaultAllocators;
74
75
76 CssmAllocator &CssmAllocator::standard(uint32 request)
77 {
78 switch (request) {
79 case normal:
80 return defaultAllocators().standard;
81 case sensitive:
82 return defaultAllocators().sensitive;
83 default:
84 CssmError::throwMe(CSSM_ERRCODE_MEMORY_ERROR);
85 }
86 }
87
88 void *DefaultCssmAllocator::malloc(size_t size) throw(std::bad_alloc)
89 {
90 if (void *result = ::malloc(size))
91 return result;
92 throw std::bad_alloc();
93 }
94
95 void DefaultCssmAllocator::free(void *addr) throw()
96 {
97 ::free(addr);
98 }
99
100 void *DefaultCssmAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc)
101 {
102 if (void *result = ::realloc(addr, newSize))
103 return result;
104 throw std::bad_alloc();
105 }
106
107 void SensitiveCssmAllocator::free(void *addr) throw()
108 {
109 memset(addr, 0, malloc_size(addr));
110 DefaultCssmAllocator::free(addr);
111 }
112
113 void *SensitiveCssmAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc)
114 {
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);
119 }
120
121 TrackingAllocator::~TrackingAllocator()
122 {
123 AllocSet::iterator first = mAllocSet.begin(), last = mAllocSet.end();
124 for (; first != last; ++first)
125 mAllocator.free(*first);
126 }
127
128 //
129 // CssmMemoryFunctionsAllocators
130 //
131 void *CssmMemoryFunctionsAllocator::malloc(size_t size) throw(std::bad_alloc)
132 { return functions.malloc(size); }
133
134 void CssmMemoryFunctionsAllocator::free(void *addr) throw()
135 { return functions.free(addr); }
136
137 void *CssmMemoryFunctionsAllocator::realloc(void *addr, size_t size) throw(std::bad_alloc)
138 { return functions.realloc(addr, size); }
139
140
141 //
142 // CssmAllocatorMemoryFunctions
143 //
144 CssmAllocatorMemoryFunctions::CssmAllocatorMemoryFunctions(CssmAllocator &alloc)
145 {
146 AllocRef = &alloc;
147 malloc_func = relayMalloc;
148 free_func = relayFree;
149 realloc_func = relayRealloc;
150 calloc_func = relayCalloc;
151 }
152
153 void *CssmAllocatorMemoryFunctions::relayMalloc(size_t size, void *ref) throw(std::bad_alloc)
154 { return allocator(ref).malloc(size); }
155
156 void CssmAllocatorMemoryFunctions::relayFree(void *mem, void *ref) throw()
157 { allocator(ref).free(mem); }
158
159 void *CssmAllocatorMemoryFunctions::relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc)
160 { return allocator(ref).realloc(mem, size); }
161
162 void *CssmAllocatorMemoryFunctions::relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc)
163 {
164 // CssmAllocator doesn't have a calloc() method
165 void *mem = allocator(ref).malloc(size * count);
166 memset(mem, 0, size * count);
167 return mem;
168 }
169
170
171 //
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.
177 //
178 void *CssmHeap::operator new (size_t size, CssmAllocator *alloc) throw(std::bad_alloc)
179 {
180 if (alloc == NULL)
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;
186 return addr;
187 }
188
189 void CssmHeap::operator delete (void *addr, size_t size, CssmAllocator *alloc) throw()
190 {
191 alloc->free(addr); // as per C++ std, called (only) if construction fails
192 }
193
194 void CssmHeap::operator delete (void *addr, size_t size) throw()
195 {
196 void *end = increment(addr, alignUp(size, alignof<CssmAllocator *>()));
197 (*(CssmAllocator **)end)->free(addr);
198 }
199
200
201 //
202 // CssmVector
203 //