]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/smartall.c
Fix bat crash due to alignment diff in bat and core code
[bacula/bacula] / bacula / src / lib / smartall.c
index 0f7c00fd5dfe1ba8b3de74361978398af5ac4794..acc27295aeb2615d1f17dd68a4d262fd7d5a8a5b 100644 (file)
@@ -1,42 +1,51 @@
 /*
 /*
+   Bacula® - The Network Backup Solution
 
 
-                        S M A R T A L L O C
-                       Smart Memory Allocator
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
 
 
-       Evolved   over   several  years,  starting  with  the  initial
-       SMARTALLOC code for AutoSketch in 1986, guided  by  the  Blind
-       Watchbreaker,  John  Walker.  Isolated in this general-purpose
-       form in  September  of  1989.   Updated  with  be  more  POSIX
-       compliant  and  to  include Web-friendly HTML documentation in
-       October  of  1998  by  the  same  culprit.    For   additional
-       information and the current version visit the Web page:
-
-                 http://www.fourmilab.ch/smartall/
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
 
 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
 
 
-        Version $Id$
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 
+   Bacula® is a registered trademark of Kern Sibbald.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
 */
 */
-
 /*
 /*
-   Copyright (C) 2000-2004 Kern Sibbald and John Walker
 
 
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+                         S M A R T A L L O C
+                        Smart Memory Allocator
 
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
+        Evolved   over   several  years,  starting  with  the  initial
+        SMARTALLOC code for AutoSketch in 1986, guided  by  the  Blind
+        Watchbreaker,  John  Walker.  Isolated in this general-purpose
+        form in  September  of  1989.   Updated  with  be  more  POSIX
+        compliant  and  to  include Web-friendly HTML documentation in
+        October  of  1998  by  the  same  culprit.    For   additional
+        information and the current version visit the Web page:
 
 
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+                  http://www.fourmilab.ch/smartall/
 
 
- */
+
+         Version $Id$
+
+*/
+
+#define _LOCKMGR_COMPLIANT
 
 #include "bacula.h"
 /* Use the real routines here */
 
 #include "bacula.h"
 /* Use the real routines here */
@@ -68,7 +77,7 @@ uint32_t sm_buffers = 0;
 
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
 
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
-extern char my_name[];               /* daemon name */
+extern char my_name[];                /* daemon name */
 
 typedef unsigned short sm_ushort;
 
 
 typedef unsigned short sm_ushort;
 
