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 #define __STDC_WANT_LIB_EXT1__ 1
33 #include <security_utilities/alloc.h>
34 #include <security_utilities/memutils.h>
35 #include <security_utilities/globalizer.h>
39 using LowLevelMemoryUtilities::alignof_template
;
40 using LowLevelMemoryUtilities::increment
;
41 using LowLevelMemoryUtilities::alignUp
;
43 extern "C" size_t malloc_size(void *);
47 // Features of the Allocator root class
49 bool Allocator::operator == (const Allocator
&alloc
) const _NOEXCEPT
51 return this == &alloc
;
54 Allocator::~Allocator()
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.
65 struct DefaultAllocator
: public Allocator
{
66 void *malloc(size_t size
);
67 void free(void *addr
) _NOEXCEPT
;
68 void *realloc(void *addr
, size_t size
);
71 struct SensitiveAllocator
: public DefaultAllocator
{
72 void free(void *addr
) _NOEXCEPT
;
73 void *realloc(void *addr
, size_t size
);
76 struct DefaultAllocators
{
77 DefaultAllocator standard
;
78 SensitiveAllocator sensitive
;
81 static ModuleNexus
<DefaultAllocators
> defaultAllocators
;
84 Allocator
&Allocator::standard(UInt32 request
)
88 return defaultAllocators().standard
;
90 return defaultAllocators().sensitive
;
92 UnixError::throwMe(ENOMEM
);
96 void *DefaultAllocator::malloc(size_t size
)
98 if (void *result
= ::malloc(size
))
100 throw std::bad_alloc();
103 void DefaultAllocator::free(void *addr
) _NOEXCEPT
108 void *DefaultAllocator::realloc(void *addr
, size_t newSize
)
110 if (void *result
= ::realloc(addr
, newSize
))
112 throw std::bad_alloc();
115 void SensitiveAllocator::free(void *addr
) _NOEXCEPT
117 size_t size
= malloc_size(addr
);
118 ::memset_s(addr
, size
, 0, size
);
119 DefaultAllocator::free(addr
);
122 void *SensitiveAllocator::realloc(void *addr
, size_t newSize
)
124 size_t oldSize
= malloc_size(addr
);
125 if (newSize
< oldSize
)
126 ::memset_s(increment(addr
, newSize
), oldSize
- newSize
, 0, oldSize
- newSize
);
127 return DefaultAllocator::realloc(addr
, newSize
);
132 // Memory allocators for CssmHeap objects.
133 // This implementation stores a pointer to the allocator used into memory
134 // *after* the object's proper storage block. This allows the usual free()
135 // functions to safely free our (hidden) pointer without knowing about it.
136 // An allocator argument of NULL is interpreted as the standard allocator.
138 void *CssmHeap::operator new (size_t size
, Allocator
*alloc
)
140 if (size
> SIZE_T_MAX
/ 2) {
141 throw std::bad_alloc();
144 alloc
= &Allocator::standard();
146 size
= alignUp(size
, alignof_template
<Allocator
*>());
147 size_t totalSize
= size
+ sizeof(Allocator
*);
148 void *addr
= alloc
->malloc(totalSize
);
149 *(Allocator
**)increment(addr
, size
) = alloc
;
153 void CssmHeap::operator delete (void *addr
, size_t size
, Allocator
*alloc
) _NOEXCEPT
155 alloc
->free(addr
); // as per C++ std, called (only) if construction fails
158 void CssmHeap::operator delete (void *addr
, size_t size
) _NOEXCEPT
160 void *end
= increment(addr
, alignUp(size
, alignof_template
<Allocator
*>()));
161 (*(Allocator
**)end
)->free(addr
);