1 /*
2 ** a_alloc.c - Allocation routines that either succeeds or abort.
3 **
4 ** Copyright (c) 1997-2000 Peter Eriksson <pen@lysator.liu.se>
5 **
6 ** This program is free software; you can redistribute it and/or
7 ** modify it as you wish - as long as you don't claim that you wrote
8 ** it.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 */
14 
15 #define PLIB_IN_ALLOC_C
16 
17 #include "plib/config.h"
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <syslog.h>
22 #include <string.h>
23 
24 #include "plib/safeio.h"
25 #include "plib/threads.h"
26 
27 #include "plib/aalloc.h"
28 
29 typedef struct aahdr
30 {
31     struct aahdr *prev;
32     struct aahdr *next;
33     char fun[64];
34     char what[64];
35     size_t size;
36     unsigned short dummy;
37     unsigned short magic;
38 } AAHDR;
39 
40 #define AAHDR_MAGIC_1 0x1234
41 #define AAHDR_MAGIC_2 0x56
42 
43 
44 static pthread_mutex_t aa_mtx;
45 static AAHDR *top = NULL;
46 static int aa_debug = 0;
47 
48 static inline int
aahdr_valid(AAHDR * ap)49 aahdr_valid(AAHDR *ap)
50 {
51     unsigned char *cp;
52 
53 
54     if (ap == NULL)
55 	return 0;
56 
57     if (ap->magic != AAHDR_MAGIC_1)
58 	return 0;
59 
60     cp = (unsigned char *) (ap+1);
61 
62     if (cp[ap->size] != AAHDR_MAGIC_2)
63     {
64 	syslog(LOG_ERR, "aalloc: Buffer overrun for object at %p\n", (ap+1));
65 	return 0;
66     }
67 
68     return 1;
69 }
70 
71 
72 void
a_dump(FILE * fp)73 a_dump(FILE *fp)
74 {
75     AAHDR *ap;
76     unsigned char *p;
77 
78 
79     fprintf(fp, "a_dump(): Start\n");
80 
81     pthread_mutex_lock(&aa_mtx);
82 
83     ap = top;
84     while (ap)
85     {
86 	p = (unsigned char *) (ap+1);
87 
88 	fprintf(fp, "%08p:  magic=%04x:%02x, size=%lu, function=%s, object=%s\n",
89 	       ap, ap->magic, p[ap->size], ap->size,
90 		ap->fun ? ap->fun : "<null>",
91 		ap->what ? ap->what : "<null>");
92 
93 	ap = ap->next;
94     }
95     pthread_mutex_unlock(&aa_mtx);
96 
97     fprintf(fp, "a_dump(): Stop\n");
98 }
99 
100 
101 void
a_init(void)102 a_init(void)
103 {
104     aa_debug = (getenv("AA_DEBUG") != NULL);
105 
106     top = NULL;
107     pthread_mutex_init(&aa_mtx, NULL);
108 }
109 
110 
111 /*
112 ** A "safe" malloc, that always succeeds (or logs an
113 ** error to syslog and then abort()'s.
114 */
115 
116 static inline void *
safe_malloc(size_t size,const char * fun,const char * what)117 safe_malloc(size_t size,
118 	    const char *fun,
119 	    const char *what)
120 {
121     int rsize;
122     void *p;
123     AAHDR *ap;
124     unsigned char *cp;
125 
126 
127     if (aa_debug)
128 	rsize = size + sizeof(AAHDR) + 1;
129     else
130 	rsize = size;
131 
132     p = malloc(rsize);
133     if (p == NULL)
134     {
135 	syslog(LOG_ERR, "%s: %s: malloc(%lu - real=%lu): %m",
136 	       fun ? fun : "<unknown function>",
137 	       what ? what : "<unknown object>",
138 	       (unsigned long) size,
139 	       (unsigned long) rsize);
140 
141 	s_abort();
142     }
143 
144     if (aa_debug)
145     {
146 	ap = (AAHDR *) p;
147 
148 	pthread_mutex_lock(&aa_mtx);
149 
150 	ap->prev = NULL;
151 	if (top)
152 	    top->prev = ap;
153 	ap->next = top;
154 	top = ap;
155 
156 	ap->size = size;
157 	strlcpy(ap->fun, fun, sizeof(ap->fun));
158 	strlcpy(ap->what, what, sizeof(ap->what));
159 	ap->magic = AAHDR_MAGIC_1;
160 
161 	cp = (unsigned char *) (ap+1);
162 	cp[size] = AAHDR_MAGIC_2;
163 
164 	p = (void *) cp;
165 
166 	pthread_mutex_unlock(&aa_mtx);
167     }
168 
169     return p;
170 }
171 
172 
173 
174 void *
a_malloc(size_t size,const char * what)175 a_malloc(size_t size, const char *what)
176 {
177     void *p;
178 
179 
180     p = safe_malloc(size, "a_malloc", what);
181     memset(p, 0, size);
182 
183     return p;
184 }
185 
186 
187 void *
a_realloc(void * oldp,size_t nsize,const char * what)188 a_realloc(void *oldp, size_t nsize, const char *what)
189 {
190     void *p;
191 
192 
193     if (!oldp)
194 	return safe_malloc(nsize, "a_realloc", what);
195 
196     if (aa_debug)
197     {
198 	AAHDR *ap;
199 
200 	ap = (AAHDR *) oldp;
201 	--ap;
202 
203 	if (!aahdr_valid(ap))
204 	{
205 	    syslog(LOG_ERR, "a_realloc: INVALID pointer");
206 	    s_abort();
207 	}
208 
209 	p = safe_malloc(nsize, "a_realloc", what);
210 	memcpy(p, oldp, ap->size > nsize ? nsize : ap->size);
211 	a_free(oldp);
212 
213 	return p;
214     }
215 
216     p = (void *) realloc(oldp, nsize);
217     if (p == NULL)
218     {
219 	syslog(LOG_ERR, "a_realloc: %s: realloc(...,%lu): %m",
220 	       what ? what : "<unknown object>",
221 	       (unsigned long) nsize);
222 	s_abort();
223     }
224 
225     return p;
226 }
227 
228 
229 void
a_free(void * p)230 a_free(void *p)
231 {
232     AAHDR *ap;
233 
234 
235     if (p == NULL)
236 	return;
237 
238 
239     if (aa_debug)
240     {
241 	ap = (AAHDR *) p;
242 	--ap;
243 
244 	if (!aahdr_valid(ap))
245 	{
246 	    syslog(LOG_ERR, "a_free: INVALID pointer");
247 	    s_abort();
248 	}
249 
250 	pthread_mutex_lock(&aa_mtx);
251 	if (ap->prev)
252 	    ap->prev->next = ap->next;
253 	if (ap->next)
254 	    ap->next->prev = ap->prev;
255 	if (top == ap)
256 	    top = ap->next;
257 	pthread_mutex_unlock(&aa_mtx);
258     }
259 
260     free(p);
261 }
262 
263 
264 char *
a_strndup(const char * s,size_t len,const char * what)265 a_strndup(const char *s,
266 	  size_t len,
267 	  const char *what)
268 {
269     char *ns;
270 
271 
272     if (s == NULL)
273 	return NULL;
274 
275     ns = (char *) safe_malloc(len+1, "a_strndup", what);
276 
277     memcpy(ns, s, len);
278     ns[len] = '\0';
279 
280     return ns;
281 }
282 
283 
284 char *
a_strdup(const char * s,const char * what)285 a_strdup(const char *s,
286 	 const char *what)
287 {
288     char *ns;
289     int len;
290 
291 
292     if (s == NULL)
293 	return NULL;
294 
295     len = strlen(s);
296     ns = (char *) safe_malloc(len+1, "a_strdup", what);
297 
298     memcpy(ns, s, len+1);
299 
300     return ns;
301 }
302 
303