@@ -80,10 +89,11 @@ typedef unsigned short sm_ushort;
 /*  Memory allocation control structures and storage.  */
 
 struct abufhead {
 /*  Memory allocation control structures and storage.  */
 
 struct abufhead {
-   struct b_queue abq;        /* Links on allocated queue */
-   unsigned ablen;            /* Buffer length in bytes */
+   struct b_queue abq;         /* Links on allocated queue */
+   unsigned ablen;             /* Buffer length in bytes */
    const char *abfname;        /* File name pointer */
    const char *abfname;        /* File name pointer */
-   sm_ushort ablineno;        /* Line number of allocation */
+   sm_ushort ablineno;         /* Line number of allocation */
+   bool abin_use;              /* set when malloced and cleared when free */
 };
 
 static struct b_queue abqueue = {    /* Allocated buffer queue */
 };
 
 static struct b_queue abqueue = {    /* Allocated buffer queue */
@@ -91,13 +101,13 @@ static struct b_queue abqueue = {    /* Allocated buffer queue */
 };
 
 
 };
 
 
-static bool bufimode = false;  /* Buffers not tracked when True */
+static bool bufimode = false;   /* Buffers not tracked when True */
 
 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
 
 
 /*  SMALLOC  --  Allocate buffer, enqueing on the orphaned buffer
 
 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
 
 
 /*  SMALLOC  --  Allocate buffer, enqueing on the orphaned buffer
-                tracking list.  */
+                 tracking list.  */
 
 static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
 {
 
 static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
 {
@@ -121,40 +131,47 @@ static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
       qinsert(&abqueue, (struct b_queue *) buf);
       head->ablen = nbytes;
       head->abfname = bufimode ? NULL : fname;
       qinsert(&abqueue, (struct b_queue *) buf);
       head->ablen = nbytes;
       head->abfname = bufimode ? NULL : fname;
-      head->ablineno = (sm_ushort) lineno;
+      head->ablineno = (sm_ushort)lineno;
+      head->abin_use = true;
       /* Emplace end-clobber detector at end of buffer */
       /* Emplace end-clobber detector at end of buffer */
-      buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
+      buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5);
       buf += HEAD_SIZE;  /* Increment to user data start */
       if (++sm_buffers > sm_max_buffers) {
       buf += HEAD_SIZE;  /* Increment to user data start */
       if (++sm_buffers > sm_max_buffers) {
-        sm_max_buffers = sm_buffers;
+         sm_max_buffers = sm_buffers;
       }
       sm_bytes += nbytes;
       if (sm_bytes > sm_max_bytes) {
       }
       sm_bytes += nbytes;
       if (sm_bytes > sm_max_bytes) {
-        sm_max_bytes = sm_bytes;
+         sm_max_bytes = sm_bytes;
       }
       V(mutex);
    } else {
       Emsg0(M_ABORT, 0, _("Out of memory\n"));
    }
    Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
       }
       V(mutex);
    } else {
       Emsg0(M_ABORT, 0, _("Out of memory\n"));
    }
    Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
+#if    SMALLOC_SANITY_CHECK > 0
+   if (sm_bytes > SMALLOC_SANITY_CHECK) {
+      Emsg0(M_ABORT, 0, _("Too much memory used."));
+   }
+#endif
    return (void *)buf;
 }
 
 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
    return (void *)buf;
 }
 
 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
-                   This is to accomodate mem_pool. */
+                    This is to accomodate mem_pool. */
 
 void sm_new_owner(const char *fname, int lineno, char *buf)
 {
    buf -= HEAD_SIZE;  /* Decrement to header */
    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
    ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
 
 void sm_new_owner(const char *fname, int lineno, char *buf)
 {
    buf -= HEAD_SIZE;  /* Decrement to header */
    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
    ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
+   ((struct abufhead *)buf)->abin_use = true;
    return;
 }
 
 /*  SM_FREE  --  Update free pool availability.  FREE is never called
    return;
 }
 
 /*  SM_FREE  --  Update free pool availability.  FREE is never called
-                except  through  this interface or by actuallyfree().
-                free(x)  is  defined  to  generate  a  call  to  this
-                routine.  */
+                 except  through  this interface or by actuallyfree().
+                 free(x)  is  defined  to  generate  a  call  to  this
+                 routine.  */
 
 void sm_free(const char *file, int line, void *fp)
 {
 
 void sm_free(const char *file, int line, void *fp)
 {
@@ -166,13 +183,19 @@ void sm_free(const char *file, int line, void *fp)
    }
 
    cp -= HEAD_SIZE;
    }
 
    cp -= HEAD_SIZE;
-   qp = (struct b_queue *) cp;
+   qp = (struct b_queue *)cp;
    struct abufhead *head = (struct abufhead *)cp;
 
    P(mutex);
    Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
    struct abufhead *head = (struct abufhead *)cp;
 
    P(mutex);
    Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
-        head->ablen, fp,
-        head->abfname, head->ablineno);
+         head->ablen, fp,
+         head->abfname, head->ablineno);
+
+   if (!head->abin_use) {
+      V(mutex);
+      Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, line);
+   }
+   head->abin_use = false;
 
    /* The following assertions will catch virtually every release
       of an address which isn't an allocated buffer. */
 
    /* The following assertions will catch virtually every release
       of an address which isn't an allocated buffer. */
