Home | History | Annotate | Download | only in src
      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