]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/alloc.cpp
Security-57337.20.44.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 #include <security_utilities/alloc.h>
31 #include <security_utilities/memutils.h>
32 #include <security_utilities/globalizer.h>
33 #include <stdlib.h>
34 #include <errno.h>
35
36 using LowLevelMemoryUtilities::alignof;
37 using LowLevelMemoryUtilities::increment;
38 using LowLevelMemoryUtilities::alignUp;
39
40 extern "C" size_t malloc_size(void *);
41
42
43 //
44 // Features of the Allocator root class
45 //
46 bool Allocator::operator == (const Allocator &alloc) const throw()
47 {
48 return this == &alloc;
49 }
50
51 Allocator::~Allocator()
52 {
53 }
54
55
56 //
57 // Standard Allocator variants.
58 // Note that all calls to Allocator::standard(xxx) with the same xxx argument
59 // must produce compatible allocators (i.e. they must be work on a common memory
60 // pool). This is trivially achieved here by using singletons.
61 //
62 struct DefaultAllocator : public Allocator {
63 void *malloc(size_t size) throw(std::bad_alloc);
64 void free(void *addr) throw();
65 void *realloc(void *addr, size_t size) throw(std::bad_alloc);
66 };
67
68 struct SensitiveAllocator : public DefaultAllocator {
69 void free(void *addr) throw();
70 void *realloc(void *addr, size_t size) throw(std::bad_alloc);
71 };
72
73 struct DefaultAllocators {
74 DefaultAllocator standard;
75 SensitiveAllocator sensitive;
76 };
77
78 static ModuleNexus<DefaultAllocators> defaultAllocators;
79
80
81 Allocator &Allocator::standard(UInt32 request)
82 {
83 switch (request) {
84 case normal:
85 return defaultAllocators().standard;
86 case sensitive:
87 return defaultAllocators().sensitive;
88 default:
89 UnixError::throwMe(ENOMEM);
90 }
91 }
92
93 void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc)
94 {
95 if (void *result = ::malloc(size))
96 return result;
97 throw std::bad_alloc();
98 }
99
100 void DefaultAllocator::free(void *addr) throw()
101 {
102 ::free(addr);
103 }
104
105 void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc)
106 {
107 if (void *result = ::realloc(addr, newSize))
108 return result;
109 throw std::bad_alloc();
110 }
111
112 void SensitiveAllocator::free(void *addr) throw()
113 {
114 memset(addr, 0, malloc_size(addr));
115 DefaultAllocator::free(addr);
116 }
117
118 void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc)
119 {
120 size_t oldSize = malloc_size(addr);
121 if (newSize < oldSize)
122 memset(increment(addr, newSize), 0, oldSize - newSize);
123 return DefaultAllocator::realloc(addr, newSize);
124 }
125
126
127 //
128 // Memory allocators for CssmHeap objects.
129 // This implementation stores a pointer to the allocator used into memory
130 // *after* the object's proper storage block. This allows the usual free()
131 // functions to safely free our (hidden) pointer without knowing about it.
132 // An allocator argument of NULL is interpreted as the standard allocator.
133 //
134 void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc)
135 {
136 if (alloc == NULL)
137 alloc = &Allocator::standard();
138 size = alignUp(size, alignof<Allocator *>());
139 size_t totalSize = size + sizeof(Allocator *);
140 void *addr = alloc->malloc(totalSize);
141 *(Allocator **)increment(addr, size) = alloc;
142 return addr;
143 }
144
145 void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw()
146 {
147 alloc->free(addr); // as per C++ std, called (only) if construction fails
148 }
149
150 void CssmHeap::operator delete (void *addr, size_t size) throw()
151 {
152 void *end = increment(addr, alignUp(size, alignof<Allocator *>()));
153 (*(Allocator **)end)->free(addr);
154 }
155
156
157 //
158 // CssmVector
159 //