1 //  binutils.c
2 //  hosts2zones
3 //
4 //  Created by Dr. Rolf Jansen on 2016-08-13.
5 //  Copyright (c) 2016 projectworld.net. All rights reserved.
6 //
7 //  Redistribution and use in source and binary forms, with or without modification,
8 //  are permitted provided that the following conditions are met:
9 //
10 //  1. Redistributions of source code must retain the above copyright notice,
11 //     this list of conditions and the following disclaimer.
12 //
13 //  2. Redistributions in binary form must reproduce the above copyright notice,
14 //     this list of conditions and the following disclaimer in the documentation
15 //     and/or other materials provided with the distribution.
16 //
17 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
18 //  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 //  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 //  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 //  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 //  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 //  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
24 //  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include <syslog.h>
34 
35 #include "binutils.h"
36 
37 #pragma mark ••• Fencing Memory Allocation Wrappers •••
38 
39 ssize_t gAllocationTotal = 0;
40 
countAllocation(ssize_t size)41 static inline void countAllocation(ssize_t size)
42 {
43    if (__sync_add_and_fetch(&gAllocationTotal, size) < 0)
44    {
45       syslog(LOG_ERR, "Corruption of allocated memory detected by countAllocation().");
46       exit(EXIT_FAILURE);
47    }
48 }
49 
allocate(ssize_t size,bool cleanout)50 void *allocate(ssize_t size, bool cleanout)
51 {
52    if (size >= 0)
53    {
54       allocation *a;
55 
56       if (cleanout)
57       {
58          if ((a = calloc(1, allocationMetaSize + size + sizeof(size_t))) == NULL)
59             return NULL;
60       }
61 
62       else
63       {
64          if ((a = malloc(allocationMetaSize + size + sizeof(size_t))) == NULL)
65             return NULL;
66 
67          *(size_t *)((void *)a + allocationMetaSize + size) = 0;   // place a (size_t)0 just above the payload as the upper boundary of the allocation
68       }
69 
70       countAllocation(size);
71       a->size  = size;
72       a->check = size | (size_t)a;
73       return &a->payload;
74    }
75    else
76       return NULL;
77 }
78 
reallocate(void * p,ssize_t size,bool cleanout,bool free_on_error)79 void *reallocate(void *p, ssize_t size, bool cleanout, bool free_on_error)
80 {
81    if (size >= 0)
82       if (p)
83       {
84          allocation *a = p - allocationMetaSize;
85 
86          if (a->check == (a->size | (size_t)a) && *(ssize_t *)((void *)a + allocationMetaSize + a->size) == 0)
87             a->check = 0;
88          else
89          {
90             syslog(LOG_ERR, "Corruption of allocated memory detected by reallocate().");
91             exit(EXIT_FAILURE);
92          }
93 
94          if ((p = realloc(a, allocationMetaSize + size + sizeof(size_t))) == NULL)
95          {
96             if (free_on_error)
97             {
98                countAllocation(-a->size);
99                free(a);
100             }
101             return NULL;
102          }
103          else
104             a = p;
105 
106          if (cleanout)
107             bzero((void *)a + allocationMetaSize + a->size, size - a->size + sizeof(size_t));
108          else
109             *(ssize_t *)((void *)a + allocationMetaSize + size) = 0;   // place a (size_t)0 just above the payload as the upper boundary of the allocation
110 
111          countAllocation(size - a->size);
112          a->size  = size;
113          a->check = size | (size_t)a;
114          return &a->payload;
115       }
116       else
117          return allocate(size, cleanout);
118 
119    return NULL;
120 }
121 
deallocate(void ** p,bool cleanout)122 void deallocate(void **p, bool cleanout)
123 {
124    if (p && *p)
125    {
126       allocation *a = *p - allocationMetaSize;
127       *p = NULL;
128 
129       if (a->check == (a->size | (size_t)a) && *(ssize_t *)((void *)a + allocationMetaSize + a->size) == 0)
130          a->check = 0;
131       else
132       {
133          syslog(LOG_ERR, "Corruption of allocated memory detected by deallocate().");
134          exit(EXIT_FAILURE);
135       }
136 
137       countAllocation(-a->size);
138       if (cleanout)
139          bzero((void *)a, allocationMetaSize + a->size + sizeof(size_t));
140       free(a);
141    }
142 }
143 
deallocate_batch(unsigned cleanout,...)144 void deallocate_batch(unsigned cleanout, ...)
145 {
146    void   **p;
147    va_list  vl;
148    va_start(vl, cleanout);
149 
150    while (p = va_arg(vl, void **))
151       if (*p)
152       {
153          allocation *a = *p - allocationMetaSize;
154          *p = NULL;
155 
156          if (a->check == (a->size | (size_t)a) && *(ssize_t *)((void *)a + allocationMetaSize + a->size) == 0)
157             a->check = 0;
158          else
159          {
160             syslog(LOG_ERR, "Corruption of allocated memory detected by deallocate_batch().");
161             exit(EXIT_FAILURE);
162          }
163 
164          countAllocation(-a->size);
165          if (cleanout)
166             bzero((void *)a, allocationMetaSize + a->size + sizeof(size_t));
167          free(a);
168       }
169 
170    va_end(vl);
171 }
172