X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_utilities/lib/alloc.cpp diff --git a/Security/libsecurity_utilities/lib/alloc.cpp b/Security/libsecurity_utilities/lib/alloc.cpp new file mode 100644 index 00000000..61992434 --- /dev/null +++ b/Security/libsecurity_utilities/lib/alloc.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2000-2004,2011,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// cssmalloc - memory allocation in the CDSA world. +// +// Don't eat heavily before inspecting this code. +// +#include +#include +#include +#include +#include + +using LowLevelMemoryUtilities::alignof; +using LowLevelMemoryUtilities::increment; +using LowLevelMemoryUtilities::alignUp; + +extern "C" size_t malloc_size(void *); + + +// +// Features of the Allocator root class +// +bool Allocator::operator == (const Allocator &alloc) const throw() +{ + return this == &alloc; +} + +Allocator::~Allocator() +{ +} + + +// +// Standard Allocator variants. +// Note that all calls to Allocator::standard(xxx) with the same xxx argument +// must produce compatible allocators (i.e. they must be work on a common memory +// pool). This is trivially achieved here by using singletons. +// +struct DefaultAllocator : public Allocator { + void *malloc(size_t size) throw(std::bad_alloc); + void free(void *addr) throw(); + void *realloc(void *addr, size_t size) throw(std::bad_alloc); +}; + +struct SensitiveAllocator : public DefaultAllocator { + void free(void *addr) throw(); + void *realloc(void *addr, size_t size) throw(std::bad_alloc); +}; + +struct DefaultAllocators { + DefaultAllocator standard; + SensitiveAllocator sensitive; +}; + +static ModuleNexus defaultAllocators; + + +Allocator &Allocator::standard(UInt32 request) +{ + switch (request) { + case normal: + return defaultAllocators().standard; + case sensitive: + return defaultAllocators().sensitive; + default: + UnixError::throwMe(ENOMEM); + } +} + +void *DefaultAllocator::malloc(size_t size) throw(std::bad_alloc) +{ + if (void *result = ::malloc(size)) + return result; + throw std::bad_alloc(); +} + +void DefaultAllocator::free(void *addr) throw() +{ + ::free(addr); +} + +void *DefaultAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) +{ + if (void *result = ::realloc(addr, newSize)) + return result; + throw std::bad_alloc(); +} + +void SensitiveAllocator::free(void *addr) throw() +{ + memset(addr, 0, malloc_size(addr)); + DefaultAllocator::free(addr); +} + +void *SensitiveAllocator::realloc(void *addr, size_t newSize) throw(std::bad_alloc) +{ + size_t oldSize = malloc_size(addr); + if (newSize < oldSize) + memset(increment(addr, newSize), 0, oldSize - newSize); + return DefaultAllocator::realloc(addr, newSize); +} + + +// +// Memory allocators for CssmHeap objects. +// This implementation stores a pointer to the allocator used into memory +// *after* the object's proper storage block. This allows the usual free() +// functions to safely free our (hidden) pointer without knowing about it. +// An allocator argument of NULL is interpreted as the standard allocator. +// +void *CssmHeap::operator new (size_t size, Allocator *alloc) throw(std::bad_alloc) +{ + if (alloc == NULL) + alloc = &Allocator::standard(); + size = alignUp(size, alignof()); + size_t totalSize = size + sizeof(Allocator *); + void *addr = alloc->malloc(totalSize); + *(Allocator **)increment(addr, size) = alloc; + return addr; +} + +void CssmHeap::operator delete (void *addr, size_t size, Allocator *alloc) throw() +{ + alloc->free(addr); // as per C++ std, called (only) if construction fails +} + +void CssmHeap::operator delete (void *addr, size_t size) throw() +{ + void *end = increment(addr, alignUp(size, alignof())); + (*(Allocator **)end)->free(addr); +} + + +// +// CssmVector +//