1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #ifndef _MALLOC_INTERNAL
22: # define _MALLOC_INTERNAL
23: # include <malloc.h>
24: # include <mcheck.h>
25: # include <stdint.h>
26: # include <stdio.h>
27: # include <libintl.h>
28: #endif
29:
30:
31: static void (*old_free_hook) (__ptr_t ptr, __const __ptr_t);
32: static __ptr_t (*old_malloc_hook) (__malloc_size_t size, const __ptr_t);
33: static __ptr_t (*old_memalign_hook) (__malloc_size_t alignment,
34: __malloc_size_t size,
35: const __ptr_t);
36: static __ptr_t (*old_realloc_hook) (__ptr_t ptr, __malloc_size_t size,
37: __const __ptr_t);
38:
39:
40: static void (*abortfunc) (enum mcheck_status);
41:
42:
43: #define MAGICWORD 0xfedabeeb
44: #define MAGICFREE 0xd8675309
45: #define MAGICBYTE ((char) 0xd7)
46: #define MALLOCFLOOD ((char) 0x93)
47: #define FREEFLOOD ((char) 0x95)
48:
49: struct hdr
50: {
51: __malloc_size_t size;
52: unsigned long int magic;
53: struct hdr *prev;
54: struct hdr *next;
55: __ptr_t block;
56: unsigned long int magic2;
57: };
58:
59:
60:
61: static struct hdr *root;
62:
63: static int mcheck_used;
64:
65:
66: static int pedantic;
67:
68: #if defined _LIBC || defined STDC_HEADERS || defined USG
69: # include <string.h>
70: # define flood memset
71: #else
72: static void flood (__ptr_t, int, __malloc_size_t);
73: static void
74: flood (ptr, val, size)
75: __ptr_t ptr;
76: int val;
77: __malloc_size_t size;
78: {
79: char *cp = ptr;
80: while (size--)
81: *cp++ = val;
82: }
83: #endif
84:
85: static enum mcheck_status
86: checkhdr (const struct hdr *hdr)
87: {
88: enum mcheck_status status;
89:
90: if (!mcheck_used)
91:
92:
93: return MCHECK_OK;
94:
95: switch (hdr->magic ^ ((uintptr_t) hdr->prev + (uintptr_t) hdr->next))
96: {
97: default:
98: status = MCHECK_HEAD;
99: break;
100: case MAGICFREE:
101: status = MCHECK_FREE;
102: break;
103: case MAGICWORD:
104: if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
105: status = MCHECK_TAIL;
106: else if ((hdr->magic2 ^ (uintptr_t) hdr->block) != MAGICWORD)
107: status = MCHECK_HEAD;
108: else
109: status = MCHECK_OK;
110: break;
111: }
112: if (status != MCHECK_OK)
113: {
114: mcheck_used = 0;
115: (*abortfunc) (status);
116: mcheck_used = 1;
117: }
118: return status;
119: }
120:
121: void
122: mcheck_check_all (void)
123: {
124:
125:
126: struct hdr *runp = root;
127:
128:
129: pedantic = 0;
130:
131: while (runp != NULL)
132: {
133: (void) checkhdr (runp);
134:
135: runp = runp->next;
136: }
137:
138:
139: pedantic = 1;
140: }
141: #ifdef _LIBC
142: libc_hidden_def (mcheck_check_all)
143: #endif
144:
145: static void
146: unlink_blk (struct hdr *ptr)
147: {
148: if (ptr->next != NULL)
149: {
150: ptr->next->prev = ptr->prev;
151: ptr->next->magic = MAGICWORD ^ ((uintptr_t) ptr->next->prev
152: + (uintptr_t) ptr->next->next);
153: }
154: if (ptr->prev != NULL)
155: {
156: ptr->prev->next = ptr->next;
157: ptr->prev->magic = MAGICWORD ^ ((uintptr_t) ptr->prev->prev
158: + (uintptr_t) ptr->prev->next);
159: }
160: else
161: root = ptr->next;
162: }
163:
164: static void
165: link_blk (struct hdr *hdr)
166: {
167: hdr->prev = NULL;
168: hdr->next = root;
169: root = hdr;
170: hdr->magic = MAGICWORD ^ (uintptr_t) hdr->next;
171:
172:
173: if (hdr->next != NULL)
174: {
175: hdr->next->prev = hdr;
176: hdr->next->magic = MAGICWORD ^ ((uintptr_t) hdr
177: + (uintptr_t) hdr->next->next);
178: }
179: }
180: static void
181: freehook (__ptr_t ptr, const __ptr_t caller)
182: {
183: if (pedantic)
184: mcheck_check_all ();
185: if (ptr)
186: {
187: struct hdr *hdr = ((struct hdr *) ptr) - 1;
188: checkhdr (hdr);
189: hdr->magic = MAGICFREE;
190: hdr->magic2 = MAGICFREE;
191: unlink_blk (hdr);
192: hdr->prev = hdr->next = NULL;
193: flood (ptr, FREEFLOOD, hdr->size);
194: ptr = hdr->block;
195: }
196: __free_hook = old_free_hook;
197: if (old_free_hook != NULL)
198: (*old_free_hook) (ptr, caller);
199: else
200: free (ptr);
201: __free_hook = freehook;
202: }
203:
204: static __ptr_t
205: mallochook (__malloc_size_t size, const __ptr_t caller)
206: {
207: struct hdr *hdr;
208:
209: if (pedantic)
210: mcheck_check_all ();
211:
212: __malloc_hook = old_malloc_hook;
213: if (old_malloc_hook != NULL)
214: hdr = (struct hdr *) (*old_malloc_hook) (sizeof (struct hdr) + size + 1,
215: caller);
216: else
217: hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
218: __malloc_hook = mallochook;
219: if (hdr == NULL)
220: return NULL;
221:
222: hdr->size = size;
223: link_blk (hdr);
224: hdr->block = hdr;
225: hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
226: ((char *) &hdr[1])[size] = MAGICBYTE;
227: flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
228: return (__ptr_t) (hdr + 1);
229: }
230:
231: static __ptr_t
232: memalignhook (__malloc_size_t alignment, __malloc_size_t size,
233: const __ptr_t caller)
234: {
235: struct hdr *hdr;
236: __malloc_size_t slop;
237: char *block;
238:
239: if (pedantic)
240: mcheck_check_all ();
241:
242: slop = (sizeof *hdr + alignment - 1) & -alignment;
243:
244: __memalign_hook = old_memalign_hook;
245: if (old_memalign_hook != NULL)
246: block = (*old_memalign_hook) (alignment, slop + size + 1, caller);
247: else
248: block = memalign (alignment, slop + size + 1);
249: __memalign_hook = memalignhook;
250: if (block == NULL)
251: return NULL;
252:
253: hdr = ((struct hdr *) (block + slop)) - 1;
254:
255: hdr->size = size;
256: link_blk (hdr);
257: hdr->block = (__ptr_t) block;
258: hdr->magic2 = (uintptr_t) block ^ MAGICWORD;
259: ((char *) &hdr[1])[size] = MAGICBYTE;
260: flood ((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
261: return (__ptr_t) (hdr + 1);
262: }
263:
264: static __ptr_t
265: reallochook (__ptr_t ptr, __malloc_size_t size, const __ptr_t caller)
266: {
267: if (size == 0)
268: {
269: freehook (ptr, caller);
270: return NULL;
271: }
272:
273: struct hdr *hdr;
274: __malloc_size_t osize;
275:
276: if (pedantic)
277: mcheck_check_all ();
278:
279: if (ptr)
280: {
281: hdr = ((struct hdr *) ptr) - 1;
282: osize = hdr->size;
283:
284: checkhdr (hdr);
285: unlink_blk (hdr);
286: if (size < osize)
287: flood ((char *) ptr + size, FREEFLOOD, osize - size);
288: }
289: else
290: {
291: osize = 0;
292: hdr = NULL;
293: }
294: __free_hook = old_free_hook;
295: __malloc_hook = old_malloc_hook;
296: __memalign_hook = old_memalign_hook;
297: __realloc_hook = old_realloc_hook;
298: if (old_realloc_hook != NULL)
299: hdr = (struct hdr *) (*old_realloc_hook) ((__ptr_t) hdr,
300: sizeof (struct hdr) + size + 1,
301: caller);
302: else
303: hdr = (struct hdr *) realloc ((__ptr_t) hdr,
304: sizeof (struct hdr) + size + 1);
305: __free_hook = freehook;
306: __malloc_hook = mallochook;
307: __memalign_hook = memalignhook;
308: __realloc_hook = reallochook;
309: if (hdr == NULL)
310: return NULL;
311:
312: hdr->size = size;
313: link_blk (hdr);
314: hdr->block = hdr;
315: hdr->magic2 = (uintptr_t) hdr ^ MAGICWORD;
316: ((char *) &hdr[1])[size] = MAGICBYTE;
317: if (size > osize)
318: flood ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
319: return (__ptr_t) (hdr + 1);
320: }
321:
322: __attribute__ ((noreturn))
323: static void
324: mabort (enum mcheck_status status)
325: {
326: const char *msg;
327: switch (status)
328: {
329: case MCHECK_OK:
330: msg = _("memory is consistent, library is buggy\n");
331: break;
332: case MCHECK_HEAD:
333: msg = _("memory clobbered before allocated block\n");
334: break;
335: case MCHECK_TAIL:
336: msg = _("memory clobbered past end of allocated block\n");
337: break;
338: case MCHECK_FREE:
339: msg = _("block freed twice\n");
340: break;
341: default:
342: msg = _("bogus mcheck_status, library is buggy\n");
343: break;
344: }
345: #ifdef _LIBC
346: __libc_fatal (msg);
347: #else
348: fprintf (stderr, "mcheck: %s", msg);
349: fflush (stderr);
350: abort ();
351: #endif
352: }
353:
354: int
355: mcheck (func)
356: void (*func) (enum mcheck_status);
357: {
358: abortfunc = (func != NULL) ? func : &mabort;
359:
360:
361: if (__malloc_initialized <= 0 && !mcheck_used)
362: {
363:
364: void *p = malloc (0);
365: free (p);
366:
367: old_free_hook = __free_hook;
368: __free_hook = freehook;
369: old_malloc_hook = __malloc_hook;
370: __malloc_hook = mallochook;
371: old_memalign_hook = __memalign_hook;
372: __memalign_hook = memalignhook;
373: old_realloc_hook = __realloc_hook;
374: __realloc_hook = reallochook;
375: mcheck_used = 1;
376: }
377:
378: return mcheck_used ? 0 : -1;
379: }
380: #ifdef _LIBC
381: libc_hidden_def (mcheck)
382: #endif
383:
384: int
385: mcheck_pedantic (func)
386: void (*func) (enum mcheck_status);
387: {
388: int res = mcheck (func);
389: if (res == 0)
390: pedantic = 1;
391: return res;
392: }
393:
394: enum mcheck_status
395: mprobe (__ptr_t ptr)
396: {
397: return mcheck_used ? checkhdr (((struct hdr *) ptr) - 1) : MCHECK_DISABLED;
398: }