2 * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // cssmalloc - memory allocation in the CDSA world.
28 // Don't eat heavily before inspecting this code.
30 #include <security_utilities/alloc.h>
31 #include <security_utilities/memutils.h>
32 #include <security_utilities/globalizer.h>
36 using LowLevelMemoryUtilities::alignof;
37 using LowLevelMemoryUtilities::increment
;
38 using LowLevelMemoryUtilities::alignUp
;
40 extern "C" size_t malloc_size(void *);
44 // Features of the Allocator root class
46 bool Allocator::operator == (const Allocator
&alloc
) const throw()
48 return this == &alloc
;
51 Allocator::~Allocator()
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.
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
);
68 struct SensitiveAllocator
: public DefaultAllocator
{
69 void free(void *addr
) throw();
70 void *realloc(void *addr
, size_t size
) throw(std::bad_alloc
);
73 struct DefaultAllocators
{
74 DefaultAllocator standard
;
75 SensitiveAllocator sensitive
;
78 static ModuleNexus
<DefaultAllocators
> defaultAllocators
;
81 Allocator
&Allocator::standard(UInt32 request
)
85 return defaultAllocators().standard
;
87 return defaultAllocators().sensitive
;
89 UnixError::throwMe(ENOMEM
);
93 void *DefaultAllocator::malloc(size_t size
) throw(std::bad_alloc
)
95 if (void *result
= ::malloc(size
))
97 throw std::bad_alloc();
100 void DefaultAllocator::free(void *addr
) throw()
105 void *DefaultAllocator::realloc(void *addr
, size_t newSize
) throw(std::bad_alloc
)
107 if (void *result
= ::realloc(addr
, newSize
))
109 throw std::bad_alloc();
112 void SensitiveAllocator::free(void *addr
) throw()
114 memset(addr
, 0, malloc_size(addr
));
115 DefaultAllocator::free(addr
);
118 void *SensitiveAllocator::realloc(void *addr
, size_t newSize
) throw(std::bad_alloc
)
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
);
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.
134 void *CssmHeap::operator new (size_t size
, Allocator
*alloc
) throw(std::bad_alloc
)
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
;
145 void CssmHeap::operator delete (void *addr
, size_t size
, Allocator
*alloc
) throw()
147 alloc
->free(addr
); // as per C++ std, called (only) if construction fails
150 void CssmHeap::operator delete (void *addr
, size_t size
) throw()
152 void *end
= increment(addr
, alignUp(size
, alignof<Allocator
*>()));
153 (*(Allocator
**)end
)->free(addr
);