]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_utilities/lib/alloc.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / alloc.cpp
CommitLineData
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 39using LowLevelMemoryUtilities::alignof_template;
b1ab9ed8
A
40using LowLevelMemoryUtilities::increment;
41using LowLevelMemoryUtilities::alignUp;
42
43extern "C" size_t malloc_size(void *);
44
45
46//
47// Features of the Allocator root class
48//
d64be36e 49bool Allocator::operator == (const Allocator &alloc) const _NOEXCEPT
b1ab9ed8
A
50{
51 return this == &alloc;
52}
53
54Allocator::~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//
65struct 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
71struct SensitiveAllocator : public DefaultAllocator {
d64be36e
A
72 void free(void *addr) _NOEXCEPT;
73 void *realloc(void *addr, size_t size);
b1ab9ed8
A
74};
75
76struct DefaultAllocators {
77 DefaultAllocator standard;
78 SensitiveAllocator sensitive;
79};
80
81static ModuleNexus<DefaultAllocators> defaultAllocators;
82
83
84Allocator &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 96void *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 103void DefaultAllocator::free(void *addr) _NOEXCEPT
b1ab9ed8
A
104{
105 ::free(addr);
106}
107
d64be36e 108void *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 115void 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 122void *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 138void *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 153void 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 158void 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//