6 Evolved over several years, starting with the initial
7 SMARTALLOC code for AutoSketch in 1986, guided by the Blind
8 Watchbreaker, John Walker. Isolated in this general-purpose
9 form in September of 1989. Updated with be more POSIX
10 compliant and to include Web-friendly HTML documentation in
11 October of 1998 by the same culprit. For additional
12 information and the current version visit the Web page:
14 http://www.fourmilab.ch/smartall/
19 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
21 This program is free software; you can redistribute it and/or
22 modify it under the terms of the GNU General Public License as
23 published by the Free Software Foundation; either version 2 of
24 the License, or (at your option) any later version.
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 General Public License for more details.
31 You should have received a copy of the GNU General Public
32 License along with this program; if not, write to the Free
33 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
39 /* Use the real routines here */
45 #define FULL_SM_CHECK 1
52 extern char my_name[]; /* daemon name */
54 typedef unsigned short sm_ushort;
56 #define EOS '\0' /* End of string sentinel */
57 #define sm_min(a, b) ((a) < (b) ? (a) : (b))
59 /* Queue data structures */
61 /* Memory allocation control structures and storage. */
64 struct b_queue abq; /* Links on allocated queue */
65 unsigned ablen; /* Buffer length in bytes */
66 char *abfname; /* File name pointer */
67 sm_ushort ablineno; /* Line number of allocation */
70 static struct b_queue abqueue = { /* Allocated buffer queue */
74 static Boolean bufimode = False; /* Buffers not tracked when True */
76 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
79 /* SMALLOC -- Allocate buffer, enqueing on the orphaned buffer
82 static void *smalloc(char *fname, int lineno, unsigned int nbytes)
86 /* Note: Unix MALLOC actually permits a zero length to be
87 passed and allocates a valid block with zero user bytes.
88 Such a block can later be expanded with realloc(). We
89 disallow this based on the belief that it's better to make
90 a special case and allocate one byte in the rare case this
91 is desired than to miss all the erroneous occurrences where
92 buffer length calculation code results in a zero. */
96 nbytes += HEAD_SIZE + 1;
97 if ((buf = (char *) malloc(nbytes)) != NULL) {
98 /* Enqueue buffer on allocated list */
99 qinsert(&abqueue, (struct b_queue *) buf);
100 ((struct abufhead *) buf)->ablen = nbytes;
101 ((struct abufhead *) buf)->abfname = bufimode ? NULL : fname;
102 ((struct abufhead *) buf)->ablineno = (sm_ushort) lineno;
103 /* Emplace end-clobber detector at end of buffer */
104 buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
105 buf += HEAD_SIZE; /* Increment to user data start */
108 sm_check(fname, lineno, True);
110 Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
114 /* SM_NEW_OWNER -- Update the File and line number for a buffer
115 This is to accomodate mem_pool. */
117 void sm_new_owner(char *fname, int lineno, char *buf)
119 buf -= HEAD_SIZE; /* Decrement to header */
120 ((struct abufhead *) buf)->abfname = bufimode ? NULL : fname;
121 ((struct abufhead *) buf)->ablineno = (sm_ushort) lineno;
125 /* SM_FREE -- Update free pool availability. FREE is never called
126 except through this interface or by actuallyfree().
127 free(x) is defined to generate a call to this
130 void sm_free(char *file, int line, void *fp)
132 char *cp = (char *) fp;
136 sm_check(__FILE__, __LINE__, True);
139 Emsg2(M_ABORT, 0, "Attempt to free NULL called from %s:%d\n", file, line);
143 qp = (struct b_queue *) cp;
145 Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
146 ((struct abufhead *)cp)->ablen, fp,
147 ((struct abufhead *)cp)->abfname, ((struct abufhead *)cp)->ablineno);
149 /* The following assertions will catch virtually every release
150 of an address which isn't an allocated buffer. */
151 if (qp->qnext->qprev != qp) {
152 Emsg2(M_ABORT, 0, "qp->qnext->qprev != qp called from %s:%d\n", file, line);
154 if (qp->qprev->qnext != qp) {
155 Emsg2(M_ABORT, 0, "qp->qprev->qnext != qp called from %s:%d\n", file, line);
158 /* The following assertion detects storing off the end of the
159 allocated space in the buffer by comparing the end of buffer
160 checksum with the address of the buffer. */
162 if (((unsigned char *) cp)[((struct abufhead *) cp)->ablen - 1] !=
163 ((((long) cp) & 0xFF) ^ 0xC5)) {
164 Emsg2(M_ABORT, 0, "Buffer overrun called from %s:%d\n", file, line);
170 /* Now we wipe the contents of the just-released buffer with
171 "designer garbage" (Duff Kurland's phrase) of alternating
172 bits. This is intended to ruin the day for any miscreant who
173 attempts to access data through a pointer into storage that's
174 been previously released. */
176 memset(cp, 0xAA, (int) ((struct abufhead *) cp)->ablen);
181 /* SM_MALLOC -- Allocate buffer. NULL is returned if no memory
184 void *sm_malloc(char *fname, int lineno, unsigned int nbytes)
188 if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
190 /* To catch sloppy code that assumes buffers obtained from
191 malloc() are zeroed, we preset the buffer contents to
192 "designer garbage" consisting of alternating bits. */
194 memset(buf, 0x55, (int) nbytes);
199 /* SM_CALLOC -- Allocate an array and clear it to zero. */
201 void *sm_calloc(char *fname, int lineno,
202 unsigned int nelem, unsigned int elsize)
206 if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
207 memset(buf, 0, (int) (nelem * elsize));
212 /* SM_REALLOC -- Adjust the size of a previously allocated buffer.
213 Note that the trick of "resurrecting" a previously
214 freed buffer with realloc() is NOT supported by this
215 function. Further, because of the need to maintain
216 our control storage, SM_REALLOC must always allocate
217 a new block and copy the data in the old block.
218 This may result in programs which make heavy use of
219 realloc() running much slower than normally. */
221 void *sm_realloc(char *fname, int lineno, void *ptr, unsigned int size)
225 char *cp = (char *) ptr;
228 sm_check(fname, lineno, True);
231 e_msg(fname, lineno, M_ABORT, 0, "sm_realloc size: %d\n", size);
234 /* If the old block pointer is NULL, treat realloc() as a
235 malloc(). SVID is silent on this, but many C libraries
239 return sm_malloc(fname, lineno, size);
241 /* If the old and new sizes are the same, be a nice guy and just
242 return the buffer passed in. */
245 osize = ((struct abufhead *) cp)->ablen -
251 /* Sizes differ. Allocate a new buffer of the requested size.
252 If we can't obtain such a buffer, act as defined in SVID:
253 return NULL from realloc() and leave the buffer in PTR
256 if ((buf = smalloc(fname, lineno, size)) != NULL) {
257 memcpy(buf, ptr, (int) sm_min(size, osize));
258 /* If the new buffer is larger than the old, fill the balance
259 of it with "designer garbage". */
261 memset(((char *) buf) + osize, 0x55, (int) (size - osize));
264 /* All done. Free and dechain the original buffer. */
266 sm_free(__FILE__, __LINE__, ptr);
268 Dmsg4(150, "sm_realloc %d at %x from %s:%d\n", size, buf, fname, lineno);
270 sm_check(fname, lineno, True);
275 /* ACTUALLYMALLOC -- Call the system malloc() function to obtain
276 storage which will eventually be released
277 by system or library routines not compiled
280 void *actuallymalloc(unsigned int size)
285 /* ACTUALLYCALLOC -- Call the system calloc() function to obtain
286 storage which will eventually be released
287 by system or library routines not compiled
290 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
292 return calloc(nelem, elsize);
295 /* ACTUALLYREALLOC -- Call the system realloc() function to obtain
296 storage which will eventually be released
297 by system or library routines not compiled
300 void *actuallyrealloc(void *ptr, unsigned int size)
302 return realloc(ptr, size);
305 /* ACTUALLYFREE -- Interface to system free() function to release
306 buffers allocated by low-level routines. */
308 void actuallyfree(void *cp)
313 /* SM_DUMP -- Print orphaned buffers (and dump them if BUFDUMP is
316 void sm_dump(Boolean bufdump)
318 struct abufhead *ap = (struct abufhead *) abqueue.qnext;
320 while (ap != (struct abufhead *) &abqueue) {
323 (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
324 (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
326 "\nOrphaned buffers exist. Dump terminated following\n");
328 " discovery of bad links in chain of orphaned buffers.\n");
330 " Buffer address with bad links: %lx\n", (long) ap);
334 if (ap->abfname != NULL) {
335 unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
339 "Orphaned buffer: %6u bytes allocated at line %d of %s %s\n",
340 memsize, ap->ablineno, my_name, ap->abfname
342 fprintf(stderr, "%s", errmsg);
345 char *cp = ((char *) ap) + HEAD_SIZE;
350 strcat(errmsg, "\n");
352 fprintf(stderr, "%s", errmsg);
355 sprintf(errmsg + strlen(errmsg), " %02X",
360 fprintf(stderr, "%s\n", errmsg);
363 ap = (struct abufhead *) ap->abq.qnext;
367 /* SM_CHECK -- Check the buffers and dump if any damage exists. */
368 void sm_check(char *fname, int lineno, Boolean bufdump)
370 if (!sm_check_rtn(fname, lineno, bufdump)) {
371 Emsg2(M_ABORT, 0, "Damaged buffer found. Called from %s:%d\n",
376 /* SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
377 int sm_check_rtn(char *fname, int lineno, Boolean bufdump)
379 struct abufhead *ap = (struct abufhead *) abqueue.qnext;
382 while (ap != (struct abufhead *) &abqueue) {
385 (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
388 if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
391 if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
392 ((((long) ap) & 0xFF) ^ 0xC5)) {
398 "\nDamaged buffers found at %s:%d\n", fname, lineno);
400 Emsg0(M_FATAL, 0, " discovery of bad prev link.\n");
403 Emsg0(M_FATAL, 0, " discovery of bad next link.\n");
406 Emsg0(M_FATAL, 0, " discovery of data overrun.\n");
409 Emsg1(M_FATAL, 0, " Buffer address: %lx\n", (long) ap);
411 if (ap->abfname != NULL) {
412 unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
416 "Damaged buffer: %6u bytes allocated at line %d of %s %s\n",
417 memsize, ap->ablineno, my_name, ap->abfname
419 Emsg1(M_FATAL, 0, "%s", errmsg);
422 char *cp = ((char *) ap) + HEAD_SIZE;
427 strcat(errmsg, "\n");
429 fprintf(stderr, "%s", errmsg);
433 sprintf(errmsg + strlen(errmsg), " %02X",
436 sprintf(errmsg + strlen(errmsg), " %c ",
442 Emsg1(M_FATAL, 0, "%s\n", errmsg);
446 ap = (struct abufhead *) ap->abq.qnext;
448 return badbuf ? 0 : 1;
452 /* SM_STATIC -- Orphaned buffer detection can be disabled (for such
453 items as buffers allocated during initialisation) by
454 calling sm_static(1). Normal orphaned buffer
455 detection can be re-enabled with sm_static(0). Note
456 that all the other safeguards still apply to buffers
457 allocated when sm_static(1) mode is in effect. */
459 void sm_static(int mode)
461 bufimode = (Boolean) (mode != 0);