1 /*############################################################################ 2 # Copyright 2016-2017 Intel Corporation 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 ############################################################################*/ 16 17 /*! 18 * \file 19 * \brief Memory access implementation. 20 */ 21 22 #include "epid/common/src/memory.h" 23 24 #include <stdint.h> 25 #include <string.h> 26 27 /// Maximum size of the destination buffer 28 #ifndef RSIZE_MAX 29 #define RSIZE_MAX ((SIZE_MAX) >> 1) 30 #endif 31 32 #ifndef MIN 33 /// Evaluate to minimum of two values 34 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 35 #endif // MIN 36 37 /// Copies count of character from dest to src 38 /*! \note Implementation follows C11 memcpy_s but with checks always enabled 39 */ 40 int memcpy_S(void* dest, size_t destsz, void const* src, size_t count) { 41 size_t i; 42 if (!dest || destsz > RSIZE_MAX) return -1; 43 if (!src || count > RSIZE_MAX || count > destsz || 44 count > (dest > src ? ((uintptr_t)dest - (uintptr_t)src) 45 : ((uintptr_t)src - (uintptr_t)dest))) { 46 // zero out dest if error detected 47 memset(dest, 0, destsz); 48 return -1; 49 } 50 51 for (i = 0; i < count; i++) ((uint8_t*)dest)[i] = ((uint8_t*)src)[i]; 52 return 0; 53 } 54 55 void EpidZeroMemory(void* ptr, size_t size) { memset(ptr, 0, size); } 56 57 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 58 59 #if !defined(EPID_ALLOC_ALIGN) 60 /// Alignment constant for EpidAlloc, must be a power of two 61 #define EPID_ALLOC_ALIGN sizeof(size_t) 62 #endif // !defined(EPID_ALLOC_ALIGN) 63 64 #pragma pack(1) 65 /// Allocated memory block information 66 typedef struct EpidAllocHeader { 67 size_t length; ///< number of bytes memory block is allocated for 68 void* ptr; ///< pointer to whole memory block including EpidAllocHeader 69 } EpidAllocHeader; 70 #pragma pack() 71 72 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 73 74 void* EpidAlloc(size_t size) { 75 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 76 void* ptr = NULL; 77 if (size <= 0) return NULL; 78 // Allocate memory enough to store size bytes and EpidAllocHeader 79 ptr = calloc(1, size + EPID_ALLOC_ALIGN - 1 + sizeof(EpidAllocHeader)); 80 if (ptr) { 81 void* aligned_pointer = (void*)(((uintptr_t)ptr + EPID_ALLOC_ALIGN + 82 sizeof(EpidAllocHeader) - 1) & 83 (~(EPID_ALLOC_ALIGN - 1))); 84 ((EpidAllocHeader*)aligned_pointer)[-1].length = size; 85 ((EpidAllocHeader*)aligned_pointer)[-1].ptr = ptr; 86 return aligned_pointer; 87 } 88 return NULL; 89 #else // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 90 return calloc(1, size); 91 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 92 } 93 94 void* EpidRealloc(void* ptr, size_t new_size) { 95 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 96 void* new_ptr = EpidAlloc(new_size); 97 if (!new_ptr) return NULL; 98 if (ptr) { 99 // Memory copy is used to copy a buffer of variable length 100 if (0 != memcpy_S(new_ptr, ((EpidAllocHeader*)new_ptr)[-1].length, ptr, 101 MIN(((EpidAllocHeader*)ptr)[-1].length, 102 ((EpidAllocHeader*)new_ptr)[-1].length))) { 103 EpidFree(new_ptr); 104 return NULL; 105 } 106 EpidFree(ptr); 107 } 108 return new_ptr; 109 #else // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 110 return realloc(ptr, new_size); 111 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 112 } 113 114 void EpidFree(void* ptr) { 115 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 116 if (ptr) { 117 EpidZeroMemory(ptr, ((EpidAllocHeader*)ptr)[-1].length); 118 free(((EpidAllocHeader*)ptr)[-1].ptr); 119 } 120 #else // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 121 free(ptr); 122 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE) 123 } 124