]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/alloc.h
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / alloc.h
1 /*
2 * Copyright (c) 2000-2004,2011-2012,2014 Apple 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 // alloc - abstract malloc-like allocator abstraction
27 //
28 #ifndef _H_ALLOC
29 #define _H_ALLOC
30
31 #include <security_utilities/utilities.h>
32 #include <cstring>
33
34 namespace Security
35 {
36
37
38 //
39 // An abstract allocator superclass, based on the simple malloc/realloc/free paradigm
40 // that CDSA loves so much. If you have an allocation strategy and want objects
41 // to be allocated through it, inherit from this.
42 //
43 class Allocator {
44 public:
45 virtual ~Allocator();
46 virtual void *malloc(size_t) throw(std::bad_alloc) = 0;
47 virtual void free(void *) throw() = 0;
48 virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0;
49
50 //
51 // Template versions for added expressiveness.
52 // Note that the integers are element counts, not byte sizes.
53 //
54 template <class T> T *alloc() throw(std::bad_alloc)
55 { return reinterpret_cast<T *>(malloc(sizeof(T))); }
56
57 template <class T> T *alloc(UInt32 count) throw(std::bad_alloc)
58 {
59 size_t bytes = 0;
60 if (__builtin_mul_overflow(sizeof(T), count, &bytes)) {
61 throw std::bad_alloc();
62 }
63 return reinterpret_cast<T *>(malloc(bytes));
64
65 }
66
67 template <class T> T *alloc(T *old, UInt32 count) throw(std::bad_alloc)
68 {
69 size_t bytes = 0;
70 if (__builtin_mul_overflow(sizeof(T), count, &bytes)) {
71 throw std::bad_alloc();
72 }
73 return reinterpret_cast<T *>(realloc(old, bytes));
74 }
75
76
77 //
78 // Happier malloc/realloc for any type. Note that these still have
79 // the original (byte-sized) argument profile.
80 //
81 template <class T> T *malloc(size_t size) throw(std::bad_alloc)
82 { return reinterpret_cast<T *>(malloc(size)); }
83
84 template <class T> T *realloc(void *addr, size_t size) throw(std::bad_alloc)
85 { return reinterpret_cast<T *>(realloc(addr, size)); }
86
87 // All right, if you *really* have to have calloc...
88 void *calloc(size_t size, size_t count) throw(std::bad_alloc)
89 {
90 size_t bytes = 0;
91 if(__builtin_mul_overflow(size, count, &bytes)) {
92 // Multiplication overflowed.
93 throw std::bad_alloc();
94 }
95 void *addr = malloc(bytes);
96 memset(addr, 0, bytes);
97 return addr;
98 }
99
100 // compare Allocators for identity
101 virtual bool operator == (const Allocator &alloc) const throw();
102
103 public:
104 // allocator chooser options
105 enum {
106 normal = 0x0000,
107 sensitive = 0x0001
108 };
109
110 static Allocator &standard(UInt32 request = normal);
111 };
112
113
114 //
115 // You'd think that this is operator delete(const T *, Allocator &), but you'd
116 // be wrong. Specialized operator delete is only called during constructor cleanup.
117 // Use this to cleanly destroy things.
118 //
119 template <class T>
120 inline void destroy(T *obj, Allocator &alloc) throw()
121 {
122 obj->~T();
123 alloc.free(obj);
124 }
125
126 // untyped (release memory only, no destructor call)
127 inline void destroy(void *obj, Allocator &alloc) throw()
128 {
129 alloc.free(obj);
130 }
131
132
133 //
134 // A mixin class to automagically manage your allocator.
135 // To allow allocation (of your object) from any instance of Allocator,
136 // inherit from CssmHeap. Your users can then create heap instances of your thing by
137 // new (an-allocator) YourClass(...)
138 // or (still)
139 // new YourClass(...)
140 // for the default allocation source. The beauty is that when someone does a
141 // delete pointer-to-your-instance
142 // then the magic fairies will find the allocator that created the object and ask it
143 // to free the memory (by calling its free() method).
144 // The price of all that glory is memory overhead - typically one pointer per object.
145 //
146 class CssmHeap {
147 public:
148 void *operator new (size_t size, Allocator *alloc = NULL) throw(std::bad_alloc);
149 void operator delete (void *addr, size_t size) throw();
150 void operator delete (void *addr, size_t size, Allocator *alloc) throw();
151 };
152
153
154 //
155 // Here is a version of auto_ptr that works with Allocators. It is designed
156 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
157 // argument, of course.
158 // Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
159 // You can't dereference it, naturally.
160 //
161 template <class T>
162 class CssmAutoPtr {
163 public:
164 Allocator &allocator;
165
166 CssmAutoPtr(Allocator &alloc = Allocator::standard())
167 : allocator(alloc), mine(NULL) { }
168 CssmAutoPtr(Allocator &alloc, T *p)
169 : allocator(alloc), mine(p) { }
170 CssmAutoPtr(T *p)
171 : allocator(Allocator::standard()), mine(p) { }
172 template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
173 : allocator(src.allocator), mine(src.release()) { }
174 template <class T1> CssmAutoPtr(Allocator &alloc, CssmAutoPtr<T1> &src)
175 : allocator(alloc), mine(src.release()) { assert(allocator == src.allocator); }
176
177 ~CssmAutoPtr() { allocator.free(mine); }
178
179 T *get() const throw() { return mine; }
180 T *release() { T *result = mine; mine = NULL; return result; }
181 void reset() { allocator.free(mine); mine = NULL; }
182
183 operator T * () const { return mine; }
184 T *operator -> () const { return mine; }
185 T &operator * () const { assert(mine); return *mine; }
186
187 private:
188 T *mine;
189 };
190
191 // specialization for void (i.e. void *), omitting the troublesome dereferencing ops.
192 template <>
193 class CssmAutoPtr<void> {
194 public:
195 Allocator &allocator;
196
197 CssmAutoPtr(Allocator &alloc) : allocator(alloc), mine(NULL) { }
198 CssmAutoPtr(Allocator &alloc, void *p) : allocator(alloc), mine(p) { }
199 template <class T1> CssmAutoPtr(CssmAutoPtr<T1> &src)
200 : allocator(src.allocator), mine(src.release()) { }
201 template <class T1> CssmAutoPtr(Allocator &alloc, CssmAutoPtr<T1> &src)
202 : allocator(alloc), mine(src.release()) { assert(allocator == src.allocator); }
203
204 ~CssmAutoPtr() { destroy(mine, allocator); }
205
206 void *get() throw() { return mine; }
207 void *release() { void *result = mine; mine = NULL; return result; }
208 void reset() { allocator.free(mine); mine = NULL; }
209
210 private:
211 void *mine;
212 };
213
214
215 //
216 // Convenience forms of CssmAutoPtr that automatically make their (initial) object.
217 //
218 template <class T>
219 class CssmNewAutoPtr : public CssmAutoPtr<T> {
220 public:
221 CssmNewAutoPtr(Allocator &alloc = Allocator::standard())
222 : CssmAutoPtr<T>(alloc, new(alloc) T) { }
223
224 template <class A1>
225 CssmNewAutoPtr(Allocator &alloc, A1 &arg1) : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
226 template <class A1>
227 CssmNewAutoPtr(Allocator &alloc, const A1 &arg1)
228 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1)) { }
229
230 template <class A1, class A2>
231 CssmNewAutoPtr(Allocator &alloc, A1 &arg1, A2 &arg2)
232 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
233 template <class A1, class A2>
234 CssmNewAutoPtr(Allocator &alloc, const A1 &arg1, A2 &arg2)
235 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
236 template <class A1, class A2>
237 CssmNewAutoPtr(Allocator &alloc, A1 &arg1, const A2 &arg2)
238 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
239 template <class A1, class A2>
240 CssmNewAutoPtr(Allocator &alloc, const A1 &arg1, const A2 &arg2)
241 : CssmAutoPtr<T>(alloc, new(alloc) T(arg1, arg2)) { }
242 };
243
244
245 } // end namespace Security
246
247
248 //
249 // Global C++ allocation hooks to use Allocators (global namespace)
250 //
251 inline void *operator new (size_t size, Allocator &allocator) throw (std::bad_alloc)
252 { return allocator.malloc(size); }
253
254 inline void *operator new[] (size_t size, Allocator &allocator) throw (std::bad_alloc)
255 { return allocator.malloc(size); }
256
257
258 #endif //_H_ALLOC