@@ -185,33 +208,39 @@ void sm_free(const char *file, int line, void *fp)
       Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
    }
 
       Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
    }
 
-   /* The following assertion detects storing off the  end  of the
+   /* The following assertion detects storing off the  end  of  the
       allocated  space in the buffer by comparing the end of buffer
       allocated  space in the buffer by comparing the end of buffer
-      checksum with the address of the buffer. */
+      checksum with the address of the buffer.  */
 
 
-   if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) {
+   if (((unsigned char *)cp)[head->ablen - 1] != ((((intptr_t) cp) & 0xFF) ^ 0xC5)) {
       V(mutex);
       Emsg2(M_ABORT, 0, _("Buffer overrun called from %s:%d\n"), file, line);
    }
       V(mutex);
       Emsg2(M_ABORT, 0, _("Buffer overrun called from %s:%d\n"), file, line);
    }
-   sm_buffers--;
-   sm_bytes -= head->ablen;
+   if (sm_buffers > 0) {
+      sm_buffers--;
+      sm_bytes -= head->ablen;
+   }
 
    qdchain(qp);
    V(mutex);
 
 
    qdchain(qp);
    V(mutex);
 
-   /* Now we wipe the contents of  the just-released  buffer  with
+   /* Now we wipe the contents of  the  just-released  buffer  with
       "designer  garbage"  (Duff  Kurland's  phrase) of alternating
       bits.  This is intended to ruin the day for any miscreant who
       attempts to access data through a pointer into storage that's
       "designer  garbage"  (Duff  Kurland's  phrase) of alternating
       bits.  This is intended to ruin the day for any miscreant who
       attempts to access data through a pointer into storage that's
-      been previously released. */
+      been previously released.
+
+      Modified, kes May, 2007 to not zap the header. This allows us
+      to check the in_use bit and detect doubly freed buffers.
+   */
 
 
-   memset(cp, 0xAA, (int) head->ablen);
+   memset(cp+HEAD_SIZE, 0xAA, (int)(head->ablen - HEAD_SIZE));
 
    free(cp);
 }
 
 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
 
    free(cp);
 }
 
 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
