]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/alloc.cpp
Security-57740.60.18.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / alloc.cpp
1 /*
2 * Copyright (c) 2000-2004,2011,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 // cssmalloc - memory allocation in the CDSA world.
27 //
28 // Don't eat heavily before inspecting this code.
29 //
30 #define __STDC_WANT_LIB_EXT1__ 1
31 #include <string.h>
32
33 #include <security_utilities/alloc.h>
34 #include <security_utilities/memutils.h>
35 #include <security_utilities/globalizer.h>
36 #include <stdlib.h>
37 #include <errno.h>
38
39 using LowLevelMemoryUtilities::alignof_template;
40 using LowLevelMemoryUtilities::increment;
41 using LowLevelMemoryUtilities::alignUp;
42
43 extern "C" size_t malloc_size(void *);
44
45
46 //
47 // Features of the Allocator root class
48 //
49 bool Allocator::operator == (const Allocator &alloc) const throw()
50 {
51 return this == &alloc;
52 }
53
54 Allocator::~Allocator()
55 {
56 }
57
58
59 //
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.
64 //
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);
69 };
70
71 struct SensitiveAllocator : public DefaultAllocator {
72 void free(void *addr) throw();
73 void *realloc(void *addr, size_t size) throw(std::bad_alloc);
74 };
75
76 struct DefaultAllocators {
77 DefaultAllocator standard;
78 SensitiveAllocator sensitive;
79 };
80
81 static ModuleNexus<DefaultAllocators> defaultAllocators;
82
83
84 Allocator &Allocator::standard(UInt32 request)
85 {
86 switch (request) {
87 case normal:
88 return defaultAllocators().standard;
89 case sensitive:
90 return defaultAllocators().sensitive;
91 default:
92 UnixError::throwMe(ENOMEM);
93 }
94 }
95
96 void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc)
97 {
98 if (void *result = ::malloc(size))
99 return result;
100 throw std::bad_alloc();
101 }
102
103 void DefaultAllocator::free(void *addr) throw()
104 {
105 ::free(addr);
106 }
107
108 void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc)
109 {
110 if (void *result = ::realloc(addr, newSize))
111 return result;
112 throw std::bad_alloc();
113 }
114
115 void SensitiveAllocator::free(void *addr) throw()
116 {
117 memset(addr, 0, malloc_size(addr));
118 DefaultAllocator::free(addr);
119 }
120
121 void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc)
122 {
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);
127 }
128
129
130 //
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.
136 //
137 void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc)
138 {
139 if (alloc == NULL)
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;
145 return addr;
146 }
147
148 void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw()
149 {
150 alloc->free(addr); // as per C++ std, called (only) if construction fails
151 }
152
153 void CssmHeap::operator delete (void *addr, size_t size) throw()
154 {
155 void *end = increment(addr, alignUp(size, alignof_template<Allocator *>()));
156 (*(Allocator **)end)->free(addr);
157 }
158
159
160 //
161 // CssmVector
162 //