]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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 | // | |
6b200bc3 A |
30 | #define __STDC_WANT_LIB_EXT1__ 1 |
31 | #include <string.h> | |
32 | ||
b1ab9ed8 A |
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 | ||
6b200bc3 | 39 | using LowLevelMemoryUtilities::alignof_template; |
b1ab9ed8 A |
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 | // | |
d64be36e | 49 | bool Allocator::operator == (const Allocator &alloc) const _NOEXCEPT |
b1ab9ed8 A |
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 { | |
d64be36e A |
66 | void *malloc(size_t size); |
67 | void free(void *addr) _NOEXCEPT; | |
68 | void *realloc(void *addr, size_t size); | |
b1ab9ed8 A |
69 | }; |
70 | ||
71 | struct SensitiveAllocator : public DefaultAllocator { | |
d64be36e A |
72 | void free(void *addr) _NOEXCEPT; |
73 | void *realloc(void *addr, size_t size); | |
b1ab9ed8 A |
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 | ||
d64be36e | 96 | void *DefaultAllocator::malloc(size_t size) |
b1ab9ed8 A |
97 | { |
98 | if (void *result = ::malloc(size)) | |
99 | return result; | |
100 | throw std::bad_alloc(); | |
101 | } | |
102 | ||
d64be36e | 103 | void DefaultAllocator::free(void *addr) _NOEXCEPT |
b1ab9ed8 A |
104 | { |
105 | ::free(addr); | |
106 | } | |
107 | ||
d64be36e | 108 | void *DefaultAllocator::realloc(void *addr, size_t newSize) |
b1ab9ed8 A |
109 | { |
110 | if (void *result = ::realloc(addr, newSize)) | |
111 | return result; | |
112 | throw std::bad_alloc(); | |
113 | } | |
114 | ||
d64be36e | 115 | void SensitiveAllocator::free(void *addr) _NOEXCEPT |
b1ab9ed8 | 116 | { |
866f8763 A |
117 | size_t size = malloc_size(addr); |
118 | ::memset_s(addr, size, 0, size); | |
b1ab9ed8 A |
119 | DefaultAllocator::free(addr); |
120 | } | |
121 | ||
d64be36e | 122 | void *SensitiveAllocator::realloc(void *addr, size_t newSize) |
b1ab9ed8 A |
123 | { |
124 | size_t oldSize = malloc_size(addr); | |
125 | if (newSize < oldSize) | |
866f8763 | 126 | ::memset_s(increment(addr, newSize), oldSize - newSize, 0, oldSize - newSize); |
b1ab9ed8 A |
127 | return DefaultAllocator::realloc(addr, newSize); |
128 | } | |
129 | ||
130 | ||
131 | // | |
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. | |
137 | // | |
d64be36e | 138 | void *CssmHeap::operator new (size_t size, Allocator *alloc) |
b1ab9ed8 | 139 | { |
b54c578e A |
140 | if (size > SIZE_T_MAX / 2) { |
141 | throw std::bad_alloc(); | |
142 | } | |
143 | if (alloc == NULL) { | |
b1ab9ed8 | 144 | alloc = &Allocator::standard(); |
b54c578e | 145 | } |
6b200bc3 | 146 | size = alignUp(size, alignof_template<Allocator *>()); |
b1ab9ed8 A |
147 | size_t totalSize = size + sizeof(Allocator *); |
148 | void *addr = alloc->malloc(totalSize); | |
149 | *(Allocator **)increment(addr, size) = alloc; | |
150 | return addr; | |
151 | } | |
152 | ||
d64be36e | 153 | void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) _NOEXCEPT |
b1ab9ed8 A |
154 | { |
155 | alloc->free(addr); // as per C++ std, called (only) if construction fails | |
156 | } | |
157 | ||
d64be36e | 158 | void CssmHeap::operator delete (void *addr, size_t size) _NOEXCEPT |
b1ab9ed8 | 159 | { |
6b200bc3 | 160 | void *end = increment(addr, alignUp(size, alignof_template<Allocator *>())); |
b1ab9ed8 A |
161 | (*(Allocator **)end)->free(addr); |
162 | } | |
163 | ||
164 | ||
165 | // | |
166 | // CssmVector | |
167 | // |