-                  was available.  */
+                   was available.  */
 
 void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
 {
 
 void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
 {
@@ -220,8 +249,8 @@ void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
    if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
 
       /* To catch sloppy code that assumes  buffers  obtained  from
    if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
 
       /* To catch sloppy code that assumes  buffers  obtained  from
-        malloc()  are  zeroed,  we  preset  the buffer contents to
-        "designer garbage" consisting of alternating bits.  */
+         malloc()  are  zeroed,  we  preset  the buffer contents to
+         "designer garbage" consisting of alternating bits.  */
 
       memset(buf, 0x55, (int) nbytes);
    } else {
 
       memset(buf, 0x55, (int) nbytes);
    } else {
@@ -233,7 +262,7 @@ void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
 
 void *sm_calloc(const char *fname, int lineno,
 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
 
 void *sm_calloc(const char *fname, int lineno,
-               unsigned int nelem, unsigned int elsize)
+                unsigned int nelem, unsigned int elsize)
 {
    void *buf;
 
 {
    void *buf;
 
@@ -245,14 +274,14 @@ void *sm_calloc(const char *fname, int lineno,
    return buf;
 }
 
    return buf;
 }
 
-/*  SM_REALLOC --  Adjust the size of a  previously  allocated  buffer.
-                   Note  that  the trick of "resurrecting" a previously
-                   freed buffer with realloc() is NOT supported by this
-                   function.   Further, because of the need to maintain
-                   our control storage, SM_REALLOC must always allocate
-                   a  new  block  and  copy  the data in the old block.
-                   This may result in programs which make heavy use  of
-                   realloc() running much slower than normally.  */
+/*  SM_REALLOC  --  Adjust the size of a  previously  allocated  buffer.
+                    Note  that  the trick of "resurrecting" a previously
+                    freed buffer with realloc() is NOT supported by this
+                    function.   Further, because of the need to maintain
+                    our control storage, SM_REALLOC must always allocate
+                    a  new  block  and  copy  the data in the old block.
+                    This may result in programs which make heavy use  of
+                    realloc() running much slower than normally.  */
 
 void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
 {
 
 void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
 {
@@ -265,17 +294,15 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
    }
 
       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
    }
 
-   /*  If  the old  block  pointer  is  NULL, treat realloc() as a
+   /*  If  the  old  block  pointer  is  NULL, treat realloc() as a
       malloc().  SVID is silent  on  this,  but  many  C  libraries
       permit this.  */
       malloc().  SVID is silent  on  this,  but  many  C  libraries
       permit this.  */
-
    if (ptr == NULL) {
       return sm_malloc(fname, lineno, size);
    }
 
    /* If the old and new sizes are the same, be a nice guy and just
       return the buffer passed in.  */
    if (ptr == NULL) {
       return sm_malloc(fname, lineno, size);
    }
 
    /* If the old and new sizes are the same, be a nice guy and just
       return the buffer passed in.  */
-
    cp -= HEAD_SIZE;
    struct abufhead *head = (struct abufhead *)cp;
    osize = head->ablen - (HEAD_SIZE + 1);
    cp -= HEAD_SIZE;
    struct abufhead *head = (struct abufhead *)cp;
    osize = head->ablen - (HEAD_SIZE + 1);
@@ -285,42 +312,41 @@ void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
 
    /* Sizes differ.  Allocate a new buffer of the  requested  size.
       If  we  can't  obtain  such a buffer, act as defined in SVID:
 
    /* Sizes differ.  Allocate a new buffer of the  requested  size.
       If  we  can't  obtain  such a buffer, act as defined in SVID:
-      return NULL from realloc()  and  leave  the  buffer  in  PTR
+      return NULL from  realloc()  and  leave  the  buffer  in  PTR
       intact.  */
 
       intact.  */
 
-   sm_buffers--;
-   sm_bytes -= osize;
+// sm_buffers--;
+// sm_bytes -= head->ablen;
 
    if ((buf = smalloc(fname, lineno, size)) != NULL) {
 
    if ((buf = smalloc(fname, lineno, size)) != NULL) {
-      memcpy(buf, ptr, (int) sm_min(size, osize));
+      memcpy(buf, ptr, (int)sm_min(size, osize));
       /* If the new buffer is larger than the old, fill the balance
       /* If the new buffer is larger than the old, fill the balance
-        of it with "designer garbage". */
+         of it with "designer garbage". */
       if (size > osize) {
       if (size > osize) {
-        memset(((char *) buf) + osize, 0x55, (int) (size - osize));
+         memset(((char *) buf) + osize, 0x55, (int) (size - osize));
       }
 
       /* All done.  Free and dechain the original buffer. */
       }
 
       /* All done.  Free and dechain the original buffer. */
-
       sm_free(__FILE__, __LINE__, ptr);
    }
    Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno);
    return buf;
 }
 
       sm_free(__FILE__, __LINE__, ptr);
    }
    Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno);
    return buf;
 }
 
-/*  ACTUALLYMALLOC  -- Call the system malloc() function to obtain
-                       storage which will eventually be released
-                       by system or library routines not compiled
-                       using SMARTALLOC.  */
+/*  ACTUALLYMALLOC  --  Call the system malloc() function to obtain
+                        storage which will eventually be released
+                        by system or library routines not compiled
+                        using SMARTALLOC.  */
 
 void *actuallymalloc(unsigned int size)
 {
    return malloc(size);
 }
 
 
 void *actuallymalloc(unsigned int size)
 {
    return malloc(size);
 }
 
