]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/smartall.c
Fix compilation for Debian Stretch with GCC 6.3
[bacula/bacula] / bacula / src / lib / smartall.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20
21                          S M A R T A L L O C
22                         Smart Memory Allocator
23
24         Evolved   over   several  years,  starting  with  the  initial
25         SMARTALLOC code for AutoSketch in 1986, guided  by  the  Blind
26         Watchbreaker,  John  Walker.  Isolated in this general-purpose
27         form in  September  of  1989.   Updated  with  be  more  POSIX
28         compliant  and  to  include Web-friendly HTML documentation in
29         October  of  1998  by  the  same  culprit.    For   additional
30         information and the current version visit the Web page:
31
32                   http://www.fourmilab.ch/smartall/
33
34 */
35
36 #define LOCKMGR_COMPLIANT
37
38 #include "bacula.h"
39 /* Use the real routines here */
40 #undef realloc
41 #undef calloc
42 #undef malloc
43 #undef free
44
45 /* We normally turn off debugging here.
46  *  If you want it, simply #ifdef all the
47  *  following off.
48  */
49 #ifdef no_debug_xxxxx
50 #undef Dmsg1
51 #undef Dmsg2
52 #undef Dmsg3
53 #undef Dmsg4
54 #define Dmsg1(l,f,a1)
55 #define Dmsg2(l,f,a1,a2)
56 #define Dmsg3(l,f,a1,a2,a3)
57 #define Dmsg4(l,f,a1,a2,a3,a4)
58 #endif
59
60
61 uint64_t sm_max_bytes = 0;
62 uint64_t sm_bytes = 0;
63 uint32_t sm_max_buffers = 0;
64 uint32_t sm_buffers = 0;
65
66 #ifdef SMARTALLOC
67
68 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
69
70 extern char my_name[];                /* daemon name */
71
72 #define EOS      '\0'              /* End of string sentinel */
73 #define sm_min(a, b) ((a) < (b) ? (a) : (b))
74
75 /*  Queue data structures  */
76
77 /*  Memory allocation control structures and storage.  */
78
79 struct abufhead {
80    struct b_queue abq;         /* Links on allocated queue */
81    uint32_t ablen;             /* Buffer length in bytes */
82    const char *abfname;        /* File name pointer */
83    uint32_t ablineno;          /* Line number of allocation */
84    bool abin_use;              /* set when malloced and cleared when free */
85 };
86
87 static struct b_queue abqueue = {    /* Allocated buffer queue */
88    &abqueue, &abqueue
89 };
90
91
92 static bool bufimode = false;   /* Buffers not tracked when True */
93
94 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
95
96
97 /*  SMALLOC  --  Allocate buffer, enqueing on the orphaned buffer
98                  tracking list.  */
99
100 static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
101 {
102    char *buf;
103
104    /* Note:  Unix  MALLOC  actually  permits  a zero length to be
105       passed and allocates a valid block with  zero  user  bytes.
106       Such  a  block  can  later  be expanded with realloc().  We
107       disallow this based on the belief that it's better to  make
108       a  special case and allocate one byte in the rare case this
109       is desired than to miss all the erroneous occurrences where
110       buffer length calculation code results in a zero.  */
111
112    if (nbytes == 0) {
113       Tmsg3(0, "Invalid memory allocation. %u bytes %s:%d\n", nbytes, fname, lineno);
114       ASSERT(nbytes > 0);
115    }
116
117    nbytes += HEAD_SIZE + 1;
118    if ((buf = (char *)malloc(nbytes)) != NULL) {
119       struct abufhead *head = (struct abufhead *)buf;
120       P(mutex);
121       /* Enqueue buffer on allocated list */
122       qinsert(&abqueue, (struct b_queue *) buf);
123       head->ablen = nbytes;
124       head->abfname = bufimode ? NULL : fname;
125       head->ablineno = (uint32_t)lineno;
126       head->abin_use = true;
127       /* Emplace end-clobber detector at end of buffer */
128       buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5);
129       buf += HEAD_SIZE;  /* Increment to user data start */
130       if (++sm_buffers > sm_max_buffers) {
131          sm_max_buffers = sm_buffers;
132       }
133       sm_bytes += nbytes;
134       if (sm_bytes > sm_max_bytes) {
135          sm_max_bytes = sm_bytes;
136       }
137       V(mutex);
138    } else {
139       Emsg0(M_ABORT, 0, _("Out of memory\n"));
140    }
141    Dmsg4(DT_MEMORY|1050, "smalloc %d at %p from %s:%d\n", nbytes, buf, fname, lineno);
142 #if    SMALLOC_SANITY_CHECK > 0
143    if (sm_bytes > SMALLOC_SANITY_CHECK) {
144       Emsg0(M_ABORT, 0, _("Too much memory used."));
145    }
146 #endif
147    return (void *)buf;
148 }
149
150 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
151                     This is to accomodate mem_pool. */
152
153 void sm_new_owner(const char *fname, int lineno, char *buf)
154 {
155    buf -= HEAD_SIZE;  /* Decrement to header */
156    P(mutex);
157    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
158    ((struct abufhead *)buf)->ablineno = (uint32_t) lineno;
159    ((struct abufhead *)buf)->abin_use = true;
160    V(mutex);
161    return;
162 }
163
164 /*  SM_FREE  --  Update free pool availability.  FREE is never called
165                  except  through  this interface or by actuallyfree().
166                  free(x)  is  defined  to  generate  a  call  to  this
167                  routine.  */
168
169 void sm_free(const char *file, int line, void *fp)
170 {
171    char *cp = (char *) fp;
172    struct b_queue *qp;
173    uint32_t lineno = line;
174
175    if (cp == NULL) {
176       Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, lineno);
177    }
178
179    cp -= HEAD_SIZE;
180    qp = (struct b_queue *)cp;
181    struct abufhead *head = (struct abufhead *)cp;
182
183    P(mutex);
184    Dmsg4(DT_MEMORY|1050, "sm_free %d at %p from %s:%d\n",
185          head->ablen, fp,
186          get_basename(head->abfname), head->ablineno);
187
188    if (!head->abin_use) {
189       V(mutex);
190       Emsg2(M_ABORT, 0, _("in-use bit not set: double free from %s:%d\n"), file, lineno);
191    }
192    head->abin_use = false;
193
194    /* The following assertions will catch virtually every release
195       of an address which isn't an allocated buffer. */
196    if (qp->qnext->qprev != qp) {
197       V(mutex);
198       Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, lineno);
199    }
200    if (qp->qprev->qnext != qp) {
201       V(mutex);
202       Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, lineno);
203    }
204
205    /* The following assertion detects storing off the  end  of  the
206       allocated  space in the buffer by comparing the end of buffer
207       checksum with the address of the buffer.  */
208
209    if (((unsigned char *)cp)[head->ablen - 1] != ((((intptr_t) cp) & 0xFF) ^ 0xC5)) {
210       V(mutex);
211       Emsg6(M_ABORT, 0, _("Overrun buffer: len=%d addr=%p allocated: %s:%d called from %s:%d\n"),
212          head->ablen, fp, get_basename(head->abfname), head->ablineno, file, line);
213    }
214    if (sm_buffers > 0) {
215       sm_buffers--;
216       sm_bytes -= head->ablen;
217    }
218
219    qdchain(qp);
220    V(mutex);
221
222    /* Now we wipe the contents of  the  just-released  buffer  with
223       "designer  garbage"  (Duff  Kurland's  phrase) of alternating
224       bits.  This is intended to ruin the day for any miscreant who
225       attempts to access data through a pointer into storage that's
226       been previously released.
227
228       Modified, kes May, 2007 to not zap the header. This allows us
229       to check the in_use bit and detect doubly freed buffers.
230    */
231
232    memset(cp+HEAD_SIZE, 0xAA, (int)(head->ablen - HEAD_SIZE));
233
234    free(cp);
235 }
236
237 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
238                    was available.  */
239
240 void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
241 {
242    void *buf;
243
244    if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
245
246       /* To catch sloppy code that assumes  buffers  obtained  from
247          malloc()  are  zeroed,  we  preset  the buffer contents to
248          "designer garbage" consisting of alternating bits.  */
249
250       memset(buf, 0x55, (int) nbytes);
251    } else {
252       Emsg0(M_ABORT, 0, _("Out of memory\n"));
253    }
254    return buf;
255 }
256
257 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
258
259 void *sm_calloc(const char *fname, int lineno,
260                 unsigned int nelem, unsigned int elsize)
261 {
262    void *buf;
263
264    if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
265       memset(buf, 0, (int) (nelem * elsize));
266    } else {
267       Emsg0(M_ABORT, 0, _("Out of memory\n"));
268    }
269    return buf;
270 }
271
272 /*  SM_REALLOC  --  Adjust the size of a  previously  allocated  buffer.
273                     Note  that  the trick of "resurrecting" a previously
274                     freed buffer with realloc() is NOT supported by this
275                     function.   Further, because of the need to maintain
276                     our control storage, SM_REALLOC must always allocate
277                     a  new  block  and  copy  the data in the old block.
278                     This may result in programs which make heavy use  of
279                     realloc() running much slower than normally.  */
280
281 void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
282 {
283    unsigned osize;
284    void *buf;
285    char *cp = (char *) ptr;
286
287    Dmsg4(DT_MEMORY|1050, "sm_realloc %s:%d %p %d\n", get_basename(fname), (uint32_t)lineno, ptr, size);
288    if (size <= 0) {
289       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
290    }
291
292    /*  If  the  old  block  pointer  is  NULL, treat realloc() as a
293       malloc().  SVID is silent  on  this,  but  many  C  libraries
294       permit this.  */
295    if (ptr == NULL) {
296       return sm_malloc(fname, lineno, size);
297    }
298
299    /* If the old and new sizes are the same, be a nice guy and just
300       return the buffer passed in.  */
301    cp -= HEAD_SIZE;
302    struct abufhead *head = (struct abufhead *)cp;
303    osize = head->ablen - (HEAD_SIZE + 1);
304    if (size == osize) {
305       return ptr;
306    }
307
308    /* Sizes differ.  Allocate a new buffer of the  requested  size.
309       If  we  can't  obtain  such a buffer, act as defined in SVID:
310       return NULL from  realloc()  and  leave  the  buffer  in  PTR
311       intact.  */
312
313 // sm_buffers--;
314 // sm_bytes -= head->ablen;
315
316    if ((buf = smalloc(fname, lineno, size)) != NULL) {
317       memcpy(buf, ptr, (int)sm_min(size, osize));
318       /* If the new buffer is larger than the old, fill the balance
319          of it with "designer garbage". */
320       if (size > osize) {
321          memset(((char *) buf) + osize, 0x55, (int) (size - osize));
322       }
323
324       /* All done.  Free and dechain the original buffer. */
325       sm_free(fname, lineno, ptr);
326    }
327    Dmsg4(DT_MEMORY|1060, _("sm_realloc %d at %p from %s:%d\n"), size, buf, get_basename(fname), (uint32_t)lineno);
328    return buf;
329 }
330
331 /*  ACTUALLYMALLOC  --  Call the system malloc() function to obtain
332                         storage which will eventually be released
333                         by system or library routines not compiled
334                         using SMARTALLOC.  */
335
336 void *actuallymalloc(unsigned int size)
337 {
338    return malloc(size);
339 }
340
341 /*  ACTUALLYCALLOC  --  Call the system calloc() function to obtain
342                         storage which will eventually be released
343                         by system or library routines not compiled
344                         using SMARTALLOC.  */
345
346 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
347 {
348    return calloc(nelem, elsize);
349 }
350
351 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
352                          storage which will eventually be released
353                          by system or library routines not compiled
354                          using SMARTALLOC.  */
355
356 void *actuallyrealloc(void *ptr, unsigned int size)
357 {
358    Dmsg2(DT_MEMORY|1040, "Actuallyrealloc %p %d\n", ptr, size);
359    return realloc(ptr, size);
360 }
361
362 /*  ACTUALLYFREE  --  Interface to system free() function to release
363                       buffers allocated by low-level routines. */
364
365 void actuallyfree(void *cp)
366 {
367    free(cp);
368 }
369
370 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
371  *               True).
372  */
373 void sm_dump(bool bufdump, bool in_use)
374 {
375    struct abufhead *ap;
376
377    P(mutex);
378
379    ap = (struct abufhead *)abqueue.qnext;
380
381    while (ap != (struct abufhead *) &abqueue) {
382
383       if ((ap == NULL) ||
384           (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
385           (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
386          Pmsg1(0, _(
387             "\nOrphaned buffers exist.  Dump terminated following\n"
388             "  discovery of bad links in chain of orphaned buffers.\n"
389             "  Buffer address with bad links: %p\n"), ap);
390          break;
391       }
392
393       if (ap->abfname != NULL) {
394          char errmsg[500];
395          uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
396          char *cp = ((char *)ap) + HEAD_SIZE;
397
398          Pmsg6(0, "%s buffer: %s %d bytes at %p from %s:%d\n",
399             in_use?"In use":"Orphaned",
400             my_name, memsize, cp, get_basename(ap->abfname), ap->ablineno);
401          if (bufdump) {
402             char buf[20];
403             unsigned llen = 0;
404
405             errmsg[0] = EOS;
406             while (memsize) {
407                if (llen >= 16) {
408                   bstrncat(errmsg, "\n", sizeof(errmsg));
409                   llen = 0;
410                   Pmsg1(0, "%s", errmsg);
411                   errmsg[0] = EOS;
412                }
413                bsnprintf(buf, sizeof(buf), " %02X",
414                   (*cp++) & 0xFF);
415                bstrncat(errmsg, buf, sizeof(errmsg));
416                llen++;
417                memsize--;
418             }
419             Pmsg1(0, "%s\n", errmsg);
420          }
421       }
422       ap = (struct abufhead *) ap->abq.qnext;
423    }
424    V(mutex);
425 }
426
427 #undef sm_check
428 /*  SM_CHECK --  Check the buffers and dump if any damage exists. */
429 void sm_check(const char *fname, int lineno, bool bufdump)
430 {
431    if (!sm_check_rtn(fname, lineno, bufdump)) {
432       Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
433             get_basename(fname), (uint32_t)lineno);
434    }
435 }
436
437 #undef sm_check_rtn
438 /*  SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
439 int sm_check_rtn(const char *fname, int lineno, bool bufdump)
440 {
441    struct abufhead *ap;
442    int bad, badbuf = 0;
443
444    P(mutex);
445    ap = (struct abufhead *) abqueue.qnext;
446    while (ap != (struct abufhead *)&abqueue) {
447       bad = 0;
448       if (ap != NULL) {
449          if (ap->abq.qnext->qprev != (struct b_queue *)ap) {
450             bad = 0x1;
451          }
452          if (ap->abq.qprev->qnext != (struct b_queue *)ap) {
453             bad |= 0x2;
454          }
455          if (((unsigned char *) ap)[((struct abufhead *)ap)->ablen - 1] !=
456               ((((intptr_t) ap) & 0xFF) ^ 0xC5)) {
457             bad |= 0x4;
458          }
459       } else {
460          bad = 0x8;
461       }
462       badbuf |= bad;
463       if (bad) {
464          Pmsg2(0,
465             _("\nDamaged buffers found at %s:%d\n"), get_basename(fname), (uint32_t)lineno);
466
467          if (bad & 0x1) {
468             Pmsg0(0,  _("  discovery of bad prev link.\n"));
469          }
470          if (bad & 0x2) {
471             Pmsg0(0, _("  discovery of bad next link.\n"));
472          }
473          if (bad & 0x4) {
474             Pmsg0(0, _("  discovery of data overrun.\n"));
475          }
476          if (bad & 0x8) {
477             Pmsg0(0, _("  NULL pointer.\n"));
478          }
479
480          if (!ap) {
481             goto get_out;
482          }
483          Pmsg1(0, _("  Buffer address: %p\n"), ap);
484
485          if (ap->abfname != NULL) {
486             uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
487             char errmsg[80];
488
489             Pmsg4(0,
490               _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
491                memsize, ap->ablineno, my_name, get_basename(ap->abfname)
492             );
493             if (bufdump) {
494                unsigned llen = 0;
495                char *cp = ((char *) ap) + HEAD_SIZE;
496
497                errmsg[0] = EOS;
498                while (memsize) {
499                   if (llen >= 16) {
500                      strcat(errmsg, "\n");
501                      llen = 0;
502                      Pmsg1(0, "%s", errmsg);
503                      errmsg[0] = EOS;
504                   }
505                   if (*cp < 0x20) {
506                      sprintf(errmsg + strlen(errmsg), " %02X",
507                         (*cp++) & 0xFF);
508                   } else {
509                      sprintf(errmsg + strlen(errmsg), " %c ",
510                         (*cp++) & 0xFF);
511                   }
512                   llen++;
513                   memsize--;
514                }
515                Pmsg1(0, "%s\n", errmsg);
516             }
517          }
518       }
519       ap = (struct abufhead *)ap->abq.qnext;
520    }
521 get_out:
522    V(mutex);
523    return badbuf ? 0 : 1;
524 }
525
526
527 /*  SM_STATIC  --  Orphaned buffer detection can be disabled  (for  such
528                    items  as buffers allocated during initialisation) by
529                    calling   sm_static(1).    Normal   orphaned   buffer
530                    detection  can be re-enabled with sm_static(0).  Note
531                    that all the other safeguards still apply to  buffers
532                    allocated  when  sm_static(1)  mode is in effect.  */
533
534 void sm_static(bool mode)
535 {
536    bufimode = mode;
537 }
538
539 /*
540  * Here we overload C++'s global new and delete operators
541  *  so that the memory is allocated through smartalloc.
542  */
543
544 #ifdef xxx
545 void * operator new(size_t size)
546 {
547 // Dmsg1(000, "new called %d\n", size);
548    return sm_malloc(__FILE__, __LINE__, size);
549 }
550
551 void operator delete(void *buf)
552 {
553 // Dmsg1(000, "free called %p\n", buf);
554    sm_free(__FILE__, __LINE__, buf);
555 }
556 #endif
557
558 #endif
559
560 /* Avoid aggressive optimization */
561 void *bmemset(void *s, int c, size_t n)
562 {
563    void *ret = memset(s, c, n);
564    return ret;
565 }