-/*  ACTUALLYCALLOC  -- Call the system calloc() function to obtain
-                       storage which will eventually be released
-                       by system or library routines not compiled
-                       using SMARTALLOC.  */
+/*  ACTUALLYCALLOC  --  Call the system calloc() function to obtain
+                        storage which will eventually be released
+                        by system or library routines not compiled
+                        using SMARTALLOC.  */
 
 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
 {
 
 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
 {
@@ -328,9 +354,9 @@ void *actuallycalloc(unsigned int nelem, unsigned int elsize)
 }
 
 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
 }
 
 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
-                        storage which will eventually be released
-                        by system or library routines not compiled
-                        using SMARTALLOC.  */
+                         storage which will eventually be released
+                         by system or library routines not compiled
+                         using SMARTALLOC.  */
 
 void *actuallyrealloc(void *ptr, unsigned int size)
 {
 
 void *actuallyrealloc(void *ptr, unsigned int size)
 {
@@ -339,7 +365,7 @@ void *actuallyrealloc(void *ptr, unsigned int size)
 }
 
 /*  ACTUALLYFREE  --  Interface to system free() function to release
 }
 
 /*  ACTUALLYFREE  --  Interface to system free() function to release
-                     buffers allocated by low-level routines. */
+                      buffers allocated by low-level routines. */
 
 void actuallyfree(void *cp)
 {
 
 void actuallyfree(void *cp)
 {
@@ -347,11 +373,11 @@ void actuallyfree(void *cp)
 }
 
 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
 }
 
 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
- *              True).
+ *               True).
  *  N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
  *    as they have all been shut down at this point.
  */
  *  N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
  *    as they have all been shut down at this point.
  */
-void sm_dump(bool bufdump)
+void sm_dump(bool bufdump, bool in_use) 
 {
    struct abufhead *ap;
 
 {
    struct abufhead *ap;
 
@@ -362,45 +388,46 @@ void sm_dump(bool bufdump)
    while (ap != (struct abufhead *) &abqueue) {
 
       if ((ap == NULL) ||
    while (ap != (struct abufhead *) &abqueue) {
 
       if ((ap == NULL) ||
-         (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
-         (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
-        fprintf(stderr, _(
-           "\nOrphaned buffers exist.  Dump terminated following\n"
-           "  discovery of bad links in chain of orphaned buffers.\n"
-           "  Buffer address with bad links: %lx\n"), (long) ap);
-        break;
+          (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
+          (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
+         fprintf(stderr, _(
+            "\nOrphaned buffers exist.  Dump terminated following\n"
+            "  discovery of bad links in chain of orphaned buffers.\n"
+            "  Buffer address with bad links: %p\n"), ap);
+         break;
       }
 
       if (ap->abfname != NULL) {
       }
 
       if (ap->abfname != NULL) {
-        unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
-        char errmsg[500];
-
-        bsnprintf(errmsg, sizeof(errmsg),
-          _("Orphaned buffer:  %6u bytes allocated at line %d of %s %s\n"),
-           memsize, ap->ablineno, my_name, ap->abfname
-        );
-        fprintf(stderr, "%s", errmsg);
-        if (bufdump) {
-           char buf[20];
-           unsigned llen = 0;
-           char *cp = ((char *) ap) + HEAD_SIZE;
-
-           errmsg[0] = EOS;
-           while (memsize) {
-              if (llen >= 16) {
-                 bstrncat(errmsg, "\n", sizeof(errmsg));
-                 llen = 0;
-                 fprintf(stderr, "%s", errmsg);
-                 errmsg[0] = EOS;
-              }
-              bsnprintf(buf, sizeof(buf), " %02X",
-                 (*cp++) & 0xFF);
-              bstrncat(errmsg, buf, sizeof(errmsg));
-              llen++;
-              memsize--;
-           }
-           fprintf(stderr, "%s\n", errmsg);
-        }
+         unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+         char errmsg[500];
+         char *cp = ((char *)ap) + HEAD_SIZE;
+
+         bsnprintf(errmsg, sizeof(errmsg),
+           _("%s buffer:  %s %6u bytes buf=%p allocated at %s:%d\n"),
+            in_use?"In use":"Orphaned",
+            my_name, memsize, cp, ap->abfname, ap->ablineno
+         );
+         fprintf(stderr, "%s", errmsg);
+         if (bufdump) {
+            char buf[20];
+            unsigned llen = 0;
+
+            errmsg[0] = EOS;
+            while (memsize) {
+               if (llen >= 16) {
+                  bstrncat(errmsg, "\n", sizeof(errmsg));
+                  llen = 0;
+                  fprintf(stderr, "%s", errmsg);
+                  errmsg[0] = EOS;
+               }
+               bsnprintf(buf, sizeof(buf), " %02X",
+                  (*cp++) & 0xFF);
+               bstrncat(errmsg, buf, sizeof(errmsg));
+               llen++;
+               memsize--;
+            }
+            fprintf(stderr, "%s\n", errmsg);
+         }
       }
       ap = (struct abufhead *) ap->abq.qnext;
    }
       }
       ap = (struct abufhead *) ap->abq.qnext;
    }
@@ -411,10 +438,10 @@ void sm_dump(bool bufdump)
 /*  SM_CHECK --  Check the buffers and dump if any damage exists. */
 void sm_check(const char *fname, int lineno, bool bufdump)
 {
 /*  SM_CHECK --  Check the buffers and dump if any damage exists. */
 void sm_check(const char *fname, int lineno, bool bufdump)
 {
-       if (!sm_check_rtn(fname, lineno, bufdump)) {
-          Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
-             fname, lineno);
-       }
+   if (!sm_check_rtn(fname, lineno, bufdump)) {
+      Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
+            fname, lineno);
+   }
 }
 
 #undef sm_check_rtn
 }
 
 #undef sm_check_rtn
@@ -426,87 +453,97 @@ int sm_check_rtn(const char *fname, int lineno, bool bufdump)
 
    P(mutex);
    ap = (struct abufhead *) abqueue.qnext;
 
    P(mutex);
    ap = (struct abufhead *) abqueue.qnext;
-   while (ap != (struct abufhead *) &abqueue) {
+   while (ap != (struct abufhead *)&abqueue) {
       bad = 0;
       bad = 0;
-      if ((ap == NULL) ||
-         (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
-        bad = 0x1;
-      }
-      if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
-        bad |= 0x2;
-      }
-      if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
-          ((((long) ap) & 0xFF) ^ 0xC5)) {
-        bad |= 0x4;
+      if (ap != NULL) {
+         if (ap->abq.qnext->qprev != (struct b_queue *)ap) {
+            bad = 0x1;
+         }
+         if (ap->abq.qprev->qnext != (struct b_queue *)ap) {
+            bad |= 0x2;
+         }
+         if (((unsigned char *) ap)[((struct abufhead *)ap)->ablen - 1] !=
+              ((((intptr_t) ap) & 0xFF) ^ 0xC5)) {
+            bad |= 0x4;
+         }
+      } else {
+         bad = 0x8;
       }
       badbuf |= bad;
       if (bad) {
       }
       badbuf |= bad;
       if (bad) {
-        fprintf(stderr,
-           _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
-
-        if (bad & 0x1) {
-           fprintf(stderr, _("  discovery of bad prev link.\n"));
-        }
-        if (bad & 0x2) {
-           fprintf(stderr, _("  discovery of bad next link.\n"));
-        }
-        if (bad & 0x4) {
-           fprintf(stderr, _("  discovery of data overrun.\n"));
-        }
-
-        fprintf(stderr, _("  Buffer address: %lx\n"), (long) ap);
-
-        if (ap->abfname != NULL) {
-           unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
-           char errmsg[80];
-
-           fprintf(stderr,
-             _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
-              memsize, ap->ablineno, my_name, ap->abfname
-           );
-           if (bufdump) {
-              unsigned llen = 0;
-              char *cp = ((char *) ap) + HEAD_SIZE;
-
-              errmsg[0] = EOS;
-              while (memsize) {
-                 if (llen >= 16) {
-                    strcat(errmsg, "\n");
-                    llen = 0;
-                    fprintf(stderr, "%s", errmsg);
-                    errmsg[0] = EOS;
-                 }
-                 if (*cp < 0x20) {
-                    sprintf(errmsg + strlen(errmsg), " %02X",
-                       (*cp++) & 0xFF);
-                 } else {
-                    sprintf(errmsg + strlen(errmsg), " %c ",
-                       (*cp++) & 0xFF);
-                 }
-                 llen++;
-                 memsize--;
-              }
-              fprintf(stderr, "%s\n", errmsg);
-           }
-        }
+         fprintf(stderr,
+            _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
+
+         if (bad & 0x1) {
+            fprintf(stderr, _("  discovery of bad prev link.\n"));
+         }
+         if (bad & 0x2) {
+            fprintf(stderr, _("  discovery of bad next link.\n"));
+         }
+         if (bad & 0x4) {
+            fprintf(stderr, _("  discovery of data overrun.\n"));
+         }
+         if (bad & 0x8) {
+            fprintf(stderr, _("  NULL pointer.\n"));
+         }
+
+         if (!ap) {
+            goto get_out;
+         }
+         fprintf(stderr, _("  Buffer address: %p\n"), ap);
+
+         if (ap->abfname != NULL) {
+            unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+            char errmsg[80];
+
+            fprintf(stderr,
+              _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
+               memsize, ap->ablineno, my_name, ap->abfname
+            );
+            if (bufdump) {
+               unsigned llen = 0;
+               char *cp = ((char *) ap) + HEAD_SIZE;
+
+               errmsg[0] = EOS;
+               while (memsize) {
+                  if (llen >= 16) {
+                     strcat(errmsg, "\n");
+                     llen = 0;
+                     fprintf(stderr, "%s", errmsg);
+                     errmsg[0] = EOS;
+                  }
+                  if (*cp < 0x20) {
+                     sprintf(errmsg + strlen(errmsg), " %02X",
+                        (*cp++) & 0xFF);
+                  } else {
+                     sprintf(errmsg + strlen(errmsg), " %c ",
+                        (*cp++) & 0xFF);
+                  }
+                  llen++;
+                  memsize--;
+               }
+               fprintf(stderr, "%s\n", errmsg);
+            }
+         }
       }
       }
-      ap = (struct abufhead *) ap->abq.qnext;
+      ap = (struct abufhead *)ap->abq.qnext;
    }
    }
+get_out:
    V(mutex);
    return badbuf ? 0 : 1;
 }
 
 
 /*  SM_STATIC  --  Orphaned buffer detection can be disabled  (for  such
    V(mutex);
    return badbuf ? 0 : 1;
 }
 
 
 /*  SM_STATIC  --  Orphaned buffer detection can be disabled  (for  such
-                  items  as buffers allocated during initialisation) by
-                  calling   sm_static(1).    Normal   orphaned   buffer
-                  detection  can be re-enabled with sm_static(0).  Note
-                  that all the other safeguards still apply to  buffers
-                  allocated  when  sm_static(1)  mode is in effect.  */
+                   items  as buffers allocated during initialisation) by
+                   calling   sm_static(1).    Normal   orphaned   buffer
+                   detection  can be re-enabled with sm_static(0).  Note
+                   that all the other safeguards still apply to  buffers
+                   allocated  when  sm_static(1)  mode is in effect.  */
 
 
-void sm_static(int mode)
+void sm_static(bool mode)
 {
 {
-   bufimode = (bool) (mode != 0);
+   bufimode = mode;
 }
 
 /*
 }
 
 /*